0026576: Wrong result obtained by intersection algorithm.
[occt.git] / src / BinLDrivers / BinLDrivers_DocumentRetrievalDriver.cxx
CommitLineData
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>
27#include <CDM_MessageDriver.hxx>
7fd59977 28#include <FSD_BinaryFile.hxx>
29#include <FSD_FileHeader.hxx>
42cf5bc1 30#include <PCDM_Document.hxx>
7fd59977 31#include <Standard_ErrorHandler.hxx>
32#include <Standard_Stream.hxx>
42cf5bc1 33#include <Standard_Type.hxx>
34#include <Storage_HeaderData.hxx>
7fd59977 35#include <Storage_Schema.hxx>
42cf5bc1 36#include <TCollection_AsciiString.hxx>
37#include <TCollection_ExtendedString.hxx>
38#include <TDF_Attribute.hxx>
7fd59977 39#include <TDF_Data.hxx>
42cf5bc1 40#include <TDF_Label.hxx>
7fd59977 41#include <TDocStd_Document.hxx>
42#include <TDocStd_Owner.hxx>
43
92efcf78 44IMPLEMENT_STANDARD_RTTIEXT(BinLDrivers_DocumentRetrievalDriver,PCDM_RetrievalDriver)
45
7fd59977 46#define SHAPESECTION_POS "SHAPE_SECTION_POS:"
47#define SIZEOFSHAPELABEL 18
48
49#define DATATYPE_MIGRATION
50//#define DATATYPE_MIGRATION_DEB
51//=======================================================================
52//function : BinLDrivers_DocumentRetrievalDriver
53//purpose : Constructor
54//=======================================================================
55
56BinLDrivers_DocumentRetrievalDriver::BinLDrivers_DocumentRetrievalDriver ()
57{
58 myReaderStatus = PCDM_RS_OK;
59}
60
61//=======================================================================
62//function : CreateDocument
63//purpose : pure virtual method definition
64//=======================================================================
65
66Handle(CDM_Document) BinLDrivers_DocumentRetrievalDriver::CreateDocument()
67{
68 return new TDocStd_Document(PCDM_RetrievalDriver::GetFormat());
69}
70
71//=======================================================================
72//function : SchemaName
73//purpose : pure virtual method definition
74//=======================================================================
75
76TCollection_ExtendedString BinLDrivers_DocumentRetrievalDriver::SchemaName() const
77{
78 TCollection_ExtendedString schemaname;
79 return schemaname;
80}
81
82//=======================================================================
83//function : Make
84//purpose : pure virtual method definition
85//=======================================================================
86
87void BinLDrivers_DocumentRetrievalDriver::Make (const Handle(PCDM_Document)&,
88 const Handle(CDM_Document)&)
89{
90}
91
92//=======================================================================
93//function : Read
94//purpose :
95//=======================================================================
96
97#define START_TYPES "START_TYPES"
98#define END_TYPES "END_TYPES"
99
100void BinLDrivers_DocumentRetrievalDriver::Read
101 (const TCollection_ExtendedString& theFileName,
102 const Handle(CDM_Document)& theNewDocument,
103 const Handle(CDM_Application)& theApplication)
104{
105 myReaderStatus = PCDM_RS_DriverFailure;
106 myMsgDriver = theApplication -> MessageDriver();
107
108 const TCollection_ExtendedString aMethStr
109 ("BinLDrivers_DocumentRetrievalDriver: ");
110
111 Handle(TDocStd_Document) aDoc =
112 Handle(TDocStd_Document)::DownCast(theNewDocument);
113 if (aDoc.IsNull()) {
0797d9d3 114#ifdef OCCT_DEBUG
7fd59977 115 WriteMessage (aMethStr + "error: null document");
116#endif
117 myReaderStatus = PCDM_RS_NoDocument;
118 return;
119 }
120
d9ff84e8 121 TCollection_AsciiString aFileName (theFileName);
7fd59977 122
123 // 1. Read the information section
124 Handle(Storage_HeaderData) aHeaderData;
125 Storage_Position anInfoSectionEnd = ReadInfoSection( aFileName, aHeaderData );
126 if (!anInfoSectionEnd) {
127 WriteMessage (aMethStr + "error: file has invalid header");
128 myReaderStatus = PCDM_RS_UnrecognizedFileFormat;
129 return;
130 }
131
132 // 1.a Version of writer
133 if (!aHeaderData->StorageVersion().IsIntegerValue()) {
134 // file has no format version
135 WriteMessage (aMethStr + "error: file has no format version");
136 myReaderStatus = PCDM_RS_FormatFailure;
137 return;
138 }
139 Standard_Integer aFileVer = aHeaderData->StorageVersion().IntegerValue();
140 Standard_Integer aCurrVer = BinLDrivers::StorageVersion().IntegerValue();
141 // maintain one-way compatibility starting from version 2+
d9ff84e8 142 if (!CheckDocumentVersion(aFileVer, aCurrVer)) {
143 myReaderStatus = PCDM_RS_NoVersion;
7fd59977 144 // file was written with another version
145 WriteMessage (aMethStr + "error: wrong file version: " +
146 aHeaderData->StorageVersion() + " while current is " +
147 BinLDrivers::StorageVersion());
7fd59977 148 return;
149 }
150
151 // 1.b Retrieve the Types table
152 TColStd_SequenceOfAsciiString aTypeNames; //Sequence of types in file
153 const TColStd_SequenceOfAsciiString& aUserInfo = aHeaderData->UserInfo();
154 Standard_Boolean begin = Standard_False;
155 Standard_Integer i;
156 for (i=1; i <= aUserInfo.Length(); i++) {
157 //const TCollection_AsciiString& aStr = aUserInfo(i);
158 TCollection_AsciiString aStr = aUserInfo(i);
159 if (aStr == START_TYPES)
160 begin = Standard_True;
161 else if (aStr == END_TYPES)
162 break;
163 else if (begin) {
f47afe53 164 if ( aFileVer < 8 ) {
7fd59977 165#ifdef DATATYPE_MIGRATION
166 TCollection_AsciiString newName;
167 if(Storage_Schema::CheckTypeMigration(aStr, newName)) {
0797d9d3 168#ifdef OCCT_DEBUG
7fd59977 169 cout << "CheckTypeMigration:OldType = " <<aStr << " Len = "<<aStr.Length()<<endl;
170 cout << "CheckTypeMigration:NewType = " <<newName << " Len = "<< newName.Length()<<endl;
171#endif
172 aStr = newName;
173 }
174#endif
175 }
176 aTypeNames.Append (aStr);
177 }
178 }
179 if (myDrivers.IsNull())
180 myDrivers = AttributeDrivers (myMsgDriver);
181 myDrivers->AssignIds (aTypeNames);
182
183 // recognize types not supported by drivers
184 myMapUnsupported.Clear();
185 for (i=1; i <= aTypeNames.Length(); i++)
186 if (myDrivers->GetDriver(i).IsNull())
187 myMapUnsupported.Add(i);
188 if (!myMapUnsupported.IsEmpty()) {
189 WriteMessage (aMethStr + "warning: "
190 "the following attributes have no driver:");
191 for (i=1; i <= aTypeNames.Length(); i++)
192 if (myMapUnsupported.Contains(i))
193 WriteMessage (aTypeNames(i));
194 }
195
196 // Open the file stream
d9ff84e8 197#ifdef _WIN32
198 ifstream anIS ((const wchar_t*) theFileName.ToExtString(), ios::in | ios::binary);
7fd59977 199#else
200 ifstream anIS (aFileName.ToCString());
201#endif
202
203 if (!anIS) {
204 // Can not open file
205 WriteMessage (aMethStr + "error: can't open file " + theFileName);
206 myReaderStatus = PCDM_RS_OpenError;
207 return;
208 }
209
210 // skip info section
211 anIS.seekg( (streampos) anInfoSectionEnd );
212
213 // propagate the opened document version to data drivers
214 PropagateDocumentVersion(aFileVer);
215
216 // 2. Read document contents
217
218 // 2a. Retrieve data from the stream:
219 myRelocTable.Clear();
220 mySections.Clear();
221 myPAtt.Init();
222 Handle(TDF_Data) aData = new TDF_Data();
60be1f9b 223 streampos aDocumentPos = -1;
7fd59977 224
225 // 2b. Read the TOC of Sections
226 if (aFileVer >= 3) {
227 BinLDrivers_DocumentSection aSection;
228 do {
229 BinLDrivers_DocumentSection::ReadTOC (aSection, anIS);
230 mySections.Append(aSection);
231 } while
232 (!aSection.Name().IsEqual((Standard_CString)SHAPESECTION_POS));
233 aDocumentPos = anIS.tellg(); // position of root label
234
235 BinLDrivers_VectorOfDocumentSection::Iterator anIterS (mySections);
236 for (; anIterS.More(); anIterS.Next()) {
237 BinLDrivers_DocumentSection& aCurSection = anIterS.ChangeValue();
238 if (aCurSection.IsPostRead() == Standard_False) {
239 anIS.seekg ((streampos) aCurSection.Offset());
240 if (aCurSection.Name().IsEqual ((Standard_CString)SHAPESECTION_POS))
241 ReadShapeSection (aCurSection, anIS);
242 else
243 ReadSection (aCurSection, theNewDocument, anIS);
244 }
245 }
246 } else { //aFileVer < 3
247 aDocumentPos = anIS.tellg(); // position of root label
248
249 // retrieve SHAPESECTION_POS string
250 char aShapeSecLabel[SIZEOFSHAPELABEL + 1];
251 aShapeSecLabel[SIZEOFSHAPELABEL] = 0x00;
252 anIS.read ((char*)&aShapeSecLabel, SIZEOFSHAPELABEL);// SHAPESECTION_POS
253 TCollection_AsciiString aShapeLabel(aShapeSecLabel);
254 // detect if a file was written in old fashion (version 2 without shapes)
255 // and if so then skip reading ShapeSection
256 if (aShapeLabel.Length() > 0) {
257 // version 2+(with shapes) and higher goes here
258 if(aShapeLabel.Length() <= 0 || aShapeLabel != SHAPESECTION_POS) {
259 WriteMessage (aMethStr + "error: Format failure");
260 myReaderStatus = PCDM_RS_FormatFailure;
261 return;
262 }
263
264 // retrieve ShapeSection Position
265 Standard_Integer aShapeSectionPos; // go to ShapeSection
266 anIS.read ((char*)&aShapeSectionPos, sizeof(Standard_Integer));
267
268#if DO_INVERSE
269 aShapeSectionPos = InverseInt (aShapeSectionPos);
270#endif
0797d9d3 271#ifdef OCCT_DEBUG
7fd59977 272 cout <<"aShapeSectionPos = " <<aShapeSectionPos <<endl;
273#endif
274 if(aShapeSectionPos) {
275 aDocumentPos = anIS.tellg();
276 anIS.seekg((streampos) aShapeSectionPos);
277
105aae76 278 CheckShapeSection(aShapeSectionPos, anIS);
7fd59977 279 // Read Shapes
280 BinLDrivers_DocumentSection aCurSection;
281 ReadShapeSection (aCurSection, anIS, Standard_False);
282 }
283 }
284 } // end of reading Sections or shape section
285
286 // Return to read of the Document structure
60be1f9b 287 anIS.seekg(aDocumentPos);
7fd59977 288
289 // read the header (tag) of the root label
290 Standard_Integer aTag;
291 anIS.read ((char*)&aTag, sizeof(Standard_Integer));
292
293 // read sub-tree of the root label
294 Standard_Integer nbRead = ReadSubTree (anIS, aData->Root());
295 myPAtt.Destroy(); // free buffer
296 myRelocTable.Clear();
297 myMapUnsupported.Clear();
298
299 if (nbRead > 0) {
300 // attach data to the document
301 aDoc->SetData (aData);
302 TDocStd_Owner::SetDocument (aData, aDoc);
303 aDoc->SetComments(aHeaderData->Comments());
304 myReaderStatus = PCDM_RS_OK;
305 }
306
307 // Read Sections (post-reading type)
308 if (aFileVer >= 3) {
309 BinLDrivers_VectorOfDocumentSection::Iterator anIterS (mySections);
310 for (; anIterS.More(); anIterS.Next()) {
311 BinLDrivers_DocumentSection& aCurSection = anIterS.ChangeValue();
312 if (aCurSection.IsPostRead()) {
313 anIS.seekg ((streampos) aCurSection.Offset());
314 ReadSection (aCurSection, theNewDocument, anIS);
315 }
316 }
317 }
318}
319
320//=======================================================================
321//function : ReadSubTree
322//purpose :
323//=======================================================================
324
325Standard_Integer BinLDrivers_DocumentRetrievalDriver::ReadSubTree
326 (Standard_IStream& theIS,
327 const TDF_Label& theLabel)
328{
329 Standard_Integer nbRead = 0;
330 static TCollection_ExtendedString aMethStr
331 ("BinLDrivers_DocumentRetrievalDriver: ");
332
333 // Read attributes:
334 theIS >> myPAtt;
335 while (theIS && myPAtt.TypeId() > 0 && // not an end marker ?
336 myPAtt.Id() > 0) { // not a garbage ?
337 // get a driver according to TypeId
338 Handle(BinMDF_ADriver) aDriver = myDrivers->GetDriver (myPAtt.TypeId());
339 if (!aDriver.IsNull()) {
340 // create transient attribute
341 nbRead++;
342 Standard_Integer anID = myPAtt.Id();
343 Handle(TDF_Attribute) tAtt;
344 Standard_Boolean isBound = myRelocTable.IsBound(anID);
345 if (isBound)
346 tAtt = Handle(TDF_Attribute)::DownCast(myRelocTable.Find(anID));
347 else
348 tAtt = aDriver->NewEmpty();
349 if (tAtt->Label().IsNull())
350 theLabel.AddAttribute (tAtt);
351 else
352 WriteMessage (aMethStr +
353 "warning: attempt to attach attribute " +
354 aDriver->TypeName() + " to a second label");
355
356 Standard_Boolean ok = aDriver->Paste (myPAtt, tAtt, myRelocTable);
357 if (!ok) {
358 // error converting persistent to transient
359 WriteMessage (aMethStr + "warning: failure reading attribute " +
360 aDriver->TypeName());
361 }
362 else if (!isBound)
363 myRelocTable.Bind (anID, tAtt);
364 }
365 else if (!myMapUnsupported.Contains(myPAtt.TypeId()))
366 WriteMessage (aMethStr + "warning: type ID not registered in header: "
367 + myPAtt.TypeId());
368
369 // read next attribute
370 theIS >> myPAtt;
371 }
372 if (!theIS || myPAtt.TypeId() != BinLDrivers_ENDATTRLIST) {
373 // unexpected EOF or garbage data
374 WriteMessage (aMethStr + "error: unexpected EOF or garbage data");
375 myReaderStatus = PCDM_RS_UnrecognizedFileFormat;
376 return -1;
377 }
378
379 // Read children:
380 // read the tag of a child label
381 Standard_Integer aTag = BinLDrivers_ENDLABEL;
382 theIS.read ((char*) &aTag, sizeof(Standard_Integer));
383#if DO_INVERSE
384 aTag = InverseInt (aTag);
385#endif
386 while (theIS && aTag >= 0) { // not an end marker ?
387 // create sub-label
388 TDF_Label aLab = theLabel.FindChild (aTag, Standard_True);
389
390 // read sub-tree
391 Standard_Integer nbSubRead = ReadSubTree(theIS, aLab);
392 // check for error
393 if (nbSubRead == -1)
394 return -1;
395 nbRead += nbSubRead;
396
397 // read the tag of the next child
398 theIS.read ((char*) &aTag, sizeof(Standard_Integer));
399#if DO_INVERSE
400 aTag = InverseInt (aTag);
401#endif
402 }
403 if (aTag != BinLDrivers_ENDLABEL) {
404 // invalid end label marker
405 WriteMessage (aMethStr + "error: invalid end label marker");
406 myReaderStatus = PCDM_RS_UnrecognizedFileFormat;
407 return -1;
408 }
409
410 return nbRead;
411}
412
413//=======================================================================
414//function : AttributeDrivers
415//purpose :
416//=======================================================================
417
418Handle(BinMDF_ADriverTable) BinLDrivers_DocumentRetrievalDriver::AttributeDrivers
419 (const Handle(CDM_MessageDriver)& theMessageDriver)
420{
421 return BinLDrivers::AttributeDrivers (theMessageDriver);
422}
423
424//=======================================================================
425//function : ReadInfoSection
426//purpose : Read the info section of theFile, return a file
427// position corresponding to the info section end
428//=======================================================================
429
430Storage_Position BinLDrivers_DocumentRetrievalDriver::ReadInfoSection
431 (const TCollection_AsciiString& theFileName,
432 Handle(Storage_HeaderData)& theData)
433{
434 TCollection_ExtendedString aMsg
435 ( "BinLDrivers_DocumentRetrievalDriver: error: ");
436
437 FSD_BinaryFile aFileDriver;
438 Storage_Position aPos = 0;
439 if (aFileDriver.Open( theFileName, Storage_VSRead ) == Storage_VSOk)
440 {
441 Storage_Schema aSchema;
442 theData = aSchema.ReadHeaderSection( aFileDriver );
443
444 if (theData->ErrorStatus() == Storage_VSOk)
445 aPos = aFileDriver.Tell();
446 else
447 WriteMessage( aMsg + theData->ErrorStatusExtension() );
448 }
449 else
450 WriteMessage( aMsg + "can not open file " + theFileName);
451
452 aFileDriver.Close();
453
454 return aPos;
455}
456
457//=======================================================================
458//function : WriteMessage
459//purpose : write theMessage to the MessageDriver of
460// theApplication
461//=======================================================================
462
463void BinLDrivers_DocumentRetrievalDriver::WriteMessage
464 (const TCollection_ExtendedString& theMsg)
465{
466 if (!myMsgDriver.IsNull())
467 myMsgDriver->Write (theMsg.ToExtString());
468}
469
470//=======================================================================
471//function : ReadSection
472//purpose :
473//=======================================================================
474
475void BinLDrivers_DocumentRetrievalDriver::ReadSection
476 (BinLDrivers_DocumentSection& /*theSection*/,
477 const Handle(CDM_Document)& /*theDocument*/,
478 Standard_IStream& /*theIS*/)
479{
480 // empty; should be redefined in subclasses
481}
482
483//=======================================================================
484//function : ReadShapeSection
485//purpose :
486//=======================================================================
487
488void BinLDrivers_DocumentRetrievalDriver::ReadShapeSection
489 (BinLDrivers_DocumentSection& theSection,
490 Standard_IStream& /*theIS*/,
491 const Standard_Boolean isMess)
492
493{
494 if(isMess && theSection.Length()) {
495 const TCollection_ExtendedString aMethStr ("BinLDrivers_DocumentRetrievalDriver: ");
496 WriteMessage (aMethStr + "warning: Geometry is not supported by Lite schema. ");
497 }
498}
499
500//=======================================================================
501//function : CheckShapeSection
502//purpose :
503//=======================================================================
504void BinLDrivers_DocumentRetrievalDriver::CheckShapeSection(
505 const Storage_Position& ShapeSectionPos,
506 Standard_IStream& IS)
507{
d41f6af3 508 if (!IS.eof())
509 {
105aae76 510 const std::streamoff endPos = IS.rdbuf()->pubseekoff(0L, std::ios_base::end, std::ios_base::in);
0797d9d3 511#ifdef OCCT_DEBUG
7fd59977 512 cout << "endPos = " << endPos <<endl;
513#endif
514 if(ShapeSectionPos != endPos) {
515 const TCollection_ExtendedString aMethStr ("BinLDrivers_DocumentRetrievalDriver: ");
516 WriteMessage (aMethStr + "warning: Geometry is not supported by Lite schema. ");
517 }
518 }
519}
520
521//=======================================================================
522//function : PropagateDocumentVersion
523//purpose :
524//=======================================================================
525void BinLDrivers_DocumentRetrievalDriver::PropagateDocumentVersion(const Standard_Integer theDocVersion )
526{
527 BinMDataStd::SetDocumentVersion(theDocVersion);
528}
d9ff84e8 529
530//=======================================================================
531//function : CheckDocumentVersion
532//purpose :
533//=======================================================================
534Standard_Boolean BinLDrivers_DocumentRetrievalDriver::CheckDocumentVersion(
535 const Standard_Integer theFileVersion,
536 const Standard_Integer theCurVersion)
537{
538 if (theFileVersion < 2 || theFileVersion > theCurVersion) {
539 // file was written with another version
540 return Standard_False;
541 }
542 return Standard_True;
543}
544