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