📄 value.cc
字号:
type& Value::name() \ { \ if ( ! IsVecRef() ) \ fatal->Report( "bad use of subarray reference accessor" );\ if ( VecRefPtr()->Type() != tag ) \ Polymorph( tag ); \ return *(VecRefPtr()->name()); \ }DEFINE_REF_ACCESSOR(BoolRef,TYPE_BOOL,glish_boolref)DEFINE_REF_ACCESSOR(ByteRef,TYPE_BYTE,byteref)DEFINE_REF_ACCESSOR(ShortRef,TYPE_SHORT,shortref)DEFINE_REF_ACCESSOR(IntRef,TYPE_INT,intref)DEFINE_REF_ACCESSOR(FloatRef,TYPE_FLOAT,floatref)DEFINE_REF_ACCESSOR(DoubleRef,TYPE_DOUBLE,doubleref)DEFINE_REF_ACCESSOR(ComplexRef,TYPE_COMPLEX,complexref)DEFINE_REF_ACCESSOR(DcomplexRef,TYPE_DCOMPLEX,dcomplexref)DEFINE_REF_ACCESSOR(StringRef,TYPE_STRING,charptrref)#define XXX_VAL(name, val_type, rhs_elm, text_func, type_name, zero) \val_type Value::name( int n ) const \ { \ if ( IsRef() ) \ return Deref()->name( n ); \ \ if ( length < 1 ) \ { \ error->Report( "empty array converted to ", type_name );\ return zero; \ } \ \ if ( n < 1 || n > length ) \ { \ error->Report( "in conversion to ", type_name, " index (=", n,\ ") out of bounds, length =", length ); \ return zero; \ } \ \ switch ( type ) \ { \ case TYPE_BOOL: \ return val_type( BoolPtr()[n - 1] ? 1 : 0 ); \ \ case TYPE_BYTE: \ return val_type( BytePtr()[n - 1] ); \ \ case TYPE_SHORT: \ return val_type( ShortPtr()[n - 1] ); \ \ case TYPE_INT: \ return val_type( IntPtr()[n - 1] ); \ \ case TYPE_FLOAT: \ return val_type( FloatPtr()[n - 1] ); \ \ case TYPE_DOUBLE: \ return val_type( DoublePtr()[n - 1] ); \ \ case TYPE_COMPLEX: \ return val_type( ComplexPtr()[n - 1] rhs_elm ); \ \ case TYPE_DCOMPLEX: \ return val_type( DcomplexPtr()[n - 1] rhs_elm );\ \ case TYPE_STRING: \ { \ int successful; \ val_type result = val_type( \ text_func( StringPtr()[n - 1], successful ) );\ \ if ( ! successful ) \ warn->Report( "string \"", this, \ "\" converted to ", type_name );\ return result; \ } \ \ case TYPE_AGENT: \ case TYPE_FUNC: \ case TYPE_RECORD: \ case TYPE_OPAQUE: \ error->Report( "bad type", type_names[Type()], \ "converted to ", type_name, ":", this );\ return zero; \ \ case TYPE_SUBVEC_CONST: \ case TYPE_SUBVEC_REF: \ { \ VecRef* ref = VecRefPtr(); \ int err; \ int off = ref->TranslateIndex( n-1, &err ); \ if ( err ) \ { \ error->Report( "bad sub-vector subscript" );\ return zero; \ } \ return ref->Val()->name( off ); \ } \ \ default: \ fatal->Report( "bad type in Value::XXX_VAL()" );\ return zero; \ } \ }XXX_VAL(BoolVal, glish_bool, .r, text_to_integer, "bool", glish_false)XXX_VAL(ByteVal, byte, .r, text_to_integer, "byte", 0)XXX_VAL(ShortVal, short, .r, text_to_integer, "short", 0)XXX_VAL(IntVal, int, .r, text_to_integer, "integer", 0)XXX_VAL(FloatVal, float, .r, text_to_double, "float", 0.0)XXX_VAL(DoubleVal, double, .r, text_to_double, "double", 0.0)XXX_VAL(ComplexVal, complex,, text_to_dcomplex, "complex", complex(0.0, 0.0))XXX_VAL(DcomplexVal, dcomplex,, text_to_dcomplex, "dcomplex", dcomplex(0.0, 0.0))static void append_buf( char* &buf, char* &buf_ptr, unsigned int& buf_size, const char* a = 0, const char* b = 0, const char* c = 0 ) { a = a ? a : ""; b = b ? b : ""; c = c ? c : ""; int buf_remaining = &buf[buf_size] - buf_ptr; int size_of_addition = strlen( a ) + strlen( b ) + strlen( c ); while ( size_of_addition >= buf_remaining - 5 /* slop */ ) { // Need to grow the buffer. int buf_ptr_offset = buf_ptr - buf; buf_size *= 2; buf = (char*) realloc_memory( (void*) buf, buf_size ); if ( ! buf ) fatal->Report( "out of memory in append_buf()" ); buf_ptr = buf + buf_ptr_offset; buf_remaining = &buf[buf_size] - buf_ptr; } *buf_ptr = '\0'; strcat( buf_ptr, a ); strcat( buf_ptr, b ); strcat( buf_ptr, c ); buf_ptr += size_of_addition; }char* Value::StringVal( char sep, int useAttributes ) const { if ( IsRef() ) return Deref()->StringVal( sep, useAttributes ); if ( type == TYPE_RECORD ) return RecordStringVal(); if ( type == TYPE_AGENT ) return strdup( "<agent>" ); if ( type == TYPE_FUNC ) return strdup( "<function>" ); if ( type == TYPE_OPAQUE ) return strdup( "<opaque>" ); if ( length == 0 ) return strdup( "" ); unsigned int buf_size; // Make a guess as to a probable good size for buf. if ( type == TYPE_STRING ) { buf_size = strlen( StringPtr()[0] ) * (length + 1); if ( buf_size == 0 ) buf_size = 8; } else if ( type == TYPE_COMPLEX || type == TYPE_DCOMPLEX ) buf_size = length * 16 * 2 + 1; else if ( type == TYPE_FLOAT || type == TYPE_DOUBLE ) buf_size = length * 16; else buf_size = length * 8; char* buf = new char[buf_size]; if ( ! buf ) fatal->Report( "out of memory in Value::StringVal()" ); char* buf_ptr = buf; if ( type != TYPE_STRING && length > 1 ) { // Insert []'s around value. *buf_ptr++ = '['; } glish_bool* bool_ptr; byte* byte_ptr; short* short_ptr; int* int_ptr; float* float_ptr; double* double_ptr; complex* complex_ptr; dcomplex* dcomplex_ptr; charptr* string_ptr; switch ( VecRefDeref()->type ) {#define ASSIGN_PTR(tag,ptr_name,source) \ case tag: \ ptr_name = source; \ break; ASSIGN_PTR(TYPE_BOOL,bool_ptr,BoolPtr()) ASSIGN_PTR(TYPE_INT,int_ptr,IntPtr()) ASSIGN_PTR(TYPE_BYTE,byte_ptr,BytePtr()) ASSIGN_PTR(TYPE_SHORT,short_ptr,ShortPtr()) ASSIGN_PTR(TYPE_FLOAT,float_ptr,FloatPtr()) ASSIGN_PTR(TYPE_DOUBLE,double_ptr,DoublePtr()) ASSIGN_PTR(TYPE_COMPLEX,complex_ptr,ComplexPtr()) ASSIGN_PTR(TYPE_DCOMPLEX,dcomplex_ptr,DcomplexPtr()) ASSIGN_PTR(TYPE_STRING,string_ptr,StringPtr()) default: fatal->Report( "bad type in Value::StringVal()" ); }// Macro to generate the text corresponding to a single element of a given type.#define PLACE_ELEMENT_ACTION(buffer,str_buffer,indx) \ case TYPE_BOOL: \ strcpy( buffer, bool_ptr[indx] ? "T" : "F" ); \ break; \ \ case TYPE_BYTE: \ sprintf( buffer, "%d", byte_ptr[indx] ); \ break; \ \ case TYPE_SHORT: \ sprintf( buffer, "%d", short_ptr[indx] ); \ break; \ \ case TYPE_INT: \ sprintf( buffer, "%d", int_ptr[indx] ); \ break; \ \ case TYPE_FLOAT: \ sprintf( buffer, "%g", float_ptr[indx] ); \ break; \ \ case TYPE_DOUBLE: \ sprintf( buffer, "%g", double_ptr[indx] ); \ break; \ \ case TYPE_COMPLEX: \ sprintf( buffer, complex_ptr[indx].i >= 0.0 ? \ "%g+%gi" : "%g%gi", complex_ptr[indx].r,\ complex_ptr[indx].i ); \ break; \ \ case TYPE_DCOMPLEX: \ sprintf( buffer, dcomplex_ptr[indx].i >= 0.0 ? \ "%g+%gi":"%g%gi",dcomplex_ptr[indx].r, \ dcomplex_ptr[indx].i); \ break; \ \ case TYPE_STRING: \ str_buffer = string_ptr[ indx ]; \ break;// Generate text for an element, translating subref indices if needed.#define PLACE_ELEMENT(buffer,str_buffer,indx,alloced) \ switch ( type ) \ { \ PLACE_ELEMENT_ACTION(buffer,str_buffer,indx) \ \ case TYPE_SUBVEC_REF: \ case TYPE_SUBVEC_CONST: \ { \ VecRef* ref = VecRefPtr(); \ int err; \ int index = ref->TranslateIndex( indx, &err ); \ if ( err ) \ { \ error->Report( "invalid sub-vector" ); \ delete alloced; \ return strdup( "error" ); \ } \ switch ( ref->Type() ) \ { \ PLACE_ELEMENT_ACTION(buffer,str_buffer,index)\ \ default: \ fatal->Report( \ "bad type in Value::StringVal()" ); \ } \ } \ break; \ \ default: \ fatal->Report( \ "bad type in Value::StringVal()" ); \ } char numeric_buf[256]; const attributeptr attr = AttributePtr(); const Value* shape_val; int shape_len; if ( ! useAttributes || ! attr || ! (shape_val = (*attr)["shape"]) || ! shape_val->IsNumeric() || (shape_len = shape_val->Length()) <= 1 ) { // not an n-D array. for ( int i = 0; i < length; ++i ) { const char* addition = numeric_buf; PLACE_ELEMENT(numeric_buf, addition, i, buf); append_buf( buf, buf_ptr, buf_size, addition ); if ( i < length - 1 ) // More to come. *buf_ptr++ = sep; } if ( type != TYPE_STRING && length > 1 ) { // Insert []'s around value. *buf_ptr++ = ']'; *buf_ptr = '\0'; } return buf; } // Okay, from this point on it's an n-D array. static char indent[] = " "; // Later the pivots for outputting by planes can be made variable int r = 0; int c = 1; int shape_is_copy = 0; int* shape = shape_val->CoerceToIntArray( shape_is_copy, shape_len ); // Store for setting up a plane in advance to get the proper // spacing for the columns. Note that these and the arrays // created just below are static, so we don't free them on exit. static int column_width_len = 64; static int* column_width = new int[column_width_len]; // Arrays for iterating through the matrix. static int indices_len = 32; static int* indices = new int[indices_len]; static int* factor = new int[indices_len]; // Resize arrays as necessary. while ( shape[c] > column_width_len ) { column_width_len *= 2; column_width = (int*) realloc_memory( (void*) column_width, column_width_len * sizeof(int) ); if ( ! column_width ) fatal->Report( "out of memory in Value::StringVal()" ); } while ( shape_len > indices_len ) { indices_len *= 2; indices = (int*) realloc_memory( (void*) indices, indices_len * sizeof(int) ); factor = (int*) realloc_memory( (void*) factor, indices_len * sizeof(int) ); if ( ! indices || ! factor ) fatal->Report( "out of memory in Value::StringVal()" ); } // Calculate the size and the offset for the columns. int size = 1; int offset = 0; for ( int i = 0; i < shape_len; ++i ) { indices[i] = 0; factor[i] = size; size *= shape[i]; } // Check to see if the vector length and the shape jive. if ( size > length ) { warn->Report( "\"::shape\"/length mismatch" ); delete buf; if ( shape_is_copy ) delete shape; return StringVal( sep, 0 ); } int max_free = shape_len-1; if ( shape_len > 2 ) for ( max_free = shape_len-1; max_free > 0; --max_free ) if ( max_free != r && max_free != c ) break; while ( indices[max_free] < shape[max_free] ) { // Output the plane label for ( i = 0; i < shape_len; ++i ) { if ( i == r ) sprintf( numeric_buf, "1:%d", shape[r] ); else if ( i != c ) sprintf( numeric_buf, "%d", indices[i] + 1 ); else numeric_buf[0] = '\0'; if ( i < shape_len - 1 ) strcat( numeric_buf, "," ); else strcat( numeric_buf, "]\n" ); append_buf( buf, buf_ptr, buf_size, i==0 ? "[" : 0, numeric_buf ); } // Calculate column widths. for ( indices[r] = 0; indices[r] < shape[r]; ++indices[r] ) for ( indices[c] = 0; indices[c] < shape[c] - 1; ++indices[c] ) { for ( i = 0, offset = 0; i < shape_len; ++i ) offset += factor[i] * indices[i]; char store[256]; const char* addition = store; PLACE_ELEMENT(store,addition,offset,buf) int add_len = strlen( addition ); if ( add_len > column_width[indices[c]] || indices[r] == 0 ) column_width[indices[c]] = add_len; } // Output plane. for ( indices[r] = 0; indices[r] < shape[r]; ++indices[r] ) { for ( indices[c] = 0; indices[c] < shape[c]; ++indices[c] ) { for ( i = 0, offset = 0; i < shape_len; ++i ) offset += factor[i] * indices[i]; const char* addition = numeric_buf; PLACE_ELEMENT(numeric_buf,addition,offset,buf); char affix[256]; if ( indices[c] < shape[c] - 1 ) { int n = column_width[indices[c]] - strlen( addition ) + 1; for ( i = 0; i < n; ++i ) affix[i] = ' '; affix[i] = '\0'; } else if ( offset != size - 1 ) { affix[0] = '\n'; affix[1] = '\0'; } else affix[0] = '\0'; append_buf( buf, buf_ptr, buf_size, indices[c] == 0 ? indent : 0, addition, affix ); } } // Increment counters. for ( i = 0; i <= max_free; ++i ) { if ( i == r || i == c ) continue; else if ( ++indices[i] < shape[i] ) break; else if ( i != max_free ) indices[i] = 0; } } if ( shape_is_copy ) delete shape; append_buf( buf, buf_ptr, buf_size, "]" ); return buf; }char* Value::RecordStringVal() const { if ( VecRefDeref()->Type() != TYPE_RECORD ) fatal->Report( "non-record type in Value::RecordStringVal()" ); recordptr rptr = RecordPtr(); int len = rptr->Length(); if ( len == 0 ) return strdup( "[=]" ); const char** key_strs = new const char*[len]; char** element_strs = new char*[len]; int total_len = 0; for ( int i = 0; i < len; ++i ) { Value* nth_val = rptr->NthEntry( i, key_strs[i] ); if ( ! nth_val ) fatal->Report( "bad record in Value::RecordStringVal()" ); element_strs[i] = nth_val->StringVal(); total_len += strlen( element_strs[i] ) + strlen( key_strs[i] ); } // We generate a result of the form [key1=val1, key2=val2, ...], // so in addition to room for the keys and values we need 3 extra // characters per element (for the '=', ',', and ' '), 2 more for // the []'s (we could steal these from the last element since it // doesn't have a ", " at the end of it, but that seems a bit // evil), and 1 more for the end-of-string. char* result = new char[total_len + 3 * len + 3]; strcpy( result, "[" ); for ( i = 0; i < len; ++i ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -