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