File:  [parser3project] / parser3 / src / types / pa_vhash.h
Revision 1.89: download - view: text, annotated - select for diffs - revision graph
Sat Apr 25 13:38:46 2026 UTC (2 months, 1 week ago) by moko
Branches: MAIN
CVS tags: HEAD
Copyright year updated, websites links changed to https://

/** @file
	Parser: @b hash parser type decl.

	Copyright (c) 2001-2026 Art. Lebedev Studio (https://www.artlebedev.com)
	Authors: Konstantin Morshnev <moko@design.ru>, Alexandr Petrosian <paf@design.ru>
*/

#ifndef PA_VHASH_H
#define PA_VHASH_H

#define IDENT_PA_VHASH_H "$Id: pa_vhash.h,v 1.89 2026/04/25 13:38:46 moko Exp $"

#include "classes.h"
#include "pa_value.h"
#include "pa_hash.h"
#include "pa_vint.h"
#include "pa_globals.h"
#include "pa_symbols.h"

// defines

#define VHASH_TYPE "hash"

extern Methoded* hash_class;

class VHashBase: public VStateless_object {
public: // value

	override const char* type() const { return VHASH_TYPE; }
	override VStateless_class *get_class() { return hash_class; }

public: // usage

	virtual HashStringValue& hash()=0;
	virtual void set_default(Value* adefault)=0;
	virtual Value* get_default()=0;
	virtual void add(Value* avalue)=0;
};


/// value of type 'hash', implemented with Hash
class VHash: public VHashBase {
public: // value

	/// VHash: count
	override int as_int() const { return fhash.count(); }
	override double as_double() const { return fhash.count(); }
	override bool is_defined() const { return fhash.count()!=0 || _default!=NULL; }
	override bool as_bool() const { return fhash.count()!=0; }
	override Value& as_expr_result() { return *new VInt(fhash.count()); }

	/// VHash: fhash
	override HashStringValue *get_hash() { return &fhash; }
	override HashStringValue* get_fields() { return &fhash; }
	override HashStringValue* get_fields_reference() { return &fhash; }

	/// VHash: (key)=value
	override Value* get_element(const String& aname) {
		// $element first
		if(Value* result=fhash.get(aname))
			return result;

		// $fields -- pseudo field to make 'hash' more like 'table'
		if(SYMBOLS_EQ(aname,FIELDS_SYMBOL))
			return this;

#if !defined(FEATURE_GET_ELEMENT4CALL) || !defined(OPTIMIZE_BYTECODE_GET_ELEMENT__SPECIAL)
		// $method, CLASS, CLASS_NAME
		if(Value* result=VStateless_object::get_element(aname))
			return result;
#endif

		// default value
		return get_default();
	}

#ifdef FEATURE_GET_ELEMENT4CALL
	override Value* get_element4call(const String& aname) {
		// $method first
		if(Value* result=VStateless_object::get_element(aname))
			return result;

		// $element
		if(Value* result=fhash.get(aname))
			return result;

		// default value
		if(Value* result=get_default())
			return result;

		return bark("%s method not found", &aname);
	}
#endif

	/// VHash: (key)=value
	override const VJunction* put_element(const String& aname, Value* avalue) {
		if(SYMBOLS_EQ(aname,_DEFAULT_SYMBOL))
			set_default(avalue);
		else 
			fhash.put(aname, avalue);

		return 0;
	}

	override VFile* as_vfile(String::Language lang, const Request_charsets *charsets=0);

public: // usage

	VHash(): _default(0) {}

	VHash(const HashStringValue& source): fhash(source), _default(0) {}

	override HashStringValue& hash() { return fhash; }
	override void set_default(Value* adefault) { _default=adefault; }
	override Value* get_default() { return _default; }
	override void add(Value* avalue) { fhash.put(String::Body::uitoa(fhash.count()), avalue); }

	void extract_default();

private:

	HashStringValue fhash;
	Value* _default;

};

/// value of type 'hash', implemented with Hash reference
class VHashReference: public VHashBase {
public: // value

	/// VHash: count
	override int as_int() const { return fhash->count(); }
	override double as_double() const { return fhash->count(); }
	override bool is_defined() const { return fhash->count()!=0; }
	override bool as_bool() const { return fhash->count()!=0; }
	override Value& as_expr_result() { return *new VInt(fhash->count()); }

	/// VHash: fhash
	override HashStringValue *get_hash() { return fhash; }
	override HashStringValue* get_fields() { return fhash; }
	override HashStringValue* get_fields_reference() { return fhash; }

	/// VHash: (key)=value
	override Value* get_element(const String& aname) { 
		// $element first
		if(Value* result=fhash->get(aname))
			return result;

		// $fields -- pseudo field to make 'hash' more like 'table'
		if(SYMBOLS_EQ(aname,FIELDS_SYMBOL))
			return this;

#if !defined(FEATURE_GET_ELEMENT4CALL) || !defined(OPTIMIZE_BYTECODE_GET_ELEMENT__SPECIAL)
		// $method, CLASS, CLASS_NAME
		if(Value* result=VStateless_object::get_element(aname))
			return result;
#endif

		return 0;
	}
	
#ifdef FEATURE_GET_ELEMENT4CALL
	override Value* get_element4call(const String& aname) {
		// $method first
		if(Value* result=VStateless_object::get_element(aname))
			return result;

		// $element
		if(Value* result=fhash->get(aname))
			return result;

		return 0;
	}
#endif
	
	/// VHash: (key)=value
	override const VJunction* put_element(const String& aname, Value* avalue) {
		fhash->put(aname, avalue);
		return 0;
	}

public: // usage

	VHashReference(HashStringValue& source): fhash(&source) {}

	override HashStringValue& hash() { return *fhash; }
	override void set_default(Value*) { }
	override Value* get_default() { return 0; }
	override void add(Value* avalue) { fhash->put(String::Body::uitoa(fhash->count()), avalue); }

private:

	HashStringValue *fhash;
};

#endif

E-mail: