0022627: Change OCCT memory management defaults
[occt.git] / src / BinObjMgt / BinObjMgt_Persistent.cxx
1 // File:      BinObjMgt_Persistent.cxx
2 // Created:   30.10.02 10:14:33
3 // Author:    Michael SAZONOV
4 // Copyright: Open CASCADE 2002
5
6 #include <BinObjMgt_Persistent.ixx>
7 #include <TColStd_ListOfInteger.hxx>
8 #include <TDF_Tool.hxx>
9 #include <TColStd_ListIteratorOfListOfInteger.hxx>
10 #include <FSD_FileHeader.hxx>
11
12 #define BP_INTSIZE         ((Standard_Integer)sizeof(Standard_Integer))
13 #define BP_EXTCHARSIZE     ((Standard_Integer)sizeof(Standard_ExtCharacter))
14 #define BP_REALSIZE        ((Standard_Integer)sizeof(Standard_Real))
15 #define BP_SHORTREALSIZE   ((Standard_Integer)sizeof(Standard_ShortReal))
16 #define BP_UUIDSIZE        ((Standard_Integer)sizeof(BinObjMgt_UUID))
17
18 // We define a GUID structure that is different from Standard_UUID because
19 // the latter contains a 'unsigned long' member that has variables size
20 // (4 or 8 bits) thus making the persistent files non-portable.
21 // This structure below ensures the portability.
22 typedef struct {
23   unsigned int   Data1 ;        // 4-bytes long on all OS
24   unsigned short Data2 ;        // 2-bytes long on all OS
25   unsigned short Data3 ;        // 2-bytes long on all OS
26   unsigned char  Data4[8] ;     // 8-bytes long on all OS
27 } BinObjMgt_UUID ;
28
29 //=======================================================================
30 //function : BinObjMgt_Persistent
31 //purpose  : Empty constructor
32 //=======================================================================
33
34 BinObjMgt_Persistent::BinObjMgt_Persistent ()
35      : myIndex (1),
36        myOffset(BP_HEADSIZE),
37        mySize  (BP_HEADSIZE),
38        myIsError (Standard_False)
39 {
40   Init();
41 }
42
43 //=======================================================================
44 //function : Init
45 //purpose  : Initializes me to reuse again
46 //=======================================================================
47
48 void BinObjMgt_Persistent::Init ()
49 {
50   if (myData.IsEmpty()) {
51     Standard_Address aPiece = Standard::Allocate (BP_PIECESIZE);
52     myData.Append (aPiece);
53   }
54   Standard_Integer *aData = (Standard_Integer*) myData(1);
55   aData[0] = 0;         // Type Id
56   aData[1] = 0;         // Object Id
57   aData[2] = 0;         // Data length
58   myIndex = 1;
59   myOffset = BP_HEADSIZE;
60   mySize = BP_HEADSIZE;
61   myIsError = Standard_False;
62 }
63
64 //=======================================================================
65 //function : Write
66 //purpose  : Stores <me> to the stream.
67 //           inline Standard_OStream& operator<< (Standard_OStream&,
68 //           const BinObjMgt_Persistent&) is also available
69 //=======================================================================
70
71 Standard_OStream& BinObjMgt_Persistent::Write (Standard_OStream& theOS)
72 {
73   Standard_Integer nbWritten = 0;
74   Standard_Integer *aData = (Standard_Integer*) myData(1);
75   // update data length
76   aData[2] = mySize - BP_HEADSIZE;
77 #if DO_INVERSE
78   aData[0] = InverseInt (aData[0]);
79   aData[1] = InverseInt (aData[1]);
80   aData[2] = InverseInt (aData[2]);
81 #endif
82   for (Standard_Integer i=1;
83        theOS && nbWritten < mySize && i <= myData.Length();
84        i++) {
85     Standard_Integer nbToWrite = Min (mySize - nbWritten, BP_PIECESIZE);
86     theOS.write ((char*)myData(i), nbToWrite);
87     nbWritten += nbToWrite;
88   }
89   myIndex = 1;
90   myOffset = BP_HEADSIZE;
91   mySize = BP_HEADSIZE;
92   myIsError = Standard_False;
93   return theOS;
94 }
95
96 //=======================================================================
97 //function : Read
98 //purpose  : Retrieves <me> from the stream.
99 //           inline Standard_IStream& operator>> (Standard_IStream&,
100 //           BinObjMgt_Persistent&) is also available
101 //=======================================================================
102
103 Standard_IStream& BinObjMgt_Persistent::Read (Standard_IStream& theIS)
104 {
105   myIndex = 1;
106   myOffset = BP_HEADSIZE;
107   mySize = BP_HEADSIZE;
108   myIsError = Standard_False;
109
110   Standard_Integer *aData = (Standard_Integer*) myData(1);
111   aData[0] = 0;         // Type Id
112   aData[1] = 0;         // Object Id
113   aData[2] = 0;         // Data length
114
115   // read TypeId
116   theIS.read ((char*) &aData[0], BP_INTSIZE);
117 #if DO_INVERSE
118   aData[0] = InverseInt (aData[0]);
119 #endif
120   if (theIS && aData[0] > 0) {
121     // read Id and Length
122     theIS.read ((char*)&aData[1], 2 * BP_INTSIZE);
123 #if DO_INVERSE
124     aData[1] = InverseInt (aData[1]);
125     aData[2] = InverseInt (aData[2]);
126 #endif
127     if (theIS && aData[1] > 0 && aData[2] > 0) {
128       mySize += aData[2];
129       // read remaining data
130       Standard_Integer nbRead = BP_HEADSIZE;
131       for (Standard_Integer i=1;
132            theIS && nbRead < mySize;
133            i++) {
134         if (i > myData.Length()) {
135           // grow myData dynamically
136           Standard_Address aPiece = Standard::Allocate (BP_PIECESIZE);
137           myData.Append (aPiece);
138         }
139         Standard_Integer nbToRead = Min (mySize - nbRead, BP_PIECESIZE);
140         char *ptr = (char*)myData(i);
141         if (i == 1) {
142           // 1st piece: reduce the number of bytes by header size
143           ptr += BP_HEADSIZE;
144           if (nbToRead == BP_PIECESIZE) nbToRead -= BP_HEADSIZE;
145         }
146         theIS.read (ptr, nbToRead);
147         nbRead += nbToRead;
148       }
149     }
150     else
151       aData[2] = 0;
152   }
153   return theIS;
154 }
155
156 //=======================================================================
157 //function : Destroy
158 //purpose  : Frees the allocated memory
159 //=======================================================================
160
161 void BinObjMgt_Persistent::Destroy ()
162 {
163   for (Standard_Integer i=1; i <= myData.Length(); i++) {
164     Standard::Free (myData(i));
165   }
166   myData.Clear();
167   myIndex = myOffset = mySize = 0;
168 }
169
170 //=======================================================================
171 //function : incrementData
172 //purpose  : Allocates theNbPieces more pieces
173 //=======================================================================
174
175 void BinObjMgt_Persistent::incrementData
176   (const Standard_Integer theNbPieces)
177 {
178   for (Standard_Integer i=1; i <= theNbPieces; i++) {
179     Standard_Address aPiece = Standard::Allocate (BP_PIECESIZE);
180     myData.Append (aPiece);
181   }
182 }
183
184 //=======================================================================
185 //function : PutCharacter
186 //purpose  : 
187 //=======================================================================
188
189 BinObjMgt_Persistent& BinObjMgt_Persistent::PutCharacter
190   (const Standard_Character theValue)
191 {
192   alignOffset (1);
193   prepareForPut (1);
194   Standard_Character *aData = (Standard_Character*) myData(myIndex) + myOffset;
195   *aData = theValue;
196   myOffset++;
197   return *this;
198 }
199
200 //=======================================================================
201 //function : PutByte
202 //purpose  : 
203 //=======================================================================
204
205 BinObjMgt_Persistent& BinObjMgt_Persistent::PutByte
206   (const Standard_Byte theValue)
207 {
208   alignOffset (1);
209   prepareForPut (1);
210   Standard_Byte *aData = (Standard_Byte*) myData(myIndex) + myOffset;
211   *aData = theValue;
212   myOffset++;
213   return *this;
214 }
215
216 //=======================================================================
217 //function : PutExtCharacter
218 //purpose  : 
219 //=======================================================================
220
221 BinObjMgt_Persistent& BinObjMgt_Persistent::PutExtCharacter
222   (const Standard_ExtCharacter theValue)
223 {
224   alignOffset (BP_EXTCHARSIZE, Standard_True);
225   prepareForPut (BP_EXTCHARSIZE);
226   Standard_ExtCharacter *aData =
227     (Standard_ExtCharacter*) ((char*)myData(myIndex) + myOffset);
228 #if DO_INVERSE
229   *aData = InverseExtChar (theValue);
230 #else
231   *aData = theValue;
232 #endif
233   myOffset += BP_EXTCHARSIZE;
234   return *this;
235 }
236
237 //=======================================================================
238 //function : PutInteger
239 //purpose  : 
240 //=======================================================================
241
242 BinObjMgt_Persistent& BinObjMgt_Persistent::PutInteger
243   (const Standard_Integer theValue)
244 {
245   alignOffset (BP_INTSIZE, Standard_True);
246   prepareForPut (BP_INTSIZE);
247   Standard_Integer *aData = (Standard_Integer*) ((char*)myData(myIndex) + myOffset);
248 #if DO_INVERSE
249   *aData = InverseInt (theValue);
250 #else
251   *aData = theValue;
252 #endif
253   myOffset += BP_INTSIZE;
254   return *this;
255 }
256
257 //=======================================================================
258 //function : PutReal
259 //purpose  : 
260 //=======================================================================
261
262 BinObjMgt_Persistent& BinObjMgt_Persistent::PutReal
263   (const Standard_Real theValue)
264 {
265   alignOffset (BP_INTSIZE, Standard_True);
266   Standard_Integer nbPieces = prepareForPut (BP_REALSIZE);
267   if (nbPieces > 0) {
268     // the value intersects a piece boundary => go a long way
269 #if DO_INVERSE
270     Standard_Integer aStartIndex = myIndex;
271     Standard_Integer aStartOffset = myOffset;
272 #endif
273     putArray ((void*) &theValue, BP_REALSIZE);
274 #if DO_INVERSE
275     inverseRealData (aStartIndex, aStartOffset, BP_REALSIZE);
276 #endif
277   }
278   else {
279     // the value fits in the current piece => put it quickly
280     Standard_Real *aData = (Standard_Real*) ((char*)myData(myIndex) + myOffset);
281 #if DO_INVERSE
282     *aData = InverseReal (theValue);
283 #else
284     *aData = theValue;
285 #endif
286     myOffset += BP_REALSIZE;
287   }
288   return *this;
289 }
290
291 //=======================================================================
292 //function : PutShortReal
293 //purpose  : 
294 //=======================================================================
295
296 BinObjMgt_Persistent& BinObjMgt_Persistent::PutShortReal
297   (const Standard_ShortReal theValue)
298 {
299   alignOffset (BP_INTSIZE, Standard_True);
300   prepareForPut (BP_SHORTREALSIZE);
301   Standard_ShortReal *aData = (Standard_ShortReal*) ((char*)myData(myIndex) + myOffset);
302 #if DO_INVERSE
303   *aData = InverseShortReal (theValue);
304 #else
305   *aData = theValue;
306 #endif
307   myOffset += BP_SHORTREALSIZE;
308   return *this;
309 }
310
311 //=======================================================================
312 //function : PutCString
313 //purpose  : Offset in output buffer is not aligned
314 //=======================================================================
315
316 BinObjMgt_Persistent& BinObjMgt_Persistent::PutCString
317   (const Standard_CString theValue)
318 {
319   alignOffset (1);
320   Standard_Integer aSize = strlen (theValue) + 1;
321   prepareForPut (aSize);
322   putArray ((void* const)theValue, aSize);
323   return *this;
324 }
325
326 //=======================================================================
327 //function : PutAsciiString
328 //purpose  : Offset in output buffer is word-aligned
329 //=======================================================================
330
331 BinObjMgt_Persistent& BinObjMgt_Persistent::PutAsciiString
332   (const TCollection_AsciiString& theValue)
333 {
334   alignOffset (BP_INTSIZE, Standard_True);
335   Standard_Integer aSize = theValue.Length() + 1;
336   prepareForPut (aSize);
337   putArray ((void* const)theValue.ToCString(), aSize);
338   return *this;
339 }
340
341 //=======================================================================
342 //function : PutExtendedString
343 //purpose  : Offset in output buffer is word-aligned
344 //=======================================================================
345
346 BinObjMgt_Persistent& BinObjMgt_Persistent::PutExtendedString
347   (const TCollection_ExtendedString& theValue)
348 {
349   alignOffset (BP_INTSIZE, Standard_True);
350   Standard_Integer aSize = (theValue.Length() + 1) * BP_EXTCHARSIZE;
351   prepareForPut (aSize);
352 #if DO_INVERSE
353   Standard_Integer aStartIndex = myIndex;
354   Standard_Integer aStartOffset = myOffset;
355 #endif
356   putArray ((void* const)theValue.ToExtString(), aSize);
357 #if DO_INVERSE
358   inverseExtCharData (aStartIndex, aStartOffset, aSize - BP_EXTCHARSIZE);
359 #endif
360   return *this;
361 }
362
363 //=======================================================================
364 //function : PutLabel
365 //purpose  : 
366 //=======================================================================
367
368 BinObjMgt_Persistent& BinObjMgt_Persistent::PutLabel
369   (const TDF_Label& theValue)
370 {
371   alignOffset (BP_INTSIZE, Standard_True);
372   Standard_Integer aLen = (theValue.IsNull() ? 0 : theValue.Depth()+1);
373   prepareForPut ((aLen + 1) * BP_INTSIZE);
374   Standard_Integer *aData = (Standard_Integer*) ((char*)myData(myIndex) + myOffset);
375   // store nb of tags
376 #if DO_INVERSE
377   *aData++ = InverseInt (aLen);
378 #else
379   *aData++ = aLen;
380 #endif
381   myOffset += BP_INTSIZE;
382   if (!theValue.IsNull()) {
383     TColStd_ListOfInteger aTagList;
384     TDF_Tool::TagList (theValue, aTagList);
385     TColStd_ListIteratorOfListOfInteger itTag(aTagList);
386     for (; itTag.More(); itTag.Next()) {
387       if (myOffset >= BP_PIECESIZE) {
388         myOffset = 0;
389         myIndex++;
390         aData = (Standard_Integer*) ((char*)myData(myIndex) + myOffset);
391       }
392 #if DO_INVERSE
393       *aData++ = InverseInt (itTag.Value());
394 #else
395       *aData++ = itTag.Value();
396 #endif
397       myOffset += BP_INTSIZE;
398     }
399   }
400   return *this;
401 }
402
403 //=======================================================================
404 //function : PutGUID
405 //purpose  : 
406 //=======================================================================
407
408 BinObjMgt_Persistent& BinObjMgt_Persistent::PutGUID
409   (const Standard_GUID& theValue)
410 {
411   alignOffset (BP_INTSIZE, Standard_True);
412   prepareForPut (BP_UUIDSIZE);
413   const Standard_UUID aStandardUUID = theValue.ToUUID();
414   BinObjMgt_UUID anUUID;
415   anUUID.Data1 = (unsigned int)   aStandardUUID.Data1;
416   anUUID.Data2 = (unsigned short) aStandardUUID.Data2;
417   anUUID.Data3 = (unsigned short) aStandardUUID.Data3;
418   anUUID.Data4[0] = aStandardUUID.Data4[0];
419   anUUID.Data4[1] = aStandardUUID.Data4[1];
420   anUUID.Data4[2] = aStandardUUID.Data4[2];
421   anUUID.Data4[3] = aStandardUUID.Data4[3];
422   anUUID.Data4[4] = aStandardUUID.Data4[4];
423   anUUID.Data4[5] = aStandardUUID.Data4[5];
424   anUUID.Data4[6] = aStandardUUID.Data4[6];
425   anUUID.Data4[7] = aStandardUUID.Data4[7];
426 #if DO_INVERSE
427   anUUID.Data1 = (unsigned int)   InverseInt     (anUUID.Data1);
428   anUUID.Data2 = (unsigned short) InverseExtChar (anUUID.Data2);
429   anUUID.Data3 = (unsigned short) InverseExtChar (anUUID.Data3);
430 #endif
431   putArray (&anUUID, BP_UUIDSIZE);
432   return *this;
433 }
434
435 //=======================================================================
436 //function : PutCharArray
437 //purpose  : Put C array of char, theLength is the number of elements
438 //=======================================================================
439
440 BinObjMgt_Persistent& BinObjMgt_Persistent::PutCharArray
441   (const BinObjMgt_PChar  theArray,
442    const Standard_Integer theLength)
443 {
444   alignOffset (1);
445   prepareForPut (theLength);
446   putArray (theArray, theLength);
447   return *this;
448 }
449
450 //=======================================================================
451 //function : PutByteArray
452 //purpose  : Put C array of byte, theLength is the number of elements
453 //=======================================================================
454
455 BinObjMgt_Persistent& BinObjMgt_Persistent::PutByteArray
456   (const BinObjMgt_PByte  theArray,
457    const Standard_Integer theLength)
458 {
459   alignOffset (1);
460   prepareForPut (theLength);
461   putArray (theArray, theLength);
462   return *this;
463 }
464
465 //=======================================================================
466 //function : PutExtCharArray
467 //purpose  : Put C array of ExtCharacter, theLength is the number of elements
468 //=======================================================================
469
470 BinObjMgt_Persistent& BinObjMgt_Persistent::PutExtCharArray
471   (const BinObjMgt_PExtChar theArray,
472    const Standard_Integer   theLength)
473 {
474   alignOffset (BP_EXTCHARSIZE, Standard_True);
475   Standard_Integer aSize = theLength * BP_EXTCHARSIZE;
476   prepareForPut (aSize);
477 #if DO_INVERSE
478   Standard_Integer aStartIndex = myIndex;
479   Standard_Integer aStartOffset = myOffset;
480 #endif
481   putArray (theArray, aSize);
482 #if DO_INVERSE
483   inverseExtCharData (aStartIndex, aStartOffset, aSize);
484 #endif
485   return *this;
486 }
487
488 //=======================================================================
489 //function : PutIntArray
490 //purpose  : Put C array of int, theLength is the number of elements
491 //=======================================================================
492
493 BinObjMgt_Persistent& BinObjMgt_Persistent::PutIntArray
494   (const BinObjMgt_PInteger theArray,
495    const Standard_Integer   theLength)
496 {
497   alignOffset (BP_INTSIZE, Standard_True);
498   Standard_Integer aSize = theLength * BP_INTSIZE;
499   prepareForPut (aSize);
500 #if DO_INVERSE
501   Standard_Integer aStartIndex = myIndex;
502   Standard_Integer aStartOffset = myOffset;
503 #endif
504   putArray (theArray, aSize);
505 #if DO_INVERSE
506   inverseIntData (aStartIndex, aStartOffset, aSize);
507 #endif
508   return *this;
509 }
510
511 //=======================================================================
512 //function : PutRealArray
513 //purpose  : Put C array of double, theLength is the number of elements
514 //=======================================================================
515
516 BinObjMgt_Persistent& BinObjMgt_Persistent::PutRealArray
517   (const BinObjMgt_PReal  theArray,
518    const Standard_Integer theLength)
519 {
520   alignOffset (BP_INTSIZE, Standard_True);
521   Standard_Integer aSize = theLength * BP_REALSIZE;
522   prepareForPut (aSize);
523 #if DO_INVERSE
524   Standard_Integer aStartIndex = myIndex;
525   Standard_Integer aStartOffset = myOffset;
526 #endif
527   putArray (theArray, aSize);
528 #if DO_INVERSE
529   inverseRealData (aStartIndex, aStartOffset, aSize);
530 #endif
531   return *this;
532 }
533
534 //=======================================================================
535 //function : PutShortRealArray
536 //purpose  : Put C array of float, theLength is the number of elements
537 //=======================================================================
538
539 BinObjMgt_Persistent& BinObjMgt_Persistent::PutShortRealArray
540   (const BinObjMgt_PShortReal theArray,
541    const Standard_Integer     theLength)
542 {
543   alignOffset (BP_INTSIZE, Standard_True);
544   Standard_Integer aSize = theLength * BP_SHORTREALSIZE;
545   prepareForPut (aSize);
546 #if DO_INVERSE
547   Standard_Integer aStartIndex = myIndex;
548   Standard_Integer aStartOffset = myOffset;
549 #endif
550   putArray (theArray, aSize);
551 #if DO_INVERSE
552   inverseShortRealData (aStartIndex, aStartOffset, aSize);
553 #endif
554   return *this;
555 }
556
557 //=======================================================================
558 //function : GetCharacter
559 //purpose  : 
560 //=======================================================================
561
562 const BinObjMgt_Persistent& BinObjMgt_Persistent::GetCharacter
563   (Standard_Character& theValue) const
564 {
565   alignOffset (1);
566   if (noMoreData (1)) return *this;
567   Standard_Character *aData = (Standard_Character*) myData(myIndex) + myOffset;
568   theValue = *aData;
569   ((BinObjMgt_Persistent*)this)->myOffset++;
570   return *this;
571 }
572
573 //=======================================================================
574 //function : GetByte
575 //purpose  : 
576 //=======================================================================
577
578 const BinObjMgt_Persistent& BinObjMgt_Persistent::GetByte
579   (Standard_Byte& theValue) const
580 {
581   alignOffset (1);
582   if (noMoreData (1)) return *this;
583   Standard_Byte *aData = (Standard_Byte*) myData(myIndex) + myOffset;
584   theValue = *aData;
585   ((BinObjMgt_Persistent*)this)->myOffset++;
586   return *this;
587 }
588
589 //=======================================================================
590 //function : GetExtCharacter
591 //purpose  : 
592 //=======================================================================
593
594 const BinObjMgt_Persistent& BinObjMgt_Persistent::GetExtCharacter
595   (Standard_ExtCharacter& theValue) const
596 {
597   alignOffset (BP_EXTCHARSIZE);
598   if (noMoreData (BP_EXTCHARSIZE)) return *this;
599   Standard_ExtCharacter *aData =
600     (Standard_ExtCharacter*) ((char*)myData(myIndex) + myOffset);
601 #if DO_INVERSE
602   theValue = InverseExtChar (*aData);
603 #else
604   theValue = *aData;
605 #endif
606   ((BinObjMgt_Persistent*)this)->myOffset += BP_EXTCHARSIZE;
607   return *this;
608 }
609
610 //=======================================================================
611 //function : GetInteger
612 //purpose  : 
613 //=======================================================================
614
615 const BinObjMgt_Persistent& BinObjMgt_Persistent::GetInteger
616   (Standard_Integer& theValue) const
617 {
618   alignOffset (BP_INTSIZE);
619   if (noMoreData (BP_INTSIZE)) return *this;
620   Standard_Integer *aData = (Standard_Integer*) ((char*)myData(myIndex) + myOffset);
621 #if DO_INVERSE
622   theValue = InverseInt (*aData);
623 #else
624   theValue = *aData;
625 #endif
626   ((BinObjMgt_Persistent*)this)->myOffset += BP_INTSIZE;
627   return *this;
628 }
629
630 //=======================================================================
631 //function : GetReal
632 //purpose  : 
633 //=======================================================================
634
635 const BinObjMgt_Persistent& BinObjMgt_Persistent::GetReal
636   (Standard_Real& theValue) const
637 {
638   alignOffset (BP_INTSIZE);
639   if (noMoreData (BP_REALSIZE)) return *this;
640   Standard_Integer nbPieces = (myOffset + BP_REALSIZE - 1) / BP_PIECESIZE;
641   if (nbPieces > 0) {
642     // the value intersects a piece boundary => go a long way
643     getArray ((void*) &theValue, BP_REALSIZE);
644   }
645   else {
646     // the value fits in the current piece => get it quickly
647     Standard_Real *aData = (Standard_Real*) ((char*)myData(myIndex) + myOffset);
648     theValue = *aData;
649     ((BinObjMgt_Persistent*)this)->myOffset += BP_REALSIZE;
650   }
651 #if DO_INVERSE
652   theValue = InverseReal (theValue);
653 #endif
654   return *this;
655 }
656
657 //=======================================================================
658 //function : GetShortReal
659 //purpose  : 
660 //=======================================================================
661
662 const BinObjMgt_Persistent& BinObjMgt_Persistent::GetShortReal
663   (Standard_ShortReal& theValue) const
664 {
665   alignOffset (BP_INTSIZE);
666   if (noMoreData (BP_SHORTREALSIZE)) return *this;
667   Standard_ShortReal *aData = (Standard_ShortReal*) ((char*)myData(myIndex) + myOffset);
668 #if DO_INVERSE
669   theValue = InverseShortReal (*aData);
670 #else
671   theValue = *aData;
672 #endif
673   ((BinObjMgt_Persistent*)this)->myOffset += BP_SHORTREALSIZE;
674   return *this;
675 }
676
677 //=======================================================================
678 //function : GetAsciiString
679 //purpose  : 
680 //=======================================================================
681
682 const BinObjMgt_Persistent& BinObjMgt_Persistent::GetAsciiString
683   (TCollection_AsciiString& theValue) const
684 {
685   alignOffset (BP_INTSIZE);
686   Standard_Integer aStartIndex = myIndex;
687   Standard_Integer aStartOffset = myOffset;
688   BinObjMgt_Persistent* me = (BinObjMgt_Persistent*)this;
689   char *aData = (char*) myData(myIndex) + myOffset;
690
691   // count the string length
692   while (!noMoreData (1) && *aData++) {
693     me->myOffset++;
694     if (myOffset >= BP_PIECESIZE) {
695       me->myOffset = 0;
696       aData = (char*) myData(++me->myIndex);
697     }
698   }
699   if (IsError()) {
700     me->myIndex = aStartIndex;
701     me->myOffset = aStartOffset;
702     return *this;
703   }
704   me->myOffset++;  // count the end null char
705
706   if (myIndex == aStartIndex) {
707     // all string is in one piece => simply copy
708     theValue = aData - myOffset + aStartOffset;
709   }
710   else {
711     // work through buffer string
712     Standard_Integer aSize = (myIndex - aStartIndex) * BP_PIECESIZE +
713       myOffset - aStartOffset;
714     Standard_Address aString = Standard::Allocate (aSize);
715     me->myIndex = aStartIndex;
716     me->myOffset = aStartOffset;
717     getArray (aString, aSize);
718     theValue = (char*) aString;
719     Standard::Free (aString);
720   }
721
722   return *this;
723 }
724
725 //=======================================================================
726 //function : GetExtendedString
727 //purpose  : 
728 //=======================================================================
729
730 const BinObjMgt_Persistent& BinObjMgt_Persistent::GetExtendedString
731   (TCollection_ExtendedString& theValue) const
732 {
733   alignOffset (BP_INTSIZE);
734   Standard_Integer aStartIndex = myIndex;
735   Standard_Integer aStartOffset = myOffset;
736   BinObjMgt_Persistent* me = (BinObjMgt_Persistent*)this;
737   Standard_ExtCharacter *aData =
738     (Standard_ExtCharacter*) ((char*)myData(myIndex) + myOffset);
739
740   // count the string length
741   while (!noMoreData (1) && *aData++) {
742     me->myOffset += BP_EXTCHARSIZE;
743     if (myOffset >= BP_PIECESIZE) {
744       me->myOffset = 0;
745       aData = (Standard_ExtCharacter*) myData(++me->myIndex);
746     }
747   }
748   if (IsError()) {
749     me->myIndex = aStartIndex;
750     me->myOffset = aStartOffset;
751     return *this;
752   }
753   me->myOffset += BP_EXTCHARSIZE;  // count the end null char
754
755   if (myIndex == aStartIndex) {
756     // all string is in one piece => simply copy
757     theValue = aData - (myOffset - aStartOffset) / BP_EXTCHARSIZE;
758   }
759   else {
760     // work through buffer string
761     Standard_Integer aSize = (myIndex - aStartIndex) * BP_PIECESIZE +
762       (myOffset - aStartOffset);
763     Standard_Address aString = Standard::Allocate (aSize);
764     me->myIndex = aStartIndex;
765     me->myOffset = aStartOffset;
766     getArray (aString, aSize);
767     theValue = (Standard_ExtCharacter*) aString;
768     Standard::Free (aString);
769   }
770 #if DO_INVERSE
771   Standard_PExtCharacter aString = (Standard_PExtCharacter)theValue.ToExtString();
772   for (Standard_Integer i=0; i < theValue.Length(); i++)
773     aString[i] = InverseExtChar (aString[i]);
774 #endif
775
776   return *this;
777 }
778
779 //=======================================================================
780 //function : GetLabel
781 //purpose  : 
782 //=======================================================================
783
784 const BinObjMgt_Persistent& BinObjMgt_Persistent::GetLabel
785   (const Handle(TDF_Data)& theDS,
786    TDF_Label& theValue) const
787 {
788   theValue.Nullify();
789   alignOffset (BP_INTSIZE);
790   if (noMoreData (BP_INTSIZE)) return *this;
791   BinObjMgt_Persistent* me = (BinObjMgt_Persistent*)this;
792   // retrieve nb of tags
793   Standard_Integer *aData = (Standard_Integer*) ((char*)myData(myIndex) + myOffset);
794   Standard_Integer aLen = *aData++;
795 #if DO_INVERSE
796   aLen = InverseInt (aLen);
797 #endif
798   me->myOffset += BP_INTSIZE;
799   if (noMoreData (aLen * BP_INTSIZE)) return *this;
800
801   if (aLen > 0) {
802     // retrieve tag list
803     TColStd_ListOfInteger aTagList;
804     while (aLen > 0) {
805       if (myOffset >= BP_PIECESIZE) {
806         me->myOffset = 0;
807         me->myIndex++;
808         aData = (Standard_Integer*) ((char*)myData(myIndex) + myOffset);
809       }
810 #if DO_INVERSE
811       aTagList.Append (InverseInt (*aData++));
812 #else
813       aTagList.Append (*aData++);
814 #endif
815       me->myOffset += BP_INTSIZE;
816       aLen--;
817     }
818     // find label by entry
819     TDF_Tool::Label (theDS, aTagList, theValue, Standard_True);
820   }
821   return *this;
822 }
823
824 //=======================================================================
825 //function : GetGUID
826 //purpose  : 
827 //=======================================================================
828
829 const BinObjMgt_Persistent& BinObjMgt_Persistent::GetGUID
830   (Standard_GUID& theValue) const
831 {
832   alignOffset (BP_INTSIZE);
833   if (noMoreData (BP_UUIDSIZE))
834     return *this;
835   BinObjMgt_UUID anUUID;
836   getArray (&anUUID, BP_UUIDSIZE);
837 #if DO_INVERSE
838   anUUID.Data1 = (unsigned int)   InverseInt     (anUUID.Data1);
839   anUUID.Data2 = (unsigned short) InverseExtChar (anUUID.Data2);
840   anUUID.Data3 = (unsigned short) InverseExtChar (anUUID.Data3);
841 #endif
842   theValue = Standard_GUID (anUUID.Data1, anUUID.Data2, anUUID.Data3,
843                             ((anUUID.Data4[0] << 8) | (anUUID.Data4[1])),
844                             anUUID.Data4[2], anUUID.Data4[3], anUUID.Data4[4],
845                             anUUID.Data4[5], anUUID.Data4[6], anUUID.Data4[7]);
846   return *this;
847 }
848
849 //=======================================================================
850 //function : GetCharArray
851 //purpose  : Get C array of char, theLength is the number of elements;
852 //           theArray must point to a 
853 //           space enough to place theLength elements
854 //=======================================================================
855
856 const BinObjMgt_Persistent& BinObjMgt_Persistent::GetCharArray
857   (const BinObjMgt_PChar  theArray,
858    const Standard_Integer theLength) const
859 {
860   alignOffset (1);
861   if (noMoreData (theLength)) return *this;
862   getArray (theArray, theLength);
863   return *this;
864 }
865
866 //=======================================================================
867 //function : GetByteArray
868 //purpose  : Get C array of unsigned chars, theLength is the number of elements;
869 //           theArray must point to a 
870 //           space enough to place theLength elements
871 //=======================================================================
872
873 const BinObjMgt_Persistent& BinObjMgt_Persistent::GetByteArray
874   (const BinObjMgt_PByte  theArray,
875    const Standard_Integer theLength) const
876 {
877   alignOffset (1);
878   if (noMoreData (theLength)) return *this;
879   getArray (theArray, theLength);
880   return *this;
881 }
882
883 //=======================================================================
884 //function : GetExtCharArray
885 //purpose  : Get C array of ExtCharacter, theLength is the number of elements;
886 //           theArray must point to a 
887 //           space enough to place theLength elements
888 //=======================================================================
889
890 const BinObjMgt_Persistent& BinObjMgt_Persistent::GetExtCharArray
891   (const BinObjMgt_PExtChar theArray,
892    const Standard_Integer   theLength) const
893 {
894   alignOffset (BP_EXTCHARSIZE, Standard_True);
895   Standard_Integer aSize = theLength * BP_EXTCHARSIZE;
896   if (noMoreData (aSize)) return *this;
897   getArray (theArray, aSize);
898 #if DO_INVERSE
899   for (Standard_Integer i=0; i < theLength; i++)
900     theArray[i] = InverseExtChar (theArray[i]);
901 #endif
902   return *this;
903 }
904
905 //=======================================================================
906 //function : GetIntArray
907 //purpose  : Get C array of int, theLength is the number of elements;
908 //           theArray must point to a 
909 //           space enough to place theLength elements
910 //=======================================================================
911
912 const BinObjMgt_Persistent& BinObjMgt_Persistent::GetIntArray
913   (const BinObjMgt_PInteger theArray,
914    const Standard_Integer   theLength) const
915 {
916   alignOffset (BP_INTSIZE, Standard_True);
917   Standard_Integer aSize = theLength * BP_INTSIZE;
918   if (noMoreData (aSize)) return *this;
919   getArray (theArray, aSize);
920 #if DO_INVERSE
921   for (Standard_Integer i=0; i < theLength; i++)
922     theArray[i] = InverseInt (theArray[i]);
923 #endif
924   return *this;
925 }
926
927 //=======================================================================
928 //function : GetRealArray
929 //purpose  : Get C array of double, theLength is the number of elements;
930 //           theArray must point to a 
931 //           space enough to place theLength elements
932 //=======================================================================
933
934 const BinObjMgt_Persistent& BinObjMgt_Persistent::GetRealArray
935   (const BinObjMgt_PReal  theArray,
936    const Standard_Integer theLength) const
937 {
938   alignOffset (BP_INTSIZE, Standard_True);
939   Standard_Integer aSize = theLength * BP_REALSIZE;
940   if (noMoreData (aSize)) return *this;
941   getArray (theArray, aSize);
942 #if DO_INVERSE
943   for (Standard_Integer i=0; i < theLength; i++)
944     theArray[i] = InverseReal (theArray[i]);
945 #endif
946   return *this;
947 }
948
949 //=======================================================================
950 //function : GetShortRealArray
951 //purpose  : Get C array of float, theLength is the number of elements;
952 //           theArray must point to a 
953 //           space enough to place theLength elements
954 //=======================================================================
955
956 const BinObjMgt_Persistent& BinObjMgt_Persistent::GetShortRealArray
957   (const BinObjMgt_PShortReal theArray,
958    const Standard_Integer     theLength) const
959 {
960   alignOffset (BP_INTSIZE, Standard_True);
961   Standard_Integer aSize = theLength * BP_SHORTREALSIZE;
962   if (noMoreData (aSize)) return *this;
963   getArray (theArray, aSize);
964 #if DO_INVERSE
965   for (Standard_Integer i=0; i < theLength; i++)
966     theArray[i] = InverseShortReal (theArray[i]);
967 #endif
968   return *this;
969 }
970
971 //=======================================================================
972 //function : putArray
973 //purpose  : Puts theSize bytes from theArray
974 //=======================================================================
975
976 void BinObjMgt_Persistent::putArray
977   (const Standard_Address theArray,
978    const Standard_Integer theSize)
979 {
980   char *aPtr = (char*) theArray;
981   Standard_Integer aLen = theSize;
982   while (aLen > 0) {
983     if (myOffset >= BP_PIECESIZE) {
984       myIndex++;
985       myOffset = 0;
986     }
987     Standard_Integer aLenInPiece = Min (aLen, BP_PIECESIZE - myOffset);
988     char *aData = (char*) myData(myIndex) + myOffset;
989     memcpy (aData, aPtr, aLenInPiece);
990     aLen -= aLenInPiece;
991     aPtr += aLenInPiece;
992     myOffset += aLenInPiece;
993   }
994 }
995
996 //=======================================================================
997 //function : getArray
998 //purpose  : Gets theLength bytes into theArray
999 //=======================================================================
1000
1001 void BinObjMgt_Persistent::getArray
1002   (const Standard_Address theArray,
1003    const Standard_Integer theSize) const
1004 {
1005   char *aPtr = (char*) theArray;
1006   Standard_Integer aLen = theSize;
1007   BinObjMgt_Persistent *me = (BinObjMgt_Persistent*) this;
1008   while (aLen > 0) {
1009     if (myOffset >= BP_PIECESIZE) {
1010       me->myIndex++;
1011       me->myOffset = 0;
1012     }
1013     Standard_Integer aLenInPiece = Min (aLen, BP_PIECESIZE - myOffset);
1014     char *aData = (char*) myData(myIndex) + myOffset;
1015     memcpy (aPtr, aData, aLenInPiece);
1016     aLen -= aLenInPiece;
1017     aPtr += aLenInPiece;
1018     me->myOffset += aLenInPiece;
1019   }
1020 }
1021
1022 //=======================================================================
1023 //function : inverseExtCharData
1024 //purpose  : Inverses bytes in the data addressed by the given values
1025 //=======================================================================
1026
1027 void BinObjMgt_Persistent::inverseExtCharData
1028   (const Standard_Integer theIndex,
1029    const Standard_Integer theOffset,
1030    const Standard_Integer theSize)
1031 {
1032   Standard_Integer anIndex = theIndex;
1033   Standard_Integer anOffset = theOffset;
1034   Standard_Integer aLen = theSize;
1035   while (aLen > 0) {
1036     Standard_Integer aLenInPiece = Min (aLen, BP_PIECESIZE - anOffset);
1037     Standard_ExtCharacter *aData = (Standard_ExtCharacter*)
1038       ( (char*) myData(anIndex) + anOffset);
1039     for (Standard_Integer i=0; i < aLenInPiece / BP_EXTCHARSIZE; i++)
1040       aData[i] = InverseExtChar (aData[i]);
1041     aLen -= aLenInPiece;
1042     anOffset += aLenInPiece;
1043     if (anOffset >= BP_PIECESIZE) {
1044       anIndex++;
1045       anOffset = 0;
1046     }
1047   }
1048 }
1049
1050 //=======================================================================
1051 //function : inverseIntData
1052 //purpose  : Inverses bytes in the data addressed by the given values
1053 //=======================================================================
1054
1055 void BinObjMgt_Persistent::inverseIntData
1056   (const Standard_Integer theIndex,
1057    const Standard_Integer theOffset,
1058    const Standard_Integer theSize)
1059 {
1060   Standard_Integer anIndex = theIndex;
1061   Standard_Integer anOffset = theOffset;
1062   Standard_Integer aLen = theSize;
1063   while (aLen > 0) {
1064     Standard_Integer aLenInPiece = Min (aLen, BP_PIECESIZE - anOffset);
1065     Standard_Integer *aData = (Standard_Integer*) ((char*)myData(anIndex) + anOffset);
1066     for (Standard_Integer i=0; i < aLenInPiece / BP_INTSIZE; i++)
1067       aData[i] = InverseInt (aData[i]);
1068     aLen -= aLenInPiece;
1069     anOffset += aLenInPiece;
1070     if (anOffset >= BP_PIECESIZE) {
1071       anIndex++;
1072       anOffset = 0;
1073     }
1074   }
1075 }
1076
1077 //=======================================================================
1078 //function : inverseRealData
1079 //purpose  : Inverses bytes in the data addressed by the given values
1080 //=======================================================================
1081
1082 void BinObjMgt_Persistent::inverseRealData
1083   (const Standard_Integer theIndex,
1084    const Standard_Integer theOffset,
1085    const Standard_Integer theSize)
1086 {
1087   Standard_Integer anIndex = theIndex;
1088   Standard_Integer anOffset = theOffset;
1089   Standard_Integer aLen = theSize;
1090   void *aPrevPtr = 0;
1091   while (aLen > 0) {
1092     Standard_Integer aLenInPiece = Min (aLen, BP_PIECESIZE - anOffset);
1093     Standard_Real *aData = (Standard_Real*) ((char*)myData(anIndex) + anOffset);
1094     if (aPrevPtr) {
1095       Standard_Integer aTmp;
1096       aTmp = InverseInt (*(Standard_Integer*)aPrevPtr);
1097       *(Standard_Integer*)aPrevPtr = InverseInt (*(Standard_Integer*)aData);
1098       *(Standard_Integer*)aData = aTmp;
1099       ((Standard_Integer*&)aData)++;
1100       aPrevPtr = 0;
1101     }
1102     for (Standard_Integer i=0; i < aLenInPiece / BP_REALSIZE; i++)
1103       aData[i] = InverseReal (aData[i]);
1104     if (aLenInPiece % BP_REALSIZE)
1105       aPrevPtr = &aData[aLenInPiece / BP_REALSIZE];
1106     aLen -= aLenInPiece;
1107     anOffset += aLenInPiece;
1108     if (anOffset >= BP_PIECESIZE) {
1109       anIndex++;
1110       anOffset = 0;
1111     }
1112   }
1113 }
1114
1115 //=======================================================================
1116 //function : inverseShortRealData
1117 //purpose  : Inverses bytes in the data addressed by the given values
1118 //=======================================================================
1119
1120 void BinObjMgt_Persistent::inverseShortRealData
1121   (const Standard_Integer theIndex,
1122    const Standard_Integer theOffset,
1123    const Standard_Integer theSize)
1124 {
1125   Standard_Integer anIndex = theIndex;
1126   Standard_Integer anOffset = theOffset;
1127   Standard_Integer aLen = theSize;
1128   while (aLen > 0) {
1129     Standard_Integer aLenInPiece = Min (aLen, BP_PIECESIZE - anOffset);
1130     Standard_ShortReal *aData =
1131       (Standard_ShortReal *) ((char *)myData(anIndex) + anOffset);
1132     for (Standard_Integer i=0; i < aLenInPiece / BP_INTSIZE; i++)
1133       aData[i] = InverseShortReal (aData[i]);
1134     aLen -= aLenInPiece;
1135     anOffset += aLenInPiece;
1136     if (anOffset >= BP_PIECESIZE) {
1137       anIndex++;
1138       anOffset = 0;
1139     }
1140   }
1141 }