PageRenderTime 38ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/ATF2/control-software/epics-3.14.8/base/src/gdd/gdd.cc

http://atf2flightsim.googlecode.com/
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
  1. /*************************************************************************\
  2. * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
  3. * National Laboratory.
  4. * Copyright (c) 2002 The Regents of the University of California, as
  5. * Operator of Los Alamos National Laboratory.
  6. * EPICS BASE Versions 3.13.7
  7. * and higher are distributed subject to a Software License Agreement found
  8. * in file LICENSE that is included with this distribution.
  9. \*************************************************************************/
  10. // Author: Jim Kowalkowski
  11. // Date: 2/96
  12. //
  13. // gdd.cc,v 1.44.2.6 2009/03/20 06:19:47 anj Exp
  14. //
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <stdarg.h>
  18. #include <string>
  19. #include <stdexcept>
  20. #define epicsExportSharedSymbols
  21. #include "gdd.h"
  22. gdd_NEWDEL_NEW(gdd)
  23. gdd_NEWDEL_DEL(gdd)
  24. gdd_NEWDEL_STAT(gdd)
  25. epicsMutex * gdd::pGlobalMutex;
  26. static epicsThreadOnceId gddOnce = EPICS_THREAD_ONCE_INIT;
  27. class gddFlattenDestructor : public gddDestructor
  28. {
  29. public:
  30. gddFlattenDestructor(void) { }
  31. gddFlattenDestructor(void* user_arg):gddDestructor(user_arg) { }
  32. void run(void*);
  33. };
  34. class gddContainerCleaner : public gddDestructor
  35. {
  36. public:
  37. gddContainerCleaner(void) { }
  38. gddContainerCleaner(void* user_arg):gddDestructor(user_arg) { }
  39. void run(void*);
  40. };
  41. void gddFlattenDestructor::run(void*)
  42. {
  43. return;
  44. }
  45. void gddContainerCleaner::run(void* v)
  46. {
  47. gddContainer* cdd = (gddContainer*)v;
  48. int tot = cdd->total();
  49. int i;
  50. for(i=0;i<tot;i++) cdd->remove(0);
  51. }
  52. //
  53. // special gddDestructor guarantees same form of new and delete
  54. //
  55. class gddAitUint8Destructor: public gddDestructor {
  56. virtual void run (void *);
  57. };
  58. //
  59. // special gddDestructor guarantees same form of new and delete
  60. //
  61. class gddAitStringDestructor: public gddDestructor {
  62. virtual void run (void *);
  63. };
  64. // --------------------------The gdd functions-------------------------
  65. extern "C" void gddStaticInit ( void * p )
  66. {
  67. epicsMutex * * pMutex = static_cast < epicsMutex * * > ( p );
  68. *pMutex = new epicsMutex ();
  69. }
  70. gdd::gdd(int app, aitEnum prim, int dimen)
  71. {
  72. init(app,prim,dimen);
  73. }
  74. gdd::gdd(int app, aitEnum prim, int dimen, aitUint32* val)
  75. {
  76. init(app,prim,dimen);
  77. for(int i=0;i<dimen;i++) bounds[i].set(0,val[i]);
  78. }
  79. void gdd::init(int app, aitEnum prim, int dimen)
  80. {
  81. epicsThreadOnce ( & gddOnce, gddStaticInit, & gdd::pGlobalMutex );
  82. setApplType(app);
  83. //
  84. // joh - we intentionally dont call setPrimType()
  85. // here because the assumption is that init() is only
  86. // called from the constructor, and we dont want
  87. // to destroy a non-existent string if the uninitialized
  88. // prim type is a string
  89. //
  90. this->prim_type = prim;
  91. dim=(aitUint8)dimen;
  92. destruct=NULL;
  93. ref_cnt=1;
  94. flags=0;
  95. bounds=NULL;
  96. setStatSevr(0u,0u);
  97. if(dim)
  98. {
  99. switch(dim)
  100. {
  101. case 1: bounds=(gddBounds*)new gddBounds1D; bounds->set(0,0); break;
  102. case 2: bounds=(gddBounds*)new gddBounds2D; break;
  103. case 3: bounds=(gddBounds*)new gddBounds3D; break;
  104. default: bounds=(gddBounds*)new gddBounds[dim]; break;
  105. }
  106. memset ( & this->data, '\0', sizeof ( this->data ) );
  107. }
  108. else if(primitiveType()==aitEnumString)
  109. {
  110. aitString* str=(aitString*)dataAddress();
  111. str->init();
  112. }
  113. else if (primitiveType()==aitEnumFixedString)
  114. {
  115. this->data.FString = new aitFixedString;
  116. memset ( this->data.FString, '\0', sizeof(aitFixedString) );
  117. }
  118. else {
  119. memset ( & this->data, '\0', sizeof ( this->data ) );
  120. }
  121. }
  122. gdd::gdd(gdd* dd)
  123. {
  124. //
  125. // added this because the "copy()" below bombs
  126. // if the GDD isnt initialized
  127. // joh - 4-23-99
  128. //
  129. this->init (dd->appl_type, dd->primitiveType(), dd->dimension());
  130. copyInfo(dd);
  131. }
  132. gdd::~gdd(void)
  133. {
  134. gdd* dd;
  135. gdd* temp;
  136. // fprintf(stderr,"A gdd is really being deleted %8.8x!!\n",this);
  137. if(isContainer())
  138. {
  139. if(destruct)
  140. destruct->destroy(dataPointer());
  141. else
  142. {
  143. for(dd=(gdd*)dataPointer();dd;)
  144. {
  145. temp=dd;
  146. dd=dd->next();
  147. temp->unreference();
  148. }
  149. freeBounds();
  150. }
  151. }
  152. else if(isAtomic())
  153. {
  154. if(destruct) destruct->destroy(dataPointer());
  155. if(bounds) freeBounds();
  156. }
  157. else
  158. {
  159. //
  160. // this destroys any scalar string data that may be present
  161. //
  162. this->setPrimType (aitEnumInvalid);
  163. }
  164. this->setApplType (0);
  165. memset ( & this->data, '\0', sizeof ( this->data ) );
  166. }
  167. // this routine is private so we dont need to initialize
  168. // string data when changing to a scalar, but we do need
  169. // to be careful about how it is called
  170. void gdd::freeBounds(void)
  171. {
  172. if(bounds)
  173. {
  174. switch(dim)
  175. {
  176. case 0:
  177. fprintf ( stderr, "gdd: freeing bounds, bounds exist, but gdd is scalar?\n" );
  178. break;
  179. case 1: { gddBounds1D* d1=(gddBounds1D*)bounds; delete d1; } break;
  180. case 2: { gddBounds2D* d2=(gddBounds2D*)bounds; delete d2; } break;
  181. case 3: { gddBounds3D* d3=(gddBounds3D*)bounds; delete d3; } break;
  182. default: delete [] bounds; break;
  183. }
  184. bounds=NULL;
  185. }
  186. dim=0;
  187. }
  188. void gdd::setDimension(int d, const gddBounds* bnds)
  189. {
  190. if ( dim != 0 ) {
  191. if ( isFlat() || isManaged() ) {
  192. throw std::logic_error (
  193. "sorry: cant change the bounds on an atomic, managed or flat gdd" );
  194. }
  195. }
  196. if(dim!=d)
  197. {
  198. if ( dim == 0 ) {
  199. // run destructors for scalar string data
  200. if ( primitiveType() == aitEnumFixedString )
  201. {
  202. // aitString type could have destructors
  203. if ( destruct ) {
  204. destruct->destroy(dataPointer());
  205. destruct = 0;
  206. }
  207. else
  208. if (data.FString) delete data.FString;
  209. }
  210. else if ( primitiveType() == aitEnumString )
  211. {
  212. // aitString type could have destructors
  213. if ( destruct ) {
  214. destruct->destroy(dataAddress());
  215. destruct = 0;
  216. }
  217. else
  218. {
  219. aitString* s = (aitString*)dataAddress();
  220. s->clear();
  221. }
  222. }
  223. // changing from scalar to vector so set the
  224. // vector pointer to nill
  225. memset ( & this->data, '\0', sizeof ( this->data ) );
  226. }
  227. else {
  228. this->freeBounds();
  229. }
  230. dim=(aitUint8)d;
  231. switch(dim)
  232. {
  233. case 0: bounds=0; break;
  234. case 1: bounds=(gddBounds*)new gddBounds1D; bounds->set(0,0); break;
  235. case 2: bounds=(gddBounds*)new gddBounds2D; break;
  236. case 3: bounds=(gddBounds*)new gddBounds3D; break;
  237. default: bounds=(gddBounds*)new gddBounds[dim]; break;
  238. }
  239. if ( dim == 0 ) {
  240. if ( destruct ) {
  241. destruct->destroy(dataAddress());
  242. destruct = 0;
  243. }
  244. // run constructers for scalar string data types
  245. if ( primitiveType() == aitEnumString ) {
  246. aitString* str=(aitString*)dataAddress();
  247. str->init();
  248. }
  249. else if ( primitiveType() ==aitEnumFixedString ) {
  250. this->data.FString = new aitFixedString;
  251. memset (this->data.FString, '\0', sizeof(aitFixedString));
  252. }
  253. else {
  254. memset ( & this->data, '\0', sizeof ( this->data ) );
  255. }
  256. }
  257. }
  258. if ( bnds )
  259. {
  260. for(int i=0;i<dim;i++)
  261. bounds[i]=bnds[i];
  262. }
  263. }
  264. gddStatus gdd::registerDestructor(gddDestructor* dest)
  265. {
  266. // this is funky, will not register a destructor if one is present
  267. if(destruct)
  268. {
  269. gddAutoPrint("gdd::registerDestructor()",gddErrorAlreadyDefined);
  270. return gddErrorAlreadyDefined;
  271. }
  272. else
  273. return replaceDestructor(dest);
  274. }
  275. gddStatus gdd::replaceDestructor(gddDestructor* dest)
  276. {
  277. destruct=dest;
  278. destruct->reference();
  279. if(isContainer()||isFlat())
  280. markManaged();
  281. return 0;
  282. }
  283. gddStatus gdd::genCopy(aitEnum t, const void* d, aitDataFormat f)
  284. {
  285. gddStatus rc=0;
  286. if(isScalar())
  287. set(t,d,f);
  288. else if(isAtomic())
  289. {
  290. if(!dataPointer())
  291. {
  292. if ( primitiveType()==aitEnumString ) {
  293. size_t nElem = describedDataSizeElements ();
  294. aitString * pStrVec = new aitString [ nElem ];
  295. if ( ! pStrVec ) {
  296. gddAutoPrint("gdd::genCopy()",gddErrorNewFailed);
  297. rc = gddErrorNewFailed;
  298. }
  299. else {
  300. destruct = new gddAitStringDestructor;
  301. if ( destruct ) {
  302. destruct->reference();
  303. setData ( pStrVec );
  304. }
  305. else {
  306. delete [] pStrVec;
  307. gddAutoPrint("gdd::genCopy()",gddErrorNewFailed);
  308. rc = gddErrorNewFailed;
  309. }
  310. }
  311. }
  312. else {
  313. size_t sz=describedDataSizeBytes();
  314. aitUint8 * buf = new aitUint8[sz];
  315. if ( buf == NULL ) {
  316. gddAutoPrint("gdd::genCopy()",gddErrorNewFailed);
  317. rc=gddErrorNewFailed;
  318. }
  319. else
  320. {
  321. destruct=new gddAitUint8Destructor;
  322. if (destruct==NULL) {
  323. gddAutoPrint("gdd::genCopy()",gddErrorNewFailed);
  324. rc=gddErrorNewFailed;
  325. delete [] buf;
  326. }
  327. else {
  328. setData(buf);
  329. destruct->reference();
  330. }
  331. }
  332. }
  333. }
  334. if(rc==0)
  335. {
  336. if(f==aitLocalDataFormat)
  337. aitConvert(primitiveType(),dataPointer(),t,d,
  338. getDataSizeElements());
  339. else
  340. aitConvertFromNet(primitiveType(),dataPointer(),t,d,
  341. getDataSizeElements());
  342. markLocalDataFormat();
  343. }
  344. }
  345. else
  346. {
  347. gddAutoPrint("gdd::genCopy()",gddErrorTypeMismatch);
  348. rc=gddErrorTypeMismatch;
  349. }
  350. return rc;
  351. }
  352. gddStatus gdd::changeType(int app,aitEnum prim)
  353. {
  354. gddStatus rc=0;
  355. // this should only be allowed for setting the type if it is
  356. // undefined or if the data is a scalar
  357. if(isScalar() || primitiveType()==aitEnumInvalid)
  358. {
  359. setApplType(app);
  360. setPrimType(prim);
  361. }
  362. else
  363. {
  364. gddAutoPrint("gdd::changeType()",gddErrorTypeMismatch);
  365. rc=gddErrorTypeMismatch;
  366. }
  367. return rc;
  368. }
  369. gddStatus gdd::setBound(unsigned index_dim, aitIndex first, aitIndex count)
  370. {
  371. gddStatus rc=0;
  372. if(index_dim<dimension())
  373. bounds[index_dim].set(first,count);
  374. else
  375. {
  376. gddAutoPrint("gdd::setBound()",gddErrorOutOfBounds);
  377. rc=gddErrorOutOfBounds;
  378. }
  379. return rc;
  380. }
  381. gddStatus gdd::getBound(unsigned index_dim, aitIndex& first, aitIndex& count) const
  382. {
  383. gddStatus rc=0;
  384. if(index_dim<dimension())
  385. bounds[index_dim].get(first,count);
  386. else
  387. {
  388. gddAutoPrint("gdd::getBound()",gddErrorOutOfBounds);
  389. rc=gddErrorOutOfBounds;
  390. }
  391. return rc;
  392. }
  393. // should the copy functions in gdd use the flatten technique?
  394. gddStatus gdd::copyStuff(const gdd* dd,int ctype)
  395. {
  396. gddStatus rc=0;
  397. gddContainer* cdd;
  398. gdd *pdd,*ndd;
  399. // blow me out quickly here
  400. if(isFlat()||isManaged())
  401. {
  402. gddAutoPrint("gdd::copyStuff()",gddErrorNotAllowed);
  403. return gddErrorNotAllowed;
  404. }
  405. clear();
  406. setApplType(dd->appl_type);
  407. setPrimType(aitEnumContainer);
  408. setStatSevr(dd->getStat(),dd->getSevr());
  409. if(dd->isContainer())
  410. {
  411. cdd=(gddContainer*)dd;
  412. gddCursor cur=cdd->getCursor();
  413. for(ndd=cur.first();ndd;ndd=cur.next())
  414. {
  415. pdd=new gdd(ndd->applicationType(),
  416. ndd->primitiveType(),ndd->dimension());
  417. pdd->setNext((gdd*)dataPointer());
  418. setData(pdd);
  419. bounds->setSize(bounds->size()+1);
  420. pdd->copyStuff(ndd,ctype);
  421. }
  422. }
  423. else if(dd->isScalar()) {
  424. if (dd->primitiveType()==aitEnumString) {
  425. aitString* pStrDest =(aitString*)&data;
  426. aitString* pStrSrc =(aitString*)&dd->data;
  427. *pStrDest = *pStrSrc;
  428. }
  429. else if (dd->primitiveType()==aitEnumFixedString) {
  430. aitFixedString* pStrDest =(aitFixedString*)data.Pointer;
  431. aitFixedString* pStrSrc =(aitFixedString*)dd->data.Pointer;
  432. memcpy (pStrDest, pStrSrc, sizeof(aitFixedString));
  433. }
  434. else {
  435. data=dd->data;
  436. }
  437. }
  438. else // atomic
  439. {
  440. const gddBounds* bnds = dd->getBounds();
  441. for(unsigned i=0;i<dd->dimension();i++) bounds[i]=bnds[i];
  442. switch(ctype)
  443. {
  444. case 1: // copy()
  445. if ( primitiveType()==aitEnumString ) {
  446. size_t nElem = dd->describedDataSizeElements ();
  447. aitString * pStrVec = new aitString [ nElem ];
  448. if ( ! pStrVec ) {
  449. gddAutoPrint("gdd::copyStuff()",gddErrorNewFailed);
  450. rc=gddErrorNewFailed;
  451. }
  452. else {
  453. destruct = new gddAitStringDestructor;
  454. if ( destruct ) {
  455. const aitString * pSrc =
  456. static_cast <const aitString *> ( dd->dataPointer() );
  457. for ( unsigned j=0; j < nElem; j++ ) {
  458. pStrVec[j] = pSrc[j];
  459. }
  460. destruct->reference();
  461. setData ( pStrVec );
  462. }
  463. else {
  464. delete [] pStrVec;
  465. gddAutoPrint("gdd::copyStuff()",gddErrorNewFailed);
  466. rc=gddErrorNewFailed;
  467. }
  468. }
  469. }
  470. else {
  471. size_t a_size = dd->getDataSizeBytes();
  472. aitUint8* array = new aitUint8[a_size];
  473. if ( array ) {
  474. destruct=new gddAitUint8Destructor;
  475. if (destruct!=NULL) {
  476. destruct->reference();
  477. memcpy(array,dd->dataPointer(),a_size);
  478. setData(array);
  479. }
  480. else {
  481. delete [] array;
  482. gddAutoPrint("gdd::copyStuff()",gddErrorNewFailed);
  483. rc=gddErrorNewFailed;
  484. }
  485. }
  486. else
  487. {
  488. gddAutoPrint("gdd::copyStuff()",gddErrorNewFailed);
  489. rc=gddErrorNewFailed;
  490. }
  491. }
  492. break;
  493. case 2: // Dup()
  494. data=dd->getData(); // copy the data reference
  495. destruct=dd->destruct;
  496. if(destruct) destruct->reference();
  497. break;
  498. case 0: // copyInfo()
  499. default: break;
  500. }
  501. }
  502. return rc;
  503. }
  504. size_t gdd::getDataSizeBytes(void) const
  505. {
  506. size_t sz=0;
  507. const gdd* pdd;
  508. aitString* str;
  509. if(isContainer())
  510. {
  511. const gddContainer* cdd=(const gddContainer*)this;
  512. constGddCursor cur=cdd->getCursor();
  513. for(pdd=cur.first();pdd;pdd=cur.next())
  514. sz+=pdd->getTotalSizeBytes();
  515. }
  516. else
  517. {
  518. if(aitValid(primitiveType()))
  519. {
  520. if(primitiveType()==aitEnumString)
  521. {
  522. if(dimension()) str=(aitString*)dataPointer();
  523. else str=(aitString*)dataAddress();
  524. sz+=(size_t)(aitString::totalLength(str,
  525. getDataSizeElements()));
  526. }
  527. else
  528. sz+=(size_t)(getDataSizeElements())*aitSize[primitiveType()];
  529. }
  530. }
  531. return sz;
  532. }
  533. size_t gdd::describedDataSizeBytes(void) const
  534. {
  535. size_t sz=0;
  536. // does not work well for aitString - only reports the aitString info
  537. if(!isContainer())
  538. sz+=(size_t)(describedDataSizeElements())*aitSize[primitiveType()];
  539. return sz;
  540. }
  541. size_t gdd::getTotalSizeBytes(void) const
  542. {
  543. size_t sz;
  544. unsigned long tsize;
  545. const gdd* pdd;
  546. // add up size of bounds + size of this DD
  547. sz=sizeof(gdd)+(sizeof(gddBounds)*dimension());
  548. // special case the aitString/aitFixedString here - sucks bad
  549. if(isScalar())
  550. {
  551. if(primitiveType()==aitEnumString)
  552. {
  553. aitString* str=(aitString*)dataAddress();
  554. sz+=str->length()+1; // include the NULL
  555. }
  556. else if(primitiveType()==aitEnumFixedString)
  557. sz+=sizeof(aitFixedString);
  558. }
  559. else if(isAtomic())
  560. {
  561. if(aitValid(primitiveType()))
  562. {
  563. if(primitiveType()==aitEnumString)
  564. {
  565. // special case the aitString here
  566. tsize=(size_t)(aitString::totalLength((aitString*)dataPointer(),
  567. getDataSizeElements()));
  568. }
  569. else
  570. tsize=(size_t)(getDataSizeElements())*aitSize[primitiveType()];
  571. sz+=(size_t)align8(tsize); // include alignment
  572. }
  573. }
  574. else if(isContainer())
  575. {
  576. const gddContainer* cdd=(const gddContainer*)this;
  577. constGddCursor cur=cdd->getCursor();
  578. for(pdd=cur.first();pdd;pdd=cur.next())
  579. sz+=pdd->getTotalSizeBytes();
  580. }
  581. return sz;
  582. }
  583. aitUint32 gdd::getDataSizeElements(void) const
  584. {
  585. unsigned long total=1u;
  586. unsigned i;
  587. if(dimension()>0u && dataPointer())
  588. {
  589. for(i=0u;i<dimension();i++)
  590. total*=bounds[i].size();
  591. }
  592. return total;
  593. }
  594. aitUint32 gdd::describedDataSizeElements(void) const
  595. {
  596. unsigned long total=0;
  597. unsigned i;
  598. if(dimension()==0)
  599. total=1;
  600. else
  601. for(i=0;i<dimension();i++) total+=bounds[i].size();
  602. return total;
  603. }
  604. size_t gdd::flattenWithOffsets(void* buf, size_t size, aitIndex* total_dd)
  605. {
  606. gdd* flat_dd;
  607. size_t sz;
  608. sz = flattenWithAddress(buf,size,total_dd);
  609. flat_dd=(gdd*)buf;
  610. if(sz>0) flat_dd->convertAddressToOffsets();
  611. return sz;
  612. }
  613. // IMPORTANT NOTE:
  614. // Currently the user cannot register an empty container as a prototype.
  615. // The destructor will not be installed to clean up the container when
  616. // it is freed.
  617. // This is an important function
  618. // Data should be flattened as follows:
  619. // 1) all the GDDs, seen as an array an GDDs
  620. // 2) all the bounds info for all the GDDs
  621. // 3) all the data for all GDDs
  622. //
  623. // In addition, the user should be able to flatten GDDs without the data
  624. // and flatten portions or all the data without flattening GDDs
  625. size_t gdd::flattenWithAddress(void* buf, size_t size, aitIndex* total_dd)
  626. {
  627. gdd* pdd = (gdd*)buf;
  628. size_t pos,sz,spos;
  629. aitUint32 i;
  630. gddBounds* bnds;
  631. // copy this gdd (first one) to get things started
  632. // this is done in two passes - one to copy DDs, one for bounds/data
  633. // need to be able to check if the DD has been flattened already
  634. if((sz=getTotalSizeBytes())>size) return 0;
  635. pdd[0]=*this;
  636. pdd[0].destruct=NULL;
  637. pdd[0].flags=0;
  638. pos=1;
  639. // not enough to just copy the gdd info if the primitive type is
  640. // aitString or aitFixedString (even if scalar gdd)
  641. // must special case the strings - that really sucks
  642. if(isScalar())
  643. {
  644. // here is special case for the string types
  645. if(primitiveType()==aitEnumFixedString)
  646. {
  647. if(data.FString)
  648. memcpy((char*)&pdd[pos],data.FString,sizeof(aitFixedString));
  649. pdd[0].data.FString=(aitFixedString*)&pdd[pos];
  650. }
  651. else if(primitiveType()==aitEnumString)
  652. {
  653. aitString* str=(aitString*)pdd[0].dataAddress();
  654. if(str->string())
  655. {
  656. memcpy((char*)&pdd[pos],str->string(),str->length()+1);
  657. str->installBuf((char*)&pdd[pos],str->length(),str->length()+1);
  658. }
  659. else
  660. str->init();
  661. }
  662. }
  663. else if(isContainer())
  664. {
  665. // need to check for bounds in the container and flatten them
  666. if(dataPointer())
  667. {
  668. // process all the container's DDs
  669. spos=pos;
  670. pos+=flattenDDs((gddContainer*)this,&pdd[pos],
  671. size-(pos*sizeof(gdd)));
  672. // copy all the data from the entire container into the buffer
  673. flattenData(&pdd[0],pos,&pdd[pos],size-(pos*sizeof(gdd)));
  674. pdd[0].markFlat();
  675. pdd[0].setData(&pdd[spos]);
  676. }
  677. else
  678. sz=0; // failure should occur - cannot flatten an empty container
  679. }
  680. else if(isAtomic())
  681. {
  682. // Just copy the data from this DD into the buffer, copy bounds
  683. if(bounds)
  684. {
  685. pdd[0].markFlat();
  686. bnds=(gddBounds*)(&pdd[pos]);
  687. for(i=0;i<dimension();i++) bnds[i]=bounds[i];
  688. pdd[0].bounds=bnds;
  689. if(dataPointer())
  690. {
  691. if(primitiveType()==aitEnumString)
  692. {
  693. // not very good way to do it, size info bad
  694. aitString* str = (aitString*)dataPointer();
  695. aitString::compact(str,getDataSizeElements(),&bnds[i],size);
  696. }
  697. else
  698. memcpy(&bnds[i],dataPointer(),getDataSizeBytes());
  699. pdd[0].setData(&bnds[i]);
  700. }
  701. else
  702. sz=0; // should return a failure
  703. }
  704. else
  705. sz=0; // should return failure
  706. }
  707. if(total_dd) *total_dd=pos;
  708. return sz;
  709. }
  710. gddStatus gdd::flattenData(gdd* dd, int tot_dds, void* buf,size_t size)
  711. {
  712. int i;
  713. unsigned j;
  714. size_t sz;
  715. gddBounds* bnds;
  716. aitUint8* ptr = (aitUint8*)buf;
  717. // This functions needs to be divided into two sections
  718. // 1) copy ALL the bounds out
  719. // 2) copy ALL the data out
  720. for(i=0;i<tot_dds;i++)
  721. {
  722. if(dd[i].isContainer())
  723. {
  724. // don't mark flat if container - 1D bounds must be present
  725. if(dd[i].bounds)
  726. {
  727. bnds=(gddBounds*)(ptr);
  728. for(j=0;j<dd[i].dimension();j++) bnds[j]=dd[i].bounds[j];
  729. dd[i].bounds=bnds;
  730. ptr+=j*sizeof(gddBounds);
  731. }
  732. else
  733. {
  734. // this is an error condition!
  735. dd[i].bounds=NULL;
  736. }
  737. }
  738. else if(dd[i].isAtomic())
  739. {
  740. if(dd[i].bounds)
  741. {
  742. // copy the bounds
  743. // need to mark flat if bounds are present in an atomic type
  744. dd[i].markFlat();
  745. bnds=(gddBounds*)(ptr);
  746. for(j=0;j<dd[i].dimension();j++) bnds[j]=dd[i].bounds[j];
  747. dd[i].bounds=bnds;
  748. ptr+=j*sizeof(gddBounds);
  749. // copy the data
  750. if(dd[i].dataPointer())
  751. {
  752. if(dd[i].primitiveType()==aitEnumString)
  753. {
  754. // not very good way to do it, size info bad
  755. aitString* str = (aitString*)dd[i].dataPointer();
  756. sz=aitString::compact(str,
  757. dd[i].getDataSizeElements(),ptr,size);
  758. }
  759. else
  760. {
  761. // need to copy data here, align to size of double
  762. sz=dd[i].getDataSizeBytes();
  763. memcpy(ptr,dd[i].dataPointer(),sz);
  764. }
  765. dd[i].setData(ptr);
  766. ptr+=align8(sz); // do alignment
  767. }
  768. }
  769. else
  770. {
  771. // bounds not required
  772. dd[i].bounds=NULL;
  773. }
  774. }
  775. else if(dd[i].isScalar())
  776. {
  777. // here is special case for String types
  778. if(dd[i].primitiveType()==aitEnumString)
  779. {
  780. aitString* str=(aitString*)dd[i].dataAddress();
  781. if(str->string())
  782. {
  783. memcpy(ptr,str->string(),str->length()+1);
  784. str->installBuf((char *)ptr, str->length(), str->length()+1);
  785. ptr+=str->length()+1;
  786. }
  787. else
  788. str->init();
  789. }
  790. else if(dd[i].primitiveType()==aitEnumFixedString)
  791. {
  792. if(dd[i].data.FString)
  793. memcpy(ptr,dd[i].data.FString,sizeof(aitFixedString));
  794. dd[i].data.FString=(aitFixedString*)ptr;
  795. ptr+=sizeof(aitFixedString);
  796. }
  797. }
  798. }
  799. return 0;
  800. }
  801. int gdd::flattenDDs(gddContainer* dd, void* buf, size_t size)
  802. {
  803. gdd* ptr=(gdd*)buf;
  804. int i,tot,pos,spos;
  805. gdd *pdd;
  806. gddCursor cur;
  807. cur=dd->getCursor();
  808. // make first pass to copy all the container's DDs into the buffer
  809. for(tot=0,pdd=cur.first();pdd;pdd=pdd->next(),tot++)
  810. {
  811. ptr[tot]=*pdd;
  812. ptr[tot].destruct=NULL;
  813. ptr[tot].setNext(&ptr[tot+1]);
  814. ptr[tot].noReferencing();
  815. }
  816. ptr[tot-1].setNext(NULL);
  817. // make second pass to copy all child containers into buffer
  818. for(pos=tot,i=0;i<tot;i++)
  819. {
  820. if(ptr[i].isContainer())
  821. {
  822. if(ptr[i].dataPointer())
  823. {
  824. spos=pos;
  825. pos+=flattenDDs((gddContainer*)&ptr[i],&ptr[pos],
  826. size-(pos*sizeof(gdd)));
  827. ptr[i].markFlat();
  828. ptr[i].setData(&ptr[spos]);
  829. }
  830. else
  831. {
  832. ptr[i].setData(NULL);
  833. ptr[i].destruct=new gddContainerCleaner(&ptr[i]);
  834. ptr[i].destruct->reference();
  835. }
  836. }
  837. }
  838. return pos;
  839. }
  840. gddStatus gdd::convertOffsetsToAddress(void)
  841. {
  842. aitUint8* pdd = (aitUint8*)this;
  843. unsigned long bnds = (unsigned long)(bounds);
  844. unsigned long dp = (unsigned long)(dataPointer());
  845. gdd* tdd;
  846. gddContainer* cdd;
  847. gddCursor cur;
  848. aitString* str;
  849. aitIndex i;
  850. const char* cstr;
  851. if(isContainer())
  852. {
  853. // change bounds and data first
  854. bounds=(gddBounds*)(pdd+bnds);
  855. setData(pdd+dp);
  856. cdd=(gddContainer*)this;
  857. cur=cdd->getCursor();
  858. for(tdd=cur.first();tdd;tdd=cur.next())
  859. {
  860. if(tdd->next()) tdd->setNext((gdd*)(pdd+(unsigned long)tdd->next()));
  861. tdd->convertOffsetsToAddress();
  862. }
  863. }
  864. else
  865. {
  866. if(isAtomic())
  867. {
  868. bounds=(gddBounds*)(pdd+bnds);
  869. setData(pdd+dp);
  870. if(primitiveType()==aitEnumString)
  871. {
  872. // force all the strings in the array to offsets
  873. str=(aitString*)dataPointer();
  874. for(i=0;i<getDataSizeElements();i++)
  875. {
  876. if(str[i].string())
  877. {
  878. cstr=str[i].string();
  879. str[i].installBuf((char *)(pdd+(unsigned long)cstr),
  880. str[i].length(), str[i].length()+1);
  881. }
  882. else
  883. str[i].init();
  884. }
  885. }
  886. }
  887. else if(isScalar())
  888. {
  889. if(primitiveType()==aitEnumFixedString)
  890. {
  891. if(data.FString) setData(pdd+dp);
  892. }
  893. else if(primitiveType()==aitEnumString)
  894. {
  895. str=(aitString*)dataAddress();
  896. if(str->string())
  897. {
  898. cstr=str->string();
  899. str->installBuf((char *)(pdd+(unsigned long)cstr),
  900. str->length(), str->length()+1u);
  901. }
  902. else
  903. str->init();
  904. }
  905. }
  906. }
  907. return 0;
  908. }
  909. gddStatus gdd::convertAddressToOffsets(void)
  910. {
  911. aitUint8* pdd = (aitUint8*)this;
  912. aitUint8* bnds = (aitUint8*)(bounds);
  913. aitUint8* dp = (aitUint8*)(dataPointer());
  914. gddContainer* tdd;
  915. gddCursor cur;
  916. gdd *cdd,*ddd;
  917. aitString* str;
  918. aitIndex i;
  919. const char* cstr;
  920. // does not ensure that all the members of a container are flat!
  921. if(!isFlat())
  922. {
  923. gddAutoPrint("gdd::convertAddressToOffsets()",gddErrorNotAllowed);
  924. return gddErrorNotAllowed;
  925. }
  926. if(isContainer())
  927. {
  928. tdd=(gddContainer*)this;
  929. cur=tdd->getCursor();
  930. for(cdd=cur.first();cdd;)
  931. {
  932. ddd=cdd;
  933. cdd=cur.next();
  934. ddd->convertAddressToOffsets();
  935. if(cdd) ddd->setNext((gdd*)((aitUint8*)(ddd->next())-pdd));
  936. }
  937. // bounds and data of container to offsets
  938. setData((gdd*)(dp-pdd));
  939. bounds=(gddBounds*)(bnds-pdd);
  940. }
  941. else
  942. {
  943. if(isAtomic())
  944. {
  945. if(primitiveType()==aitEnumString)
  946. {
  947. // force all the strings in the array to offsets
  948. str=(aitString*)dataPointer();
  949. for(i=0;i<getDataSizeElements();i++)
  950. {
  951. cstr=str[i].string();
  952. if(cstr) str[i].installBuf((char *)(cstr-(const char*)pdd),
  953. str[i].length(), str[i].length()+1u);
  954. else str[i].init();
  955. }
  956. }
  957. // bounds and data of atomic to offsets
  958. setData((gdd*)(dp-pdd));
  959. bounds=(gddBounds*)(bnds-pdd);
  960. }
  961. else if(isScalar())
  962. {
  963. // handle the special string scalar cases
  964. if(primitiveType()==aitEnumFixedString)
  965. {
  966. if(data.FString) setData((gdd*)(dp-pdd));
  967. }
  968. else if(primitiveType()==aitEnumString)
  969. {
  970. str=(aitString*)dataAddress();
  971. cstr=str->string();
  972. if(cstr) str->installBuf((char *)(cstr-(const char*)pdd),
  973. str->length(), str->length()+1u);
  974. else str->init();
  975. }
  976. }
  977. }
  978. return 0;
  979. }
  980. void gdd::destroyData(void)
  981. {
  982. if (isScalar())
  983. {
  984. // this destroys the string types
  985. this->setPrimType (aitEnumInvalid);
  986. memset ( & this->data, '\0', sizeof ( this->data ) );
  987. }
  988. else {
  989. if(destruct)
  990. {
  991. if(isContainer())
  992. destruct->destroy(this);
  993. else
  994. destruct->destroy(dataPointer());
  995. destruct=NULL;
  996. }
  997. freeBounds();
  998. this->prim_type = aitEnumInvalid;
  999. memset ( & this->data, '\0', sizeof ( this->data ) );
  1000. }
  1001. }
  1002. gddStatus gdd::clearData(void)
  1003. {
  1004. gddStatus rc=0;
  1005. if(isContainer()||isManaged()||isFlat())
  1006. {
  1007. gddAutoPrint("gdd::clearData()",gddErrorNotAllowed);
  1008. rc=gddErrorNotAllowed;
  1009. }
  1010. else if ( this->isScalar () ) {
  1011. // clear scaler types
  1012. if ( this->primitiveType() == aitEnumString ) {
  1013. aitString * str=(aitString*)dataAddress();
  1014. str->clear();
  1015. }
  1016. else if ( this->primitiveType() == aitEnumFixedString ) {
  1017. memset ( this->data.FString, '\0', sizeof ( this->data.FString ) );
  1018. }
  1019. else {
  1020. memset ( & this->data, '\0', sizeof ( this->data ) );
  1021. }
  1022. }
  1023. else {
  1024. if(destruct)
  1025. {
  1026. destruct->destroy(dataPointer());
  1027. destruct=NULL;
  1028. }
  1029. setDimension ( 0, 0 );
  1030. }
  1031. return rc;
  1032. }
  1033. gddStatus gdd::clear(void)
  1034. {
  1035. if(isFlat()||isManaged())
  1036. {
  1037. gddAutoPrint("gdd::clear()",gddErrorNotAllowed);
  1038. return gddErrorNotAllowed;
  1039. }
  1040. if(isAtomic())
  1041. {
  1042. destroyData();
  1043. }
  1044. else if(isContainer())
  1045. {
  1046. gddContainer* cdd = (gddContainer*)this;
  1047. gddCursor cur = cdd->getCursor();
  1048. gdd *dd,*tdd;
  1049. for(dd=cur.first();dd;)
  1050. {
  1051. tdd=dd;
  1052. dd=cur.next();
  1053. if(tdd->unreference()<0) delete tdd;
  1054. }
  1055. freeBounds();
  1056. }
  1057. //
  1058. // this code clears out aitString and
  1059. // aitFixedString scalars (the doc says
  1060. // that every field is set to invalid)
  1061. //
  1062. changeType(0,aitEnumInvalid);
  1063. memset ( & this->data, '\0', sizeof ( this->data ) );
  1064. return 0;
  1065. }
  1066. // Curently gives no indication of failure, which is bad.
  1067. // Obviously managed or flattened DDs cannot be redone.
  1068. // However, a DD that is within a managed or flattened container can
  1069. // use this to describe data - how's that for obscure
  1070. // This is required if the "value" is to be allowed within a container
  1071. // The "value" could be scalar or an array of unknown size. The same is
  1072. // true of the enum strings and "units" attribute.
  1073. gddStatus gdd::reset(aitEnum prim, int dimen, aitIndex* cnt)
  1074. {
  1075. int i;
  1076. gddStatus rc;
  1077. if((rc=clear())==0)
  1078. {
  1079. setPrimType(prim);
  1080. setDimension(dimen);
  1081. for(i=0;i<dimen;i++)
  1082. setBound(i,0,cnt[i]);
  1083. }
  1084. return rc;
  1085. }
  1086. void gdd::get(aitString& d) const
  1087. {
  1088. if(primitiveType()==aitEnumString)
  1089. {
  1090. aitString* s=(aitString*)dataAddress();
  1091. d=*s;
  1092. }
  1093. else
  1094. get(aitEnumString,&d);
  1095. }
  1096. void gdd::get(aitFixedString& d) const
  1097. {
  1098. if(primitiveType()==aitEnumFixedString){
  1099. strncpy(d.fixed_string,data.FString->fixed_string,
  1100. sizeof(d));
  1101. d.fixed_string[sizeof(d)-1u] = '\0';
  1102. }
  1103. else
  1104. get(aitEnumFixedString,&d);
  1105. }
  1106. void gdd::getConvert(aitString& d) const
  1107. {
  1108. get(aitEnumString,&d);
  1109. }
  1110. void gdd::getConvert(aitFixedString& d) const
  1111. {
  1112. get(aitEnumFixedString,d.fixed_string);
  1113. }
  1114. gddStatus gdd::put(const aitString& d)
  1115. {
  1116. gddStatus rc=0;
  1117. if(isScalar())
  1118. {
  1119. //
  1120. // destroy existing fixed string if it exists
  1121. // and construct new aitString object
  1122. //
  1123. setPrimType(aitEnumString);
  1124. aitString* s=(aitString*)dataAddress();
  1125. *s=d;
  1126. }
  1127. else
  1128. {
  1129. gddAutoPrint("gdd::put(aitString&)",gddErrorNotAllowed);
  1130. rc=gddErrorNotAllowed;
  1131. }
  1132. return rc;
  1133. }
  1134. gddStatus gdd::put(const aitFixedString& d)
  1135. {
  1136. gddStatus rc=0;
  1137. if(isScalar())
  1138. {
  1139. this->setPrimType(aitEnumFixedString);
  1140. if (data.FString!=NULL)
  1141. memcpy (data.FString->fixed_string, d.fixed_string, sizeof(d.fixed_string));
  1142. }
  1143. else
  1144. {
  1145. gddAutoPrint("gdd::put(aitString&)",gddErrorNotAllowed);
  1146. rc=gddErrorNotAllowed;
  1147. }
  1148. return rc;
  1149. }
  1150. void gdd::putConvert(const aitString& d)
  1151. {
  1152. set(aitEnumString,&d);
  1153. }
  1154. void gdd::putConvert(const aitFixedString& d)
  1155. {
  1156. set(aitEnumFixedString,(void*)d.fixed_string);
  1157. }
  1158. // copy each of the strings into this DDs storage area
  1159. gddStatus gdd::put(const aitString* const d)
  1160. {
  1161. return genCopy(aitEnumString,d);
  1162. }
  1163. // copy each of the strings into this DDs storage area
  1164. gddStatus gdd::put(const aitFixedString* const d)
  1165. {
  1166. gddStatus rc=0;
  1167. if(isAtomic())
  1168. if(dataPointer())
  1169. aitConvert(primitiveType(),dataPointer(),aitEnumFixedString,d,
  1170. getDataSizeElements());
  1171. else
  1172. genCopy(aitEnumFixedString,d);
  1173. else
  1174. {
  1175. gddAutoPrint("gdd::put(const aitFixedString*const)",gddErrorNotAllowed);
  1176. rc=gddErrorTypeMismatch;
  1177. }
  1178. return rc;
  1179. }
  1180. gddStatus gdd::putRef(const gdd*)
  1181. {
  1182. gddAutoPrint("gdd::putRef(const gdd*) - NOT IMPLEMENTED",
  1183. gddErrorNotSupported);
  1184. return gddErrorNotSupported;
  1185. }
  1186. gddStatus gdd::put ( const gdd * dd )
  1187. {
  1188. if ( this->isScalar() && dd->isScalar() )
  1189. {
  1190. // this is the simple case - just make this scalar look like the other
  1191. this->set(dd->primitiveType(),dd->dataVoid());
  1192. }
  1193. else if ( isContainer() || dd->isContainer() )
  1194. {
  1195. gddAutoPrint("gdd::put(const gdd*)",gddErrorNotSupported);
  1196. return gddErrorNotSupported;
  1197. }
  1198. else if ( this->dimension() > 1 || dd->dimension() > 1 )
  1199. {
  1200. // sorry, no support currently for multidimensional arrays
  1201. return gddErrorOutOfBounds;
  1202. }
  1203. else if ( this->isScalar() ) // dd must be atomic if this is true
  1204. {
  1205. this->set ( dd->primitiveType(), dd->dataPointer() );
  1206. }
  1207. // at this point this GDD must be atomic
  1208. // and the src gdd is either atomic or scalar
  1209. else {
  1210. // this must be single dimensional atomic at this point
  1211. // dd can be scaler or single dimensional atomic at this point
  1212. // so fetch the bounds carefully
  1213. aitUint32 srcFirst;
  1214. aitUint32 srcElemCount;
  1215. if ( dd->isScalar() ) {
  1216. srcFirst = 0;
  1217. srcElemCount = 1;
  1218. }
  1219. else {
  1220. srcFirst = dd->getBounds()->first();
  1221. srcElemCount = dd->getBounds()->size();
  1222. }
  1223. // clip to lower limit of source
  1224. aitUint32 srcCopyFirst;
  1225. if ( this->getBounds()->first () > srcFirst ) {
  1226. srcCopyFirst = this->getBounds()->first();
  1227. }
  1228. else {
  1229. srcCopyFirst = srcFirst;
  1230. }
  1231. // clip to upper limit of source
  1232. aitUint32 srcCopySize;
  1233. const aitUint32 unusedSrcBelow = srcCopyFirst - srcFirst;
  1234. if ( srcElemCount <= unusedSrcBelow ) {
  1235. return gddErrorOutOfBounds;
  1236. }
  1237. aitUint32 srcAvailSize = srcElemCount - unusedSrcBelow;
  1238. if ( srcAvailSize > this->getBounds()->size() ) {
  1239. srcCopySize = this->getBounds()->size();
  1240. }
  1241. else {
  1242. srcCopySize = srcAvailSize;
  1243. }
  1244. if ( dataVoid() == NULL )
  1245. {
  1246. if (primitiveType()==aitEnumInvalid) {
  1247. setPrimType (dd->primitiveType());
  1248. }
  1249. if ( primitiveType()==aitEnumString ) {
  1250. aitString * pStrVec = new aitString [ srcCopySize ];
  1251. if( ! pStrVec ) {
  1252. return gddErrorNewFailed;
  1253. }
  1254. destruct = new gddAitStringDestructor;
  1255. if ( destruct ) {
  1256. destruct->reference();
  1257. setData ( pStrVec );
  1258. }
  1259. else {
  1260. delete [] pStrVec;
  1261. gddAutoPrint("gdd::copyData(const gdd*)",gddErrorNewFailed);
  1262. return gddErrorNewFailed;
  1263. }
  1264. }
  1265. else {
  1266. size_t sz = srcCopySize * aitSize[primitiveType()];
  1267. // allocate a data buffer for the user
  1268. aitUint8 * arr = new aitUint8[sz];
  1269. if( ! arr ) {
  1270. return gddErrorNewFailed;
  1271. }
  1272. destruct=new gddAitUint8Destructor;
  1273. if (destruct!=NULL) {
  1274. destruct->reference();
  1275. setData(arr);
  1276. }
  1277. else {
  1278. delete [] arr;
  1279. gddAutoPrint("gdd::copyData(const gdd*)",gddErrorNewFailed);
  1280. return gddErrorNewFailed;
  1281. }
  1282. }
  1283. // the rule is that if storage is not preallocated then its ok
  1284. // for the dest bounds to shrink to match the original dest
  1285. // bounds intersection with the source data bounds
  1286. for ( unsigned i = 0; i < this->dimension(); i++ ) {
  1287. if ( i == 0 ) {
  1288. this->setBound ( i, srcCopyFirst, srcCopySize );
  1289. }
  1290. else {
  1291. this->setBound ( i, 0, 1 );
  1292. }
  1293. }
  1294. }
  1295. aitUint8* pDst = (aitUint8*) this->dataPointer();
  1296. assert ( srcCopyFirst >= this->getBounds()->first() );
  1297. const aitUint32 unusedDstLow = srcCopyFirst - this->getBounds()->first();
  1298. if ( unusedDstLow > 0 ) {
  1299. //
  1300. // zero portions that dont match
  1301. // (should eventually throw an exception ?)
  1302. //
  1303. aitUint32 byteCount = aitSize[primitiveType()] * unusedDstLow;
  1304. memset (pDst, '\0', byteCount);
  1305. pDst += byteCount;
  1306. }
  1307. aitUint8* pSrc = (aitUint8*) dd->dataVoid();
  1308. pSrc += aitSize[dd->primitiveType()] * unusedSrcBelow;
  1309. int gddStatus = aitConvert (this->primitiveType(), pDst,
  1310. dd->primitiveType(), pSrc, srcCopySize);
  1311. if ( gddStatus < 0 ) {
  1312. return gddErrorTypeMismatch;
  1313. }
  1314. assert ( this->getBounds()->size() >= srcCopySize + unusedDstLow );
  1315. const aitUint32 unusedDstHigh = this->getBounds()->size() - ( srcCopySize + unusedDstLow );
  1316. if ( unusedDstHigh > 0 ) {
  1317. pDst += aitSize[primitiveType()] * srcCopySize;
  1318. //
  1319. // zero portions that dont match
  1320. // (should eventually throw an exception ?)
  1321. //
  1322. aitUint32 byteCount = aitSize[primitiveType()] * unusedDstHigh;
  1323. memset (pDst, '\0', byteCount);
  1324. }
  1325. }
  1326. setStatSevr(dd->getStat(),dd->getSevr());
  1327. aitTimeStamp ts;
  1328. dd->getTimeStamp(&ts);
  1329. setTimeStamp(&ts);
  1330. return 0; // success
  1331. }
  1332. size_t gdd::outHeader(void* buf,aitUint32 bufsize) const
  1333. {
  1334. // simple encoding for now.. will change later
  1335. // this is the SLOW, simple version
  1336. aitUint8* b = (aitUint8*)buf;
  1337. aitUint8* app = (aitUint8*)&appl_type;
  1338. aitUint8* stat = (aitUint8*)&status;
  1339. aitUint8* ts_sec = (aitUint8*)&time_stamp.tv_sec;
  1340. aitUint8* ts_nsec = (aitUint8*)&time_stamp.tv_nsec;
  1341. size_t i,j,sz;
  1342. aitIndex ff,ss;
  1343. aitUint8 *f,*s;
  1344. // verify that header will fit into buffer first
  1345. sz=4+sizeof(status)+sizeof(time_stamp)+sizeof(appl_type)+
  1346. sizeof(prim_type)+sizeof(dim)+(dim*sizeof(gddBounds));
  1347. if(sz>bufsize) return 0; // blow out here!
  1348. *(b++)='H'; *(b++)='E'; *(b++)='A'; *(b++)='D';
  1349. // how's this for putrid
  1350. *(b++)=dim;
  1351. *(b++)=prim_type;
  1352. if(aitLocalNetworkDataFormatSame)
  1353. {
  1354. *(b++)=app[0]; *(b++)=app[1];
  1355. for(i=0;i<sizeof(status);i++) *(b++)=stat[i];
  1356. for(i=0;i<sizeof(time_stamp.tv_sec);i++) *(b++)=ts_sec[i];
  1357. for(i=0;i<sizeof(time_stamp.tv_nsec);i++) *(b++)=ts_nsec[i];
  1358. }
  1359. else
  1360. {
  1361. *(b++)=app[1]; *(b++)=app[0];
  1362. i=sizeof(status)-1u; do { *(b++)=stat[i]; } while(i-->0u);
  1363. i=sizeof(time_stamp.tv_sec)-1u; do { *(b++)=ts_sec[i]; } while(i-->0u);
  1364. i=sizeof(time_stamp.tv_nsec)-1u; do { *(b++)=ts_nsec[i]; } while(i-->0u);
  1365. }
  1366. // put out the bounds info
  1367. for(j=0;j<dim;j++)
  1368. {
  1369. ff=bounds[j].first(); f=(aitUint8*)&ff;
  1370. ss=bounds[j].size(); s=(aitUint8*)&ss;
  1371. if(aitLocalNetworkDataFormatSame)
  1372. {
  1373. for(i=0;i<sizeof(aitIndex);i++) *(b++)=s[i];
  1374. for(i=0;i<sizeof(aitIndex);i++) *(b++)=f[i];
  1375. }
  1376. else
  1377. {
  1378. i=sizeof(aitIndex)-1u; do { *(b++)=s[i]; } while(i-->0u);
  1379. i=sizeof(aitIndex)-1u; do { *(b++)=f[i]; } while(i-->0u);
  1380. }
  1381. }
  1382. return sz;
  1383. }
  1384. size_t gdd::outData(void* buf,aitUint32 bufsize, aitEnum e, aitDataFormat f) const
  1385. {
  1386. // put data into user's buffer in the format that the user wants (e/f).
  1387. // if e is invalid, then use whatever format this gdd describes.
  1388. aitUint32 sz = getDataSizeElements();
  1389. aitUint32 len = getDataSizeBytes();
  1390. aitEnum type=(e==aitEnumInvalid)?primitiveType():e;
  1391. if(len>bufsize) return 0; // blow out early
  1392. if(sz>0)
  1393. {
  1394. if(f==aitLocalDataFormat)
  1395. aitConvert(type,buf,primitiveType(),dataVoid(),sz);
  1396. else
  1397. aitConvertToNet(type,buf,primitiveType(),dataVoid(),sz);
  1398. }
  1399. return len;
  1400. }
  1401. size_t gdd::out(void* buf,aitUint32 bufsize,aitDataFormat f) const
  1402. {
  1403. size_t index = outHeader(buf,bufsize);
  1404. size_t rc;
  1405. if(index>0)
  1406. rc=outData(((char*)buf)+index,bufsize-index,aitEnumInvalid,f)+index;
  1407. else
  1408. rc=0;
  1409. return rc;
  1410. }
  1411. size_t gdd::inHeader(void* buf)
  1412. {
  1413. // simple encoding for now.. will change later
  1414. // this is the SLOW, simple version
  1415. aitUint16 inapp;
  1416. aitUint8 inprim;
  1417. aitUint8 indim;
  1418. aitUint8* b = (aitUint8*)buf;
  1419. aitUint8* b1 = b;
  1420. aitUint8* app = (aitUint8*)&inapp;
  1421. aitUint8* stat = (aitUint8*)&status;
  1422. aitUint8* ts_sec = (aitUint8*)&time_stamp.tv_sec;
  1423. aitUint8* ts_nsec = (aitUint8*)&time_stamp.tv_nsec;
  1424. size_t i,j;
  1425. aitIndex ff,ss;
  1426. aitUint8 *f,*s;
  1427. if(strncmp((char*)b,"HEAD",4)!=0) return 0;
  1428. b+=4;
  1429. indim=*(b++);
  1430. inprim=*(b++);
  1431. if(aitLocalNetworkDataFormatSame)
  1432. {
  1433. app[0]=*(b++); app[1]=*(b++);
  1434. init(inapp,(aitEnum)inprim,indim);
  1435. for(i=0u;i<sizeof(status);i++) stat[i]=*(b++);
  1436. for(i=0u;i<sizeof(time_stamp.tv_sec);i++) ts_sec[i]=*(b++);
  1437. for(i=0u;i<sizeof(time_stamp.tv_nsec);i++) ts_nsec[i]=*(b++);
  1438. }
  1439. else
  1440. {
  1441. app[1]=*(b++); app[0]=*(b++);
  1442. init(inapp,(aitEnum)inprim,indim);
  1443. i=sizeof(status)-1u; do { stat[i]=*(b++); } while(i-->0u);
  1444. i=sizeof(time_stamp.tv_sec)-1u; do { ts_sec[i]=*(b++); } while(i-->0u);
  1445. i=sizeof(time_stamp.tv_nsec)-1u; do { ts_nsec[i]=*(b++); } while(i-->0u);
  1446. }
  1447. // read in the bounds info
  1448. f=(aitUint8*)&ff;
  1449. s=(aitUint8*)&ss;
  1450. for(j=0u;j<dim;j++)
  1451. {
  1452. if(aitLocalNetworkDataFormatSame)
  1453. {
  1454. for(i=0;i<sizeof(aitIndex);i++) s[i]=*(b++);
  1455. for(i=0;i<sizeof(aitIndex);i++) f[i]=*(b++);
  1456. }
  1457. else
  1458. {
  1459. i=sizeof(aitIndex)-1u; do { s[i]=*(b++); } while(i-->0u);
  1460. i=sizeof(aitIndex)-1u; do { f[i]=*(b++); } while(i-->0u);
  1461. }
  1462. bounds[j].setFirst(ff);
  1463. bounds[j].setSize(ss);
  1464. }
  1465. return (size_t)(b-b1);
  1466. }
  1467. size_t gdd::inData(void* buf,aitUint32 tot, aitEnum e, aitDataFormat f)
  1468. {
  1469. size_t rc;
  1470. // Get data from a buffer and put it into this gdd. Lots of rules here.
  1471. // 1) tot is the total number of elements to copy from buf to this gdd.
  1472. // * if tot is zero, then use the element count described in the gdd.
  1473. // * if tot is not zero, then set the gdd up as a 1 dimensional array
  1474. // with tot elements in it.
  1475. // 2) e is the primitive data type of the incoming data.
  1476. // * if e is aitEnumInvalid, then use the gdd primitive type.
  1477. // * if e is valid and gdd primitive type is invalid, set the gdd
  1478. // primitive type to e.
  1479. // * if e is valid and so is this gdd primitive type, then convert the
  1480. // incoming data from type e to gdd primitive type.
  1481. // Bad error condition, don't do anything.
  1482. if(e==aitEnumInvalid && primitiveType()==aitEnumInvalid)
  1483. return 0;
  1484. aitIndex sz=tot;
  1485. aitEnum src_type=(e==aitEnumInvalid)?primitiveType():e;
  1486. aitEnum dest_type=(primitiveType()==aitEnumInvalid)?e:primitiveType();
  1487. // I'm not sure if this is the best way to do this.
  1488. if(sz>0)
  1489. reset(dest_type,dimension(),&sz);
  1490. if(genCopy(src_type,buf,f)==0)
  1491. rc=getDataSizeBytes();
  1492. else
  1493. rc=0;
  1494. return rc;
  1495. }
  1496. size_t gdd::in(void* buf, aitDataFormat f)
  1497. {
  1498. size_t index = inHeader(buf);
  1499. size_t rc;
  1500. if(index>0)
  1501. rc=inData(((char*)buf)+index,0,aitEnumInvalid,f)+index;
  1502. else
  1503. rc=0;
  1504. return rc;
  1505. }
  1506. //
  1507. // rewrote this to properly construct/destruct
  1508. // scalar string types when the prim type changes
  1509. // joh 05-22-98
  1510. //
  1511. //
  1512. void gdd::setPrimType (aitEnum t)
  1513. {
  1514. //
  1515. // NOOP if there is no change
  1516. //
  1517. if ( this->prim_type == t ) {
  1518. return;
  1519. }
  1520. //
  1521. // I (joh) assume that something needs to be done when
  1522. // the primative type of a container changes. For now I
  1523. // assuming that the gdd should be cleared.
  1524. //
  1525. if(isContainer()) {
  1526. this->clear();
  1527. }
  1528. //
  1529. // run constructors/destructors for string data
  1530. // if it is scalar
  1531. //
  1532. if (isScalar())
  1533. {
  1534. //
  1535. // run destructors for existing string data
  1536. //
  1537. if(primitiveType()==aitEnumFixedString)
  1538. {
  1539. // aitString type could have destructors
  1540. if ( destruct ) {
  1541. destruct->destroy(dataPointer());
  1542. destruct = 0;
  1543. }
  1544. else
  1545. if (data.FString) delete data.FString;
  1546. }
  1547. else if(primitiveType()==aitEnumString)
  1548. {
  1549. // aitString type could have destructors
  1550. if ( destruct ) {
  1551. destruct->destroy(dataAddress());
  1552. destruct = 0;
  1553. }
  1554. else
  1555. {
  1556. aitString* s = (aitString*)dataAddress();
  1557. s->clear();
  1558. }
  1559. }
  1560. //
  1561. // run constructors for new string data types
  1562. //
  1563. if (t==aitEnumString) {
  1564. aitString* str=(aitString*)dataAddress();
  1565. str->init();
  1566. }
  1567. else if (t==aitEnumFixedString) {
  1568. this->data.FString = new aitFixedString;
  1569. memset ( this->data.FString, '\0', sizeof(aitFixedString) );
  1570. }
  1571. else {
  1572. memset ( & this->data, '\0', sizeof(this->data) );
  1573. }
  1574. }
  1575. //
  1576. // I (joh) assume that Jim intended that
  1577. // calling of the destructors for arrays of string
  1578. // data when the primitive type changes is handled
  1579. // by the application. Not sure - nothing was done
  1580. // by Jim to take care of this as far as I can tell.
  1581. //
  1582. else if(isAtomic())
  1583. {
  1584. if ( dataPointer() && destruct ) {
  1585. destruct->destroy(dataPointer());
  1586. destruct=NULL;
  1587. }
  1588. memset (&this->data, '\0', sizeof(this->data));
  1589. }
  1590. this->prim_type = t;
  1591. }
  1592. //
  1593. // gdd::indexDD()
  1594. //
  1595. // modified by JOH 4-23-99 so that the correct method
  1596. // is used if the container gdd is not organized
  1597. // as an array of GDDs in memory (i.e. its not flat)
  1598. //
  1599. const gdd* gdd::indexDD (aitIndex index) const
  1600. {
  1601. aitIndex i;
  1602. unsigned nElem;
  1603. if (index==0u) {
  1604. return this;
  1605. }
  1606. //
  1607. // otherwise this had better be a container
  1608. // we are indexing
  1609. //
  1610. assert (this->prim_type==aitEnumContainer);
  1611. //
  1612. // catch out of bounds index
  1613. //
  1614. nElem = getDataSizeElements();
  1615. assert (index<=nElem);
  1616. //
  1617. // if the container GDD is "flat"
  1618. //
  1619. if (this->isFlat()) {
  1620. return this + index;
  1621. }
  1622. //
  1623. // otherwise linear search for it
  1624. //
  1625. gdd* dd = (gdd*) dataPointer();
  1626. i = nElem;
  1627. while (i>index) {
  1628. dd=(gdd*)dd->next();
  1629. i--;
  1630. }
  1631. return dd;
  1632. }
  1633. //
  1634. // gddAitUint8Destructor::run()
  1635. //
  1636. // special gddDestructor guarantees same form of new and delete
  1637. //
  1638. void gddAitUint8Destructor::run (void *pUntyped)
  1639. {
  1640. aitUint8 *pui8 = (aitUint8 *) pUntyped;
  1641. delete [] pui8;
  1642. }
  1643. //
  1644. // gddAitStringDestructor::run()
  1645. //
  1646. // special gddDestructor guarantees same form of new and delete
  1647. //
  1648. void gddAitStringDestructor::run (void *pUntyped)
  1649. {
  1650. aitString *pStr = (aitString *) pUntyped;
  1651. delete [] pStr;
  1652. }