/ATF2/control-software/epics-3.14.8/base/src/gdd/gdd.cc
C++ | 1829 lines | 1425 code | 177 blank | 227 comment | 294 complexity | b9eff8b9589e25f0a4363df43487c3f6 MD5 | raw file
Possible License(s): BSD-2-Clause, LGPL-2.0, IPL-1.0, BSD-3-Clause
- /*************************************************************************\
- * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
- * National Laboratory.
- * Copyright (c) 2002 The Regents of the University of California, as
- * Operator of Los Alamos National Laboratory.
- * EPICS BASE Versions 3.13.7
- * and higher are distributed subject to a Software License Agreement found
- * in file LICENSE that is included with this distribution.
- \*************************************************************************/
- // Author: Jim Kowalkowski
- // Date: 2/96
- //
- // gdd.cc,v 1.44.2.6 2009/03/20 06:19:47 anj Exp
- //
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdarg.h>
- #include <string>
- #include <stdexcept>
- #define epicsExportSharedSymbols
- #include "gdd.h"
- gdd_NEWDEL_NEW(gdd)
- gdd_NEWDEL_DEL(gdd)
- gdd_NEWDEL_STAT(gdd)
- epicsMutex * gdd::pGlobalMutex;
- static epicsThreadOnceId gddOnce = EPICS_THREAD_ONCE_INIT;
- class gddFlattenDestructor : public gddDestructor
- {
- public:
- gddFlattenDestructor(void) { }
- gddFlattenDestructor(void* user_arg):gddDestructor(user_arg) { }
- void run(void*);
- };
- class gddContainerCleaner : public gddDestructor
- {
- public:
- gddContainerCleaner(void) { }
- gddContainerCleaner(void* user_arg):gddDestructor(user_arg) { }
- void run(void*);
- };
- void gddFlattenDestructor::run(void*)
- {
- return;
- }
- void gddContainerCleaner::run(void* v)
- {
- gddContainer* cdd = (gddContainer*)v;
- int tot = cdd->total();
- int i;
- for(i=0;i<tot;i++) cdd->remove(0);
- }
- //
- // special gddDestructor guarantees same form of new and delete
- //
- class gddAitUint8Destructor: public gddDestructor {
- virtual void run (void *);
- };
- //
- // special gddDestructor guarantees same form of new and delete
- //
- class gddAitStringDestructor: public gddDestructor {
- virtual void run (void *);
- };
- // --------------------------The gdd functions-------------------------
- extern "C" void gddStaticInit ( void * p )
- {
- epicsMutex * * pMutex = static_cast < epicsMutex * * > ( p );
- *pMutex = new epicsMutex ();
- }
- gdd::gdd(int app, aitEnum prim, int dimen)
- {
- init(app,prim,dimen);
- }
- gdd::gdd(int app, aitEnum prim, int dimen, aitUint32* val)
- {
- init(app,prim,dimen);
- for(int i=0;i<dimen;i++) bounds[i].set(0,val[i]);
- }
- void gdd::init(int app, aitEnum prim, int dimen)
- {
- epicsThreadOnce ( & gddOnce, gddStaticInit, & gdd::pGlobalMutex );
- setApplType(app);
- //
- // joh - we intentionally dont call setPrimType()
- // here because the assumption is that init() is only
- // called from the constructor, and we dont want
- // to destroy a non-existent string if the uninitialized
- // prim type is a string
- //
- this->prim_type = prim;
- dim=(aitUint8)dimen;
- destruct=NULL;
- ref_cnt=1;
- flags=0;
- bounds=NULL;
- setStatSevr(0u,0u);
- if(dim)
- {
- switch(dim)
- {
- case 1: bounds=(gddBounds*)new gddBounds1D; bounds->set(0,0); break;
- case 2: bounds=(gddBounds*)new gddBounds2D; break;
- case 3: bounds=(gddBounds*)new gddBounds3D; break;
- default: bounds=(gddBounds*)new gddBounds[dim]; break;
- }
- memset ( & this->data, '\0', sizeof ( this->data ) );
- }
- else if(primitiveType()==aitEnumString)
- {
- aitString* str=(aitString*)dataAddress();
- str->init();
- }
- else if (primitiveType()==aitEnumFixedString)
- {
- this->data.FString = new aitFixedString;
- memset ( this->data.FString, '\0', sizeof(aitFixedString) );
- }
- else {
- memset ( & this->data, '\0', sizeof ( this->data ) );
- }
- }
- gdd::gdd(gdd* dd)
- {
- //
- // added this because the "copy()" below bombs
- // if the GDD isnt initialized
- // joh - 4-23-99
- //
- this->init (dd->appl_type, dd->primitiveType(), dd->dimension());
- copyInfo(dd);
- }
- gdd::~gdd(void)
- {
- gdd* dd;
- gdd* temp;
- // fprintf(stderr,"A gdd is really being deleted %8.8x!!\n",this);
- if(isContainer())
- {
- if(destruct)
- destruct->destroy(dataPointer());
- else
- {
- for(dd=(gdd*)dataPointer();dd;)
- {
- temp=dd;
- dd=dd->next();
- temp->unreference();
- }
- freeBounds();
- }
- }
- else if(isAtomic())
- {
- if(destruct) destruct->destroy(dataPointer());
- if(bounds) freeBounds();
- }
- else
- {
- //
- // this destroys any scalar string data that may be present
- //
- this->setPrimType (aitEnumInvalid);
- }
- this->setApplType (0);
- memset ( & this->data, '\0', sizeof ( this->data ) );
- }
- // this routine is private so we dont need to initialize
- // string data when changing to a scalar, but we do need
- // to be careful about how it is called
- void gdd::freeBounds(void)
- {
- if(bounds)
- {
- switch(dim)
- {
- case 0:
- fprintf ( stderr, "gdd: freeing bounds, bounds exist, but gdd is scalar?\n" );
- break;
- case 1: { gddBounds1D* d1=(gddBounds1D*)bounds; delete d1; } break;
- case 2: { gddBounds2D* d2=(gddBounds2D*)bounds; delete d2; } break;
- case 3: { gddBounds3D* d3=(gddBounds3D*)bounds; delete d3; } break;
- default: delete [] bounds; break;
- }
- bounds=NULL;
- }
- dim=0;
- }
- void gdd::setDimension(int d, const gddBounds* bnds)
- {
- if ( dim != 0 ) {
- if ( isFlat() || isManaged() ) {
- throw std::logic_error (
- "sorry: cant change the bounds on an atomic, managed or flat gdd" );
- }
- }
- if(dim!=d)
- {
- if ( dim == 0 ) {
- // run destructors for scalar string data
- if ( primitiveType() == aitEnumFixedString )
- {
- // aitString type could have destructors
- if ( destruct ) {
- destruct->destroy(dataPointer());
- destruct = 0;
- }
- else
- if (data.FString) delete data.FString;
- }
- else if ( primitiveType() == aitEnumString )
- {
- // aitString type could have destructors
- if ( destruct ) {
- destruct->destroy(dataAddress());
- destruct = 0;
- }
- else
- {
- aitString* s = (aitString*)dataAddress();
- s->clear();
- }
- }
- // changing from scalar to vector so set the
- // vector pointer to nill
- memset ( & this->data, '\0', sizeof ( this->data ) );
- }
- else {
- this->freeBounds();
- }
- dim=(aitUint8)d;
- switch(dim)
- {
- case 0: bounds=0; break;
- case 1: bounds=(gddBounds*)new gddBounds1D; bounds->set(0,0); break;
- case 2: bounds=(gddBounds*)new gddBounds2D; break;
- case 3: bounds=(gddBounds*)new gddBounds3D; break;
- default: bounds=(gddBounds*)new gddBounds[dim]; break;
- }
- if ( dim == 0 ) {
- if ( destruct ) {
- destruct->destroy(dataAddress());
- destruct = 0;
- }
- // run constructers for scalar string data types
- if ( primitiveType() == aitEnumString ) {
- aitString* str=(aitString*)dataAddress();
- str->init();
- }
- else if ( primitiveType() ==aitEnumFixedString ) {
- this->data.FString = new aitFixedString;
- memset (this->data.FString, '\0', sizeof(aitFixedString));
- }
- else {
- memset ( & this->data, '\0', sizeof ( this->data ) );
- }
- }
- }
- if ( bnds )
- {
- for(int i=0;i<dim;i++)
- bounds[i]=bnds[i];
- }
- }
- gddStatus gdd::registerDestructor(gddDestructor* dest)
- {
- // this is funky, will not register a destructor if one is present
- if(destruct)
- {
- gddAutoPrint("gdd::registerDestructor()",gddErrorAlreadyDefined);
- return gddErrorAlreadyDefined;
- }
- else
- return replaceDestructor(dest);
- }
- gddStatus gdd::replaceDestructor(gddDestructor* dest)
- {
- destruct=dest;
- destruct->reference();
- if(isContainer()||isFlat())
- markManaged();
- return 0;
- }
- gddStatus gdd::genCopy(aitEnum t, const void* d, aitDataFormat f)
- {
- gddStatus rc=0;
- if(isScalar())
- set(t,d,f);
- else if(isAtomic())
- {
- if(!dataPointer())
- {
- if ( primitiveType()==aitEnumString ) {
- size_t nElem = describedDataSizeElements ();
- aitString * pStrVec = new aitString [ nElem ];
- if ( ! pStrVec ) {
- gddAutoPrint("gdd::genCopy()",gddErrorNewFailed);
- rc = gddErrorNewFailed;
- }
- else {
- destruct = new gddAitStringDestructor;
- if ( destruct ) {
- destruct->reference();
- setData ( pStrVec );
- }
- else {
- delete [] pStrVec;
- gddAutoPrint("gdd::genCopy()",gddErrorNewFailed);
- rc = gddErrorNewFailed;
- }
- }
- }
- else {
- size_t sz=describedDataSizeBytes();
- aitUint8 * buf = new aitUint8[sz];
- if ( buf == NULL ) {
- gddAutoPrint("gdd::genCopy()",gddErrorNewFailed);
- rc=gddErrorNewFailed;
- }
- else
- {
- destruct=new gddAitUint8Destructor;
- if (destruct==NULL) {
- gddAutoPrint("gdd::genCopy()",gddErrorNewFailed);
- rc=gddErrorNewFailed;
- delete [] buf;
- }
- else {
- setData(buf);
- destruct->reference();
- }
- }
- }
- }
- if(rc==0)
- {
- if(f==aitLocalDataFormat)
- aitConvert(primitiveType(),dataPointer(),t,d,
- getDataSizeElements());
- else
- aitConvertFromNet(primitiveType(),dataPointer(),t,d,
- getDataSizeElements());
- markLocalDataFormat();
- }
- }
- else
- {
- gddAutoPrint("gdd::genCopy()",gddErrorTypeMismatch);
- rc=gddErrorTypeMismatch;
- }
- return rc;
- }
- gddStatus gdd::changeType(int app,aitEnum prim)
- {
- gddStatus rc=0;
- // this should only be allowed for setting the type if it is
- // undefined or if the data is a scalar
- if(isScalar() || primitiveType()==aitEnumInvalid)
- {
- setApplType(app);
- setPrimType(prim);
- }
- else
- {
- gddAutoPrint("gdd::changeType()",gddErrorTypeMismatch);
- rc=gddErrorTypeMismatch;
- }
- return rc;
- }
- gddStatus gdd::setBound(unsigned index_dim, aitIndex first, aitIndex count)
- {
- gddStatus rc=0;
- if(index_dim<dimension())
- bounds[index_dim].set(first,count);
- else
- {
- gddAutoPrint("gdd::setBound()",gddErrorOutOfBounds);
- rc=gddErrorOutOfBounds;
- }
- return rc;
- }
- gddStatus gdd::getBound(unsigned index_dim, aitIndex& first, aitIndex& count) const
- {
- gddStatus rc=0;
- if(index_dim<dimension())
- bounds[index_dim].get(first,count);
- else
- {
- gddAutoPrint("gdd::getBound()",gddErrorOutOfBounds);
- rc=gddErrorOutOfBounds;
- }
- return rc;
- }
- // should the copy functions in gdd use the flatten technique?
- gddStatus gdd::copyStuff(const gdd* dd,int ctype)
- {
- gddStatus rc=0;
- gddContainer* cdd;
- gdd *pdd,*ndd;
- // blow me out quickly here
- if(isFlat()||isManaged())
- {
- gddAutoPrint("gdd::copyStuff()",gddErrorNotAllowed);
- return gddErrorNotAllowed;
- }
- clear();
- setApplType(dd->appl_type);
- setPrimType(aitEnumContainer);
- setStatSevr(dd->getStat(),dd->getSevr());
- if(dd->isContainer())
- {
- cdd=(gddContainer*)dd;
- gddCursor cur=cdd->getCursor();
- for(ndd=cur.first();ndd;ndd=cur.next())
- {
- pdd=new gdd(ndd->applicationType(),
- ndd->primitiveType(),ndd->dimension());
- pdd->setNext((gdd*)dataPointer());
- setData(pdd);
- bounds->setSize(bounds->size()+1);
- pdd->copyStuff(ndd,ctype);
- }
- }
- else if(dd->isScalar()) {
- if (dd->primitiveType()==aitEnumString) {
- aitString* pStrDest =(aitString*)&data;
- aitString* pStrSrc =(aitString*)&dd->data;
- *pStrDest = *pStrSrc;
- }
- else if (dd->primitiveType()==aitEnumFixedString) {
- aitFixedString* pStrDest =(aitFixedString*)data.Pointer;
- aitFixedString* pStrSrc =(aitFixedString*)dd->data.Pointer;
- memcpy (pStrDest, pStrSrc, sizeof(aitFixedString));
- }
- else {
- data=dd->data;
- }
- }
- else // atomic
- {
- const gddBounds* bnds = dd->getBounds();
- for(unsigned i=0;i<dd->dimension();i++) bounds[i]=bnds[i];
- switch(ctype)
- {
- case 1: // copy()
- if ( primitiveType()==aitEnumString ) {
- size_t nElem = dd->describedDataSizeElements ();
- aitString * pStrVec = new aitString [ nElem ];
- if ( ! pStrVec ) {
- gddAutoPrint("gdd::copyStuff()",gddErrorNewFailed);
- rc=gddErrorNewFailed;
- }
- else {
- destruct = new gddAitStringDestructor;
- if ( destruct ) {
- const aitString * pSrc =
- static_cast <const aitString *> ( dd->dataPointer() );
- for ( unsigned j=0; j < nElem; j++ ) {
- pStrVec[j] = pSrc[j];
- }
- destruct->reference();
- setData ( pStrVec );
- }
- else {
- delete [] pStrVec;
- gddAutoPrint("gdd::copyStuff()",gddErrorNewFailed);
- rc=gddErrorNewFailed;
- }
- }
- }
- else {
- size_t a_size = dd->getDataSizeBytes();
- aitUint8* array = new aitUint8[a_size];
- if ( array ) {
- destruct=new gddAitUint8Destructor;
- if (destruct!=NULL) {
- destruct->reference();
- memcpy(array,dd->dataPointer(),a_size);
- setData(array);
- }
- else {
- delete [] array;
- gddAutoPrint("gdd::copyStuff()",gddErrorNewFailed);
- rc=gddErrorNewFailed;
- }
- }
- else
- {
- gddAutoPrint("gdd::copyStuff()",gddErrorNewFailed);
- rc=gddErrorNewFailed;
- }
- }
- break;
- case 2: // Dup()
- data=dd->getData(); // copy the data reference
- destruct=dd->destruct;
- if(destruct) destruct->reference();
- break;
- case 0: // copyInfo()
- default: break;
- }
- }
- return rc;
- }
- size_t gdd::getDataSizeBytes(void) const
- {
- size_t sz=0;
- const gdd* pdd;
- aitString* str;
- if(isContainer())
- {
- const gddContainer* cdd=(const gddContainer*)this;
- constGddCursor cur=cdd->getCursor();
- for(pdd=cur.first();pdd;pdd=cur.next())
- sz+=pdd->getTotalSizeBytes();
- }
- else
- {
- if(aitValid(primitiveType()))
- {
- if(primitiveType()==aitEnumString)
- {
- if(dimension()) str=(aitString*)dataPointer();
- else str=(aitString*)dataAddress();
- sz+=(size_t)(aitString::totalLength(str,
- getDataSizeElements()));
- }
- else
- sz+=(size_t)(getDataSizeElements())*aitSize[primitiveType()];
- }
- }
- return sz;
- }
- size_t gdd::describedDataSizeBytes(void) const
- {
- size_t sz=0;
- // does not work well for aitString - only reports the aitString info
- if(!isContainer())
- sz+=(size_t)(describedDataSizeElements())*aitSize[primitiveType()];
- return sz;
- }
- size_t gdd::getTotalSizeBytes(void) const
- {
- size_t sz;
- unsigned long tsize;
- const gdd* pdd;
- // add up size of bounds + size of this DD
- sz=sizeof(gdd)+(sizeof(gddBounds)*dimension());
- // special case the aitString/aitFixedString here - sucks bad
- if(isScalar())
- {
- if(primitiveType()==aitEnumString)
- {
- aitString* str=(aitString*)dataAddress();
- sz+=str->length()+1; // include the NULL
- }
- else if(primitiveType()==aitEnumFixedString)
- sz+=sizeof(aitFixedString);
- }
- else if(isAtomic())
- {
- if(aitValid(primitiveType()))
- {
- if(primitiveType()==aitEnumString)
- {
- // special case the aitString here
- tsize=(size_t)(aitString::totalLength((aitString*)dataPointer(),
- getDataSizeElements()));
- }
- else
- tsize=(size_t)(getDataSizeElements())*aitSize[primitiveType()];
- sz+=(size_t)align8(tsize); // include alignment
- }
- }
- else if(isContainer())
- {
- const gddContainer* cdd=(const gddContainer*)this;
- constGddCursor cur=cdd->getCursor();
- for(pdd=cur.first();pdd;pdd=cur.next())
- sz+=pdd->getTotalSizeBytes();
- }
- return sz;
- }
- aitUint32 gdd::getDataSizeElements(void) const
- {
- unsigned long total=1u;
- unsigned i;
- if(dimension()>0u && dataPointer())
- {
- for(i=0u;i<dimension();i++)
- total*=bounds[i].size();
- }
- return total;
- }
- aitUint32 gdd::describedDataSizeElements(void) const
- {
- unsigned long total=0;
- unsigned i;
- if(dimension()==0)
- total=1;
- else
- for(i=0;i<dimension();i++) total+=bounds[i].size();
- return total;
- }
- size_t gdd::flattenWithOffsets(void* buf, size_t size, aitIndex* total_dd)
- {
- gdd* flat_dd;
- size_t sz;
-
- sz = flattenWithAddress(buf,size,total_dd);
- flat_dd=(gdd*)buf;
- if(sz>0) flat_dd->convertAddressToOffsets();
- return sz;
- }
- // IMPORTANT NOTE:
- // Currently the user cannot register an empty container as a prototype.
- // The destructor will not be installed to clean up the container when
- // it is freed.
- // This is an important function
- // Data should be flattened as follows:
- // 1) all the GDDs, seen as an array an GDDs
- // 2) all the bounds info for all the GDDs
- // 3) all the data for all GDDs
- //
- // In addition, the user should be able to flatten GDDs without the data
- // and flatten portions or all the data without flattening GDDs
- size_t gdd::flattenWithAddress(void* buf, size_t size, aitIndex* total_dd)
- {
- gdd* pdd = (gdd*)buf;
- size_t pos,sz,spos;
- aitUint32 i;
- gddBounds* bnds;
- // copy this gdd (first one) to get things started
- // this is done in two passes - one to copy DDs, one for bounds/data
- // need to be able to check if the DD has been flattened already
- if((sz=getTotalSizeBytes())>size) return 0;
- pdd[0]=*this;
- pdd[0].destruct=NULL;
- pdd[0].flags=0;
- pos=1;
- // not enough to just copy the gdd info if the primitive type is
- // aitString or aitFixedString (even if scalar gdd)
- // must special case the strings - that really sucks
- if(isScalar())
- {
- // here is special case for the string types
- if(primitiveType()==aitEnumFixedString)
- {
- if(data.FString)
- memcpy((char*)&pdd[pos],data.FString,sizeof(aitFixedString));
- pdd[0].data.FString=(aitFixedString*)&pdd[pos];
- }
- else if(primitiveType()==aitEnumString)
- {
- aitString* str=(aitString*)pdd[0].dataAddress();
- if(str->string())
- {
- memcpy((char*)&pdd[pos],str->string(),str->length()+1);
- str->installBuf((char*)&pdd[pos],str->length(),str->length()+1);
- }
- else
- str->init();
- }
- }
- else if(isContainer())
- {
- // need to check for bounds in the container and flatten them
- if(dataPointer())
- {
- // process all the container's DDs
- spos=pos;
- pos+=flattenDDs((gddContainer*)this,&pdd[pos],
- size-(pos*sizeof(gdd)));
- // copy all the data from the entire container into the buffer
- flattenData(&pdd[0],pos,&pdd[pos],size-(pos*sizeof(gdd)));
- pdd[0].markFlat();
- pdd[0].setData(&pdd[spos]);
- }
- else
- sz=0; // failure should occur - cannot flatten an empty container
- }
- else if(isAtomic())
- {
- // Just copy the data from this DD into the buffer, copy bounds
- if(bounds)
- {
- pdd[0].markFlat();
- bnds=(gddBounds*)(&pdd[pos]);
- for(i=0;i<dimension();i++) bnds[i]=bounds[i];
- pdd[0].bounds=bnds;
- if(dataPointer())
- {
- if(primitiveType()==aitEnumString)
- {
- // not very good way to do it, size info bad
- aitString* str = (aitString*)dataPointer();
- aitString::compact(str,getDataSizeElements(),&bnds[i],size);
- }
- else
- memcpy(&bnds[i],dataPointer(),getDataSizeBytes());
- pdd[0].setData(&bnds[i]);
- }
- else
- sz=0; // should return a failure
- }
- else
- sz=0; // should return failure
- }
- if(total_dd) *total_dd=pos;
- return sz;
- }
- gddStatus gdd::flattenData(gdd* dd, int tot_dds, void* buf,size_t size)
- {
- int i;
- unsigned j;
- size_t sz;
- gddBounds* bnds;
- aitUint8* ptr = (aitUint8*)buf;
- // This functions needs to be divided into two sections
- // 1) copy ALL the bounds out
- // 2) copy ALL the data out
- for(i=0;i<tot_dds;i++)
- {
- if(dd[i].isContainer())
- {
- // don't mark flat if container - 1D bounds must be present
- if(dd[i].bounds)
- {
- bnds=(gddBounds*)(ptr);
- for(j=0;j<dd[i].dimension();j++) bnds[j]=dd[i].bounds[j];
- dd[i].bounds=bnds;
- ptr+=j*sizeof(gddBounds);
- }
- else
- {
- // this is an error condition!
- dd[i].bounds=NULL;
- }
- }
- else if(dd[i].isAtomic())
- {
- if(dd[i].bounds)
- {
- // copy the bounds
- // need to mark flat if bounds are present in an atomic type
- dd[i].markFlat();
- bnds=(gddBounds*)(ptr);
- for(j=0;j<dd[i].dimension();j++) bnds[j]=dd[i].bounds[j];
- dd[i].bounds=bnds;
- ptr+=j*sizeof(gddBounds);
- // copy the data
- if(dd[i].dataPointer())
- {
- if(dd[i].primitiveType()==aitEnumString)
- {
- // not very good way to do it, size info bad
- aitString* str = (aitString*)dd[i].dataPointer();
- sz=aitString::compact(str,
- dd[i].getDataSizeElements(),ptr,size);
- }
- else
- {
- // need to copy data here, align to size of double
- sz=dd[i].getDataSizeBytes();
- memcpy(ptr,dd[i].dataPointer(),sz);
- }
- dd[i].setData(ptr);
- ptr+=align8(sz); // do alignment
- }
- }
- else
- {
- // bounds not required
- dd[i].bounds=NULL;
- }
- }
- else if(dd[i].isScalar())
- {
- // here is special case for String types
- if(dd[i].primitiveType()==aitEnumString)
- {
- aitString* str=(aitString*)dd[i].dataAddress();
- if(str->string())
- {
- memcpy(ptr,str->string(),str->length()+1);
- str->installBuf((char *)ptr, str->length(), str->length()+1);
- ptr+=str->length()+1;
- }
- else
- str->init();
- }
- else if(dd[i].primitiveType()==aitEnumFixedString)
- {
- if(dd[i].data.FString)
- memcpy(ptr,dd[i].data.FString,sizeof(aitFixedString));
- dd[i].data.FString=(aitFixedString*)ptr;
- ptr+=sizeof(aitFixedString);
- }
- }
- }
- return 0;
- }
- int gdd::flattenDDs(gddContainer* dd, void* buf, size_t size)
- {
- gdd* ptr=(gdd*)buf;
- int i,tot,pos,spos;
- gdd *pdd;
- gddCursor cur;
- cur=dd->getCursor();
- // make first pass to copy all the container's DDs into the buffer
- for(tot=0,pdd=cur.first();pdd;pdd=pdd->next(),tot++)
- {
- ptr[tot]=*pdd;
- ptr[tot].destruct=NULL;
- ptr[tot].setNext(&ptr[tot+1]);
- ptr[tot].noReferencing();
- }
- ptr[tot-1].setNext(NULL);
- // make second pass to copy all child containers into buffer
- for(pos=tot,i=0;i<tot;i++)
- {
- if(ptr[i].isContainer())
- {
- if(ptr[i].dataPointer())
- {
- spos=pos;
- pos+=flattenDDs((gddContainer*)&ptr[i],&ptr[pos],
- size-(pos*sizeof(gdd)));
- ptr[i].markFlat();
- ptr[i].setData(&ptr[spos]);
- }
- else
- {
- ptr[i].setData(NULL);
- ptr[i].destruct=new gddContainerCleaner(&ptr[i]);
- ptr[i].destruct->reference();
- }
- }
- }
- return pos;
- }
- gddStatus gdd::convertOffsetsToAddress(void)
- {
- aitUint8* pdd = (aitUint8*)this;
- unsigned long bnds = (unsigned long)(bounds);
- unsigned long dp = (unsigned long)(dataPointer());
- gdd* tdd;
- gddContainer* cdd;
- gddCursor cur;
- aitString* str;
- aitIndex i;
- const char* cstr;
- if(isContainer())
- {
- // change bounds and data first
- bounds=(gddBounds*)(pdd+bnds);
- setData(pdd+dp);
- cdd=(gddContainer*)this;
- cur=cdd->getCursor();
- for(tdd=cur.first();tdd;tdd=cur.next())
- {
- if(tdd->next()) tdd->setNext((gdd*)(pdd+(unsigned long)tdd->next()));
- tdd->convertOffsetsToAddress();
- }
- }
- else
- {
- if(isAtomic())
- {
- bounds=(gddBounds*)(pdd+bnds);
- setData(pdd+dp);
- if(primitiveType()==aitEnumString)
- {
- // force all the strings in the array to offsets
- str=(aitString*)dataPointer();
- for(i=0;i<getDataSizeElements();i++)
- {
- if(str[i].string())
- {
- cstr=str[i].string();
- str[i].installBuf((char *)(pdd+(unsigned long)cstr),
- str[i].length(), str[i].length()+1);
- }
- else
- str[i].init();
- }
- }
- }
- else if(isScalar())
- {
- if(primitiveType()==aitEnumFixedString)
- {
- if(data.FString) setData(pdd+dp);
- }
- else if(primitiveType()==aitEnumString)
- {
- str=(aitString*)dataAddress();
- if(str->string())
- {
- cstr=str->string();
- str->installBuf((char *)(pdd+(unsigned long)cstr),
- str->length(), str->length()+1u);
- }
- else
- str->init();
- }
- }
- }
- return 0;
- }
- gddStatus gdd::convertAddressToOffsets(void)
- {
- aitUint8* pdd = (aitUint8*)this;
- aitUint8* bnds = (aitUint8*)(bounds);
- aitUint8* dp = (aitUint8*)(dataPointer());
- gddContainer* tdd;
- gddCursor cur;
- gdd *cdd,*ddd;
- aitString* str;
- aitIndex i;
- const char* cstr;
- // does not ensure that all the members of a container are flat!
- if(!isFlat())
- {
- gddAutoPrint("gdd::convertAddressToOffsets()",gddErrorNotAllowed);
- return gddErrorNotAllowed;
- }
- if(isContainer())
- {
- tdd=(gddContainer*)this;
- cur=tdd->getCursor();
- for(cdd=cur.first();cdd;)
- {
- ddd=cdd;
- cdd=cur.next();
- ddd->convertAddressToOffsets();
- if(cdd) ddd->setNext((gdd*)((aitUint8*)(ddd->next())-pdd));
- }
- // bounds and data of container to offsets
- setData((gdd*)(dp-pdd));
- bounds=(gddBounds*)(bnds-pdd);
- }
- else
- {
- if(isAtomic())
- {
- if(primitiveType()==aitEnumString)
- {
- // force all the strings in the array to offsets
- str=(aitString*)dataPointer();
- for(i=0;i<getDataSizeElements();i++)
- {
- cstr=str[i].string();
- if(cstr) str[i].installBuf((char *)(cstr-(const char*)pdd),
- str[i].length(), str[i].length()+1u);
- else str[i].init();
- }
- }
- // bounds and data of atomic to offsets
- setData((gdd*)(dp-pdd));
- bounds=(gddBounds*)(bnds-pdd);
- }
- else if(isScalar())
- {
- // handle the special string scalar cases
- if(primitiveType()==aitEnumFixedString)
- {
- if(data.FString) setData((gdd*)(dp-pdd));
- }
- else if(primitiveType()==aitEnumString)
- {
- str=(aitString*)dataAddress();
- cstr=str->string();
- if(cstr) str->installBuf((char *)(cstr-(const char*)pdd),
- str->length(), str->length()+1u);
- else str->init();
- }
- }
- }
- return 0;
- }
- void gdd::destroyData(void)
- {
- if (isScalar())
- {
- // this destroys the string types
- this->setPrimType (aitEnumInvalid);
- memset ( & this->data, '\0', sizeof ( this->data ) );
- }
- else {
- if(destruct)
- {
- if(isContainer())
- destruct->destroy(this);
- else
- destruct->destroy(dataPointer());
- destruct=NULL;
- }
- freeBounds();
- this->prim_type = aitEnumInvalid;
- memset ( & this->data, '\0', sizeof ( this->data ) );
- }
- }
- gddStatus gdd::clearData(void)
- {
- gddStatus rc=0;
-
- if(isContainer()||isManaged()||isFlat())
- {
- gddAutoPrint("gdd::clearData()",gddErrorNotAllowed);
- rc=gddErrorNotAllowed;
- }
- else if ( this->isScalar () ) {
- // clear scaler types
- if ( this->primitiveType() == aitEnumString ) {
- aitString * str=(aitString*)dataAddress();
- str->clear();
- }
- else if ( this->primitiveType() == aitEnumFixedString ) {
- memset ( this->data.FString, '\0', sizeof ( this->data.FString ) );
- }
- else {
- memset ( & this->data, '\0', sizeof ( this->data ) );
- }
- }
- else {
- if(destruct)
- {
- destruct->destroy(dataPointer());
- destruct=NULL;
- }
- setDimension ( 0, 0 );
- }
- return rc;
- }
- gddStatus gdd::clear(void)
- {
- if(isFlat()||isManaged())
- {
- gddAutoPrint("gdd::clear()",gddErrorNotAllowed);
- return gddErrorNotAllowed;
- }
- if(isAtomic())
- {
- destroyData();
- }
- else if(isContainer())
- {
- gddContainer* cdd = (gddContainer*)this;
- gddCursor cur = cdd->getCursor();
- gdd *dd,*tdd;
- for(dd=cur.first();dd;)
- {
- tdd=dd;
- dd=cur.next();
- if(tdd->unreference()<0) delete tdd;
- }
- freeBounds();
- }
- //
- // this code clears out aitString and
- // aitFixedString scalars (the doc says
- // that every field is set to invalid)
- //
- changeType(0,aitEnumInvalid);
- memset ( & this->data, '\0', sizeof ( this->data ) );
- return 0;
- }
- // Curently gives no indication of failure, which is bad.
- // Obviously managed or flattened DDs cannot be redone.
- // However, a DD that is within a managed or flattened container can
- // use this to describe data - how's that for obscure
- // This is required if the "value" is to be allowed within a container
- // The "value" could be scalar or an array of unknown size. The same is
- // true of the enum strings and "units" attribute.
- gddStatus gdd::reset(aitEnum prim, int dimen, aitIndex* cnt)
- {
- int i;
- gddStatus rc;
- if((rc=clear())==0)
- {
- setPrimType(prim);
- setDimension(dimen);
- for(i=0;i<dimen;i++)
- setBound(i,0,cnt[i]);
- }
- return rc;
- }
- void gdd::get(aitString& d) const
- {
- if(primitiveType()==aitEnumString)
- {
- aitString* s=(aitString*)dataAddress();
- d=*s;
- }
- else
- get(aitEnumString,&d);
- }
- void gdd::get(aitFixedString& d) const
- {
- if(primitiveType()==aitEnumFixedString){
- strncpy(d.fixed_string,data.FString->fixed_string,
- sizeof(d));
- d.fixed_string[sizeof(d)-1u] = '\0';
- }
- else
- get(aitEnumFixedString,&d);
- }
- void gdd::getConvert(aitString& d) const
- {
- get(aitEnumString,&d);
- }
- void gdd::getConvert(aitFixedString& d) const
- {
- get(aitEnumFixedString,d.fixed_string);
- }
- gddStatus gdd::put(const aitString& d)
- {
- gddStatus rc=0;
- if(isScalar())
- {
- //
- // destroy existing fixed string if it exists
- // and construct new aitString object
- //
- setPrimType(aitEnumString);
- aitString* s=(aitString*)dataAddress();
- *s=d;
- }
- else
- {
- gddAutoPrint("gdd::put(aitString&)",gddErrorNotAllowed);
- rc=gddErrorNotAllowed;
- }
- return rc;
- }
- gddStatus gdd::put(const aitFixedString& d)
- {
- gddStatus rc=0;
- if(isScalar())
- {
- this->setPrimType(aitEnumFixedString);
- if (data.FString!=NULL)
- memcpy (data.FString->fixed_string, d.fixed_string, sizeof(d.fixed_string));
- }
- else
- {
- gddAutoPrint("gdd::put(aitString&)",gddErrorNotAllowed);
- rc=gddErrorNotAllowed;
- }
- return rc;
- }
- void gdd::putConvert(const aitString& d)
- {
- set(aitEnumString,&d);
- }
- void gdd::putConvert(const aitFixedString& d)
- {
- set(aitEnumFixedString,(void*)d.fixed_string);
- }
- // copy each of the strings into this DDs storage area
- gddStatus gdd::put(const aitString* const d)
- {
- return genCopy(aitEnumString,d);
- }
- // copy each of the strings into this DDs storage area
- gddStatus gdd::put(const aitFixedString* const d)
- {
- gddStatus rc=0;
- if(isAtomic())
- if(dataPointer())
- aitConvert(primitiveType(),dataPointer(),aitEnumFixedString,d,
- getDataSizeElements());
- else
- genCopy(aitEnumFixedString,d);
- else
- {
- gddAutoPrint("gdd::put(const aitFixedString*const)",gddErrorNotAllowed);
- rc=gddErrorTypeMismatch;
- }
- return rc;
- }
- gddStatus gdd::putRef(const gdd*)
- {
- gddAutoPrint("gdd::putRef(const gdd*) - NOT IMPLEMENTED",
- gddErrorNotSupported);
- return gddErrorNotSupported;
- }
- gddStatus gdd::put ( const gdd * dd )
- {
- if ( this->isScalar() && dd->isScalar() )
- {
- // this is the simple case - just make this scalar look like the other
- this->set(dd->primitiveType(),dd->dataVoid());
- }
- else if ( isContainer() || dd->isContainer() )
- {
- gddAutoPrint("gdd::put(const gdd*)",gddErrorNotSupported);
- return gddErrorNotSupported;
- }
- else if ( this->dimension() > 1 || dd->dimension() > 1 )
- {
- // sorry, no support currently for multidimensional arrays
- return gddErrorOutOfBounds;
- }
- else if ( this->isScalar() ) // dd must be atomic if this is true
- {
- this->set ( dd->primitiveType(), dd->dataPointer() );
- }
- // at this point this GDD must be atomic
- // and the src gdd is either atomic or scalar
- else {
- // this must be single dimensional atomic at this point
- // dd can be scaler or single dimensional atomic at this point
- // so fetch the bounds carefully
- aitUint32 srcFirst;
- aitUint32 srcElemCount;
- if ( dd->isScalar() ) {
- srcFirst = 0;
- srcElemCount = 1;
- }
- else {
- srcFirst = dd->getBounds()->first();
- srcElemCount = dd->getBounds()->size();
- }
- // clip to lower limit of source
- aitUint32 srcCopyFirst;
- if ( this->getBounds()->first () > srcFirst ) {
- srcCopyFirst = this->getBounds()->first();
- }
- else {
- srcCopyFirst = srcFirst;
- }
-
- // clip to upper limit of source
- aitUint32 srcCopySize;
- const aitUint32 unusedSrcBelow = srcCopyFirst - srcFirst;
- if ( srcElemCount <= unusedSrcBelow ) {
- return gddErrorOutOfBounds;
- }
- aitUint32 srcAvailSize = srcElemCount - unusedSrcBelow;
- if ( srcAvailSize > this->getBounds()->size() ) {
- srcCopySize = this->getBounds()->size();
- }
- else {
- srcCopySize = srcAvailSize;
- }
- if ( dataVoid() == NULL )
- {
- if (primitiveType()==aitEnumInvalid) {
- setPrimType (dd->primitiveType());
- }
- if ( primitiveType()==aitEnumString ) {
- aitString * pStrVec = new aitString [ srcCopySize ];
- if( ! pStrVec ) {
- return gddErrorNewFailed;
- }
- destruct = new gddAitStringDestructor;
- if ( destruct ) {
- destruct->reference();
- setData ( pStrVec );
- }
- else {
- delete [] pStrVec;
- gddAutoPrint("gdd::copyData(const gdd*)",gddErrorNewFailed);
- return gddErrorNewFailed;
- }
- }
- else {
- size_t sz = srcCopySize * aitSize[primitiveType()];
-
- // allocate a data buffer for the user
- aitUint8 * arr = new aitUint8[sz];
- if( ! arr ) {
- return gddErrorNewFailed;
- }
- destruct=new gddAitUint8Destructor;
- if (destruct!=NULL) {
- destruct->reference();
- setData(arr);
- }
- else {
- delete [] arr;
- gddAutoPrint("gdd::copyData(const gdd*)",gddErrorNewFailed);
- return gddErrorNewFailed;
- }
- }
- // the rule is that if storage is not preallocated then its ok
- // for the dest bounds to shrink to match the original dest
- // bounds intersection with the source data bounds
- for ( unsigned i = 0; i < this->dimension(); i++ ) {
- if ( i == 0 ) {
- this->setBound ( i, srcCopyFirst, srcCopySize );
- }
- else {
- this->setBound ( i, 0, 1 );
- }
- }
- }
- aitUint8* pDst = (aitUint8*) this->dataPointer();
- assert ( srcCopyFirst >= this->getBounds()->first() );
- const aitUint32 unusedDstLow = srcCopyFirst - this->getBounds()->first();
- if ( unusedDstLow > 0 ) {
- //
- // zero portions that dont match
- // (should eventually throw an exception ?)
- //
- aitUint32 byteCount = aitSize[primitiveType()] * unusedDstLow;
- memset (pDst, '\0', byteCount);
- pDst += byteCount;
- }
-
- aitUint8* pSrc = (aitUint8*) dd->dataVoid();
- pSrc += aitSize[dd->primitiveType()] * unusedSrcBelow;
- int gddStatus = aitConvert (this->primitiveType(), pDst,
- dd->primitiveType(), pSrc, srcCopySize);
- if ( gddStatus < 0 ) {
- return gddErrorTypeMismatch;
- }
-
- assert ( this->getBounds()->size() >= srcCopySize + unusedDstLow );
- const aitUint32 unusedDstHigh = this->getBounds()->size() - ( srcCopySize + unusedDstLow );
- if ( unusedDstHigh > 0 ) {
- pDst += aitSize[primitiveType()] * srcCopySize;
- //
- // zero portions that dont match
- // (should eventually throw an exception ?)
- //
- aitUint32 byteCount = aitSize[primitiveType()] * unusedDstHigh;
- memset (pDst, '\0', byteCount);
- }
- }
-
- setStatSevr(dd->getStat(),dd->getSevr());
- aitTimeStamp ts;
- dd->getTimeStamp(&ts);
- setTimeStamp(&ts);
-
- return 0; // success
- }
- size_t gdd::outHeader(void* buf,aitUint32 bufsize) const
- {
- // simple encoding for now.. will change later
- // this is the SLOW, simple version
- aitUint8* b = (aitUint8*)buf;
- aitUint8* app = (aitUint8*)&appl_type;
- aitUint8* stat = (aitUint8*)&status;
- aitUint8* ts_sec = (aitUint8*)&time_stamp.tv_sec;
- aitUint8* ts_nsec = (aitUint8*)&time_stamp.tv_nsec;
- size_t i,j,sz;
- aitIndex ff,ss;
- aitUint8 *f,*s;
- // verify that header will fit into buffer first
- sz=4+sizeof(status)+sizeof(time_stamp)+sizeof(appl_type)+
- sizeof(prim_type)+sizeof(dim)+(dim*sizeof(gddBounds));
- if(sz>bufsize) return 0; // blow out here!
- *(b++)='H'; *(b++)='E'; *(b++)='A'; *(b++)='D';
- // how's this for putrid
- *(b++)=dim;
- *(b++)=prim_type;
- if(aitLocalNetworkDataFormatSame)
- {
- *(b++)=app[0]; *(b++)=app[1];
- for(i=0;i<sizeof(status);i++) *(b++)=stat[i];
- for(i=0;i<sizeof(time_stamp.tv_sec);i++) *(b++)=ts_sec[i];
- for(i=0;i<sizeof(time_stamp.tv_nsec);i++) *(b++)=ts_nsec[i];
- }
- else
- {
- *(b++)=app[1]; *(b++)=app[0];
- i=sizeof(status)-1u; do { *(b++)=stat[i]; } while(i-->0u);
- i=sizeof(time_stamp.tv_sec)-1u; do { *(b++)=ts_sec[i]; } while(i-->0u);
- i=sizeof(time_stamp.tv_nsec)-1u; do { *(b++)=ts_nsec[i]; } while(i-->0u);
- }
- // put out the bounds info
- for(j=0;j<dim;j++)
- {
- ff=bounds[j].first(); f=(aitUint8*)&ff;
- ss=bounds[j].size(); s=(aitUint8*)&ss;
- if(aitLocalNetworkDataFormatSame)
- {
- for(i=0;i<sizeof(aitIndex);i++) *(b++)=s[i];
- for(i=0;i<sizeof(aitIndex);i++) *(b++)=f[i];
- }
- else
- {
- i=sizeof(aitIndex)-1u; do { *(b++)=s[i]; } while(i-->0u);
- i=sizeof(aitIndex)-1u; do { *(b++)=f[i]; } while(i-->0u);
- }
- }
- return sz;
- }
- size_t gdd::outData(void* buf,aitUint32 bufsize, aitEnum e, aitDataFormat f) const
- {
- // put data into user's buffer in the format that the user wants (e/f).
- // if e is invalid, then use whatever format this gdd describes.
- aitUint32 sz = getDataSizeElements();
- aitUint32 len = getDataSizeBytes();
- aitEnum type=(e==aitEnumInvalid)?primitiveType():e;
- if(len>bufsize) return 0; // blow out early
- if(sz>0)
- {
- if(f==aitLocalDataFormat)
- aitConvert(type,buf,primitiveType(),dataVoid(),sz);
- else
- aitConvertToNet(type,buf,primitiveType(),dataVoid(),sz);
- }
- return len;
- }
- size_t gdd::out(void* buf,aitUint32 bufsize,aitDataFormat f) const
- {
- size_t index = outHeader(buf,bufsize);
- size_t rc;
- if(index>0)
- rc=outData(((char*)buf)+index,bufsize-index,aitEnumInvalid,f)+index;
- else
- rc=0;
- return rc;
- }
- size_t gdd::inHeader(void* buf)
- {
- // simple encoding for now.. will change later
- // this is the SLOW, simple version
- aitUint16 inapp;
- aitUint8 inprim;
- aitUint8 indim;
- aitUint8* b = (aitUint8*)buf;
- aitUint8* b1 = b;
- aitUint8* app = (aitUint8*)&inapp;
- aitUint8* stat = (aitUint8*)&status;
- aitUint8* ts_sec = (aitUint8*)&time_stamp.tv_sec;
- aitUint8* ts_nsec = (aitUint8*)&time_stamp.tv_nsec;
- size_t i,j;
- aitIndex ff,ss;
- aitUint8 *f,*s;
- if(strncmp((char*)b,"HEAD",4)!=0) return 0;
- b+=4;
- indim=*(b++);
- inprim=*(b++);
- if(aitLocalNetworkDataFormatSame)
- {
- app[0]=*(b++); app[1]=*(b++);
- init(inapp,(aitEnum)inprim,indim);
- for(i=0u;i<sizeof(status);i++) stat[i]=*(b++);
- for(i=0u;i<sizeof(time_stamp.tv_sec);i++) ts_sec[i]=*(b++);
- for(i=0u;i<sizeof(time_stamp.tv_nsec);i++) ts_nsec[i]=*(b++);
- }
- else
- {
- app[1]=*(b++); app[0]=*(b++);
- init(inapp,(aitEnum)inprim,indim);
- i=sizeof(status)-1u; do { stat[i]=*(b++); } while(i-->0u);
- i=sizeof(time_stamp.tv_sec)-1u; do { ts_sec[i]=*(b++); } while(i-->0u);
- i=sizeof(time_stamp.tv_nsec)-1u; do { ts_nsec[i]=*(b++); } while(i-->0u);
- }
- // read in the bounds info
- f=(aitUint8*)&ff;
- s=(aitUint8*)&ss;
-
- for(j=0u;j<dim;j++)
- {
- if(aitLocalNetworkDataFormatSame)
- {
- for(i=0;i<sizeof(aitIndex);i++) s[i]=*(b++);
- for(i=0;i<sizeof(aitIndex);i++) f[i]=*(b++);
- }
- else
- {
- i=sizeof(aitIndex)-1u; do { s[i]=*(b++); } while(i-->0u);
- i=sizeof(aitIndex)-1u; do { f[i]=*(b++); } while(i-->0u);
- }
- bounds[j].setFirst(ff);
- bounds[j].setSize(ss);
- }
- return (size_t)(b-b1);
- }
- size_t gdd::inData(void* buf,aitUint32 tot, aitEnum e, aitDataFormat f)
- {
- size_t rc;
- // Get data from a buffer and put it into this gdd. Lots of rules here.
- // 1) tot is the total number of elements to copy from buf to this gdd.
- // * if tot is zero, then use the element count described in the gdd.
- // * if tot is not zero, then set the gdd up as a 1 dimensional array
- // with tot elements in it.
- // 2) e is the primitive data type of the incoming data.
- // * if e is aitEnumInvalid, then use the gdd primitive type.
- // * if e is valid and gdd primitive type is invalid, set the gdd
- // primitive type to e.
- // * if e is valid and so is this gdd primitive type, then convert the
- // incoming data from type e to gdd primitive type.
- // Bad error condition, don't do anything.
- if(e==aitEnumInvalid && primitiveType()==aitEnumInvalid)
- return 0;
- aitIndex sz=tot;
- aitEnum src_type=(e==aitEnumInvalid)?primitiveType():e;
- aitEnum dest_type=(primitiveType()==aitEnumInvalid)?e:primitiveType();
- // I'm not sure if this is the best way to do this.
- if(sz>0)
- reset(dest_type,dimension(),&sz);
- if(genCopy(src_type,buf,f)==0)
- rc=getDataSizeBytes();
- else
- rc=0;
- return rc;
- }
- size_t gdd::in(void* buf, aitDataFormat f)
- {
- size_t index = inHeader(buf);
- size_t rc;
- if(index>0)
- rc=inData(((char*)buf)+index,0,aitEnumInvalid,f)+index;
- else
- rc=0;
- return rc;
- }
- //
- // rewrote this to properly construct/destruct
- // scalar string types when the prim type changes
- // joh 05-22-98
- //
- //
- void gdd::setPrimType (aitEnum t)
- {
- //
- // NOOP if there is no change
- //
- if ( this->prim_type == t ) {
- return;
- }
- //
- // I (joh) assume that something needs to be done when
- // the primative type of a container changes. For now I
- // assuming that the gdd should be cleared.
- //
- if(isContainer()) {
- this->clear();
- }
- //
- // run constructors/destructors for string data
- // if it is scalar
- //
- if (isScalar())
- {
- //
- // run destructors for existing string data
- //
- if(primitiveType()==aitEnumFixedString)
- {
- // aitString type could have destructors
- if ( destruct ) {
- destruct->destroy(dataPointer());
- destruct = 0;
- }
- else
- if (data.FString) delete data.FString;
- }
- else if(primitiveType()==aitEnumString)
- {
- // aitString type could have destructors
- if ( destruct ) {
- destruct->destroy(dataAddress());
- destruct = 0;
- }
- else
- {
- aitString* s = (aitString*)dataAddress();
- s->clear();
- }
- }
- //
- // run constructors for new string data types
- //
- if (t==aitEnumString) {
- aitString* str=(aitString*)dataAddress();
- str->init();
- }
- else if (t==aitEnumFixedString) {
- this->data.FString = new aitFixedString;
- memset ( this->data.FString, '\0', sizeof(aitFixedString) );
- }
- else {
- memset ( & this->data, '\0', sizeof(this->data) );
- }
- }
- //
- // I (joh) assume that Jim intended that
- // calling of the destructors for arrays of string
- // data when the primitive type changes is handled
- // by the application. Not sure - nothing was done
- // by Jim to take care of this as far as I can tell.
- //
- else if(isAtomic())
- {
- if ( dataPointer() && destruct ) {
- destruct->destroy(dataPointer());
- destruct=NULL;
- }
- memset (&this->data, '\0', sizeof(this->data));
- }
- this->prim_type = t;
- }
- //
- // gdd::indexDD()
- //
- // modified by JOH 4-23-99 so that the correct method
- // is used if the container gdd is not organized
- // as an array of GDDs in memory (i.e. its not flat)
- //
- const gdd* gdd::indexDD (aitIndex index) const
- {
- aitIndex i;
- unsigned nElem;
- if (index==0u) {
- return this;
- }
- //
- // otherwise this had better be a container
- // we are indexing
- //
- assert (this->prim_type==aitEnumContainer);
- //
- // catch out of bounds index
- //
- nElem = getDataSizeElements();
- assert (index<=nElem);
- //
- // if the container GDD is "flat"
- //
- if (this->isFlat()) {
- return this + index;
- }
- //
- // otherwise linear search for it
- //
- gdd* dd = (gdd*) dataPointer();
- i = nElem;
- while (i>index) {
- dd=(gdd*)dd->next();
- i--;
- }
- return dd;
- }
- //
- // gddAitUint8Destructor::run()
- //
- // special gddDestructor guarantees same form of new and delete
- //
- void gddAitUint8Destructor::run (void *pUntyped)
- {
- aitUint8 *pui8 = (aitUint8 *) pUntyped;
- delete [] pui8;
- }
- //
- // gddAitStringDestructor::run()
- //
- // special gddDestructor guarantees same form of new and delete
- //
- void gddAitStringDestructor::run (void *pUntyped)
- {
- aitString *pStr = (aitString *) pUntyped;
- delete [] pStr;
- }