void DaoxDataColumn_SetCell( DaoxDataColumn *self, daoint i, DaoValue *value ) { if( value == NULL ){ complex16 zero = {0.0,0.0}; switch( self->type->tid ){ default : GC_DecRC( self->cells->data.values[i] ); self->cells->data.values[i] = value; break; case DAO_INTEGER : self->cells->data.daoints[i] = 0; break; case DAO_FLOAT : self->cells->data.floats[i] = 0.0; break; case DAO_DOUBLE : self->cells->data.doubles[i] = 0.0; break; case DAO_COMPLEX : self->cells->data.complexes[i] = zero; break; case DAO_STRING : DString_Reset( & self->cells->data.strings[i], 0 ); break; } return; } switch( self->type->tid ){ default : GC_ShiftRC( value, self->cells->data.values[i] ); self->cells->data.values[i] = value; break; case DAO_INTEGER : self->cells->data.daoints[i] = DaoValue_GetInteger( value ); break; case DAO_FLOAT : self->cells->data.floats[i] = DaoValue_GetFloat( value ); break; case DAO_DOUBLE : self->cells->data.doubles[i] = DaoValue_GetDouble( value ); break; case DAO_COMPLEX : self->cells->data.complexes[i] = DaoValue_GetComplex( value ); break; case DAO_STRING : DaoValue_GetString( value, & self->cells->data.strings[i] ); break; } }
DLong* DaoValue_GetLong( DaoValue *self, DLong *lng ) { #ifdef DAO_WITH_LONGINT switch( self->type ){ case DAO_INTEGER : DLong_FromInteger( lng, DaoValue_GetInteger( self ) ); break; case DAO_FLOAT : case DAO_DOUBLE : DLong_FromDouble( lng, DaoValue_GetDouble( self ) ); break; case DAO_COMPLEX : DLong_FromDouble( lng, self->xComplex.value.real ); break; case DAO_LONG : DLong_Move( lng, self->xLong.value ); break; case DAO_STRING : DLong_FromString( lng, self->xString.data ); break; default : break; /* TODO list array? */ } #endif return lng; }
static daoint DaoxDF_MakeIndex( DaoxDataFrame *self, int dim, DaoValue *value, DaoProcess *p ) { daoint idx = -1; if( value->type >= DAO_INTEGER && value->type <= DAO_DOUBLE ){ idx = DaoValue_GetInteger( value ); }else if( value->type == DAO_STRING ){ DString_ToMBS( value->xString.data ); idx = DaoxDataFrame_GetIndex( self, dim, value->xString.data->mbs ); }else if( value->type == DAO_NONE && self->dims[2] == 1 ){ idx = 0; } if( idx < 0 || idx >= self->dims[dim] ){ DaoProcess_RaiseException( p, DAO_ERROR_INDEX_OUTOFRANGE, "" ); return -1; } return idx; }
static void STD_Array( DaoProcess *proc, DaoValue *p[], int N ) { DaoInteger idint = {DAO_INTEGER,0,0,0,0,0}; DaoValue *res, *index = (DaoValue*)(void*)&idint; DaoVmCode *sect = DaoGetSectionCode( proc->activeCode ); DaoArray *array = DaoProcess_PutArray( proc ); DaoArray *first = NULL; DaoArray *sub = NULL; daoint i, j, k, entry, size = 1; /* if multi-dimensional array is disabled, DaoProcess_PutArray() will raise exception. */ #ifdef DAO_WITH_NUMARRAY for(i=0; i<N; i++){ daoint d = p[i]->xInteger.value; if( d < 0 ){ DaoProcess_RaiseException( proc, DAO_ERROR_PARAM, NULL ); break; } size *= d; } if( size == 0 ) return; if( sect == NULL ) return; // TODO exception if( DaoProcess_PushSectionFrame( proc ) == NULL ) return; entry = proc->topFrame->entry; DaoProcess_AcquireCV( proc ); for(i=0; i<size; i++){ idint.value = i; if( sect->b >0 ) DaoProcess_SetValue( proc, sect->a, index ); proc->topFrame->entry = entry; DaoProcess_Execute( proc ); if( proc->status == DAO_PROCESS_ABORTED ) break; res = proc->stackValues[0]; if( i == 0 ){ int D = N; DaoArray_SetDimCount( array, N + (res->type == DAO_ARRAY ? res->xArray.ndim : 0) ); for(j=0; j<N; j++) array->dims[j] = p[j]->xInteger.value; if( res->type == DAO_ARRAY ){ first = DaoArray_Copy( (DaoArray*) res ); if( first->ndim == 2 && (first->dims[0] == 1 || first->dims[1] == 1) ){ D += 1; array->dims[N] = first->dims[ first->dims[0] == 1 ]; }else{ D += first->ndim; memmove( array->dims + N, first->dims, first->ndim*sizeof(daoint) ); } } DaoArray_ResizeArray( array, array->dims, D ); } if( res->type == DAO_ARRAY ){ sub = (DaoArray*) res; if( first == NULL || DaoArray_AlignShape( sub, NULL, first->dims, first->ndim ) ==0 ){ DaoProcess_RaiseException( proc, DAO_ERROR, "inconsistent elements or subarrays" ); break; } k = i * sub->size; for(j=0; j<sub->size; j++){ switch( array->etype ){ case DAO_INTEGER : array->data.i[k+j] = DaoArray_GetInteger( sub, j ); break; case DAO_FLOAT : array->data.f[k+j] = DaoArray_GetFloat( sub, j ); break; case DAO_DOUBLE : array->data.d[k+j] = DaoArray_GetDouble( sub, j ); break; case DAO_COMPLEX : array->data.c[k+j] = DaoArray_GetComplex( sub, j ); break; } } }else{ switch( array->etype ){ case DAO_INTEGER : array->data.i[i] = DaoValue_GetInteger( res ); break; case DAO_FLOAT : array->data.f[i] = DaoValue_GetFloat( res ); break; case DAO_DOUBLE : array->data.d[i] = DaoValue_GetDouble( res ); break; case DAO_COMPLEX : array->data.c[i] = DaoValue_GetComplex( res ); break; } } } DaoProcess_ReleaseCV( proc ); DaoProcess_PopFrame( proc ); if( first ) DaoArray_Delete( first ); #endif }
/* // Assumming the value "self" is compatible to the type "tp", if it is not null. */ DaoValue* DaoValue_SimpleCopyWithTypeX( DaoValue *self, DaoType *tp, DaoDataCache *cache ) { DaoEnum *e; daoint i, n; if( self == NULL ) return dao_none_value; if( (tp == NULL || tp->tid == self->type) && self->type < DAO_ENUM ){ if( cache ){ DaoValue *value = DaoDataCache_MakeValue( cache, self->type ); switch( self->type ){ case DAO_NONE : return self; case DAO_INTEGER : value->xInteger.value = self->xInteger.value; break; case DAO_FLOAT : value->xFloat.value = self->xFloat.value; break; case DAO_DOUBLE : value->xDouble.value = self->xDouble.value; break; case DAO_COMPLEX : value->xComplex.value = self->xComplex.value; break; #ifdef DAO_WITH_LONGINT case DAO_LONG : DLong_Move( value->xLong.value, self->xLong.value ); break; #endif case DAO_STRING : DString_Assign( value->xString.data, self->xString.data ); break; } return value; }else{ switch( self->type ){ case DAO_NONE : return self; case DAO_INTEGER : return (DaoValue*) DaoInteger_New( self->xInteger.value ); case DAO_FLOAT : return (DaoValue*) DaoFloat_New( self->xFloat.value ); case DAO_DOUBLE : return (DaoValue*) DaoDouble_New( self->xDouble.value ); case DAO_COMPLEX : return (DaoValue*) DaoComplex_New( self->xComplex.value ); case DAO_LONG : return (DaoValue*) DaoLong_Copy( & self->xLong ); case DAO_STRING : return (DaoValue*) DaoString_Copy( & self->xString ); } } return self; /* unreachable; */ }else if( self->type == DAO_ENUM ){ return (DaoValue*) DaoEnum_Copy( & self->xEnum, tp ); }else if( tp && tp->tid >= DAO_INTEGER && tp->tid <= DAO_DOUBLE ){ DaoValue *value = cache ? DaoDataCache_MakeValue( cache, tp->tid ) : NULL; switch( value == NULL ? tp->tid : 0 ){ case DAO_INTEGER : value = (DaoValue*) DaoInteger_New(0); break; case DAO_FLOAT : value = (DaoValue*) DaoFloat_New(0); break; case DAO_DOUBLE : value = (DaoValue*) DaoDouble_New(0); break; } switch( tp->tid ){ case DAO_INTEGER : value->xInteger.value = DaoValue_GetInteger( self ); break; case DAO_FLOAT : value->xFloat.value = DaoValue_GetFloat( self ); break; case DAO_DOUBLE : value->xDouble.value = DaoValue_GetDouble( self ); break; } return value; } #ifdef DAO_WITH_NUMARRAY if( self->type == DAO_ARRAY && self->xArray.original ){ DaoArray_Sliced( (DaoArray*)self ); return self; }else #endif if( self->type == DAO_CSTRUCT || self->type == DAO_CDATA ){ FuncPtrSliced sliced = self->xCstruct.ctype->kernel->Sliced; if( sliced ) (*sliced)( self ); return self; } if( self->xBase.trait & DAO_VALUE_NOCOPY ) return self; if( (self->xBase.trait & DAO_VALUE_CONST) == 0 ) return self; switch( self->type ){ case DAO_LIST : return (DaoValue*) DaoList_Copy( (DaoList*) self, tp ); case DAO_MAP : return (DaoValue*) DaoMap_Copy( (DaoMap*) self, tp ); case DAO_TUPLE : return (DaoValue*) DaoTuple_Copy( (DaoTuple*) self, tp ); #ifdef DAO_WITH_NUMARRAY case DAO_ARRAY : return (DaoValue*) DaoArray_CopyX( (DaoArray*) self, tp ); #endif default : break; } return self; }
static void MakeSlice( DaoProcess *proc, DaoValue *pid, daoint N, DVector *slice ) { daoint j, id, from, to, rc = 1; if( pid == NULL || pid->type == 0 ){ SliceRange2( slice, N, 0, N ); return; } switch( pid->type ){ case DAO_INTEGER : case DAO_FLOAT : case DAO_DOUBLE : { id = DaoValue_GetInteger( pid ); rc = SliceRange2( slice, N, id, 1 ); break; } case DAO_STRING : { break; } case DAO_TUPLE : { DaoValue **data = pid->xTuple.items; DVector_Clear( slice ); if( data[0]->type == DAO_INTEGER && data[1]->type == DAO_INTEGER ){ from = data[0]->xInteger.value; to = data[1]->xInteger.value; rc = SliceRange( slice, N, from, to ); }else if( data[0]->type == DAO_NONE && data[1]->type == DAO_NONE ){ rc = SliceRange2( slice, N, 0, N ); }else if( data[0]->type <= DAO_DOUBLE && data[1]->type == DAO_NONE ){ from = DaoValue_GetInteger( data[0] ); rc = SliceRange( slice, N, from, -1 ); }else if( data[0]->type == DAO_NONE && data[1]->type <= DAO_DOUBLE ){ to = DaoValue_GetInteger( data[1] ); rc = SliceRange( slice, N, 0, to ); }else if( data[0]->type == DAO_STRING && data[1]->type == DAO_STRING ){ }else if( data[0]->type == DAO_STRING && data[1]->type == DAO_NONE ){ }else if( data[0]->type == DAO_NONE && data[1]->type == DAO_STRING ){ }else{ DaoProcess_RaiseException( proc, DAO_ERROR_INDEX, "need number" ); } break; } case DAO_LIST : { DaoList *list = & pid->xList; DaoValue **v = list->items.items.pValue; DVector_Resize( slice, list->items.size + 2 ); slice->data.daoints[0] = SLICE_ENUM; slice->data.daoints[1] = list->items.size; for( j=0; j<list->items.size; j++){ if( v[j]->type < DAO_INTEGER || v[j]->type > DAO_DOUBLE ) DaoProcess_RaiseException( proc, DAO_ERROR_INDEX, "need number" ); id = DaoValue_GetInteger( v[j] ); if( id <0 ) id += N; if( id <0 || id >= N ){ rc = id = 0; break; } slice->data.daoints[j+2] = id; } break; } case DAO_ARRAY : { DaoArray *na = & pid->xArray; daoint *p; if( na->etype == DAO_COMPLEX ){ DaoProcess_RaiseException( proc, DAO_ERROR_INDEX, "complex array can not be used as index" ); break; } DVector_Resize( slice, na->size + 2 ); slice->data.daoints[0] = SLICE_ENUM; slice->data.daoints[1] = na->size; p = slice->data.daoints + 2; for( j=0; j<na->size; j++){ id = DaoArray_GetInteger( na, j ); if( id <0 ) id += N; if( id <0 || id >= N ){ rc = id = 0; break; } p[j] = id; } break; } default: break; } if( slice->size < 2 ) SliceRange2( slice, N, 0, N ); if( rc == 0 ) DaoProcess_RaiseException( proc, DAO_ERROR_INDEX_OUTOFRANGE, "" ); }
/* // C printf format: %[parameter][flags][width][.precision][length]type // // Dao writef format: %[flags][width][.precision]type[color] // // Where 'flags', 'width' and 'precision' will conform to the C format, // but 'type' can only be: // d, i, o, u, x/X : for integer; // e/E, f/F, g/G : for float and double; // c/C : for character, C for local encoding; // s/S : for string, S for local encoding; // p : for any type, write address; // a : automatic, for any type, write in the default format; // Namely the standard ones except 'n', and plus 'a'. // // Optional 'color' format will be in form of: [foreground:background], [foreground] // or [:background]. The supported color name format will depend on the color printing // handle. Mininum requirement is the support of the following 8 color names: // black, white, red, green, blue, yellow, magenta, cyan. */ static void DaoIO_Writef0( DaoStream *self, DaoProcess *proc, DaoValue *p[], int N ) { DaoValue *value; DString *fmt2; DString *fgcolor = NULL; DString *bgcolor = NULL; DMap *cycmap = NULL; const char *convs = "asSpcCdiouxXfFeEgG"; char F, *s, *end, *fg, *bg, *fmt, message[100]; int i, k, id = 0; if( DaoIO_CheckMode( self, proc, DAO_STREAM_WRITABLE ) == 0 ) return; fmt2 = DString_New(); for(i=0; i<N; i++){ if( p[i]->type > DAO_ARRAY ){ cycmap = DHash_New(0,0); break; } } s = p[0]->xString.value->chars; end = s + p[0]->xString.value->size; for(; s<end; s++){ if( *s != '%' ){ DaoStream_WriteChar( self, *s ); continue; } fmt = s; s += 1; if( *s =='%' || *s == '[' ){ DaoStream_WriteChar( self, *s ); continue; } if( ++id >= N || p[id] == NULL ) goto NullParameter; value = p[id]; /* flags: */ while( *s == '+' || *s == '-' || *s == '#' || *s == '0' || *s == ' ' ) s += 1; while( isdigit( *s ) ) s += 1; /* width; */ if( *s == '.' ){ /* precision: */ s += 1; while( isdigit( *s ) ) s += 1; } DString_SetBytes( fmt2, fmt, s - fmt + 1 ); if( strchr( convs, *s ) == NULL ){ DaoProcess_RaiseWarning( proc, NULL, "invalid format conversion" ); continue; } F = *s; s += 1; fg = bg = NULL; if( *s == '[' ){ s += 1; fmt = s; while( isalnum( *s ) ) s += 1; if( fgcolor == NULL ) fgcolor = DString_New(); DString_SetBytes( fgcolor, fmt, s - fmt ); if( fgcolor->size ) fg = fgcolor->chars; if( *s == ':' ){ s += 1; fmt = s; while( isalnum( *s ) ) s += 1; if( bgcolor == NULL ) bgcolor = DString_New(); DString_SetBytes( bgcolor, fmt, s - fmt ); if( bgcolor->size ) bg = bgcolor->chars; } if( *s != ']' ) goto WrongColor; }else{ s -= 1; } if( fg || bg ){ if( DaoStream_SetColor( self, fg, bg ) == 0 ) goto WrongColor; } self->format = fmt2->chars; if( F == 'c' || F == 'C' ){ if( value->type != DAO_INTEGER ) goto WrongParameter; DString_Reset( fmt2, 0 ); DString_AppendWChar( fmt2, value->xInteger.value ); self->format = "%s"; if( F == 'C' ) DString_ToLocal( fmt2 ); DaoStream_WriteString( self, fmt2 ); }else if( F == 'd' || F == 'i' || F == 'o' || F == 'x' || F == 'X' ){ if( value->type == DAO_NONE || value->type > DAO_FLOAT ) goto WrongParameter; DString_InsertChars( fmt2, "ll", fmt2->size-1, 0, 2 ); self->format = fmt2->chars; DaoStream_WriteInt( self, DaoValue_GetInteger( value ) ); }else if( toupper( F ) == 'E' || toupper( F ) == 'F' || toupper( F ) == 'G' ){ if( value->type == DAO_NONE || value->type > DAO_FLOAT ) goto WrongParameter; DaoStream_WriteFloat( self, DaoValue_GetFloat( value ) ); }else if( F == 's' && value->type == DAO_STRING ){ DaoStream_WriteString( self, value->xString.value ); }else if( F == 'S' && value->type == DAO_STRING ){ DaoStream_WriteLocalString( self, value->xString.value ); }else if( F == 'p' ){ DaoStream_WritePointer( self, value ); }else if( F == 'a' ){ self->format = NULL; if( value->type > DAO_ARRAY ) DMap_Reset( cycmap ); DaoValue_Print( value, self, cycmap, proc ); }else{ goto WrongParameter; } self->format = NULL; if( fg || bg ) DaoStream_SetColor( self, NULL, NULL ); continue; NullParameter: sprintf( message, "%i-th parameter is null!", id ); DaoProcess_RaiseWarning( proc, NULL, message ); continue; WrongColor: sprintf( message, "%i-th parameter has wrong color format!", id ); DaoProcess_RaiseWarning( proc, NULL, message ); continue; WrongParameter: self->format = NULL; if( fg || bg ) DaoStream_SetColor( self, NULL, NULL ); sprintf( message, "%i-th parameter has wrong type for format \"%s\"!", id, fmt2->chars ); DaoProcess_RaiseWarning( proc, NULL, message ); } if( cycmap ) DMap_Delete( cycmap ); if( fgcolor ) DString_Delete( fgcolor ); if( bgcolor ) DString_Delete( bgcolor ); DString_Delete( fmt2 ); }
/* // Assumming the value "self" is compatible to the type "tp", if it is not null. */ DaoValue* DaoValue_SimpleCopyWithTypeX( DaoValue *self, DaoType *tp, DaoType *cst ) { if( self == NULL ) return dao_none_value; if( self->type < DAO_ENUM && (tp == NULL || tp->tid == self->type) ){ /* // The following optimization is safe theoretically. // But it is not practically safe for DaoProcess_PutChars() etc., // which often uses shallow wraps of "const char*" as the source value, // and expects it to be copied at the destination as a primitive value. */ /* if( cst && cst->invar ) return self; */ switch( self->type ){ case DAO_NONE : return self; case DAO_BOOLEAN : return (DaoValue*) DaoBoolean_New( self->xBoolean.value ); case DAO_INTEGER : return (DaoValue*) DaoInteger_New( self->xInteger.value ); case DAO_FLOAT : return (DaoValue*) DaoFloat_New( self->xFloat.value ); case DAO_COMPLEX : return (DaoValue*) DaoComplex_New( self->xComplex.value ); case DAO_STRING : return (DaoValue*) DaoString_Copy( & self->xString ); } return self; /* unreachable; */ }else if( tp && tp->tid >= DAO_BOOLEAN && tp->tid <= DAO_FLOAT ){ DaoValue *va = NULL; switch( tp->tid ){ case DAO_BOOLEAN : va = (DaoValue*) DaoBoolean_New( DaoValue_GetInteger(self) ); break; case DAO_INTEGER : va = (DaoValue*) DaoInteger_New( DaoValue_GetInteger(self) ); break; case DAO_FLOAT : va = (DaoValue*) DaoFloat_New( DaoValue_GetFloat(self) ); break; } return va; }else if( self->type == DAO_ENUM ){ switch( tp ? tp->tid : 0 ){ case DAO_ENUM : if( tp->subtid == DAO_ENUM_ANY ) tp = NULL; return (DaoValue*) DaoEnum_Copy( & self->xEnum, tp ); case DAO_BOOLEAN : return (DaoValue*) DaoBoolean_New( self->xEnum.value ); case DAO_INTEGER : return (DaoValue*) DaoInteger_New( self->xEnum.value ); case DAO_FLOAT : return (DaoValue*) DaoFloat_New( self->xEnum.value ); } return (DaoValue*) DaoEnum_Copy( & self->xEnum, NULL ); }else if( tp && tp->tid == DAO_ENUM ){ switch( self->type ){ case DAO_BOOLEAN : case DAO_INTEGER : return (DaoValue*) DaoEnum_New( tp, self->xInteger.value ); case DAO_FLOAT : return (DaoValue*) DaoEnum_New( tp, self->xFloat.value ); } }else if( self->type == DAO_CINVALUE ){ return (DaoValue*) DaoCinValue_Copy( (DaoCinValue*) self ); } if( tp != NULL ){ assert( tp->tid == 0 || tp->tid > DAO_ENUM ); assert( self->type == 0 || self->type > DAO_ENUM ); } #ifdef DAO_WITH_NUMARRAY if( self->type == DAO_ARRAY && self->xArray.original ){ DaoArray_Sliced( (DaoArray*)self ); return self; }else #endif if( self->type == DAO_CSTRUCT || self->type == DAO_CDATA ){ if( self->xCstruct.ctype->core->Slice ) self->xCstruct.ctype->core->Slice( self ); return self; } if( tp == NULL ){ switch( self->type ){ case DAO_LIST : if( self->xList.ctype->empty ) tp = self->xList.ctype; break; case DAO_MAP : if( self->xMap.ctype->empty ) tp = self->xMap.ctype; break; default : break; } } if( self->xBase.trait & DAO_VALUE_NOCOPY ) return self; if( (self->xBase.trait & DAO_VALUE_CONST) == 0 ) return self; if( cst != NULL && cst->invar != 0 ) return self; if( tp ) tp = DaoType_GetBaseType( tp ); return DaoValue_CopyContainer( self, tp ); }