#include "mymalloc/mymalloc.h" // This is -*- C++ -*- /* * 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 . */ /************************************************************* * * * PURPOSE: * * * COMMENTS: * code common to all database interface implementations */ #include "structtype.hh" #include "catalogmgr/typefactory.hh" #include #include #include "reladminif/sqlerror.hh" #include "reladminif/externs.h" #include "raslib/rmdebug.hh" #include "reladminif/objectbroker.hh" #include "raslib/error.hh" #include /************************************************************* * Method name...: StructType(); * * Arguments.....: none * Return value..: none * Description...: initializes member variables for an * StructType. ************************************************************/ r_Bytes StructType::getMemorySize() const { r_Bytes retval = DBNamedObject::getMemorySize() + sizeof(int) + sizeof(int) + sizeof(std::vector< BaseType* >) + sizeof(std::vector< unsigned int >) + sizeof(std::vector< char* >) + sizeof(int) * numElems + sizeof(BaseType*) * numElems; for (int i = 0; i < numElems; i++) retval = retval + 1 + strlen(elementNames[i]); return retval; } StructType::StructType() : CompositeType("unnamed structtype", 0), numElems(0), elements(0), elementNames(0), elementOffsets(0), align(1) { myType = STRUCT; objecttype = OId::STRUCTTYPEOID; } StructType::StructType(const char* newTypeName, unsigned int numElem ) : CompositeType(newTypeName, 0), elements(numElem), elementNames(numElem), elementOffsets(numElem), numElems(0), align(1) { myType = STRUCT; objecttype = OId::STRUCTTYPEOID; } /************************************************************* * Method name...: StructType(const StructType& old); * * Arguments.....: none * Return value..: none * Description...: copy constructor ************************************************************/ StructType::StructType(const StructType& old) : CompositeType(old) { elements = old.elements; elementNames = old.elementNames; elementOffsets = old.elementOffsets; numElems = old.numElems; align = old.align; } StructType::StructType(const OId& structtypeid) throw (r_Error) : CompositeType(structtypeid), elements(0), elementNames(0), elementOffsets(0), numElems(0), align(1) { RMDBGENTER(4, RMDebug::module_catalogif, "StructType", "StructType(" << myOId << ")"); myType = STRUCT; objecttype = OId::STRUCTTYPEOID; readFromDb(); RMDBGEXIT(4, RMDebug::module_catalogif, "StructType", "StructType(" << myOId << ")"); } /************************************************************* * Method name...: operator=(const StructType&); * * Arguments.....: none * Return value..: none * Description...: copy constructor ************************************************************/ StructType& StructType::operator=(const StructType& old) { // Gracefully handle self assignment //FIXME memory leak with char* in elementNames and elements if (this == &old) return *this; CompositeType::operator=(old); elements = old.elements; elementNames = old.elementNames; elementOffsets = old.elementOffsets; numElems = old.numElems; align = old.align; return *this; } StructType::~StructType() { ObjectBroker::deregisterDBObject(myOId); validate(); for (int i = 0; i < getNumElems(); i++) free((void*)elementNames[i]);//is ok because noone is using it } /************************************************************* * Method name...: void printCell( ostream& stream, * const char* cell ) * * Arguments.....: * stream: stream to print on * cell: pointer to cell to print * Return value..: none * Description...: prints a cell cell in hex on stream * followed by a space. * Assumes that Struct is stored MSB..LSB * on HP. ************************************************************/ void StructType::printCell( ostream& stream, const char* cell ) const { int i; stream << "\t|"; for(i=0; iprintCell(stream, cell + elementOffsets[i]); stream << "\t "; } stream << "\t| "; } char* StructType::getTypeStructure() const { // this implementation is not very clever, perhaps should use // an intelligent string class char* result = (char*)mymalloc(10); char* newResult; int i; strcpy(result, "struct { "); if(numElems == 0) { newResult = (char*)mymalloc(strlen(result) + 1 + 2); strcpy(newResult, result); strcat(newResult, " }"); free(result); return newResult; } for(i = 0; i < numElems; i++) { char* dummy = elements[i]->getTypeStructure(); newResult = (char*)mymalloc(strlen(result) + strlen(elementNames[i]) + strlen(dummy) + 1 + 3 ); strcpy(newResult, result); strcat(newResult, dummy); strcat(newResult, " "); strcat(newResult, elementNames[i]); strcat(newResult, ", "); free(result); free(dummy); result = newResult; } newResult = (char*)mymalloc(strlen(result) + 1 ); strcpy(newResult, result); newResult[strlen(newResult) - 2] = ' '; newResult[strlen(newResult) - 1] = '}'; free(result); result = newResult; return result; } unsigned int StructType::addElement(const char* elemName, const char* elemType) { BaseType* stuff = 0; stuff = (BaseType*)ObjectBroker::getObjectByName(OId::ATOMICTYPEOID, elemType); if (stuff == 0) stuff = (BaseType*)ObjectBroker::getObjectByName(OId::STRUCTTYPEOID, elemType); return addElement(elemName, stuff); } unsigned int StructType::addElement(const char* elemName, const BaseType* newType) { if (newType) { if (!_isPersistent) { addElementPriv(elemName, newType); } } return numElems; } unsigned int StructType::addElementPriv(const char* elemName, const BaseType* newType) { int currPos = 0; int i, j; char* myElemName = 0; myElemName = (char*)mymalloc(strlen(elemName) + 1); strcpy(myElemName, elemName); if(numElems+1 > elements.size()) { BaseType* dummyB = 0; char* dummyN = 0; unsigned int dummyO = 0; elements.push_back(dummyB); elementNames.push_back(dummyN); elementOffsets.push_back(dummyO); } if(numElems == 0) { // first element elementOffsets[currPos] = 0; ++numElems; } else { // All cases have to set currPos and numElems correctly! // The array has to be ordered by offsets. if(newType->getType() == STRUCT) { unsigned int myAlign = ((StructType*)(newType))->getAlignment(); if( align < myAlign ) align = myAlign; // append at the end, align offset to 4 bytes. currPos = numElems; ++numElems; elementOffsets[currPos] = ((elementOffsets[currPos-1] + elements[currPos-1]->getSize()-1)/myAlign+1)*myAlign; } else { if(newType->getSize() >= 4) { if(align < 4) align = 4; // append at the end, align offset to 4 bytes. currPos = numElems; ++numElems; elementOffsets[currPos] = ((elementOffsets[currPos-1] + elements[currPos-1]->getSize()-1)/4+1)*4; } else { if(newType->getSize() == 2) { if(align < 2) align = 2; currPos = numElems; numElems++; elementOffsets[currPos] = ((elementOffsets[currPos-1] + elements[currPos-1]->getSize()-1)/2+1)*2; } else { if(newType->getSize() == 1) { currPos = numElems; numElems++; elementOffsets[currPos] = elementOffsets[currPos-1] + elements[currPos-1]->getSize(); } else { RMDBGONCE(0, RMDebug::module_catalogif,"StructType", "addType() ERROR!"); // for debugging purposes only, shouldn't happen. } } } } } // actually insert type and name of element elements[currPos] = newType; elementNames[currPos] = myElemName; // calculate current size calcSize(); return numElems; } unsigned int StructType::getOffset(const char* elemName) const { RMDBGENTER(6, RMDebug::module_catalogif, "StructType", "getOffset(" << elemName << ") " << getName() << " " << myOId); int i; unsigned int retval = 0; bool found = false; for(i=0; i= numElems) { RMDBGONCE(0, RMDebug::module_catalogif, "StructType", "ERROR in StructType::getOffset(" << num << ") offset out of bounds " << getName() << " retval " << 0); RMDBGIF(0, RMDebug::module_catalogif, "StructType", throw r_Error(STRUCTTYPE_ELEMENT_OUT_OF_BOUNDS); ) return 0; } return elementOffsets[num]; } const BaseType* StructType::getElemType(const char* elemName) const { RMDBGENTER(6, RMDebug::module_catalogif, "StructType", "getElemType(" << elemName << ") " << getName() << " " << myOId); const BaseType* retval = 0; int i; for(i=0; igetType() == STRUCT) if(((StructType*)elements[i])->contains(aStruct)) return 1; } return 0; } int StructType::compatibleWith(const Type* aType) const { RMDBGENTER(7, RMDebug::module_catalogif, "StructType", "compatibleWith(" << aType->getName() << ") " << getName()); int retval; if(aType->getType() != STRUCT) { RMDBGMIDDLE(8, RMDebug::module_catalogif, "StructType", "no structtype"); retval = 0; } else { if(elements.size() != ((StructType*)aType)->elements.size()) { RMDBGMIDDLE(8, RMDebug::module_catalogif, "StructType", "not the same size"); retval = 0; } else { const BaseType* myBaseType; const BaseType* otherBaseType; int i; retval = 1; for( i = 0; i < elements.size(); i++ ) { myBaseType = elements[i]; otherBaseType = ((StructType*)aType)->elements[i]; if(!myBaseType->compatibleWith(otherBaseType)) { RMDBGMIDDLE(8, RMDebug::module_catalogif, "StructType", i << ". element " << otherBaseType->getName() << " does not match " << myBaseType); retval = 0; break; } } } } RMDBGEXIT(7, RMDebug::module_catalogif, "StructType", "compatibleWith(" << aType->getName() << ") " << getName() << " retval " << retval); return retval; } void StructType::calcSize() { int alignSize = 1; // check for alignment of size for(int i=0; igetSize() == 4 || elements[i]->getType() == STRUCT ) { alignSize = 4; break; } else { if( elements[i]->getSize() == 2 ) { alignSize = 2; } } } // align size to alignSize bytes (there may be unused bytes at the end!) size = ((elementOffsets[numElems-1]+elements[numElems-1]->getSize()-1)/alignSize+1)*alignSize; }