0031136: Modeling Data - BinXCAF persistence loses normals from triangulation-only...
[occt.git] / src / BinLDrivers / BinLDrivers_DocumentSection.cxx
1 // Created on: 2008-06-20
2 // Created by: Alexander GRIGORIEV
3 // Copyright (c) 2008-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 #include <BinLDrivers_DocumentSection.hxx>
17 #include <TDocStd_FormatVersion.hxx>
18 #include <FSD_FileHeader.hxx>
19 #include <BinMDataStd.hxx>
20
21 //=======================================================================
22 //function : BinLDrivers_DocumentSection
23 //purpose  : Empty constructor
24 //=======================================================================
25
26 BinLDrivers_DocumentSection::BinLDrivers_DocumentSection ()
27   : myIsPostRead (Standard_False)
28 {
29   myValue[0] = 0;
30   myValue[1] = 0;
31 }
32
33 //=======================================================================
34 //function : BinLDrivers_DocumentSection
35 //purpose  : Constructor
36 //=======================================================================
37
38 BinLDrivers_DocumentSection::BinLDrivers_DocumentSection
39                         (const TCollection_AsciiString& theName,
40                          const Standard_Boolean         isPostRead)
41   : myName       (theName),
42     myIsPostRead (isPostRead)
43 {
44   myValue[0] = 0;
45   myValue[1] = 0;
46 }
47
48 //=======================================================================
49 //function : Name
50 //purpose  : 
51 //=======================================================================
52
53 const TCollection_AsciiString&  BinLDrivers_DocumentSection::Name () const
54 {
55   return myName;
56 }
57
58 //=======================================================================
59 //function : Offset
60 //purpose  : 
61 //=======================================================================
62
63 uint64_t BinLDrivers_DocumentSection::Offset () const
64 {
65   return myValue[0];
66 }
67
68 //=======================================================================
69 //function : SetOffset
70 //purpose  : 
71 //=======================================================================
72
73 void BinLDrivers_DocumentSection::SetOffset (const uint64_t theOffset)
74 {
75   myValue[0] = theOffset;
76 }
77
78 //=======================================================================
79 //function : IsPostRead
80 //purpose  : 
81 //=======================================================================
82
83 Standard_Boolean BinLDrivers_DocumentSection::IsPostRead () const
84 {
85   return myIsPostRead;
86 }
87
88 //=======================================================================
89 //function : Length
90 //purpose  : 
91 //=======================================================================
92
93 uint64_t BinLDrivers_DocumentSection::Length () const
94 {
95   return myValue[1];
96 }
97
98 //=======================================================================
99 //function : SetLength
100 //purpose  : 
101 //=======================================================================
102
103 void BinLDrivers_DocumentSection::SetLength (const uint64_t theLength)
104 {
105   myValue[1] = theLength;
106 }
107
108 //=======================================================================
109 //function : WriteTOC
110 //purpose  : 
111 //=======================================================================
112
113 void BinLDrivers_DocumentSection::WriteTOC (Standard_OStream& theStream,
114                                             const TDocStd_FormatVersion theDocFormatVersion)
115 {
116   char aBuf[512];
117
118   if (myName.IsEmpty() == Standard_False) {
119     Standard_Integer * aBufSz = reinterpret_cast<Standard_Integer *> (&aBuf[0]);
120     const Standard_Size aBufSzSize = sizeof(aBuf) / sizeof(Standard_Integer);
121     aBufSz[aBufSzSize-1] = 0;
122
123     strncpy (&aBuf[sizeof(Standard_Integer)],
124              myName.ToCString(),
125              sizeof(aBuf)-sizeof(Standard_Integer)-1);
126
127     // Calculate the length of the buffer: Standard_Size + string.
128     // If the length is not multiple of Standard_Size, it is properly increased
129     const Standard_Size aLen = strlen (&aBuf[sizeof(Standard_Integer)]);
130     Standard_Size aBufSize =
131       (aLen/sizeof(Standard_Integer))*sizeof(Standard_Integer);
132     if (aBufSize < aLen)
133       aBufSize += sizeof(Standard_Integer);
134
135     // Write the buffer: size + string
136 #if DO_INVERSE
137     aBufSz[0] = InverseInt ((Standard_Integer)aBufSize);
138 #else
139     aBufSz[0] = (Standard_Integer)aBufSize;
140 #endif
141     theStream.write (&aBuf[0], aBufSize + sizeof(Standard_Integer));
142
143     // Store the address of Offset word in the file
144     myValue[0] = (uint64_t) theStream.tellp();
145     myValue[1] = 0;
146
147     // Write the placeholders of Offset and Length of the section that should
148     // be written afterwards
149     aBufSz[0] = 0;
150     aBufSz[1] = 0;
151     aBufSz[2] = 0;
152     if (theDocFormatVersion <= TDocStd_FormatVersion_VERSION_9)
153     {
154       theStream.write(&aBuf[0], 3*sizeof(Standard_Integer));
155     }
156     else
157     {
158       theStream.write(&aBuf[0], 3*sizeof(uint64_t));
159     }
160   }
161 }
162
163 //=======================================================================
164 //function : Write
165 //purpose  : 
166 //=======================================================================
167
168 void BinLDrivers_DocumentSection::Write (Standard_OStream&   theStream,
169                                          const uint64_t theOffset,
170                                          const TDocStd_FormatVersion theDocFormatVersion)
171 {
172   const uint64_t aSectionEnd = (uint64_t) theStream.tellp();
173   theStream.seekp((std::streamsize)myValue[0]);
174   myValue[0] = theOffset;
175   myValue[1] = aSectionEnd - theOffset;
176   if (theDocFormatVersion <= TDocStd_FormatVersion_VERSION_9)
177   {
178     // Check the limits for a 4-bytes integer.
179     if (myValue[0] > INT_MAX || myValue[1] > INT_MAX)
180       throw Standard_OutOfRange("BinLDrivers_DocumentSection::Write : file size is too big, needs int64.");
181
182     // Old documents stored file position as 4-bytes values.
183     int32_t aValInt[3] = {
184       int32_t(myValue[0]),
185       int32_t(myValue[1]),
186       int32_t(myIsPostRead ? 1 : 0)
187     };
188 #if DO_INVERSE
189     aValInt[0] = InverseInt(aValInt[0]);
190     aValInt[1] = InverseInt(aValInt[1]);
191     aValInt[2] = InverseInt(aValInt[2]);
192 #endif
193     theStream.write((char *)&aValInt[0], 3*sizeof(int32_t));
194   }
195   else
196   {
197     uint64_t aVal[3] = {
198       myValue[0],
199       myValue[1],
200       uint64_t(myIsPostRead ? 1 : 0)
201     };
202 #if DO_INVERSE
203     aVal[0] = InverseUint64(aVal[0]);
204     aVal[1] = InverseUint64(aVal[1]);
205     aVal[2] = InverseUint64(aVal[2]);
206 #endif
207     theStream.write((char *)&aVal[0], 3*sizeof(uint64_t));
208   }
209
210   theStream.seekp((std::streamsize)aSectionEnd);
211 }
212
213 //=======================================================================
214 //function : ReadTOC
215 //purpose  : 
216 //=======================================================================
217
218 void BinLDrivers_DocumentSection::ReadTOC
219                                 (BinLDrivers_DocumentSection& theSection,
220                                  Standard_IStream&            theStream,
221                                  const TDocStd_FormatVersion  theDocFormatVersion)
222 {
223   char aBuf[512];
224   Standard_Integer aNameBufferSize;
225   theStream.read ((char *)&aNameBufferSize, sizeof(Standard_Integer));
226 #if DO_INVERSE
227   aNameBufferSize = InverseSize(aNameBufferSize);
228 #endif
229   if (aNameBufferSize > 0) {
230     theStream.read ((char *)&aBuf[0], (Standard_Size)aNameBufferSize);
231     theSection.myName = (Standard_CString)&aBuf[0];
232
233     uint64_t aValue[3];
234     if (theDocFormatVersion <= TDocStd_FormatVersion_VERSION_9)
235     {
236       // Old documents stored file position as 4-bytes values.
237       int32_t aValInt[3];
238       theStream.read ((char *)&aValInt[0], 3*sizeof(int32_t));
239 #if DO_INVERSE
240       aValue[0] = InverseInt (aValInt[0]);
241       aValue[1] = InverseInt (aValInt[1]);
242       aValue[2] = InverseInt (aValInt[2]);
243 #else
244       aValue[0] = aValInt[0];
245       aValue[1] = aValInt[1];
246       aValue[2] = aValInt[2];
247 #endif
248     }
249     else
250     {
251       theStream.read ((char *)&aValue[0], 3*sizeof(uint64_t));
252 #if DO_INVERSE
253       aValue[0] = InverseUint64 (aValue[0]);
254       aValue[1] = InverseUint64 (aValue[1]);
255       aValue[2] = InverseUint64 (aValue[2]);
256 #endif
257     }
258
259     theSection.myValue[0] = aValue[0];
260     theSection.myValue[1] = aValue[1];
261     theSection.myIsPostRead = (aValue[2] != 0);
262   }
263 }