📄 value.cc
字号:
// $Header$#include "system.h"#include <string.h>#include <stream.h>#include <stdlib.h>#include "Sds/sdsgen.h"#include "Glish/Value.h"#include "glish_event.h"#include "BinOpExpr.h"#include "Func.h"#include "Reporter.h"int num_Values_created = 0;int num_Values_deleted = 0;const char* type_names[NUM_GLISH_TYPES] = { "error", "ref", "const", "subref", "subconst", "boolean", "byte", "short", "integer", "float", "double", "string", "agent", "function", "record", "complex", "dcomplex", "opaque", };const Value* false_value;#define AGENT_MEMBER_NAME "*agent*"class SDS_ValueManager : public GlishObject { public: SDS_ValueManager( int sds_index ) { sds = sds_index; } ~SDS_ValueManager() { sds_destroy( sds ); sds_discard( sds ); } protected: int sds; };class DelObj : public GlishObject {public: DelObj( GlishObject* arg_obj ) { obj = arg_obj; ptr = 0; } DelObj( void* arg_ptr ) { obj = 0; ptr = arg_ptr; } ~DelObj();protected: GlishObject* obj; void* ptr;};DelObj::~DelObj() { Unref( obj ); delete ptr; }#define DEFINE_SINGLETON_CONSTRUCTOR(constructor_type) \Value::Value( constructor_type value ) \ { \ InitValue(); \ SetValue( &value, 1, COPY_ARRAY ); \ }#define DEFINE_ARRAY_CONSTRUCTOR(constructor_type) \Value::Value( constructor_type value[], int len, array_storage_type storage )\ { \ InitValue(); \ SetValue( value, len, storage ); \ }#define DEFINE_ARRAY_REF_CONSTRUCTOR(constructor_type) \Value::Value( constructor_type& value_ref ) \ { \ InitValue(); \ SetValue( value_ref ); \ }#define DEFINE_CONSTRUCTORS(type,reftype) \ DEFINE_SINGLETON_CONSTRUCTOR(type) \ DEFINE_ARRAY_CONSTRUCTOR(type) \ DEFINE_ARRAY_REF_CONSTRUCTOR(reftype)DEFINE_CONSTRUCTORS(glish_bool,glish_boolref)DEFINE_CONSTRUCTORS(byte,byteref)DEFINE_CONSTRUCTORS(short,shortref)DEFINE_CONSTRUCTORS(int,intref)DEFINE_CONSTRUCTORS(float,floatref)DEFINE_CONSTRUCTORS(double,doubleref)DEFINE_CONSTRUCTORS(complex,complexref)DEFINE_CONSTRUCTORS(dcomplex,dcomplexref)DEFINE_CONSTRUCTORS(charptr,charptrref)DEFINE_SINGLETON_CONSTRUCTOR(agentptr)DEFINE_SINGLETON_CONSTRUCTOR(funcptr)DEFINE_ARRAY_CONSTRUCTOR(funcptr)Value::Value( recordptr value, Agent* agent ) { InitValue(); SetValue( value, agent ); }Value::Value( SDS_Index& value ) { InitValue(); SetValue( value ); }Value::Value( Value* ref_value, value_type val_type ) { InitValue(); storage = TAKE_OVER_ARRAY; if ( val_type == VAL_CONST ) type = TYPE_CONST; else if ( val_type == VAL_REF ) type = TYPE_REF; else fatal->Report( "bad value_type in Value::Value" ); if ( ref_value->IsConst() && val_type == VAL_REF ) warn->Report( "\"ref\" reference created from \"const\" reference" ); ref_value = ref_value->Deref(); attributes = ref_value->CopyAttributePtr(); Ref( ref_value ); values = (void*) ref_value; }Value::Value( Value* ref_value, int index[], int num_elements, value_type val_type ) { InitValue(); SetValue( ref_value, index, num_elements, val_type ); attributes = ref_value->CopyAttributePtr(); }void Value::TakeValue( Value* new_value ) { new_value = new_value->Deref(); if ( new_value == this ) { error->Report( "reference loop created" ); return; } DeleteValue(); int my_ref_count = ref_count; *this = *new_value; ref_count = my_ref_count; new_value->type = TYPE_ERROR; Unref( new_value ); }Value::~Value() { DeleteValue(); ++num_Values_deleted; }#define DEFINE_ARRAY_SET_VALUE(type, glish_type) \void Value::SetValue( type array[], int len, array_storage_type arg_storage )\ { \ SetType( glish_type ); \ max_size = length = len; \ storage = arg_storage; \ values = storage == COPY_ARRAY ? copy_values( array, type ) : array;\ }#define DEFINE_REF_SET_VALUE(reftype, glish_type) \void Value::SetValue( reftype& value_ref ) \ { \ SetType( glish_type ); \ max_size = length = value_ref.Length(); \ storage = COPY_ARRAY; \ values = value_ref.DupVec(); \ }#define DEFINE_SET_VALUE(type, reftype, glish_type) \DEFINE_ARRAY_SET_VALUE(type, glish_type) \DEFINE_REF_SET_VALUE(reftype, glish_type)DEFINE_SET_VALUE(glish_bool,glish_boolref,TYPE_BOOL)DEFINE_SET_VALUE(byte,byteref,TYPE_BYTE)DEFINE_SET_VALUE(short,shortref,TYPE_SHORT)DEFINE_SET_VALUE(int,intref,TYPE_INT)DEFINE_SET_VALUE(float,floatref,TYPE_FLOAT)DEFINE_SET_VALUE(double,doubleref,TYPE_DOUBLE)DEFINE_SET_VALUE(complex,complexref,TYPE_COMPLEX)DEFINE_SET_VALUE(dcomplex,dcomplexref,TYPE_DCOMPLEX)DEFINE_ARRAY_SET_VALUE(agentptr,TYPE_AGENT)DEFINE_ARRAY_SET_VALUE(funcptr,TYPE_FUNC)DEFINE_REF_SET_VALUE(charptrref,TYPE_STRING)void Value::SetValue( const char* array[], int len, array_storage_type arg_storage ) { SetType( TYPE_STRING ); max_size = length = len; storage = arg_storage; if ( storage == COPY_ARRAY ) { values = (void*) new charptr[len]; charptr* sptr = StringPtr(); for ( int i = 0; i < len; ++i ) sptr[i] = strdup( array[i] ); } else values = array; }void Value::SetValue( recordptr value, Agent* agent ) { SetType( TYPE_RECORD ); values = (void*) value; max_size = length = 1; storage = TAKE_OVER_ARRAY; if ( agent ) RecordPtr()->Insert( strdup( AGENT_MEMBER_NAME ), new Value( agent ) ); }void Value::SetValue( SDS_Index& value ) { SetType( TYPE_OPAQUE ); values = (void*) value.Index(); max_size = length = 1; storage = PRESERVE_ARRAY; }void Value::SetValue( Value* ref_value, int index[], int num_elements, value_type val_type ) { if ( val_type == VAL_CONST ) SetType( TYPE_SUBVEC_CONST ); else if ( val_type == VAL_REF ) SetType( TYPE_SUBVEC_REF ); else fatal->Report( "bad value_type in Value::Value" ); storage = TAKE_OVER_ARRAY; if ( ref_value->IsConst() && val_type == VAL_REF ) warn->Report( "\"ref\" reference created from \"const\" reference" ); ref_value = ref_value->Deref(); length = num_elements; int max_index; if ( ! IndexRange( index, num_elements, max_index ) ) fatal->Report( "bad index in Value::Value" ); if ( max_index > ref_value->Length() ) if ( ! ref_value->Grow( max_index ) ) return; switch ( ref_value->Type() ) { case TYPE_BOOL: case TYPE_BYTE: case TYPE_SHORT: case TYPE_INT: case TYPE_FLOAT: case TYPE_DOUBLE: case TYPE_COMPLEX: case TYPE_DCOMPLEX: case TYPE_STRING: case TYPE_SUBVEC_REF: case TYPE_SUBVEC_CONST: values = (void*) new VecRef( ref_value, index, num_elements, max_index ); break; default: fatal->Report( "bad Value in Value::Value" ); } }void Value::InitValue() { type = TYPE_ERROR; description = 0; value_manager = 0; attributes = 0; ++num_Values_created; }void Value::SetType( glish_type new_type ) { DeleteValue(); type = new_type; }void Value::DeleteValue() { switch ( type ) { case TYPE_CONST: case TYPE_REF: Unref( RefPtr() ); // So we don't also delete "values" ... type = TYPE_ERROR; break; case TYPE_SUBVEC_CONST: case TYPE_SUBVEC_REF: Unref( VecRefPtr() ); type = TYPE_ERROR; break; case TYPE_STRING: if ( ! value_manager && storage != PRESERVE_ARRAY ) { charptr* sptr = StringPtr(); for ( int i = 0; i < length; ++i ) delete (char*) sptr[i]; } break; case TYPE_AGENT: // Here we rely on the fact that Agent is derived // GlishObject, which has a virtual destructor. Unref( (GlishObject*) AgentVal() ); break; case TYPE_RECORD: { delete_record( RecordPtr() ); // So we don't delete "values" again ... type = TYPE_ERROR; break; } default: break; } if ( type != TYPE_ERROR ) { if ( value_manager ) { Unref( value_manager ); // It's important to get rid of our value_manager // pointer here; a call to DeleteValue does not // necessarily mean we're throwing away the entire // Value object. (For example, we may be called // by SetType, called in turn by Polymorph.) Thus // as we're done with this value_manager, mark it // as so. value_manager = 0; } else if ( storage != PRESERVE_ARRAY ) delete values; DeleteAttributes(); } }void Value::DeleteAttributes() { Unref( attributes ); attributes = 0; }void Value::DeleteAttribute( const Value* index ) { char* index_string = index->StringVal(); DeleteAttribute( index_string ); delete index_string; }void Value::DeleteAttribute( const char field[] ) { attributeptr attr = ModAttributePtr(); if ( attr ) delete attr->Remove( field ); }int Value::IsNumeric() const { switch ( type ) { case TYPE_BOOL: case TYPE_BYTE: case TYPE_SHORT: case TYPE_INT: case TYPE_FLOAT: case TYPE_DOUBLE: case TYPE_COMPLEX: case TYPE_DCOMPLEX: return 1; case TYPE_CONST: case TYPE_REF: case TYPE_STRING: case TYPE_AGENT: case TYPE_FUNC: case TYPE_RECORD: case TYPE_OPAQUE: return 0; case TYPE_SUBVEC_CONST: case TYPE_SUBVEC_REF: return VecRefPtr()->Val()->IsNumeric(); case TYPE_ERROR: default: fatal->Report( "bad type in Value::IsNumeric()" ); return 0; // for overly clever compilers } }int Value::IsAgentRecord() const { if ( VecRefDeref()->Type() == TYPE_RECORD && (*RecordPtr())[AGENT_MEMBER_NAME] ) return 1; else return 0; }#define DEFINE_CONST_ACCESSOR(name,tag,type) \type Value::name() const \ { \ if ( IsVecRef() ) \ return ((const Value*) VecRefPtr()->Val())->name(); \ else if ( Type() != tag ) \ fatal->Report( "bad use of const accessor" ); \ return (type) values; \ }DEFINE_CONST_ACCESSOR(BoolPtr,TYPE_BOOL,glish_bool*)DEFINE_CONST_ACCESSOR(BytePtr,TYPE_BYTE,byte*)DEFINE_CONST_ACCESSOR(ShortPtr,TYPE_SHORT,short*)DEFINE_CONST_ACCESSOR(IntPtr,TYPE_INT,int*)DEFINE_CONST_ACCESSOR(FloatPtr,TYPE_FLOAT,float*)DEFINE_CONST_ACCESSOR(DoublePtr,TYPE_DOUBLE,double*)DEFINE_CONST_ACCESSOR(ComplexPtr,TYPE_COMPLEX,complex*)DEFINE_CONST_ACCESSOR(DcomplexPtr,TYPE_DCOMPLEX,dcomplex*)DEFINE_CONST_ACCESSOR(StringPtr,TYPE_STRING,charptr*)DEFINE_CONST_ACCESSOR(FuncPtr,TYPE_FUNC,funcptr*)DEFINE_CONST_ACCESSOR(AgentPtr,TYPE_AGENT,agentptr*)DEFINE_CONST_ACCESSOR(RecordPtr,TYPE_RECORD,recordptr)#define DEFINE_ACCESSOR(name,tag,type) \type Value::name() \ { \ if ( IsVecRef() ) \ return VecRefPtr()->Val()->name(); \ if ( Type() != tag ) \ Polymorph( tag ); \ return (type) values; \ }DEFINE_ACCESSOR(BoolPtr,TYPE_BOOL,glish_bool*)DEFINE_ACCESSOR(BytePtr,TYPE_BYTE,byte*)DEFINE_ACCESSOR(ShortPtr,TYPE_SHORT,short*)DEFINE_ACCESSOR(IntPtr,TYPE_INT,int*)DEFINE_ACCESSOR(FloatPtr,TYPE_FLOAT,float*)DEFINE_ACCESSOR(DoublePtr,TYPE_DOUBLE,double*)DEFINE_ACCESSOR(ComplexPtr,TYPE_COMPLEX,complex*)DEFINE_ACCESSOR(DcomplexPtr,TYPE_DCOMPLEX,dcomplex*)DEFINE_ACCESSOR(StringPtr,TYPE_STRING,charptr*)DEFINE_ACCESSOR(FuncPtr,TYPE_FUNC,funcptr*)DEFINE_ACCESSOR(AgentPtr,TYPE_AGENT,agentptr*)DEFINE_ACCESSOR(RecordPtr,TYPE_RECORD,recordptr)#define DEFINE_CONST_REF_ACCESSOR(name,tag,type) \type& Value::name() const \ { \ if ( ! IsVecRef() ) \ fatal->Report( "bad use of subarray reference accessor" );\ if ( VecRefPtr()->Type() != tag ) \ fatal->Report( "bad use of subarray reference accessor" );\ return *(VecRefPtr()->name()); \ }DEFINE_CONST_REF_ACCESSOR(BoolRef,TYPE_BOOL,glish_boolref)DEFINE_CONST_REF_ACCESSOR(ByteRef,TYPE_BYTE,byteref)DEFINE_CONST_REF_ACCESSOR(ShortRef,TYPE_SHORT,shortref)DEFINE_CONST_REF_ACCESSOR(IntRef,TYPE_INT,intref)DEFINE_CONST_REF_ACCESSOR(FloatRef,TYPE_FLOAT,floatref)DEFINE_CONST_REF_ACCESSOR(DoubleRef,TYPE_DOUBLE,doubleref)DEFINE_CONST_REF_ACCESSOR(ComplexRef,TYPE_COMPLEX,complexref)DEFINE_CONST_REF_ACCESSOR(DcomplexRef,TYPE_DCOMPLEX,dcomplexref)DEFINE_CONST_REF_ACCESSOR(StringRef,TYPE_STRING,charptrref)#define DEFINE_REF_ACCESSOR(name,tag,type) \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -