/***********************************************************************/ /* Open Visualization Data Explorer */ /* (C) Copyright IBM Corp. 1989,1999 */ /* ALL RIGHTS RESERVED */ /* This code licensed under the */ /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */ /***********************************************************************/ #include #include #include "DXValue.h" #include "List.h" #include "ListIterator.h" #include "DXTensor.h" #include "Strings.h" #include "lex.h" // // Clip the trail zeros off of a scalar printed with %#g format that // winds up '6.00000'. // Changes '6.0[0]*' into '6.0'. // Changes '6.0[0]* ' into '6.0 '. // static void clip_trailing_zeros(char *buf) { char *c = strstr(buf,".0"); if (c) { char a, *p = c+2; boolean doit = TRUE; boolean space = FALSE; while (a = *p) { if (a == ' ') { space = TRUE; break; } if (a != '0') { doit = FALSE; break; } p++; } if (doit && p != c) { // char a = *(c+6); // char b = *(c+7); if (space) { *(c+2) = ' '; *(c+3) = '\0'; } else { *(c+2) = '\0'; } } } } // // Returns TRUE if a NULL string is found; returns FALSE otherwise. // The index variable is updated to the character following the lexed // string upon successful return. // static boolean _IsNULL(const char* string, int& index) { int i; i = index; SkipWhiteSpace(string, i); if (EqualSubstring(&string[i], "NULL", 4) OR EqualSubstring(&string[i], "null", 4)) { index = i + 4; return TRUE; } else { return FALSE; } } // // Returns TRUE if a value string is found; returns FALSE otherwise. // If the type of value is specified (scalar, vector, or tensor), a // comparison will be only against the specified type; otherwise, all // three types will be checked. // // The index variable is updated to the character following the lexed // string, and the type variable to the matching type, upon successful // return. // static boolean _IsValue(const char* string, int& index, Type& type) { int tuple; if (string == NUL(char*)) { return FALSE; } switch(type) { case DXType::ScalarType: return IsScalar(string, index); case DXType::VectorType: return IsVector(string, index, tuple); case DXType::TensorType: return IsTensor(string, index); default: // // Scalar value? // if (IsScalar(string, index)) { type = DXType::ScalarType; return TRUE; } // // Vector value? // if (IsVector(string, index, tuple)) { type = DXType::VectorType; return TRUE; } // // Tensor value? // if (IsTensor(string, index)) { type = DXType::TensorType; return TRUE; } // // No match... return unsuccessfully. // return FALSE; } } // // Returns TRUE if a list of specified type is found; returns FALSE // otherwise. // The index variable is updated to the character following the lexed // string upon successful return. // This does NOT check for list constructors. // static boolean _IsList(const char* string, int& index, const Type type) { Type value_type; int i; int tuple; int first_tuple; int elements; boolean lexed; // // Parameter validity check... // if (string == NUL(char*)) { return FALSE; } ASSERT(index >= 0 AND index <= STRLEN(string) + 1); elements = 0; value_type = DXType::UndefinedType; // // Skip space. // i = index; SkipWhiteSpace(string, i); // // Lex '{'. // if (string[i] == '{') { i++; SkipWhiteSpace(string, i); } else { return FALSE; } while (string[i] != '\0' AND string[i] != '}') { if (elements > 0) { // // Lex optional comma. // if (string[i] == ',') { i++; SkipWhiteSpace(string, i); } } switch(type) { case DXType::FlagType: lexed = IsFlag(string, i); break; case DXType::IntegerType: lexed = IsInteger(string, i); break; case DXType::ScalarType: lexed = IsScalar(string, i); break; case DXType::VectorType: lexed = IsVector(string, i, tuple); if (elements == 0) { first_tuple = tuple; } else if (tuple != first_tuple) { return FALSE; } break; case DXType::TensorType: lexed = IsTensor(string, i); break; case DXType::ValueType: lexed = _IsValue(string, i, value_type); break; case DXType::StringType: lexed = IsString(string, i); break; default: return FALSE; } if (lexed) { elements++; } else { return FALSE; } boolean value_ok = FALSE; switch (type) { default: break; case DXType::ValueType: switch (value_type) { default: break; case DXType::VectorType: case DXType::TensorType: if (string[i] == '[') value_ok = TRUE; break; } // Fall through case DXType::ScalarType: // // Make sure there is a separator // If we don't do this, then '{.01.01.01}' is a scalar list. // if (!value_ok && !IsWhiteSpace(&string[i]) && (string[i] != ',') && (string[i] != '}')) return FALSE; break; } // // Skip space. // SkipWhiteSpace(string, i); } // // No end delimiter and no elements... return unsuccessfully. // if (string[i] != '}' OR elements == 0) { return FALSE; } // // Return successfully. // index = i + 1; return TRUE; } // // Returns TRUE if a list constructor is found; returns FALSE // otherwise. The index variable is updated to the character // following the lexed string upon successful return. // static boolean _uinIsListConstructor(const char* string, int& index) { boolean parsed_dot_dot; boolean parsed_colon; int elements; int i; // // Parameter validity check... // if (string == NUL(char*)) { return FALSE; } ASSERT(index >= 0 AND index <= STRLEN(string) + 1); elements = 0; parsed_dot_dot = FALSE; parsed_colon = FALSE; // // Skip space. // i = index; SkipWhiteSpace(string, i); // // Lex '{'. // if (string[i] != '{') { return FALSE; } i++; SkipWhiteSpace(string, i); while (string[i] != '\0' AND string[i] != '}') { if (IsScalar(string, i)) { elements++; SkipWhiteSpace(string, i); } else { return FALSE; } switch(elements) { case 1: if (string[i] == '.' AND string[i + 1] == '.') { parsed_dot_dot = TRUE; i += 2; SkipWhiteSpace(string, i); } else { return FALSE; } break; case 2: if (parsed_dot_dot AND string[i] == ':') { parsed_colon = TRUE; i++; SkipWhiteSpace(string, i); } break; case 3: if (NOT parsed_colon) { return FALSE; } break; } } // // No end delimiter... return unsuccessfully. // if (string[i] != '}') { return FALSE; } // // Semantic error? Return unsuccessfully. // if (parsed_colon) { if (elements != 3) { return FALSE; } } else if (elements != 2) { return FALSE; } // // Return successfully. // index = i + 1; return TRUE; } // // Returns TRUE if a list of specified type is found; returns FALSE // otherwise. // The index variable is updated to the character following the lexed // string upon successful return. // This checks for both standard lists and list constructors. // static boolean IsList(const char* string, int& index, const Type type) { boolean r = _IsList(string, index, type); if (!r && (type & DXType::ValueType)) r = _uinIsListConstructor(string,index); return r; } // // Returns TRUE if an object string is found; returns FALSE // otherwise. The index variable is updated to the character // following the lexed string upon successful return. // static boolean _IsObject(const char* string, int& index) { Type value_type; int tuple; if (string == NUL(char*)) { return FALSE; } ASSERT(index >= 0 AND index <= STRLEN(string) + 1); if (IsInteger(string, index)) { return TRUE; } if (IsScalar(string, index)) { return TRUE; } if (IsVector(string, index, tuple)) { return TRUE; } if (IsTensor(string, index)) { return TRUE; } value_type = DXType::UndefinedType; if (_IsValue(string, index, value_type)) { return TRUE; } if (IsString(string, index)) { return TRUE; } if (IsList(string, index, DXType::IntegerType)) { return TRUE; } if (IsList(string, index, DXType::ScalarType)) { return TRUE; } if (IsList(string, index, DXType::VectorType)) { return TRUE; } if (IsList(string, index, DXType::TensorType)) { return TRUE; } if (IsList(string, index, DXType::StringType)) { return TRUE; } #if 0 if (_uinIsListConstructor(string, index)) { return TRUE; } #endif return FALSE; } // // Determines whether the specified string is a valid string value // of the specified type (of DXType constant). // // FIXME: this needs to know about user types (also see DXType::ValueToType()). // boolean DXValue::IsValidValue(const char* string, const Type type) { char* value; boolean result; Type value_type; Type list_type; int tuple; int i; // // No string... return unsuccessfully. // if (string == NUL(char*)) { return FALSE; } // // Copy the string. // value = DuplicateString(string); for (i = 0; value[i] != '\0'; i++) { // // FIXME: tolower returns junk if the input is negative. // This was that cute bug found by gresh just hours before the // final build. Cheers. // #if defined(aviion) value[i] = (value[i]>=0 ? tolower(value[i]): value[i]); #else value[i] = tolower(value[i]); #endif } // // Remove the trailing blanks. // for (i = (int)STRLEN(value) - 1; value[i] == ' ' OR value[i] == '\t'; i--) ; value[i + 1] = '\0'; // // Find the first non-blank letter. // i = 0; SkipWhiteSpace(value, i); // // Initialize the result. // result = FALSE; // // Special-case NULL. // if (_IsNULL(value, i)) { result = TRUE; } // // Flag type: // else if (type == DXType::FlagType) { result = IsFlag(value, i); } // // Integer type: // else if (type == DXType::IntegerType) { result = IsInteger(value, i); } // // Scalar type: // else if (type == DXType::ScalarType) { result = IsScalar(value, i); } // // Vector type: // else if (type == DXType::VectorType) { result = IsVector(value, i, tuple); } // // Tensor type: // else if (type == DXType::TensorType) { result = IsTensor(value, i); } // // Value type: // else if (type == DXType::ValueType) { value_type = DXType::UndefinedType; result = _IsValue(value, i, value_type); } // // String type: // else if (type == DXType::StringType) { result = IsString(value, i); } // // Object type: // else if (type == DXType::ObjectType) { result = _IsObject(value, i); } // // List type: // else if (type & DXType::ListType) { list_type = type & DXType::ListTypeMask; result = IsList(value, i, list_type); } // // Where paramter type // else if (type & DXType::WhereType) { result = IsWhere(value, i); } else if (type & DXType::UserType1 OR type & DXType::UserType2 OR type & DXType::UserType4 OR type & DXType::UserType5 OR type & DXType::UserType6 OR type & DXType::DescriptionType) { result = TRUE; } // // Check for end of string. // if (result) { result = IsEndOfString(value, i); } // // Free the value string. // delete value; // // Return the result. // return result; } DXValue::DXValue() { // // Initialize instance data. // this->type.setType(DXType::UndefinedType); this->defined = FALSE; this->string = NUL(char*); this->integer = 0; this->scalar = 0.0; this->tensor = NUL(DXTensor*); } DXValue::~DXValue() { // // Clear this object. // this->clear(); } void DXValue::clear() { // // Clear all values. // if (this->string) { delete this->string; this->string = NUL(char*); } this->integer = 0; this->scalar = 0.0; if (this->tensor) { delete this->tensor; this->tensor= NUL(DXTensor*); } // // Set this value object to be undefined. // this->defined = FALSE; (void)this->type.setType(DXType::UndefinedType); } // // Assigns a string value of the specified type (DXType constant). // Returns TRUE if the new value has been assigned; // returns FALSE otherwise. // boolean DXValue::setValue(const char* string, const Type type) { int i; boolean r; ASSERT(this); if (DXValue::IsValidValue(string, type)) { // // Avoid the case where string and this->string are the same. // char *s = DuplicateString(string); // // Clear the value and reset the type. // this->clear(); this->type.setType(type); // // Save the string representation of the value (ALWAYS!!!). // this->string = s; string = (const char*) s; // in case string == this->string // // Special case NULL value. // i = 0; if (_IsNULL(string, i)) { // Allow NULL to match any type. this->type.setType(type); } else { // // Convert the string to internal, native form according to type. // char *newval, *p, buf[64]; int index; switch(type) { case DXType::FlagType: // // The executive does not recognize 'true' or 'false', so // we convert them to integer values. // if (strstr(string,"false")) { this->integer = this->scalar = 0; delete this->string; this->string = DuplicateString("0"); } else if (strstr(string,"true")) { this->integer = this->scalar = 1; delete this->string; this->string = DuplicateString("1"); } else { sscanf(string, "%d", &this->integer); sscanf(string, "%lg", &this->scalar); } break; case DXType::IntegerType: sscanf(string, "%d", &this->integer); sscanf(string, "%lg", &this->scalar); break; case DXType::ScalarType: sscanf(string, "%lg", &this->scalar); if (!strchr(string,'.')) { // // Need to make sure that the string representation, really // represents a floating point number and not an integer. // delete this->string; this->string = DXValue::FormatDouble(this->scalar); } break; case DXType::VectorType: this->tensor = new DXTensor; r = this->tensor->setValue(string); ASSERT(r); break; case DXType::TensorType: case DXType::ValueType: case DXType::StringType: case DXType::ObjectType: case DXType::WhereType: case DXType::DescriptionType: break; default: if (type & DXType::ListType) { switch(type & DXType::ListTypeMask) { case DXType::ScalarType: // // Convert '{ 1 2.0000 3.3 }' into '{ 1.0 2.0 3.3 }' // Ignore lists specified with the elipsis '{ 1..2: 3}' // if (strchr(this->string,':')) break; newval = new char[STRLEN(this->string) + 1024]; index = -1; strcpy(newval,"{ "); p = newval + STRLEN(newval); while (DXValue::NextListItem(this->string, &index,type, buf)) { if (strchr(buf,'.')) { // Already has a decimal, just copy. sprintf(p,"%s ",buf); } else { double d = (double)atof(buf); this->FormatDouble(d,p); strcat(p," "); } clip_trailing_zeros(p); p += STRLEN(p); } strcat(p,"}"); delete this->string; // Copy this so we don't waste space (1024 above). this->string = DuplicateString(newval); delete newval; break; case DXType::IntegerType: case DXType::FlagType: case DXType::VectorType: case DXType::TensorType: case DXType::ValueType: case DXType::StringType: break; } } else if (type & DXType::UserType1 OR type & DXType::UserType2 OR type & DXType::UserType4 OR type & DXType::UserType5 OR type & DXType::UserType6) { } else { ASSERT(FALSE); } break; } } return TRUE; } else { return FALSE; } } const char* DXValue::getValueString() { //return DuplicateString(this->string ? this->string : "NULL"); return this->string ? this->string : "NULL"; } // // Assigns a value in string representation. // Returns TRUE if the string is correct; returns FALSE, otherwise. // boolean DXValue::setString(const char* string) { ASSERT(this); if (DXValue::IsValidValue(string, (Type)DXType::StringType)) { this->clear(); this->type.setType(DXType::StringType); this->string = DuplicateString(string); return TRUE; } else { return FALSE; } } // // Assigns an integer value. // Returns TRUE if successful, FALSE otherwise. // boolean DXValue::setInteger(const int integer) { ASSERT(this); // // Clear the old values and reset the type. // this->clear(); this->type.setType(DXType::IntegerType); // // Set the new integer value. // this->integer = integer; // // Generate a string equivalent of this new value. // this->string = new char[32]; sprintf(this->string, "%d", integer); // // Return successfully. // return TRUE; } // // Assigns a scalar value. // Returns TRUE if successful, FALSE otherwise. // boolean DXValue::setScalar(const double scalar) { ASSERT(this); // // Clear the old values and reset the type. // this->clear(); this->type.setType(DXType::ScalarType); // // Set the new scalar value. // this->scalar = scalar; // // Generate a string equivalent of this new value. // this->string = this->FormatDouble(scalar); // // Return successfully. // return TRUE; } // // Format a double into a string to preserve the double precision. // The values is formatted into buf if provided otherwise into a // newly allocated string. // The value is formatted with a number of decimal places as indicated // by 'decimals'. If decimals is greater than 0, then that number // of decimal places is always printed (upto that number supported by // sprintf()). If decimals is less than or equal to 0, then we use 8 // decimals, except that we clip any trailing zeros down to ".0". // Further, if decimals is 0 then we clip off the ".0" too. // // The strip_all_zeros argument was added 9/12/95 because vector interactors // want to get converted to ints whenever possible but it's wrong to do // a strstr for ".0". The default value of strip_all_zeros is FALSE and it's // specified as TRUE by ScalarInstance (as of 9/12/95 anyway). // char *DXValue::FormatDouble(double value, char *buf, int decimals, boolean strip_all_zeros) { if (!buf) buf = new char[64]; int precision; if (decimals <= 0) precision = 8; else precision = decimals; // // Use a format that will preserver the precision. %#g prints // 407.0000006 as 407.0000 and drops the 6. // sprintf(buf, "%.*g", precision, value); // // If the number is not in exponential form and does not // have a decimal point, then add one (%.8g may leave off the .000 // if the value is an integer value). // if (!strchr(buf,'.') && !strchr(buf,'e')) { strcat(buf,".0"); if (decimals > 1) { int i; for (i=1 ; i=2) && (buf[len-1] == '0') && (buf[len-2] == '.')) { buf[len-2] = '\0'; } } else if (decimals <= 0) { clip_trailing_zeros(buf); if (decimals == 0) { char *p = (char*)strrstr(buf,".0"); if (p) *p = '\0'; } } return buf; } boolean DXValue::setVector(DXTensor& vector) { ASSERT(this); ASSERT(this->tensor); ASSERT(this->tensor->getDimensions() == 1); // // Clear the old values and reset the type. // this->clear(); this->type.setType(DXType::VectorType); // // Make a copy of the vector and generate a string image. // this->tensor = vector.dup(); this->string = DuplicateString(vector.getValueString()); return TRUE; } // // Get the next item from a list of the given type. // Currently, only ScalarListType, IntegerListType, VectorListType and // StringListType are supported. // Search for the item is started a s[*index], and upon a successfull return, // *index is updated to point to the character not parsed as a list item. // If *index is less than zero then we parse the initial list delimiter '}'. // If buf is provided (!NULL), then the list item is copied into it otherwise // a new string is allocated to hold the list item. In either case a pointer // the string holding the list item is returned upon success. // char *DXValue::NextListItem(const char *s, int *index, Type listtype, char *buf) { int start, i = *index; boolean r; char *p ; if (!s) return NULL; ASSERT(listtype & DXType::ListType); if (i < 0) { // First item in list, handle the '{' i = 0; SkipWhiteSpace(s,i); if (s[i] != '{') return NULL; i++; SkipWhiteSpace(s,i); } else { // Not the first item, handle the optional ',' SkipWhiteSpace(s,i); if (s[i] == ',') { i++; SkipWhiteSpace(s,i); } } start = i; int tuple; switch (listtype & DXType::ListTypeMask) { case DXType::ScalarType: r = IsScalar(s, i); break; case DXType::IntegerType: r = IsInteger(s, i); break; case DXType::VectorType: r = IsVector(s, i, tuple); break; case DXType::TensorType: r = IsTensor(s, i); break; case DXType::StringType: r = IsString(s, i); break; case DXType::ValueType: r = IsInteger(s, i) || IsScalar(s,i) || IsVector(s,i,tuple) || IsTensor(s,i); break; default: printf("Can't get list items from a list of type 0x%x\n",listtype); ASSERT(0); } p = NULL; if (r) { p = buf; int len = i - start; if (!p) p = new char[len + 1]; strncpy(p,&s[start], len); p[len] = '\0'; *index = i; } return p; } #if 0 // // Create a string representation of the given number with the give decimal // places. // char *DXValue::FormatNumber(double val, int decimals) { char format[64], tmp[8]; if ((val > -0.001 && val < 0.0) || (val > 0.0 && val < .001)) { sprintf(format, "%%.%de", decimals); } else { sprintf(format, "%%.%df", decimals); } char *s = new char [64]; sprintf(s, format,val); return s; } #endif // // For the given type, try and augment the given string value with // syntactic sugar to coerce the given value to the given type. // The types we can coerce are StringType, ListType, VectorType and TensorType. // If the value is coerceable return a new string that does not need to // be coerced to the given value, otherwise return NULL. // char *DXValue::CoerceValue(const char *value, Type type) { char *s; if (type == DXType::ValueType) { s = DXValue::CoerceValue(value,DXType::VectorType); } else { char *p = (char*)value; int cnt, end; boolean failed; SkipWhiteSpace(p); cnt = STRLEN(p); s = new char[cnt+3]; s[0] = ' '; strcpy(&s[1],p); cnt = STRLEN(s); // Skip trailing white space. while (s[--cnt] == ' ' || s[cnt] == '\t') continue; end = cnt+1; s[end+1] = '\0'; // // window must be surrounded by quotes just a string is. // if ((type == DXType::StringType) || (type == DXType::WhereType)) { s[0] = '"'; s[end] = '"'; } else if (type & DXType::ListType) { s[0] = '{'; s[end] = '}'; } else if ((type == DXType::TensorType) || (type == DXType::VectorType)) { s[0] = '['; s[end] = ']'; } else { // Allow anything that does not need syntax help strcpy(s,p); } if (!DXValue::IsValidValue(s,type)) failed = TRUE; else failed = FALSE; // // Try and coerce a list with a single element (i.e. coerce both the // element and the overall value). // if (failed && (type & DXType::ListType)) { Type basetype = type & DXType::ListTypeMask; if ((p = DXValue::CoerceValue(value,basetype))) { char *p2 = DXValue::CoerceValue(p,type); if (p2) { delete s; s = p2; failed = FALSE; } delete p; } } if (failed) { delete s; s = NULL; } } return s; } // // Append a list item to a list value. // The returned string must be deleted by the caller. // NULL is returned on failure. // char *DXValue::AppendListItem(const char *list, const char *item) { int itemlen = STRLEN(item); char *nlist; if (EqualString(list,"NULL")) { nlist = new char[itemlen + 5]; sprintf(nlist,"{ %s }",item); } else { nlist = new char [STRLEN(list) + itemlen + 8 ]; strcpy(nlist,list); char *c = strrchr(nlist,'}'); if (!c) { delete nlist; nlist = NULL; } else { *c = '\0'; strcat(c-1, item); strcat(c, " }"); } } return nlist; } // // Get the index'th list item from the given string which // is expected to be a list. // The return list item must be deleted by the caller. // NULL is returned if the item was not found or if the listtype is wrong. // char *DXValue::GetListItem(const char *list, int index, Type listtype) { char *value = NULL, *buf = new char [STRLEN(list)]; int i, idx = -1; for (i=0 ; itype.getType() == DXType::VectorType); ASSERT(this->tensor); boolean r = this->tensor->setVectorComponentValue(component, val); if (r) { if (this->string) delete this->string; this->string = DuplicateString(this->tensor->getValueString()); } return r; } // // Change the dimensionality of the given vector to the given dimensions. // If added components, use the dflt value. // Returns NULL on failure. // Otherwise, the returned string must be deleted by the caller. // char *DXValue::AdjustVectorDimensions(const char *vec, int new_dim, double dflt, boolean is_int) { DXTensor vector; int i; if (!vector.setValue(vec)) return NULL; int old_dim = vector.getVectorComponentCount(); char *value = new char[32 * new_dim]; int min_dim = (old_dim > new_dim ? new_dim : old_dim); // // Adjust the value // strcpy(value,"["); char *p = value; for (i = 1, p += STRLEN(value); i<=min_dim; i++, p+= STRLEN(p)) { double v = vector.getVectorComponentValue(i); if (is_int) sprintf(p, "%d ", (int)v); else { DXValue::FormatDouble(v,p); strcat(p," "); } } for (i = min_dim+1 ; i<=new_dim; i++) { p += STRLEN(p); if (is_int) sprintf(p, "%d ", (int)dflt); else { DXValue::FormatDouble(dflt,p); strcat(p," "); } } strcat(p,"]"); return value; } // // Make sure all values (Scalar[List], Integer[List] and Vector[List] // components) are within the given ranges for each component. // 'val' is the given string value representing the Scalar, Integer or // Vector and 'valtype' is expected to be its type. // mins/maxs are arrays of minimum and maximum values for the // corresponding components (scalar and integer only have a single // component). // TRUE is returned if the value needs to be clamped to be within the // given ranges, FALSE otherwise. If clampedval is provided, then a // string is passed back which represents the clamped value. // boolean DXValue::ClampVSIValue(const char *val, Type valtype, double *mins, double *maxs, char **clampedval) { boolean reset = FALSE; char valbuf[64], itembuf[1024]; Type itemtype; DXValue dxval; ASSERT(val); if (!dxval.setValue(val,valtype)) { if (clampedval) *clampedval = NULL; return FALSE; } itemtype = valtype & DXType::ListTypeMask; ASSERT((itemtype == DXType::IntegerType) || (itemtype == DXType::ScalarType) || (itemtype == DXType::VectorType)); if (valtype & DXType::ListType) { int index = -1; char *clamped = NULL; char *p; int maxlen = 0, clampedlen = 0; if (clampedval) { maxlen = STRLEN(val) + 16; clamped = new char[maxlen]; strcpy(clamped,"{"); clampedlen = 1; p = clamped; } while (DXValue::NextListItem(val,&index,valtype,itembuf)) { char *newval, *s; if (ClampVSIValue(itembuf,itemtype,mins,maxs,&newval)) { ASSERT(newval); s = newval; reset = TRUE; } else { s = itembuf; } if (clamped) { int newchars = STRLEN(s) + 2; if (clampedlen + newchars >= maxlen ) { if (newchars < clampedlen) maxlen = 2 * clampedlen; else maxlen = clampedlen + newchars; clamped = (char*)REALLOC(clamped, maxlen); p = clamped; clampedlen = 0; // Set correctly below. } strcat(p, " "); strcat(p, s); int l = STRLEN(p); p += l; clampedlen += l; } if (newval) delete newval; } if (reset) { if (clamped) { if (maxlen - clampedlen <= 1) p = clamped = (char*)REALLOC(clamped, maxlen + 2); strcat(p,"}"); } } else { if (clamped) delete clamped; clamped = NULL; } if (clampedval) *clampedval = clamped; } else { int i, ncomp; boolean isvector = (itemtype == DXType::VectorType); boolean isinteger = (itemtype == DXType::IntegerType); if (isvector) ncomp = dxval.getVectorComponentCount(); else ncomp = 1; itembuf[0] = '\0'; if (isvector) strcat(itembuf,"["); for (i=0 ; i max) { val = max; reset = TRUE; } else if (val < min) { val = min; reset = TRUE; } if (isinteger) { sprintf(valbuf,"%d ", (int)(val)); } else { DXValue::FormatDouble(val,valbuf); strcat(valbuf," "); } strcat(itembuf, valbuf); } if (clampedval) { if (reset) { if (isvector) strcat(itembuf,"]"); *clampedval = DuplicateString(itembuf); } else *clampedval = NULL; } } return reset; } // // Parse the floating point numbers out of either a ScalarList or a // VectorList. Numbers are parsed into an array created from within. // The values are placed into the array in the order they are encountered // in the list. In the case of VectorLists, all vectors in the list must // be of the same dimensionality. // The return value is the number of list items (and not numbers) parsed out // of the list. // *data is the allocated array of values, and must be freed by the caller. // *tuple is the dimensionality of the VectorList items (1 for ScalarList). // '*tuple * return-val' is the number of items in the *data array. // int DXValue::GetDoublesFromList(const char *list, Type listtype, double **data, int *tuple) { int count = DXValue::GetListItemCount(list, listtype); double *values = NULL; int vtuple, nitems = 0; if (count) { int i, index = -1, offset = 0; DXTensor t; // // Get the floating point values out of the string list. // for (i=0 ; i 0); if (EqualString(list,"NULL")) return DuplicateString("NULL"); buf = new char[listlen + 1]; newlist= new char [listlen + itemlen + position + 4]; // // Skip over the first list delimiter. // for (idx=0 ; list[idx] != '{' ; idx++); idx++; // // Skip over the first 'position-1' items. // strcpy(newlist,"{"); p = newlist; premature_end = FALSE; for (i=1, p+=STRLEN(p); itype.getType()) { case DXType::VectorType: ASSERT(this->tensor); t = this->tensor; break; case DXType::VectorListType: ASSERT(this->string); listitem = DXValue::GetListItem(this->string,1, DXType::VectorListType); ASSERT(listitem); r = vlist_item.setValue(listitem); delete listitem; ASSERT(r); t = &vlist_item; break; default: ASSERT(0); } return t->getVectorComponentCount(); } Type DXValue::getType() { return this->type.getType(); } const char* DXValue::getTypeName() { return this->type.getName(); } int DXValue::getInteger() { ASSERT(this->type.getType() == DXType::IntegerType || this->type.getType() == DXType::FlagType); return this->integer; } double DXValue::getScalar() { ASSERT(this->type.getType() == DXType::ScalarType); return this->scalar; } double DXValue::getVectorComponentValue(int component) { ASSERT(this->type.getType() == DXType::VectorType); ASSERT(this->tensor); return this->tensor->getVectorComponentValue(component); } #if 00 // Not needed yet // // Insert a list item into a list value. // The returned string must be deleted by the caller. // NULL is returned on failure. Positions begin at 1, but if position // is less than or equal to 0, then an Append is implied. This works // on the same list types that NextListItem() does. // char *DXValue::InsertListItem(const char *list, const char *item, Type listtype, int position) { char *p, *value = NULL, *newlist, *buf; int i, idx; boolean premature_end; int listlen = STRLEN(list); int itemlen = STRLEN(item); if (position <= 0) { return DXValue::AppendListItem(list,item); } else if (EqualString(list,"NULL")) { newlist = new char[itemlen + 5]; sprintf(newlist,"{ %s }",item); return newlist; } buf = new char[(listlen > itemlen ? listlen : itemlen)]; newlist= new char [listlen + itemlen + 32]; // // Skip over the first list delimiter. // for (idx=0 ; list[idx] != '{' ; idx++); idx++; // // Skip over the first 'position-1' items. // strcpy(newlist,"{"); p = newlist; premature_end = FALSE; for (i=1, p+=STRLEN(p); i