/* * Copyright (c) 2001,2006 Scott E. Johnston * Copyright (c) 2000 IET Inc. * Copyright (c) 1994-1997 Vectaport Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the names of the copyright holders not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. The copyright holders make * no representations about the suitability of this software for any purpose. * It is provided "as is" without express or implied warranty. * * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. * IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * */ #include #include #include #include #include #if !defined(solaris) #include #endif #include #include /*****************************************************************************/ int* AttributeValue::_type_syms = nil; AttributeValue::AttributeValue(ValueType valtype) { clear(); type(valtype); } AttributeValue::AttributeValue(ValueType valtype, attr_value value) { clear(); type(valtype); _v = value; } AttributeValue::AttributeValue(AttributeValue& sv) { *this = sv; } AttributeValue::AttributeValue(AttributeValue* sv) { *this = *sv; dup_as_needed(); } AttributeValue::AttributeValue() { clear(); type(UnknownType); _command_symid = -1; } AttributeValue::AttributeValue(unsigned char v) { clear(); _type = AttributeValue::UCharType; _v.ucharval = v; } AttributeValue::AttributeValue(char v) { clear(); _type = AttributeValue::CharType; _v.charval = v; } AttributeValue::AttributeValue(unsigned short v) { clear(); _type = AttributeValue::UShortType; _v.ushortval = v; } AttributeValue::AttributeValue(short v) { clear(); _type = AttributeValue::ShortType; _v.shortval = v; } AttributeValue::AttributeValue(unsigned int v, ValueType type) { clear(); _type = type; if ( type >= CharType && type <= UShortType ) { switch (type) { case CharType: _v.charval = v; break; case UCharType: _v.ucharval = v; break; case ShortType: _v.shortval = v; break; case UShortType: _v.ushortval = v; break; } } else _v.dfunsval = v; } AttributeValue::AttributeValue(unsigned int kv, unsigned int kn, ValueType type) { clear(); _type = type; _v.keyval.keyid = kv; _v.keyval.keynarg = kn; } AttributeValue::AttributeValue(int v, ValueType type) { clear(); _type = type; if ( type >= CharType && type <= UShortType ) { switch (type) { case CharType: _v.charval = v; break; case UCharType: _v.ucharval = v; break; case ShortType: _v.shortval = v; break; case UShortType: _v.ushortval = v; break; } } else _v.dfintval = v; } AttributeValue::AttributeValue(unsigned long v) { clear(); _type = AttributeValue::ULongType; _v.lnunsval = v; } AttributeValue::AttributeValue(long v) { clear(); _type = AttributeValue::LongType; _v.lnintval = v; } AttributeValue::AttributeValue(float v) { clear(); _type = AttributeValue::FloatType; _v.floatval = v; } AttributeValue::AttributeValue(double v) { clear(); _type = AttributeValue::DoubleType; _v.doublval = v; } AttributeValue::AttributeValue(int classid, void* ptr) { _type = AttributeValue::ObjectType; _v.objval.ptr = ptr; _v.objval.type = classid; _object_compview = false; } AttributeValue::AttributeValue(AttributeValueList* ptr) { _type = AttributeValue::ArrayType; _v.arrayval.ptr = ptr; _v.arrayval.type = 0; Resource::ref(ptr); } AttributeValue::AttributeValue(void* comfuncptr, AttributeValueList* vallist) { _type = AttributeValue::StreamType; _v.streamval.funcptr = comfuncptr; _v.streamval.listptr = vallist; Resource::ref(vallist); } AttributeValue::AttributeValue(const char* string) { _type = AttributeValue::StringType; _v.dfintval = symbol_add((char*)string); } AttributeValue::~AttributeValue() { #if 0 // disable symbol reference counting if (_type == StringType || _type == SymbolType) symbol_del(string_val()); else #endif unref_as_needed(); type(UnknownType); } void AttributeValue::clear() { unsigned char* buf = (unsigned char*)(void*)&_v; for (int i=0; iNumber(); else return 0; } int AttributeValue::list_len() { if (is_type(AttributeValue::ArrayType)) return array_val()->Number(); else return 0; } int AttributeValue::command_symid() { return _command_symid; } void AttributeValue::command_symid(int id, boolean alias) { _command_symid = (alias ? -1 : 1) * id; } ostream& operator<< (ostream& out, const AttributeValue& sv) { AttributeValue* svp = (AttributeValue*)&sv; char* title; char* symbol; int counter; #if 0 switch( svp->type() ) { case AttributeValue::KeywordType: out << "Keyword (" << symbol_pntr( svp->symbol_ref() ) << ")"; break; case AttributeValue::CommandType: title = "Command ("; symbol = symbol_pntr( svp->symbol_ref() ); out << title << symbol; counter = strlen(title) + strlen(symbol); while( ++counter < 32 ) out << ' '; out << ")"; break; case AttributeValue::SymbolType: out << "symbol (" << svp->symbol_ptr() << ")"; break; case AttributeValue::StringType: out << "string (" << svp->string_ptr() << ")"; break; case AttributeValue::BooleanType: out << "boolean (" << svp->boolean_ref() << ")"; break; case AttributeValue::CharType: out << "char (" << svp->char_ref() << ":" << (int)svp->char_ref() << ")"; break; case AttributeValue::UCharType: out << "uchar (" << svp->char_ref() << ":" << (int)svp->char_ref() << ")"; break; case AttributeValue::IntType: out << "int (" << svp->int_ref() << ")"; break; case AttributeValue::UIntType: if (svp->state()==AttributeValue::OctState) out << "uint (" << svp->uint_ref() << ")"; else if (svp->state()==AttributeValue::HexState) out << "uint (" << svp->uint_ref() << ")"; else out << "uint (" << svp->uint_ref() << ")"; break; case AttributeValue::LongType: out << "Long (" << svp->long_ref() << ")"; break; case AttributeValue::ULongType: out << "ulong (" << svp->ulong_ref() << ")"; break; case AttributeValue::FloatType: out << "float (" << svp->float_ref() << ")"; break; case AttributeValue::DoubleType: out << "double (" << svp->double_ref() << ")"; //printf("%9.2f\n", svp->double_ref()); break; case AttributeValue::EofType: out << "eof"; break; case AttributeValue::ArrayType: { out << "list of length " << svp->array_len(); ALIterator i; AttributeValueList* avl = svp->array_val(); avl->First(i); boolean first = true; while (!avl->Done(i)) { out << "\n\t" << *avl->GetAttrVal(i); avl->Next(i); } } break; case AttributeValue::BlankType: break; default: break; } #else switch(svp->type()) { case AttributeValue::KeywordType: out << "Keyword (" << symbol_pntr( svp->symbol_ref() ) << ")"; break; case AttributeValue::CommandType: title = "Command ("; symbol = symbol_pntr( svp->symbol_ref() ); out << title << symbol; counter = strlen(title) + strlen(symbol); while( ++counter < 32 ) out << ' '; out << ")"; break; case AttributeValue::SymbolType: out << svp->symbol_ptr(); break; case AttributeValue::StringType: out << "\"" << svp->string_ptr() << "\""; break; case AttributeValue::CharType: out << svp->char_ref(); break; case AttributeValue::UCharType: out << svp->char_ref(); break; case AttributeValue::IntType: out << svp->int_ref(); break; case AttributeValue::UIntType: if (svp->state()==AttributeValue::OctState) out << "0" << std::oct << svp->uint_ref() << std::dec; else if (svp->state()==AttributeValue::HexState) out << "0x" << std::hex << svp->uint_ref() << std::dec; else out << svp->uint_ref(); break; case AttributeValue::BooleanType: out << svp->uint_ref(); break; case AttributeValue::ShortType: out << svp->short_ref(); break; case AttributeValue::UShortType: if (svp->state()==AttributeValue::OctState) out << "0" << std::oct << svp->ushort_ref() << std::dec; else if (svp->state()==AttributeValue::HexState) out << "0x" << std::hex << svp->ushort_ref() << std::dec; else out << svp->ushort_ref(); break; case AttributeValue::LongType: out << svp->long_ref(); break; case AttributeValue::ULongType: if (svp->state()==AttributeValue::OctState) out << "0" << std::oct << svp->ulong_ref() << std::dec; else if (svp->state()==AttributeValue::HexState) out << "0x" << std::hex << svp->ulong_ref() << std::dec; else out << svp->ulong_ref(); break; case AttributeValue::FloatType: #if __GNUG__<3 out.form("%.6f", svp->float_val()); #else { const int bufsiz=256; char buffer[bufsiz]; snprintf(buffer, bufsiz, "%.6f", svp->float_val()); out << buffer; } #endif break; case AttributeValue::DoubleType: #if __GNUG__<3 out.form("%.6f", svp->double_val()); #else { const int bufsiz=256; char buffer[bufsiz]; snprintf(buffer, bufsiz, "%.6f", svp->double_val()); out << buffer; } #endif break; case AttributeValue::EofType: out << "eof"; break; case AttributeValue::ArrayType: { //out << "array of length " << svp->array_len(); ALIterator i; AttributeValueList* avl = svp->array_val(); avl->First(i); boolean first = true; while (!avl->Done(i)) { if (!first) out << ","; out << *avl->GetAttrVal(i); avl->Next(i); first = false; } } break; case AttributeValue::BlankType: break; case AttributeValue::ObjectType: out << "<" << symbol_pntr(svp->class_symid()) << ">"; break; case AttributeValue::StreamType: out << "stream_mode() << ">"; break; default: out << "nil"; break; } #endif return out; } void AttributeValue::negate() { switch (type()) { case AttributeValue::CharType: char_ref() = -char_val(); return; case AttributeValue::UCharType: char_ref() = -uchar_val(); type(CharType); return; case AttributeValue::ShortType: short_ref() = -short_val(); return; case AttributeValue::UShortType: short_ref() = -ushort_val(); type(ShortType); return; case AttributeValue::IntType: int_ref() = -int_val(); return ; case AttributeValue::UIntType: int_ref() = -uint_val(); type(IntType); return; case AttributeValue::LongType: long_ref() = -long_val(); return; case AttributeValue::ULongType: long_ref() = -ulong_ref(); type(LongType); return; case AttributeValue::FloatType: float_ref() = -float_val(); return; case AttributeValue::DoubleType: double_ref() = -double_val(); return; default: return; } } int AttributeValue::type_size(ValueType type) { switch (type) { case AttributeValue::UnknownType: return 0; case AttributeValue::CharType: return sizeof(char); case AttributeValue::UCharType: return sizeof(unsigned char); case AttributeValue::ShortType: return sizeof(short); case AttributeValue::UShortType: return sizeof(unsigned short); case AttributeValue::IntType: return sizeof(int); case AttributeValue::UIntType: return sizeof(unsigned int); case AttributeValue::LongType: return sizeof(long); case AttributeValue::ULongType: return sizeof(unsigned long); case AttributeValue::FloatType: return sizeof(float); case AttributeValue::DoubleType: return sizeof(double); default: return 0; } } void AttributeValue::assignval (const AttributeValue& av) { void* v1 = &_v; const void* v2 = &av._v; memcpy(v1, v2, sizeof(_v)); _type = av._type; _command_symid = av._command_symid; #if 0 // this end of reference counting disabled as well if (_type == StringType || _type == SymbolType) symbol_add((char *)string_ptr()); else #endif ref_as_needed(); } boolean AttributeValue::is_attributelist() { return is_object() && class_symid() == AttributeList::class_symid(); } boolean AttributeValue::is_attribute() { return is_object() && class_symid() == Attribute::class_symid(); } void* AttributeValue::geta(int id) { if (is_object(id)) return obj_val(); else return nil; } int AttributeValue::type_symid() const { if (!_type_syms) { int i = 0; _type_syms = new int[((int)BlankType)+1]; _type_syms[i++] = symbol_add("UnknownType"); _type_syms[i++] = symbol_add("CharType"); _type_syms[i++] = symbol_add("UCharType"); _type_syms[i++] = symbol_add("ShortType"); _type_syms[i++] = symbol_add("UShortType"); _type_syms[i++] = symbol_add("IntType"); _type_syms[i++] = symbol_add("UIntType"); _type_syms[i++] = symbol_add("LongType"); _type_syms[i++] = symbol_add("ULongType"); _type_syms[i++] = symbol_add("FloatType"); _type_syms[i++] = symbol_add("DoubleType"); _type_syms[i++] = symbol_add("StringType"); _type_syms[i++] = symbol_add("SymbolType"); _type_syms[i++] = symbol_add("ListType"); _type_syms[i++] = symbol_add("StreamType"); _type_syms[i++] = symbol_add("CommandType"); _type_syms[i++] = symbol_add("KeywordType"); _type_syms[i++] = symbol_add("ObjectType"); _type_syms[i++] = symbol_add("EofType"); _type_syms[i++] = symbol_add("BooleanType"); _type_syms[i++] = symbol_add("OperatorType"); _type_syms[i++] = symbol_add("BlankType"); } if (type()>=UnknownType && type()<=BlankType) return _type_syms[(int)type()]; else return -1; } void AttributeValue::ref_as_needed() { if (_type == AttributeValue::ArrayType) Resource::ref(_v.arrayval.ptr); else if (_type == AttributeValue::StreamType) Resource::ref(_v.streamval.listptr); } void AttributeValue::dup_as_needed() { if (_type == AttributeValue::ArrayType) { AttributeValueList* avl = _v.arrayval.ptr; _v.arrayval.ptr = new AttributeValueList(avl); Resource::ref(_v.arrayval.ptr); Resource::unref(avl); } else if (_type == AttributeValue::StreamType) { AttributeValueList* avl = _v.streamval.listptr; _v.streamval.listptr = new AttributeValueList(avl); Resource::ref(_v.streamval.listptr); Resource::unref(avl); } } void AttributeValue::unref_as_needed() { if (_type == AttributeValue::ArrayType) Resource::unref(_v.arrayval.ptr); else if (_type == AttributeValue::StreamType) Resource::unref(_v.streamval.listptr); } void AttributeValue::stream_list(AttributeValueList* list) { if (is_stream()) { Resource::unref(_v.streamval.listptr); _v.streamval.listptr = list; if (!list) stream_mode(0); else Resource::ref(list); } } int AttributeValue::stream_mode() { if (is_stream()) { if (!stream_list() || stream_list()->Number()==0) return 0; else return _stream_mode; } else return 0; } int AttributeValue::state() { if (!is_stream() && !is_object() && !is_command()) return _state; else return -1; } void AttributeValue::state(int val) { if (!is_stream() && !is_object() && !is_command()) _state = val; } boolean AttributeValue::is_object(int class_symid) { if (!is_type(ObjectType)) return false; if (this->class_symid() == class_symid) return true; return false; }