b311480e |
1 | // Created on: 2002-10-31 |
2 | // Created by: Michael SAZONOV |
973c2be1 |
3 | // Copyright (c) 2002-2014 OPEN CASCADE SAS |
b311480e |
4 | // |
973c2be1 |
5 | // This file is part of Open CASCADE Technology software library. |
b311480e |
6 | // |
d5f74e42 |
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 |
973c2be1 |
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. |
b311480e |
12 | // |
973c2be1 |
13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. |
7fd59977 |
15 | |
42cf5bc1 |
16 | |
7fd59977 |
17 | #include <BinLDrivers.hxx> |
42cf5bc1 |
18 | #include <BinLDrivers_DocumentRetrievalDriver.hxx> |
19 | #include <BinLDrivers_DocumentSection.hxx> |
7fd59977 |
20 | #include <BinLDrivers_Marker.hxx> |
7fd59977 |
21 | #include <BinMDataStd.hxx> |
42cf5bc1 |
22 | #include <BinMDF_ADriver.hxx> |
23 | #include <BinMDF_ADriverTable.hxx> |
7fd59977 |
24 | #include <BinObjMgt_Persistent.hxx> |
42cf5bc1 |
25 | #include <CDM_Application.hxx> |
26 | #include <CDM_Document.hxx> |
83ae3591 |
27 | #include <Message_Messenger.hxx> |
7fd59977 |
28 | #include <FSD_BinaryFile.hxx> |
29 | #include <FSD_FileHeader.hxx> |
ad3f20c6 |
30 | #include <OSD_FileSystem.hxx> |
42cf5bc1 |
31 | #include <PCDM_Document.hxx> |
4ff92abe |
32 | #include <PCDM_ReadWriter.hxx> |
7fd59977 |
33 | #include <Standard_ErrorHandler.hxx> |
34 | #include <Standard_Stream.hxx> |
42cf5bc1 |
35 | #include <Standard_Type.hxx> |
36 | #include <Storage_HeaderData.hxx> |
7fd59977 |
37 | #include <Storage_Schema.hxx> |
42cf5bc1 |
38 | #include <TCollection_AsciiString.hxx> |
39 | #include <TCollection_ExtendedString.hxx> |
40 | #include <TDF_Attribute.hxx> |
7fd59977 |
41 | #include <TDF_Data.hxx> |
42cf5bc1 |
42 | #include <TDF_Label.hxx> |
d5c71e20 |
43 | #include <TDF_Tool.hxx> |
7fd59977 |
44 | #include <TDocStd_Document.hxx> |
14eea829 |
45 | #include <TDocStd_FormatVersion.hxx> |
7fd59977 |
46 | #include <TDocStd_Owner.hxx> |
7e785937 |
47 | #include <Message_ProgressScope.hxx> |
d5c71e20 |
48 | #include <PCDM_ReaderFilter.hxx> |
6d8f9f4a |
49 | |
7fd59977 |
50 | |
92efcf78 |
51 | IMPLEMENT_STANDARD_RTTIEXT(BinLDrivers_DocumentRetrievalDriver,PCDM_RetrievalDriver) |
52 | |
7fd59977 |
53 | #define SHAPESECTION_POS "SHAPE_SECTION_POS:" |
d5c71e20 |
54 | #define ENDSECTION_POS ":" |
7fd59977 |
55 | #define SIZEOFSHAPELABEL 18 |
56 | |
57 | #define DATATYPE_MIGRATION |
58 | //#define DATATYPE_MIGRATION_DEB |
59 | //======================================================================= |
60 | //function : BinLDrivers_DocumentRetrievalDriver |
61 | //purpose : Constructor |
62 | //======================================================================= |
63 | |
64 | BinLDrivers_DocumentRetrievalDriver::BinLDrivers_DocumentRetrievalDriver () |
65 | { |
66 | myReaderStatus = PCDM_RS_OK; |
67 | } |
68 | |
7fd59977 |
69 | //======================================================================= |
70 | //function : Read |
71 | //purpose : |
72 | //======================================================================= |
7fd59977 |
73 | void BinLDrivers_DocumentRetrievalDriver::Read |
74 | (const TCollection_ExtendedString& theFileName, |
75 | const Handle(CDM_Document)& theNewDocument, |
6d8f9f4a |
76 | const Handle(CDM_Application)& theApplication, |
d5c71e20 |
77 | const Handle(PCDM_ReaderFilter)& theFilter, |
7e785937 |
78 | const Message_ProgressRange& theRange) |
4ff92abe |
79 | { |
ad3f20c6 |
80 | const Handle(OSD_FileSystem)& aFileSystem = OSD_FileSystem::DefaultFileSystem(); |
81 | opencascade::std::shared_ptr<std::istream> aFileStream = aFileSystem->OpenIStream (theFileName, std::ios::in | std::ios::binary); |
4ff92abe |
82 | |
ad3f20c6 |
83 | if (aFileStream.get() != NULL && aFileStream->good()) |
4ff92abe |
84 | { |
85 | Handle(Storage_Data) dData; |
ad3f20c6 |
86 | TCollection_ExtendedString aFormat = PCDM_ReadWriter::FileFormat (*aFileStream, dData); |
4ff92abe |
87 | |
ad3f20c6 |
88 | Read (*aFileStream, dData, theNewDocument, theApplication, theFilter, theRange); |
7e785937 |
89 | if (!theRange.More()) |
6d8f9f4a |
90 | { |
91 | myReaderStatus = PCDM_RS_UserBreak; |
92 | return; |
93 | } |
4ff92abe |
94 | } |
95 | else |
96 | { |
97 | myReaderStatus = PCDM_RS_OpenError; |
98 | } |
99 | } |
100 | |
101 | #define MODIFICATION_COUNTER "MODIFICATION_COUNTER: " |
102 | #define REFERENCE_COUNTER "REFERENCE_COUNTER: " |
103 | |
104 | #define START_TYPES "START_TYPES" |
105 | #define END_TYPES "END_TYPES" |
106 | |
107 | //======================================================================= |
108 | //function : Read |
109 | //purpose : |
110 | //======================================================================= |
d5c71e20 |
111 | void BinLDrivers_DocumentRetrievalDriver::Read (Standard_IStream& theIStream, |
112 | const Handle(Storage_Data)& theStorageData, |
113 | const Handle(CDM_Document)& theDoc, |
114 | const Handle(CDM_Application)& theApplication, |
115 | const Handle(PCDM_ReaderFilter)& theFilter, |
116 | const Message_ProgressRange& theRange) |
7fd59977 |
117 | { |
118 | myReaderStatus = PCDM_RS_DriverFailure; |
119 | myMsgDriver = theApplication -> MessageDriver(); |
120 | |
121 | const TCollection_ExtendedString aMethStr |
122 | ("BinLDrivers_DocumentRetrievalDriver: "); |
123 | |
124 | Handle(TDocStd_Document) aDoc = |
4ff92abe |
125 | Handle(TDocStd_Document)::DownCast(theDoc); |
7fd59977 |
126 | if (aDoc.IsNull()) { |
0797d9d3 |
127 | #ifdef OCCT_DEBUG |
83ae3591 |
128 | myMsgDriver->Send (aMethStr + "error: null document", Message_Fail); |
7fd59977 |
129 | #endif |
130 | myReaderStatus = PCDM_RS_NoDocument; |
131 | return; |
132 | } |
133 | |
4ff92abe |
134 | // 1. the information section |
7fd59977 |
135 | Handle(Storage_HeaderData) aHeaderData; |
4ff92abe |
136 | |
137 | if (!theStorageData.IsNull()) |
138 | { |
139 | aHeaderData = theStorageData->HeaderData(); |
140 | } |
141 | |
142 | if (!aHeaderData.IsNull()) |
143 | { |
144 | for (Standard_Integer i = 1; i <= aHeaderData->UserInfo().Length(); i++) |
145 | { |
146 | const TCollection_AsciiString& aLine = aHeaderData->UserInfo().Value(i); |
147 | |
148 | if(aLine.Search(REFERENCE_COUNTER) != -1) |
149 | { |
150 | theDoc->SetReferenceCounter (aLine.Token(" ", 2).IntegerValue()); |
151 | } |
152 | else if(aLine.Search(MODIFICATION_COUNTER) != -1) |
153 | { |
154 | theDoc->SetModifications (aLine.Token(" ", 2).IntegerValue()); |
155 | } |
156 | } |
7fd59977 |
157 | } |
158 | |
159 | // 1.a Version of writer |
160 | if (!aHeaderData->StorageVersion().IsIntegerValue()) { |
161 | // file has no format version |
83ae3591 |
162 | myMsgDriver->Send (aMethStr + "error: file has no format version", Message_Fail); |
7fd59977 |
163 | myReaderStatus = PCDM_RS_FormatFailure; |
164 | return; |
165 | } |
9f45d35b |
166 | TDocStd_FormatVersion aFileVer = static_cast<TDocStd_FormatVersion>(aHeaderData->StorageVersion().IntegerValue()); |
167 | TDocStd_FormatVersion aCurrVer = TDocStd_Document::CurrentStorageFormatVersion(); |
7fd59977 |
168 | // maintain one-way compatibility starting from version 2+ |
d9ff84e8 |
169 | if (!CheckDocumentVersion(aFileVer, aCurrVer)) { |
170 | myReaderStatus = PCDM_RS_NoVersion; |
7fd59977 |
171 | // file was written with another version |
83ae3591 |
172 | myMsgDriver->Send (aMethStr + "error: wrong file version: " + |
173 | aHeaderData->StorageVersion() + " while current is " + |
716cf4d9 |
174 | TDocStd_Document::CurrentStorageFormatVersion(), Message_Fail); |
7fd59977 |
175 | return; |
176 | } |
177 | |
178 | // 1.b Retrieve the Types table |
179 | TColStd_SequenceOfAsciiString aTypeNames; //Sequence of types in file |
180 | const TColStd_SequenceOfAsciiString& aUserInfo = aHeaderData->UserInfo(); |
181 | Standard_Boolean begin = Standard_False; |
182 | Standard_Integer i; |
183 | for (i=1; i <= aUserInfo.Length(); i++) { |
7fd59977 |
184 | TCollection_AsciiString aStr = aUserInfo(i); |
185 | if (aStr == START_TYPES) |
186 | begin = Standard_True; |
187 | else if (aStr == END_TYPES) |
188 | break; |
189 | else if (begin) { |
14eea829 |
190 | if ( aFileVer < TDocStd_FormatVersion_VERSION_8) { |
7fd59977 |
191 | #ifdef DATATYPE_MIGRATION |
83ae3591 |
192 | TCollection_AsciiString newName; |
193 | if(Storage_Schema::CheckTypeMigration(aStr, newName)) { |
0797d9d3 |
194 | #ifdef OCCT_DEBUG |
04232180 |
195 | std::cout << "CheckTypeMigration:OldType = " <<aStr << " Len = "<<aStr.Length()<<std::endl; |
196 | std::cout << "CheckTypeMigration:NewType = " <<newName << " Len = "<< newName.Length()<<std::endl; |
7fd59977 |
197 | #endif |
83ae3591 |
198 | aStr = newName; |
199 | } |
7fd59977 |
200 | #endif |
201 | } |
202 | aTypeNames.Append (aStr); |
203 | } |
204 | } |
205 | if (myDrivers.IsNull()) |
206 | myDrivers = AttributeDrivers (myMsgDriver); |
207 | myDrivers->AssignIds (aTypeNames); |
208 | |
209 | // recognize types not supported by drivers |
210 | myMapUnsupported.Clear(); |
211 | for (i=1; i <= aTypeNames.Length(); i++) |
212 | if (myDrivers->GetDriver(i).IsNull()) |
213 | myMapUnsupported.Add(i); |
214 | if (!myMapUnsupported.IsEmpty()) { |
83ae3591 |
215 | myMsgDriver->Send (aMethStr + "warning: " |
216 | "the following attributes have no driver:", Message_Warning); |
7fd59977 |
217 | for (i=1; i <= aTypeNames.Length(); i++) |
218 | if (myMapUnsupported.Contains(i)) |
83ae3591 |
219 | myMsgDriver->Send (aTypeNames(i), Message_Warning); |
7fd59977 |
220 | } |
221 | |
7fd59977 |
222 | // 2. Read document contents |
7fd59977 |
223 | // 2a. Retrieve data from the stream: |
224 | myRelocTable.Clear(); |
fe21f796 |
225 | myRelocTable.SetHeaderData(aHeaderData); |
7fd59977 |
226 | mySections.Clear(); |
227 | myPAtt.Init(); |
d5c71e20 |
228 | Handle(TDF_Data) aData = (!theFilter.IsNull() && theFilter->IsAppendMode()) ? aDoc->GetData() : new TDF_Data(); |
04232180 |
229 | std::streampos aDocumentPos = -1; |
7fd59977 |
230 | |
d5c71e20 |
231 | Message_ProgressScope aPS (theRange, "Reading data", 3); |
232 | Standard_Boolean aQuickPart = IsQuickPart (aFileVer); |
6d8f9f4a |
233 | |
7fd59977 |
234 | // 2b. Read the TOC of Sections |
14eea829 |
235 | if (aFileVer >= TDocStd_FormatVersion_VERSION_3) { |
7fd59977 |
236 | BinLDrivers_DocumentSection aSection; |
237 | do { |
b34d86cb |
238 | BinLDrivers_DocumentSection::ReadTOC (aSection, theIStream, aFileVer); |
7fd59977 |
239 | mySections.Append(aSection); |
d5c71e20 |
240 | } while (!aSection.Name().IsEqual (aQuickPart ? ENDSECTION_POS : SHAPESECTION_POS) && !theIStream.eof()); |
5ecc46c0 |
241 | |
242 | if (theIStream.eof()) { |
243 | // There is no shape section in the file. |
83ae3591 |
244 | myMsgDriver->Send (aMethStr + "error: shape section is not found", Message_Fail); |
5ecc46c0 |
245 | myReaderStatus = PCDM_RS_ReaderException; |
246 | return; |
247 | } |
248 | |
4ff92abe |
249 | aDocumentPos = theIStream.tellg(); // position of root label |
7fd59977 |
250 | |
251 | BinLDrivers_VectorOfDocumentSection::Iterator anIterS (mySections); |
252 | for (; anIterS.More(); anIterS.Next()) { |
253 | BinLDrivers_DocumentSection& aCurSection = anIterS.ChangeValue(); |
254 | if (aCurSection.IsPostRead() == Standard_False) { |
04232180 |
255 | theIStream.seekg ((std::streampos) aCurSection.Offset()); |
d5c71e20 |
256 | if (aCurSection.Name().IsEqual (SHAPESECTION_POS)) |
6d8f9f4a |
257 | { |
7e785937 |
258 | ReadShapeSection (aCurSection, theIStream, false, aPS.Next()); |
6d8f9f4a |
259 | if (!aPS.More()) |
260 | { |
261 | myReaderStatus = PCDM_RS_UserBreak; |
262 | return; |
263 | } |
6d8f9f4a |
264 | } |
d5c71e20 |
265 | else if (!aCurSection.Name().IsEqual (ENDSECTION_POS)) |
6d8f9f4a |
266 | ReadSection (aCurSection, theDoc, theIStream); |
7fd59977 |
267 | } |
268 | } |
269 | } else { //aFileVer < 3 |
4ff92abe |
270 | aDocumentPos = theIStream.tellg(); // position of root label |
7fd59977 |
271 | |
272 | // retrieve SHAPESECTION_POS string |
273 | char aShapeSecLabel[SIZEOFSHAPELABEL + 1]; |
274 | aShapeSecLabel[SIZEOFSHAPELABEL] = 0x00; |
4ff92abe |
275 | theIStream.read ((char*)&aShapeSecLabel, SIZEOFSHAPELABEL);// SHAPESECTION_POS |
7fd59977 |
276 | TCollection_AsciiString aShapeLabel(aShapeSecLabel); |
277 | // detect if a file was written in old fashion (version 2 without shapes) |
278 | // and if so then skip reading ShapeSection |
279 | if (aShapeLabel.Length() > 0) { |
280 | // version 2+(with shapes) and higher goes here |
281 | if(aShapeLabel.Length() <= 0 || aShapeLabel != SHAPESECTION_POS) { |
83ae3591 |
282 | myMsgDriver->Send (aMethStr + "error: Format failure", Message_Fail); |
7fd59977 |
283 | myReaderStatus = PCDM_RS_FormatFailure; |
284 | return; |
285 | } |
286 | |
287 | // retrieve ShapeSection Position |
288 | Standard_Integer aShapeSectionPos; // go to ShapeSection |
4ff92abe |
289 | theIStream.read ((char*)&aShapeSectionPos, sizeof(Standard_Integer)); |
7fd59977 |
290 | |
ff1f0c9a |
291 | #ifdef DO_INVERSE |
7fd59977 |
292 | aShapeSectionPos = InverseInt (aShapeSectionPos); |
293 | #endif |
0797d9d3 |
294 | #ifdef OCCT_DEBUG |
04232180 |
295 | std::cout <<"aShapeSectionPos = " <<aShapeSectionPos <<std::endl; |
7fd59977 |
296 | #endif |
297 | if(aShapeSectionPos) { |
83ae3591 |
298 | aDocumentPos = theIStream.tellg(); |
04232180 |
299 | theIStream.seekg((std::streampos) aShapeSectionPos); |
7fd59977 |
300 | |
83ae3591 |
301 | CheckShapeSection(aShapeSectionPos, theIStream); |
302 | // Read Shapes |
303 | BinLDrivers_DocumentSection aCurSection; |
7e785937 |
304 | ReadShapeSection (aCurSection, theIStream, Standard_False, aPS.Next()); |
6d8f9f4a |
305 | if (!aPS.More()) |
306 | { |
307 | myReaderStatus = PCDM_RS_UserBreak; |
308 | return; |
309 | } |
7fd59977 |
310 | } |
311 | } |
312 | } // end of reading Sections or shape section |
313 | |
314 | // Return to read of the Document structure |
4ff92abe |
315 | theIStream.seekg(aDocumentPos); |
7fd59977 |
316 | |
317 | // read the header (tag) of the root label |
318 | Standard_Integer aTag; |
4ff92abe |
319 | theIStream.read ((char*)&aTag, sizeof(Standard_Integer)); |
7fd59977 |
320 | |
d5c71e20 |
321 | if (aQuickPart) |
322 | myPAtt.SetIStream (theIStream); // for reading shapes data from the stream directly |
323 | EnableQuickPartReading (myMsgDriver, aQuickPart); |
324 | |
7fd59977 |
325 | // read sub-tree of the root label |
d5c71e20 |
326 | if (!theFilter.IsNull()) |
327 | theFilter->StartIteration(); |
328 | Standard_Integer nbRead = ReadSubTree (theIStream, aData->Root(), theFilter, aQuickPart, aPS.Next()); |
6d8f9f4a |
329 | if (!aPS.More()) |
330 | { |
331 | myReaderStatus = PCDM_RS_UserBreak; |
332 | return; |
333 | } |
7e785937 |
334 | |
bf954475 |
335 | Clear(); |
6d8f9f4a |
336 | if (!aPS.More()) |
337 | { |
338 | myReaderStatus = PCDM_RS_UserBreak; |
339 | return; |
340 | } |
341 | aPS.Next(); |
7fd59977 |
342 | |
343 | if (nbRead > 0) { |
344 | // attach data to the document |
d5c71e20 |
345 | if (theFilter.IsNull() || !theFilter->IsAppendMode()) |
346 | { |
347 | aDoc->SetData(aData); |
348 | TDocStd_Owner::SetDocument(aData, aDoc); |
349 | aDoc->SetComments(aHeaderData->Comments()); |
350 | } |
7fd59977 |
351 | myReaderStatus = PCDM_RS_OK; |
352 | } |
353 | |
354 | // Read Sections (post-reading type) |
14eea829 |
355 | if (aFileVer >= TDocStd_FormatVersion_VERSION_3) { |
4ff92abe |
356 | BinLDrivers_VectorOfDocumentSection::Iterator aSectIter (mySections); |
357 | for (; aSectIter.More(); aSectIter.Next()) { |
358 | BinLDrivers_DocumentSection& aCurSection = aSectIter.ChangeValue(); |
7fd59977 |
359 | if (aCurSection.IsPostRead()) { |
04232180 |
360 | theIStream.seekg ((std::streampos) aCurSection.Offset()); |
83ae3591 |
361 | ReadSection (aCurSection, theDoc, theIStream); |
7fd59977 |
362 | } |
363 | } |
364 | } |
365 | } |
366 | |
367 | //======================================================================= |
368 | //function : ReadSubTree |
369 | //purpose : |
370 | //======================================================================= |
371 | |
372 | Standard_Integer BinLDrivers_DocumentRetrievalDriver::ReadSubTree |
d5c71e20 |
373 | (Standard_IStream& theIS, |
374 | const TDF_Label& theLabel, |
375 | const Handle(PCDM_ReaderFilter)& theFilter, |
376 | const Standard_Boolean& theQuickPart, |
377 | const Message_ProgressRange& theRange) |
7fd59977 |
378 | { |
379 | Standard_Integer nbRead = 0; |
b34d86cb |
380 | TCollection_ExtendedString aMethStr |
d5c71e20 |
381 | ("BinLDrivers_DocumentRetrievalDriver: "); |
7fd59977 |
382 | |
7e785937 |
383 | Message_ProgressScope aPS(theRange, "Reading sub tree", 2, true); |
6d8f9f4a |
384 | |
d5c71e20 |
385 | bool aSkipAttrs = Standard_False; |
386 | if (!theFilter.IsNull() && theFilter->IsPartTree()) |
387 | aSkipAttrs = !theFilter->IsPassed(); |
388 | |
389 | if (theQuickPart) |
390 | { |
391 | uint64_t aLabelSize = 0; |
392 | theIS.read((char*)&aLabelSize, sizeof(uint64_t)); |
393 | #if DO_INVERSE |
394 | aLabelSize = InverseUint64(aLabelSize); |
395 | #endif |
396 | // no one sub-label is needed, so, skip everything |
397 | if (aSkipAttrs && !theFilter->IsSubPassed()) |
398 | { |
399 | aLabelSize -= sizeof (uint64_t); |
400 | theIS.seekg (aLabelSize, std::ios_base::cur); |
401 | if (!theFilter.IsNull()) |
402 | theFilter->Up(); |
403 | return 0; |
404 | } |
405 | } |
406 | |
7fd59977 |
407 | // Read attributes: |
d5c71e20 |
408 | for (theIS >> myPAtt; |
409 | theIS && myPAtt.TypeId() > 0 && // not an end marker ? |
410 | myPAtt.Id() > 0 && // not a garbage ? |
411 | !theIS.eof(); |
412 | theIS >> myPAtt) |
6d8f9f4a |
413 | { |
414 | if (!aPS.More()) |
415 | { |
416 | myReaderStatus = PCDM_RS_UserBreak; |
417 | return -1; |
418 | } |
d5c71e20 |
419 | if (aSkipAttrs) |
420 | { |
421 | if (myPAtt.IsDirect()) // skip direct written stream |
422 | { |
423 | uint64_t aStreamSize = 0; |
424 | theIS.read ((char*)&aStreamSize, sizeof (uint64_t)); |
425 | aStreamSize -= sizeof (uint64_t); // size is already passed, so, reduce it by size |
426 | theIS.seekg (aStreamSize, std::ios_base::cur); |
427 | } |
428 | continue; |
429 | } |
430 | |
7fd59977 |
431 | // get a driver according to TypeId |
d5c71e20 |
432 | Handle(BinMDF_ADriver) aDriver = myDrivers->GetDriver(myPAtt.TypeId()); |
7fd59977 |
433 | if (!aDriver.IsNull()) { |
434 | // create transient attribute |
7fd59977 |
435 | Standard_Integer anID = myPAtt.Id(); |
436 | Handle(TDF_Attribute) tAtt; |
437 | Standard_Boolean isBound = myRelocTable.IsBound(anID); |
438 | if (isBound) |
439 | tAtt = Handle(TDF_Attribute)::DownCast(myRelocTable.Find(anID)); |
440 | else |
441 | tAtt = aDriver->NewEmpty(); |
60fddce4 |
442 | |
d5c71e20 |
443 | if (!theFilter.IsNull() && !theFilter->IsPassed (tAtt->DynamicType())) { |
444 | if (myPAtt.IsDirect()) // skip direct written stream |
445 | { |
446 | uint64_t aStreamSize = 0; |
447 | theIS.read ((char*)&aStreamSize, sizeof (uint64_t)); |
448 | aStreamSize -= sizeof (uint64_t); // size is already passed, so, reduce it by size |
449 | theIS.seekg (aStreamSize, std::ios_base::cur); |
450 | } |
451 | continue; |
452 | } |
453 | nbRead++; |
454 | |
7fd59977 |
455 | if (tAtt->Label().IsNull()) |
60fddce4 |
456 | { |
d5c71e20 |
457 | if (!theFilter.IsNull() && theFilter->Mode() != PCDM_ReaderFilter::AppendMode_Forbid && theLabel.IsAttribute(tAtt->ID())) |
458 | { |
459 | if (theFilter->Mode() == PCDM_ReaderFilter::AppendMode_Protect) |
460 | continue; // do not overwrite the existing attribute |
461 | if (theFilter->Mode() == PCDM_ReaderFilter::AppendMode_Overwrite) |
462 | theLabel.ForgetAttribute(tAtt->ID()); // forget old attribute to write a new one |
463 | } |
60fddce4 |
464 | try |
465 | { |
d5c71e20 |
466 | theLabel.AddAttribute(tAtt); |
60fddce4 |
467 | } |
468 | catch (const Standard_DomainError&) |
469 | { |
470 | // For attributes that can have arbitrary GUID (e.g. TDataStd_Integer), exception |
471 | // will be raised in valid case if attribute of that type with default GUID is already |
472 | // present on the same label; the reason is that actual GUID will be read later. |
473 | // To avoid this, set invalid (null) GUID to the newly added attribute (see #29669) |
474 | static const Standard_GUID fbidGuid; |
d5c71e20 |
475 | tAtt->SetID(fbidGuid); |
476 | theLabel.AddAttribute(tAtt); |
60fddce4 |
477 | } |
478 | } |
7fd59977 |
479 | else |
d5c71e20 |
480 | myMsgDriver->Send(aMethStr + |
481 | "warning: attempt to attach attribute " + |
482 | aDriver->TypeName() + " to a second label", Message_Warning); |
7fd59977 |
483 | |
d5c71e20 |
484 | Standard_Boolean ok = aDriver->Paste(myPAtt, tAtt, myRelocTable); |
7fd59977 |
485 | if (!ok) { |
486 | // error converting persistent to transient |
d5c71e20 |
487 | myMsgDriver->Send(aMethStr + "warning: failure reading attribute " + |
488 | aDriver->TypeName(), Message_Warning); |
7fd59977 |
489 | } |
490 | else if (!isBound) |
d5c71e20 |
491 | myRelocTable.Bind(anID, tAtt); |
7fd59977 |
492 | } |
493 | else if (!myMapUnsupported.Contains(myPAtt.TypeId())) |
d5c71e20 |
494 | myMsgDriver->Send(aMethStr + "warning: type ID not registered in header: " |
495 | + myPAtt.TypeId(), Message_Warning); |
7fd59977 |
496 | |
7fd59977 |
497 | } |
498 | if (!theIS || myPAtt.TypeId() != BinLDrivers_ENDATTRLIST) { |
499 | // unexpected EOF or garbage data |
d5c71e20 |
500 | myMsgDriver->Send(aMethStr + "error: unexpected EOF or garbage data", Message_Fail); |
7fd59977 |
501 | myReaderStatus = PCDM_RS_UnrecognizedFileFormat; |
502 | return -1; |
503 | } |
504 | |
505 | // Read children: |
506 | // read the tag of a child label |
507 | Standard_Integer aTag = BinLDrivers_ENDLABEL; |
d5c71e20 |
508 | theIS.read((char*)&aTag, sizeof(Standard_Integer)); |
ff1f0c9a |
509 | #ifdef DO_INVERSE |
d5c71e20 |
510 | aTag = InverseInt(aTag); |
7fd59977 |
511 | #endif |
d5c71e20 |
512 | |
5ecc46c0 |
513 | while (theIS && aTag >= 0 && !theIS.eof()) { // not an end marker ? |
7fd59977 |
514 | // create sub-label |
d5c71e20 |
515 | TDF_Label aLab = theLabel.FindChild(aTag, Standard_True); |
6d8f9f4a |
516 | if (!aPS.More()) |
517 | { |
518 | myReaderStatus = PCDM_RS_UserBreak; |
519 | return -1; |
520 | } |
7fd59977 |
521 | |
7e785937 |
522 | |
7fd59977 |
523 | // read sub-tree |
d5c71e20 |
524 | if (!theFilter.IsNull()) |
525 | theFilter->Down (aTag); |
526 | Standard_Integer nbSubRead = ReadSubTree (theIS, aLab, theFilter, theQuickPart, aPS.Next()); |
7fd59977 |
527 | // check for error |
528 | if (nbSubRead == -1) |
529 | return -1; |
530 | nbRead += nbSubRead; |
531 | |
532 | // read the tag of the next child |
d5c71e20 |
533 | theIS.read((char*)&aTag, sizeof(Standard_Integer)); |
ff1f0c9a |
534 | #ifdef DO_INVERSE |
d5c71e20 |
535 | aTag = InverseInt(aTag); |
7fd59977 |
536 | #endif |
537 | } |
6d8f9f4a |
538 | |
7fd59977 |
539 | if (aTag != BinLDrivers_ENDLABEL) { |
540 | // invalid end label marker |
d5c71e20 |
541 | myMsgDriver->Send(aMethStr + "error: invalid end label marker", Message_Fail); |
7fd59977 |
542 | myReaderStatus = PCDM_RS_UnrecognizedFileFormat; |
543 | return -1; |
544 | } |
d5c71e20 |
545 | if (!theFilter.IsNull()) |
546 | theFilter->Up(); |
7fd59977 |
547 | |
548 | return nbRead; |
549 | } |
550 | |
551 | //======================================================================= |
552 | //function : AttributeDrivers |
553 | //purpose : |
554 | //======================================================================= |
555 | |
556 | Handle(BinMDF_ADriverTable) BinLDrivers_DocumentRetrievalDriver::AttributeDrivers |
83ae3591 |
557 | (const Handle(Message_Messenger)& theMessageDriver) |
7fd59977 |
558 | { |
559 | return BinLDrivers::AttributeDrivers (theMessageDriver); |
560 | } |
561 | |
7fd59977 |
562 | //======================================================================= |
563 | //function : ReadSection |
564 | //purpose : |
565 | //======================================================================= |
566 | |
567 | void BinLDrivers_DocumentRetrievalDriver::ReadSection |
568 | (BinLDrivers_DocumentSection& /*theSection*/, |
569 | const Handle(CDM_Document)& /*theDocument*/, |
570 | Standard_IStream& /*theIS*/) |
571 | { |
572 | // empty; should be redefined in subclasses |
573 | } |
574 | |
575 | //======================================================================= |
576 | //function : ReadShapeSection |
577 | //purpose : |
578 | //======================================================================= |
579 | |
580 | void BinLDrivers_DocumentRetrievalDriver::ReadShapeSection |
581 | (BinLDrivers_DocumentSection& theSection, |
6d8f9f4a |
582 | Standard_IStream& /*theIS*/, |
583 | const Standard_Boolean isMess, |
7e785937 |
584 | const Message_ProgressRange &/*theRange*/) |
7fd59977 |
585 | |
586 | { |
587 | if(isMess && theSection.Length()) { |
588 | const TCollection_ExtendedString aMethStr ("BinLDrivers_DocumentRetrievalDriver: "); |
83ae3591 |
589 | myMsgDriver->Send (aMethStr + "warning: Geometry is not supported by Lite schema. ", Message_Warning); |
7fd59977 |
590 | } |
591 | } |
592 | |
593 | //======================================================================= |
594 | //function : CheckShapeSection |
595 | //purpose : |
596 | //======================================================================= |
d5c71e20 |
597 | void BinLDrivers_DocumentRetrievalDriver::CheckShapeSection |
598 | (const Storage_Position& ShapeSectionPos, Standard_IStream& IS) |
7fd59977 |
599 | { |
d41f6af3 |
600 | if (!IS.eof()) |
601 | { |
d5c71e20 |
602 | const std::streamoff endPos = IS.rdbuf()->pubseekoff (0L, std::ios_base::end, std::ios_base::in); |
0797d9d3 |
603 | #ifdef OCCT_DEBUG |
04232180 |
604 | std::cout << "endPos = " << endPos <<std::endl; |
7fd59977 |
605 | #endif |
606 | if(ShapeSectionPos != endPos) { |
607 | const TCollection_ExtendedString aMethStr ("BinLDrivers_DocumentRetrievalDriver: "); |
83ae3591 |
608 | myMsgDriver->Send (aMethStr + "warning: Geometry is not supported by Lite schema. ", Message_Warning); |
7fd59977 |
609 | } |
610 | } |
611 | } |
612 | |
bf954475 |
613 | //======================================================================= |
614 | //function : Clear |
615 | //purpose : |
616 | //======================================================================= |
617 | void BinLDrivers_DocumentRetrievalDriver::Clear() |
618 | { |
619 | myPAtt.Destroy(); // free buffer |
620 | myRelocTable.Clear(); |
621 | myMapUnsupported.Clear(); |
622 | } |
623 | |
d9ff84e8 |
624 | //======================================================================= |
625 | //function : CheckDocumentVersion |
626 | //purpose : |
627 | //======================================================================= |
d5c71e20 |
628 | Standard_Boolean BinLDrivers_DocumentRetrievalDriver::CheckDocumentVersion |
629 | (const Standard_Integer theFileVersion, const Standard_Integer theCurVersion) |
d9ff84e8 |
630 | { |
9f45d35b |
631 | if (theFileVersion < TDocStd_FormatVersion_LOWER || theFileVersion > theCurVersion) { |
d9ff84e8 |
632 | // file was written with another version |
633 | return Standard_False; |
634 | } |
635 | return Standard_True; |
636 | } |
d5c71e20 |
637 | |
638 | //======================================================================= |
639 | //function : IsQuickPart |
640 | //purpose : |
641 | //======================================================================= |
642 | Standard_Boolean BinLDrivers_DocumentRetrievalDriver::IsQuickPart (const Standard_Integer theFileVer) |
643 | { |
644 | return theFileVer >= TDocStd_FormatVersion_VERSION_12; |
645 | } |