/* * This file is part of rasdaman community. * * Rasdaman community is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Rasdaman community is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with rasdaman community. If not, see . * * Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / rasdaman GmbH. * * For more information please see * or contact Peter Baumann via . */ static const char rcsid[] = "@(#)raslib, r_Type: $Header: /home/rasdev/CVS-repository/rasdaman/raslib/type.cc,v 1.17 2003/12/27 23:01:21 rasdev Exp $"; #include // for isalpha() #include // for strncmp() #include "raslib/type.hh" #include "raslib/collectiontype.hh" #include "raslib/primitivetype.hh" #include "raslib/complextype.hh" #include "raslib/structuretype.hh" #include "raslib/marraytype.hh" #include "raslib/sintervaltype.hh" #include "raslib/mintervaltype.hh" #include "raslib/pointtype.hh" #include "raslib/oidtype.hh" #include "raslib/attribute.hh" #include "raslib/error.hh" #include "raslib/rminit.hh" r_Type::r_Type() : r_Meta_Object() { } r_Type::r_Type(const char* newTypeName) : r_Meta_Object(newTypeName) { } r_Type::r_Type(const r_Type& oldObj) : r_Meta_Object(oldObj) { } const r_Type& r_Type::operator=(const r_Type& oldObj) { // Gracefully handle self assignment if (this == &oldObj) return *this; r_Meta_Object::operator=(oldObj); return *this; } r_Type::~r_Type() { } bool r_Type::isStructType() const { return false; } bool r_Type::isComplexType() const { return false; } bool r_Type::isBaseType() const { return false; } bool r_Type::isCollectionType() const { return false; } bool r_Type::isMarrayType() const { return false; } bool r_Type::isPrimitiveType() const { return false; } bool r_Type::isSintervalType() const { return false; } bool r_Type::isMintervalType() const { return false; } bool r_Type::isPointType() const { return false; } bool r_Type::isOidType() const { return false; } r_Type* r_Type::get_any_type(const char* type_string) { char* pos = (char*)type_string; char* identifier = NULL; r_Type* returnValue = NULL; DLTOKEN token = DLUNKNOWN; // one token look ahead char* oldPos = pos; token = getNextToken(pos, identifier); pos = oldPos; switch(token) { case DLMARRAY: returnValue = getMarrayType(pos); break; case DLSET: returnValue = getCollectionType(pos); break; default: returnValue = getType(pos); } return returnValue; } r_Type::DLTOKEN r_Type::getNextToken(char* &pos, char* &identifier) { DLTOKEN token = DLUNKNOWN; while(*pos == ' ') pos ++; if(!strncmp(pos, "marray", 6)) { token = DLMARRAY; pos += 6; } else if(!strncmp(pos, "set", 3)) { token = DLSET; pos += 3; } else if(!strncmp(pos, "struct", 6)) { token = DLSTRUCT; pos += 6; } else if(*pos == '[') { token = DLLEP; pos += 1; } else if(*pos == ']') { token = DLREP; pos += 1; } else if(*pos == '<') { token = DLLAP; pos += 1; } else if(*pos == '>') { token = DLRAP; pos += 1; } else if(*pos == '{') { token = DLLCP; pos += 1; } else if(*pos == '}') { token = DLRCP; pos += 1; } else if(*pos == ',') { token = DLCOMMA; pos += 1; } else if(!strncmp(pos, "octet", 5)) { token = DLOCTET; pos += 5; } else if(!strncmp(pos, "char", 4)) { token = DLCHAR; pos += 4; } else if(!strncmp(pos, "ulong", 5)) { token = DLULONG; pos += 5; } else if(!strncmp(pos, "long", 4)) { token = DLLONG; pos += 4; } else if(!strncmp(pos, "short", 5)) { token = DLSHORT; pos += 5; } else if(!strncmp(pos, "ushort", 6)) { token = DLUSHORT; pos += 6; } else if(!strncmp(pos, "float", 5)) { token = DLFLOAT; pos += 5; } else if(!strncmp(pos, "double", 6)) { token = DLDOUBLE; pos += 6; } else if(!strncmp(pos, "bool", 4)) { token = DLBOOL; pos += 4; } else if(!strncmp(pos, "complexd", 8)) { token = DLCOMPLEXTYPE2; pos += 8; } // the order of testing it's important here // (complex is a proper prefix of complexd!) else if(!strncmp(pos, "complex", 7)) { token = DLCOMPLEXTYPE1; pos += 7; } else if(!strncmp(pos, "interval", 8)) { token = DLINTERVAL; pos += 8; } else if(!strncmp(pos, "minterval", 9)) { token = DLMINTERVAL; pos += 9; } else if(!strncmp(pos, "point", 5)) { token = DLPOINT; pos += 5; } else if(!strncmp(pos, "oid", 3)) { token = DLOID; pos += 3; } else { token = DLIDENTIFIER; // identifier char* beginPos = pos; // read identifier while(isalnum(*pos) || *pos == '-' || *pos == '_') pos++; identifier = new char[pos-beginPos+1]; strncpy(identifier, beginPos, pos-beginPos); identifier[pos-beginPos] = '\0'; } while(*pos == ' ') pos ++; return token; } r_Collection_Type* r_Type::getCollectionType(char* &pos) { char* identifier = NULL; r_Collection_Type* returnValue = NULL; r_Type* elementType = NULL; DLTOKEN token = DLUNKNOWN; // get 'set' getNextToken(pos, identifier); // get '<' if(getNextToken(pos, identifier) != DLLAP) { RMInit::logOut << "r_Type::getCollectionType(" << pos << ") expected DLLAP" << endl; throw r_Error(INTERNALDLPARSEERROR); } // one token look ahead char* oldPos = pos; token = getNextToken(pos, identifier); pos = oldPos; switch(token) { case DLMARRAY: elementType = getMarrayType(pos); break; default: elementType = getType(pos); } returnValue = new r_Collection_Type(*elementType); delete elementType; return returnValue; } r_Type* r_Type::getType(char* &pos) { DLTOKEN token = DLUNKNOWN; char* identifier = 0; r_Type* returnValue = 0; // one token look ahead char* oldPos = pos; token = getNextToken(pos, identifier); pos = oldPos; if(token == DLSTRUCT) returnValue = getStructureType(pos); else if(token == DLINTERVAL) returnValue = getSintervalType(pos); else if(token == DLMINTERVAL) returnValue = getMintervalType(pos); else if(token == DLPOINT) returnValue = getPointType(pos); else if(token == DLOID) returnValue = getOidType(pos); else returnValue = getPrimitiveType(pos); return returnValue; } r_Marray_Type* r_Type::getMarrayType(char* &pos) { char* identifier = NULL; r_Marray_Type* returnValue = NULL; r_Base_Type* basetype = NULL; // get 'marray' getNextToken(pos, identifier); // get '<' if(getNextToken(pos, identifier) != DLLAP) { RMInit::logOut << "r_Type::getMarrayType(" << pos << ") expected DLLAP" << endl; throw r_Error(INTERNALDLPARSEERROR); } // get base type (structure or primitive type) basetype = getBaseType(pos); returnValue = new r_Marray_Type(*basetype); delete basetype; return returnValue; } r_Base_Type* r_Type::getBaseType(char* &pos, int offset) { DLTOKEN token = DLUNKNOWN; char* identifier = NULL; r_Base_Type* returnValue = NULL; // one token look ahead char* oldPos = pos; token = getNextToken(pos, identifier); pos = oldPos; if(token == DLSTRUCT) returnValue = getStructureType(pos, offset); else returnValue = getPrimitiveType(pos); return returnValue; } r_Primitive_Type* r_Type::getPrimitiveType(char* &pos) { char* dummy = NULL; r_Primitive_Type* returnValue = NULL; switch(getNextToken(pos, dummy)) { case DLCHAR: returnValue = new r_Primitive_Type("Char", r_Type::CHAR); break; case DLOCTET: returnValue = new r_Primitive_Type("Octet", r_Type::OCTET); break; case DLSHORT: returnValue = new r_Primitive_Type("Short", r_Type::SHORT); break; case DLUSHORT: returnValue = new r_Primitive_Type("UShort", r_Type::USHORT); break; case DLLONG: returnValue = new r_Primitive_Type("Long", r_Type::LONG); break; case DLULONG: returnValue = new r_Primitive_Type("ULong", r_Type::ULONG); break; case DLBOOL: returnValue = new r_Primitive_Type("Bool", r_Type::BOOL); break; case DLFLOAT: returnValue = new r_Primitive_Type("Float", r_Type::FLOAT); break; case DLDOUBLE: returnValue = new r_Primitive_Type("Double", r_Type::DOUBLE); break; case DLCOMPLEXTYPE1: returnValue = new r_Complex_Type("Complex1", r_Type::COMPLEXTYPE1); break; case DLCOMPLEXTYPE2: returnValue = new r_Complex_Type("Complex2", r_Type::COMPLEXTYPE2); break; default: { RMInit::logOut << "r_Type::getPrimitiveType(" << pos << ") unknown token" << endl; throw r_Error(INTERNALDLPARSEERROR); } } return returnValue; } r_Structure_Type* r_Type::getStructureType(char* &pos, int offset) { r_Structure_Type* returnValue = NULL; char* identifier = NULL; DLTOKEN token = DLUNKNOWN; r_Attribute* attributes = NULL; int noAttributes=0; // get 'struct' getNextToken(pos, identifier); // get '{' if(getNextToken(pos, identifier) != DLLCP) { RMInit::logOut << "r_Type::getStructureType(" << pos << ", " << offset << ") expected DLLCP" << endl; throw r_Error(INTERNALDLPARSEERROR); } int localOffset = offset; while(token != DLRCP) { // get type r_Base_Type* type = getBaseType(pos, localOffset); // adjust local offset localOffset += type->size(); // get optional name token = getNextToken(pos, identifier); // allocate another attribute (very inefficient) noAttributes++; r_Attribute* oldAttributes = attributes; attributes = new r_Attribute[noAttributes]; for(int i=0; i < noAttributes-1; i++) attributes[i] = oldAttributes[i]; if(oldAttributes) delete[] oldAttributes; oldAttributes = NULL; if(token == DLIDENTIFIER) { // with identifier attributes[noAttributes-1] = r_Attribute(identifier, *type); delete[] identifier; identifier = NULL; // read next token token = getNextToken(pos, identifier); } else { // without identifier attributes[noAttributes-1] = r_Attribute("", *type); } delete type; type = NULL; if(token != DLCOMMA && token != DLRCP) { RMInit::logOut << "r_Type::getStructureType(" << pos << ", " << offset << ") expected DLRCP or DLCOMMA" << endl; throw r_Error(INTERNALDLPARSEERROR); } } returnValue = new r_Structure_Type("Structure", noAttributes, attributes, offset); if(attributes) delete[] attributes; attributes = NULL; return returnValue; } r_Sinterval_Type* r_Type::getSintervalType(char* &pos) { char* dummy = NULL; r_Sinterval_Type* returnValue = NULL; getNextToken(pos, dummy); returnValue = new r_Sinterval_Type(); return returnValue; } r_Minterval_Type* r_Type::getMintervalType(char* &pos) { char* dummy = NULL; r_Minterval_Type* returnValue = NULL; getNextToken(pos, dummy); returnValue = new r_Minterval_Type(); return returnValue; } r_Point_Type* r_Type::getPointType(char* &pos) { char* dummy = NULL; r_Point_Type* returnValue = NULL; getNextToken(pos, dummy); returnValue = new r_Point_Type(); return returnValue; } r_Oid_Type* r_Type::getOidType(char* &pos) { char* dummy = NULL; r_Oid_Type* returnValue = NULL; getNextToken(pos, dummy); returnValue = new r_Oid_Type(); return returnValue; } std::ostream& operator<<( std::ostream& s, r_Type::r_Type_Id t ) { switch( t ) { case r_Type::ULONG: s << "ulong"; break; case r_Type::USHORT: s << "ushort"; break; case r_Type::BOOL: s << "bool"; break; case r_Type::LONG: s << "long"; break; case r_Type::SHORT: s << "short"; break; case r_Type::OCTET: s << "octet"; break; case r_Type::DOUBLE: s << "double"; break; case r_Type::FLOAT: s << "float"; break; case r_Type::CHAR: s << "char"; break; case r_Type::COMPLEXTYPE1: s << "complextype1"; break; case r_Type::COMPLEXTYPE2: s << "complextype2"; break; case r_Type::STRUCTURETYPE: s << "structuretype"; break; case r_Type::MARRAYTYPE: s << "marraytype"; break; case r_Type::COLLECTIONTYPE: s << "collectiontype"; break; case r_Type::SINTERVALTYPE: s << "sintervaltype"; break; case r_Type::MINTERVALTYPE: s << "mintervaltype"; break; case r_Type::POINTTYPE: s << "pointtype"; break; case r_Type::OIDTYPE: s << "oidtype"; break; case r_Type::UNKNOWNTYPE: s << "unknowntype"; break; default: s << "UNKNOWN r_Type_Id" << t; break; } return s; }