0024856: CLang warnings -Wunused-private-field
[occt.git] / src / BinLDrivers / BinLDrivers_DocumentStorageDriver.cxx
CommitLineData
b311480e 1// Created on: 2002-10-29
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
16#include <BinLDrivers_DocumentStorageDriver.ixx>
17#include <BinLDrivers.hxx>
18#include <BinLDrivers_Marker.hxx>
19#include <BinMDF_ADriver.hxx>
20#include <BinObjMgt_Persistent.hxx>
21#include <CDM_Application.hxx>
22#include <FSD_BinaryFile.hxx>
23#include <FSD_FileHeader.hxx>
24#include <PCDM_ReadWriter.hxx>
25#include <Standard_ErrorHandler.hxx>
26#include <Storage_Schema.hxx>
27#include <TColStd_Array1OfInteger.hxx>
28#include <TColStd_ListIteratorOfListOfInteger.hxx>
29#include <TColStd_ListOfInteger.hxx>
30#include <TCollection_AsciiString.hxx>
31#include <TDF_AttributeIterator.hxx>
32#include <TDF_ChildIterator.hxx>
33#include <TDF_Data.hxx>
34#include <TDF_Tool.hxx>
35#include <TDocStd_Document.hxx>
36
37#define SHAPESECTION_POS (Standard_CString)"SHAPE_SECTION_POS:"
38
39//=======================================================================
40//function : BinLDrivers_DocumentStorageDriver
41//purpose : Constructor
42//=======================================================================
43
44BinLDrivers_DocumentStorageDriver::BinLDrivers_DocumentStorageDriver ()
45{
46}
47
48//=======================================================================
49//function : SchemaName
50//purpose :
51//=======================================================================
52
53TCollection_ExtendedString BinLDrivers_DocumentStorageDriver::SchemaName() const
54{
55 TCollection_ExtendedString schemaname;
56 return schemaname;
57}
58
59//=======================================================================
60//function : Write
61//purpose :
62//=======================================================================
63
64void BinLDrivers_DocumentStorageDriver::Write
65 (const Handle(CDM_Document)& theDocument,
66 const TCollection_ExtendedString& theFileName)
67{
15e8b082
M
68 SetIsError(Standard_False);
69 SetStoreStatus(PCDM_SS_OK);
70
7fd59977 71 myMsgDriver = theDocument -> Application() -> MessageDriver();
72 myMapUnsupported.Clear();
73
74#if defined(_DEBUG) || defined(DEB)
75 TCollection_ExtendedString aMethStr ("BinLDrivers_DocumentStorageDriver, ");
76#else
77 TCollection_ExtendedString aMethStr;
78#endif
79 TCollection_ExtendedString anErrorStr ("Error: ");
80
81 Handle(TDocStd_Document) aDoc =
82 Handle(TDocStd_Document)::DownCast(theDocument);
83 if (aDoc.IsNull()) {
15e8b082
M
84 SetIsError(Standard_True);
85 SetStoreStatus(PCDM_SS_Doc_IsNull);
7fd59977 86 }
87 else {
88 // Open the file
89 TCollection_AsciiString aFileName (theFileName,'?');
90
91 // First pass: collect empty labels, assign IDs to the types
92 if (myDrivers.IsNull())
93 myDrivers = AttributeDrivers (myMsgDriver);
94 Handle(TDF_Data) aData = aDoc->GetData();
95 FirstPass (aData->Root());
96
97// 1. Write info section (including types table)
98 WriteInfoSection(theDocument, aFileName);
99 myTypesMap.Clear();
15e8b082
M
100 if (IsError())
101 {
102 SetStoreStatus(PCDM_SS_Info_Section_Error);
103 return;
104 }
7fd59977 105
106#if !defined(IRIX) // 10.10.2005
107 ofstream anOS (aFileName.ToCString(), ios::in | ios::binary | ios::ate);
108#else
109 ofstream anOS (aFileName.ToCString(), ios::ate);
9293178b 110 //ofstream anOS (aFileName.ToCString(), ios::out| ios::binary | ios::ate);
7fd59977 111#endif
112#ifdef DEB
9293178b 113 const Standard_Integer aP = (Standard_Integer) anOS.tellp();
7fd59977 114 cout << "POS = " << aP <<endl;
115#endif
116//#endif
117
118 if (anOS) {
119
120// 2. Write the Table of Contents of Sections
121 BinLDrivers_VectorOfDocumentSection::Iterator anIterS (mySections);
122 for (; anIterS.More(); anIterS.Next())
123 anIterS.ChangeValue().WriteTOC (anOS);
124
9293178b 125 // Shapes Section is the last one, it indicates the end of the table.
7fd59977 126 BinLDrivers_DocumentSection aShapesSection (SHAPESECTION_POS,
127 Standard_False);
9293178b 128 aShapesSection.WriteTOC (anOS);
7fd59977 129
130// 3. Write document contents
131 // (Storage data to the stream)
132 myRelocTable.Clear();
133 myPAtt.Init();
134
135// Write Doc structure
136 WriteSubTree (aData->Root(), anOS); // Doc is written
137
138// 4. Write Shapes section
139 WriteShapeSection(aShapesSection, anOS);
140
141// Write application-defined sections
142 for (anIterS.Init (mySections); anIterS.More(); anIterS.Next()) {
143 BinLDrivers_DocumentSection& aSection = anIterS.ChangeValue();
144 const Standard_Size aSectionOffset = (Standard_Size) anOS.tellp();
145 WriteSection (aSection.Name(), theDocument, anOS);
146 aSection.Write (anOS, aSectionOffset);
147 }
148
9293178b 149// End of processing: close structures and check the status
7fd59977 150 myPAtt.Destroy(); // free buffer
151 myEmptyLabels.Clear();
152 myMapUnsupported.Clear();
153
154 if (!myRelocTable.Extent()) {
155 // No objects written
156#ifdef DEB
157 WriteMessage (aMethStr + "no objects written");
158#endif
15e8b082
M
159 SetIsError(Standard_True);
160 SetStoreStatus(PCDM_SS_No_Obj);
161
7fd59977 162 }
163 myRelocTable.Clear();
164 }
165
166 if (!anOS) {
167 // A problem with the stream
168#if defined(_DEBUG) || defined(DEB)
169 WriteMessage (anErrorStr + aMethStr +
170 "Problem with the file stream, rdstate="
9293178b 171 + (Standard_Integer )anOS.rdstate());
7fd59977 172#else
173 TCollection_ExtendedString aStr =
174 anErrorStr + aMethStr + "Problem writing the file ";
175 WriteMessage (aStr + theFileName);
176#endif
15e8b082 177 SetIsError(Standard_True);
566f8441 178 SetStoreStatus(PCDM_SS_WriteFailure);
7fd59977 179 }
180
181 }
182}
183
184//=======================================================================
185//function : UnsupportedAttrMsg
9293178b 186//purpose :
7fd59977 187//=======================================================================
188
189void BinLDrivers_DocumentStorageDriver::UnsupportedAttrMsg
190 (const Handle(Standard_Type)& theType)
191{
192#ifdef DEB
193 static TCollection_ExtendedString aMsg
194 ("BinDrivers_DocumentStorageDriver: warning: attribute driver for type ");
195#endif
196 if (!myMapUnsupported.Contains(theType)) {
197 myMapUnsupported.Add(theType);
198#ifdef DEB
199 WriteMessage (aMsg + theType->Name() + " not found");
200#endif
201 }
202}
203
204//=======================================================================
205//function : WriteSubTree
206//purpose :
207//=======================================================================
208
209void BinLDrivers_DocumentStorageDriver::WriteSubTree
210 (const TDF_Label& theLabel,
211 Standard_OStream& theOS)
212{
213 // Skip empty labels
214 if (!myEmptyLabels.IsEmpty() && myEmptyLabels.First() == theLabel) {
215 myEmptyLabels.RemoveFirst();
216 return;
217 }
218
219 // Write label header: tag
220 Standard_Integer aTag = theLabel.Tag();
221#if DO_INVERSE
222 aTag = InverseInt (aTag);
223#endif
224 theOS.write ((char*)&aTag, sizeof(Standard_Integer));
225
226 // Write attributes
227 TDF_AttributeIterator itAtt (theLabel);
228 for ( ; itAtt.More() && theOS; itAtt.Next()) {
229 const Handle(TDF_Attribute)& tAtt = itAtt.Value();
230 const Handle(Standard_Type)& aType = tAtt->DynamicType();
231 // Get type ID and driver
232 Handle(BinMDF_ADriver) aDriver;
233 const Standard_Integer aTypeId = myDrivers->GetDriver (aType,aDriver);
234 if (aTypeId > 0) {
235 // Add source to relocation table
236 const Standard_Integer anId = myRelocTable.Add (tAtt);
237
238 // Create and fill data item
239 myPAtt.SetTypeId (aTypeId);
240 myPAtt.SetId (anId);
241 aDriver->Paste (tAtt, myPAtt, myRelocTable);
242
243 // Write data to the stream -->!!!
244 theOS << myPAtt;
245 }
246#ifdef DEB
247 else
248 UnsupportedAttrMsg (aType);
249#endif
250 }
251 if (!theOS) {
252 // Problem with the stream
253 return;
254 }
255
256 // Write the end attributes list marker
257 BinLDrivers_Marker anEndAttr = BinLDrivers_ENDATTRLIST;
258#if DO_INVERSE
259 anEndAttr = (BinLDrivers_Marker) InverseInt (anEndAttr);
260#endif
261 theOS.write ((char*)&anEndAttr, sizeof(anEndAttr));
262
263 // Process sub-labels
264 TDF_ChildIterator itChld (theLabel);
265 for ( ; itChld.More(); itChld.Next())
266 {
267 const TDF_Label& aChildLab = itChld.Value();
268 WriteSubTree (aChildLab, theOS);
269 }
270
271 // Write the end label marker
272 BinLDrivers_Marker anEndLabel = BinLDrivers_ENDLABEL;
273#if DO_INVERSE
274 anEndLabel = (BinLDrivers_Marker) InverseInt (anEndLabel);
275#endif
276 theOS.write ((char*)&anEndLabel, sizeof(anEndLabel));
277
278}
279
7fd59977 280//=======================================================================
281//function : AttributeDrivers
282//purpose :
283//=======================================================================
284
285Handle(BinMDF_ADriverTable) BinLDrivers_DocumentStorageDriver::AttributeDrivers
286 (const Handle(CDM_MessageDriver)& theMessageDriver)
287{
288 return BinLDrivers::AttributeDrivers (theMessageDriver);
289}
290
291//=======================================================================
292//function : FirstPassSubTree
293//purpose :
294//=======================================================================
295
296Standard_Boolean BinLDrivers_DocumentStorageDriver::FirstPassSubTree
297 (const TDF_Label& L,
298 TDF_LabelList& ListOfEmptyL)
299{
300 // are there writable attributes on L ?
301 Standard_Boolean hasAttr = Standard_False;
302 TDF_AttributeIterator itAtt (L);
303 for ( ; itAtt.More(); itAtt.Next()) {
304 const Handle(Standard_Type)& aType = itAtt.Value()->DynamicType();
305 Handle(BinMDF_ADriver) aDriver;
306 // do not rely on a value returned by GetDriver here, because
307 // the IDs have not yet been assigned to the types
308 myDrivers->GetDriver (aType, aDriver);
309 if (!aDriver.IsNull()) {
310 hasAttr = Standard_True;
311 myTypesMap.Add (aType);
312 }
313#ifdef DEB
314 else
315 UnsupportedAttrMsg (aType);
316#endif
317 }
318
319 // are there writable attributes on sub-labels ?
320 Standard_Boolean hasChildAttr = Standard_False;
321 TDF_LabelList emptyChildrenList;
322 TDF_ChildIterator itChld (L);
323 for ( ; itChld.More(); itChld.Next())
324 {
325 if (FirstPassSubTree (itChld.Value(), emptyChildrenList))
326 emptyChildrenList.Append( itChld.Value() );
327 else
328 hasChildAttr = Standard_True;
329 }
330
331 Standard_Boolean isEmpty = !(hasAttr || hasChildAttr);
332
333 if (!isEmpty)
334 ListOfEmptyL.Append( emptyChildrenList );
335
336 return isEmpty;
337}
338
339//=======================================================================
340//function : FirstPass
341//purpose :
342//=======================================================================
343
344void BinLDrivers_DocumentStorageDriver::FirstPass
345 (const TDF_Label& theRoot)
346{
347 myTypesMap.Clear();
348 myEmptyLabels.Clear();
349
350 if (FirstPassSubTree( theRoot, myEmptyLabels))
351 myEmptyLabels.Append( theRoot );
352
353 myDrivers->AssignIds (myTypesMap);
354}
355
356//=======================================================================
357//function : WriteInfoSection
358//purpose : Write info secton using FSD_BinaryFile driver
359//=======================================================================
360
361#define START_TYPES "START_TYPES"
362#define END_TYPES "END_TYPES"
363
364void BinLDrivers_DocumentStorageDriver::WriteInfoSection
365 (const Handle(CDM_Document)& theDocument,
366 const TCollection_AsciiString& theFileName)
367{
368 FSD_BinaryFile aFileDriver;
369 if (aFileDriver.Open( theFileName, Storage_VSWrite ) != Storage_VSOk) {
370#if defined(DEB) || defined(_DEBUG)
371 WriteMessage ("BinDrivers_DocumentStorageDriver: error opening file");
372#else
373 WriteMessage (TCollection_ExtendedString("Error: Cannot open file ") +
374 theFileName);
375#endif
15e8b082 376 SetIsError(Standard_True);
7fd59977 377 return;
378 }
379
380 if (aFileDriver.BeginWriteInfoSection() == Storage_VSOk)
381 {
382 // add format
383 Handle(Storage_Data) theData = new Storage_Data;
384 PCDM_ReadWriter::WriteFileFormat( theData, theDocument );
385 PCDM_ReadWriter::Writer()->WriteReferenceCounter(theData,theDocument);
386 PCDM_ReadWriter::Writer()->WriteReferences(theData,theDocument,theFileName);
387 PCDM_ReadWriter::Writer()->WriteExtensions(theData,theDocument);
388 PCDM_ReadWriter::Writer()->WriteVersion(theData,theDocument);
389
390 // add the types table
391 theData->AddToUserInfo(START_TYPES);
392 Standard_Integer i;
393 for (i = 1; i <= myTypesMap.Extent(); i++) {
394 Handle(BinMDF_ADriver) aDriver = myDrivers->GetDriver(i);
395 if (!aDriver.IsNull()) {
396 const TCollection_AsciiString& aTypeName = aDriver->TypeName();
397 theData->AddToUserInfo(aTypeName);
398 }
399 }
400 theData->AddToUserInfo(END_TYPES);
401
402 // add document comments
403 TColStd_SequenceOfExtendedString aComments;
404 theDocument->Comments(aComments);
405 for (i = 1; i <= aComments.Length(); i++)
406 theData->AddToComments(aComments(i));
407
408 // Info
409 aFileDriver.WriteInfo
9293178b 410 (1, // nbObj
7fd59977 411 BinLDrivers::StorageVersion(),
412 Storage_Schema::ICreationDate(),
413 TCollection_AsciiString(SchemaName(),'?'),
9293178b 414 1, // schemaVersion
7fd59977 415 theData->ApplicationName(),
416 theData->ApplicationVersion(),
417 theData->DataType(),
418 theData->UserInfo()
419 );
420
421 // we write a complete header section: info and comments
422 aFileDriver.EndWriteInfoSection();
423 aFileDriver.BeginWriteCommentSection();
424 aFileDriver.WriteComment(theData->Comments());// <=== !!! szy - it was missed
425 aFileDriver.EndWriteCommentSection();
426 // here the location of info and comment sections is written
427 aFileDriver.EndWriteDataSection();
428 }
429 else {
430#if defined(DEB) || defined(_DEBUG)
431 WriteMessage("BinDrivers_DocumentStorageDriver: error writing header");
432#else
433 WriteMessage(TCollection_ExtendedString("Error: Problem writing header "
434 "into file ") + theFileName);
435#endif
15e8b082 436 SetIsError(Standard_True);
7fd59977 437 }
438#ifdef DEB
9293178b 439 const Standard_Integer aP = (Standard_Integer) aFileDriver.Tell();
7fd59977 440 cout << "POS = " << aP <<endl;
9293178b 441#endif
7fd59977 442 aFileDriver.Close();
443}
444
445//=======================================================================
446//function : WriteMessage
447//purpose : write theMessage to the MessageDriver of the
448// Application
449//=======================================================================
450
451void BinLDrivers_DocumentStorageDriver::WriteMessage
452 (const TCollection_ExtendedString& theMsg)
453{
454 if (!myMsgDriver.IsNull())
455 myMsgDriver->Write (theMsg.ToExtString());
456}
457
458//=======================================================================
459//function : AddSection
9293178b 460//purpose :
7fd59977 461//=======================================================================
462
463void BinLDrivers_DocumentStorageDriver::AddSection
464 (const TCollection_AsciiString& theName,
465 const Standard_Boolean isPostRead)
466{
467 mySections.Append (BinLDrivers_DocumentSection (theName, isPostRead));
468}
469
470//=======================================================================
471//function : WriteSection
9293178b 472//purpose :
7fd59977 473//=======================================================================
474
475void BinLDrivers_DocumentStorageDriver::WriteSection
476 (const TCollection_AsciiString& /*theName*/,
477 const Handle_CDM_Document& /*theDocument*/,
478 Standard_OStream& /*theOS*/)
479{
480 // empty; should be redefined in subclasses
481}
482
483//=======================================================================
484//function : WriteShapeSection
485//purpose : defines WriteShapeSection
486//=======================================================================
487void BinLDrivers_DocumentStorageDriver::WriteShapeSection
488 (BinLDrivers_DocumentSection& theSection,
489 Standard_OStream& theOS)
490{
491 const Standard_Size aShapesSectionOffset = (Standard_Size) theOS.tellp();
492 theSection.Write (theOS, aShapesSectionOffset);
493}