// Created on: 2002-10-31 // Created by: Michael SAZONOV // Copyright (c) 2002-2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // // This library is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. // // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include IMPLEMENT_STANDARD_RTTIEXT(BinLDrivers_DocumentRetrievalDriver,PCDM_RetrievalDriver) #define SHAPESECTION_POS "SHAPE_SECTION_POS:" #define SIZEOFSHAPELABEL 18 #define DATATYPE_MIGRATION //#define DATATYPE_MIGRATION_DEB //======================================================================= //function : BinLDrivers_DocumentRetrievalDriver //purpose : Constructor //======================================================================= BinLDrivers_DocumentRetrievalDriver::BinLDrivers_DocumentRetrievalDriver () { myReaderStatus = PCDM_RS_OK; } //======================================================================= //function : CreateDocument //purpose : pure virtual method definition //======================================================================= Handle(CDM_Document) BinLDrivers_DocumentRetrievalDriver::CreateDocument() { return new TDocStd_Document(PCDM_RetrievalDriver::GetFormat()); } //======================================================================= //function : SchemaName //purpose : pure virtual method definition //======================================================================= TCollection_ExtendedString BinLDrivers_DocumentRetrievalDriver::SchemaName() const { TCollection_ExtendedString schemaname; return schemaname; } //======================================================================= //function : Make //purpose : pure virtual method definition //======================================================================= void BinLDrivers_DocumentRetrievalDriver::Make (const Handle(PCDM_Document)&, const Handle(CDM_Document)&) { } //======================================================================= //function : Read //purpose : //======================================================================= void BinLDrivers_DocumentRetrievalDriver::Read (const TCollection_ExtendedString& theFileName, const Handle(CDM_Document)& theNewDocument, const Handle(CDM_Application)& theApplication) { std::ifstream aFileStream; OSD_OpenStream (aFileStream, theFileName, std::ios::in | std::ios::binary); if (aFileStream.is_open() && aFileStream.good()) { Handle(Storage_Data) dData; TCollection_ExtendedString aFormat = PCDM_ReadWriter::FileFormat (aFileStream, dData); Read (aFileStream, dData, theNewDocument, theApplication); } else { myReaderStatus = PCDM_RS_OpenError; } } #define MODIFICATION_COUNTER "MODIFICATION_COUNTER: " #define REFERENCE_COUNTER "REFERENCE_COUNTER: " #define START_TYPES "START_TYPES" #define END_TYPES "END_TYPES" //======================================================================= //function : Read //purpose : //======================================================================= void BinLDrivers_DocumentRetrievalDriver::Read (Standard_IStream& theIStream, const Handle(Storage_Data)& theStorageData, const Handle(CDM_Document)& theDoc, const Handle(CDM_Application)& theApplication) { myReaderStatus = PCDM_RS_DriverFailure; myMsgDriver = theApplication -> MessageDriver(); const TCollection_ExtendedString aMethStr ("BinLDrivers_DocumentRetrievalDriver: "); Handle(TDocStd_Document) aDoc = Handle(TDocStd_Document)::DownCast(theDoc); if (aDoc.IsNull()) { #ifdef OCCT_DEBUG WriteMessage (aMethStr + "error: null document"); #endif myReaderStatus = PCDM_RS_NoDocument; return; } // 1. the information section Handle(Storage_HeaderData) aHeaderData; if (!theStorageData.IsNull()) { aHeaderData = theStorageData->HeaderData(); } if (!aHeaderData.IsNull()) { for (Standard_Integer i = 1; i <= aHeaderData->UserInfo().Length(); i++) { const TCollection_AsciiString& aLine = aHeaderData->UserInfo().Value(i); if(aLine.Search(REFERENCE_COUNTER) != -1) { theDoc->SetReferenceCounter (aLine.Token(" ", 2).IntegerValue()); } else if(aLine.Search(MODIFICATION_COUNTER) != -1) { theDoc->SetModifications (aLine.Token(" ", 2).IntegerValue()); } } } // 1.a Version of writer if (!aHeaderData->StorageVersion().IsIntegerValue()) { // file has no format version WriteMessage (aMethStr + "error: file has no format version"); myReaderStatus = PCDM_RS_FormatFailure; return; } Standard_Integer aFileVer = aHeaderData->StorageVersion().IntegerValue(); Standard_Integer aCurrVer = BinLDrivers::StorageVersion().IntegerValue(); // maintain one-way compatibility starting from version 2+ if (!CheckDocumentVersion(aFileVer, aCurrVer)) { myReaderStatus = PCDM_RS_NoVersion; // file was written with another version WriteMessage (aMethStr + "error: wrong file version: " + aHeaderData->StorageVersion() + " while current is " + BinLDrivers::StorageVersion()); return; } // 1.b Retrieve the Types table TColStd_SequenceOfAsciiString aTypeNames; //Sequence of types in file const TColStd_SequenceOfAsciiString& aUserInfo = aHeaderData->UserInfo(); Standard_Boolean begin = Standard_False; Standard_Integer i; for (i=1; i <= aUserInfo.Length(); i++) { //const TCollection_AsciiString& aStr = aUserInfo(i); TCollection_AsciiString aStr = aUserInfo(i); if (aStr == START_TYPES) begin = Standard_True; else if (aStr == END_TYPES) break; else if (begin) { if ( aFileVer < 8 ) { #ifdef DATATYPE_MIGRATION TCollection_AsciiString newName; if(Storage_Schema::CheckTypeMigration(aStr, newName)) { #ifdef OCCT_DEBUG cout << "CheckTypeMigration:OldType = " <= 3) { BinLDrivers_DocumentSection aSection; do { BinLDrivers_DocumentSection::ReadTOC (aSection, theIStream); mySections.Append(aSection); } while (!aSection.Name().IsEqual((Standard_CString)SHAPESECTION_POS)); aDocumentPos = theIStream.tellg(); // position of root label BinLDrivers_VectorOfDocumentSection::Iterator anIterS (mySections); for (; anIterS.More(); anIterS.Next()) { BinLDrivers_DocumentSection& aCurSection = anIterS.ChangeValue(); if (aCurSection.IsPostRead() == Standard_False) { theIStream.seekg ((streampos) aCurSection.Offset()); if (aCurSection.Name().IsEqual ((Standard_CString)SHAPESECTION_POS)) ReadShapeSection (aCurSection, theIStream); else ReadSection (aCurSection, theDoc, theIStream); } } } else { //aFileVer < 3 aDocumentPos = theIStream.tellg(); // position of root label // retrieve SHAPESECTION_POS string char aShapeSecLabel[SIZEOFSHAPELABEL + 1]; aShapeSecLabel[SIZEOFSHAPELABEL] = 0x00; theIStream.read ((char*)&aShapeSecLabel, SIZEOFSHAPELABEL);// SHAPESECTION_POS TCollection_AsciiString aShapeLabel(aShapeSecLabel); // detect if a file was written in old fashion (version 2 without shapes) // and if so then skip reading ShapeSection if (aShapeLabel.Length() > 0) { // version 2+(with shapes) and higher goes here if(aShapeLabel.Length() <= 0 || aShapeLabel != SHAPESECTION_POS) { WriteMessage (aMethStr + "error: Format failure"); myReaderStatus = PCDM_RS_FormatFailure; return; } // retrieve ShapeSection Position Standard_Integer aShapeSectionPos; // go to ShapeSection theIStream.read ((char*)&aShapeSectionPos, sizeof(Standard_Integer)); #if DO_INVERSE aShapeSectionPos = InverseInt (aShapeSectionPos); #endif #ifdef OCCT_DEBUG cout <<"aShapeSectionPos = " <Root()); myPAtt.Destroy(); // free buffer myRelocTable.Clear(); myMapUnsupported.Clear(); if (nbRead > 0) { // attach data to the document aDoc->SetData (aData); TDocStd_Owner::SetDocument (aData, aDoc); aDoc->SetComments(aHeaderData->Comments()); myReaderStatus = PCDM_RS_OK; } // Read Sections (post-reading type) if (aFileVer >= 3) { BinLDrivers_VectorOfDocumentSection::Iterator aSectIter (mySections); for (; aSectIter.More(); aSectIter.Next()) { BinLDrivers_DocumentSection& aCurSection = aSectIter.ChangeValue(); if (aCurSection.IsPostRead()) { theIStream.seekg ((streampos) aCurSection.Offset()); ReadSection (aCurSection, theDoc, theIStream); } } } } //======================================================================= //function : ReadSubTree //purpose : //======================================================================= Standard_Integer BinLDrivers_DocumentRetrievalDriver::ReadSubTree (Standard_IStream& theIS, const TDF_Label& theLabel) { Standard_Integer nbRead = 0; static TCollection_ExtendedString aMethStr ("BinLDrivers_DocumentRetrievalDriver: "); // Read attributes: theIS >> myPAtt; while (theIS && myPAtt.TypeId() > 0 && // not an end marker ? myPAtt.Id() > 0) { // not a garbage ? // get a driver according to TypeId Handle(BinMDF_ADriver) aDriver = myDrivers->GetDriver (myPAtt.TypeId()); if (!aDriver.IsNull()) { // create transient attribute nbRead++; Standard_Integer anID = myPAtt.Id(); Handle(TDF_Attribute) tAtt; Standard_Boolean isBound = myRelocTable.IsBound(anID); if (isBound) tAtt = Handle(TDF_Attribute)::DownCast(myRelocTable.Find(anID)); else tAtt = aDriver->NewEmpty(); if (tAtt->Label().IsNull()) theLabel.AddAttribute (tAtt); else WriteMessage (aMethStr + "warning: attempt to attach attribute " + aDriver->TypeName() + " to a second label"); Standard_Boolean ok = aDriver->Paste (myPAtt, tAtt, myRelocTable); if (!ok) { // error converting persistent to transient WriteMessage (aMethStr + "warning: failure reading attribute " + aDriver->TypeName()); } else if (!isBound) myRelocTable.Bind (anID, tAtt); } else if (!myMapUnsupported.Contains(myPAtt.TypeId())) WriteMessage (aMethStr + "warning: type ID not registered in header: " + myPAtt.TypeId()); // read next attribute theIS >> myPAtt; } if (!theIS || myPAtt.TypeId() != BinLDrivers_ENDATTRLIST) { // unexpected EOF or garbage data WriteMessage (aMethStr + "error: unexpected EOF or garbage data"); myReaderStatus = PCDM_RS_UnrecognizedFileFormat; return -1; } // Read children: // read the tag of a child label Standard_Integer aTag = BinLDrivers_ENDLABEL; theIS.read ((char*) &aTag, sizeof(Standard_Integer)); #if DO_INVERSE aTag = InverseInt (aTag); #endif while (theIS && aTag >= 0) { // not an end marker ? // create sub-label TDF_Label aLab = theLabel.FindChild (aTag, Standard_True); // read sub-tree Standard_Integer nbSubRead = ReadSubTree(theIS, aLab); // check for error if (nbSubRead == -1) return -1; nbRead += nbSubRead; // read the tag of the next child theIS.read ((char*) &aTag, sizeof(Standard_Integer)); #if DO_INVERSE aTag = InverseInt (aTag); #endif } if (aTag != BinLDrivers_ENDLABEL) { // invalid end label marker WriteMessage (aMethStr + "error: invalid end label marker"); myReaderStatus = PCDM_RS_UnrecognizedFileFormat; return -1; } return nbRead; } //======================================================================= //function : AttributeDrivers //purpose : //======================================================================= Handle(BinMDF_ADriverTable) BinLDrivers_DocumentRetrievalDriver::AttributeDrivers (const Handle(CDM_MessageDriver)& theMessageDriver) { return BinLDrivers::AttributeDrivers (theMessageDriver); } //======================================================================= //function : WriteMessage //purpose : write theMessage to the MessageDriver of // theApplication //======================================================================= void BinLDrivers_DocumentRetrievalDriver::WriteMessage (const TCollection_ExtendedString& theMsg) { if (!myMsgDriver.IsNull()) myMsgDriver->Write (theMsg.ToExtString()); } //======================================================================= //function : ReadSection //purpose : //======================================================================= void BinLDrivers_DocumentRetrievalDriver::ReadSection (BinLDrivers_DocumentSection& /*theSection*/, const Handle(CDM_Document)& /*theDocument*/, Standard_IStream& /*theIS*/) { // empty; should be redefined in subclasses } //======================================================================= //function : ReadShapeSection //purpose : //======================================================================= void BinLDrivers_DocumentRetrievalDriver::ReadShapeSection (BinLDrivers_DocumentSection& theSection, Standard_IStream& /*theIS*/, const Standard_Boolean isMess) { if(isMess && theSection.Length()) { const TCollection_ExtendedString aMethStr ("BinLDrivers_DocumentRetrievalDriver: "); WriteMessage (aMethStr + "warning: Geometry is not supported by Lite schema. "); } } //======================================================================= //function : CheckShapeSection //purpose : //======================================================================= void BinLDrivers_DocumentRetrievalDriver::CheckShapeSection( const Storage_Position& ShapeSectionPos, Standard_IStream& IS) { if (!IS.eof()) { const std::streamoff endPos = IS.rdbuf()->pubseekoff(0L, std::ios_base::end, std::ios_base::in); #ifdef OCCT_DEBUG cout << "endPos = " << endPos < theCurVersion) { // file was written with another version return Standard_False; } return Standard_True; }