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