1 // Copyright (c) 2017 OPEN CASCADE SAS
3 // This file is part of Open CASCADE Technology software library.
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
14 #include <NCollection_Handle.hxx>
15 #include <NCollection_Array1.hxx>
17 #include <PCDM_BaseDriverPointer.hxx>
18 #include <PCDM_ReadWriter.hxx>
19 #include <Standard_ErrorHandler.hxx>
20 #include <Standard_NullObject.hxx>
21 #include <StdObjMgt_Persistent.hxx>
22 #include <StdObjMgt_ReadData.hxx>
23 #include <StdObjMgt_WriteData.hxx>
24 #include <StdStorage.hxx>
25 #include <StdStorage_Data.hxx>
26 #include <StdStorage_HeaderData.hxx>
27 #include <StdStorage_TypeData.hxx>
28 #include <StdStorage_RootData.hxx>
29 #include <StdStorage_HSequenceOfRoots.hxx>
30 #include <StdStorage_BacketOfPersistent.hxx>
31 #include <Storage.hxx>
32 #include <Storage_BaseDriver.hxx>
33 #include <Storage_StreamTypeMismatchError.hxx>
34 #include <Storage_StreamFormatError.hxx>
35 #include <Storage_StreamWriteError.hxx>
40 //=======================================================================
41 // StdStorage::Version
42 //=======================================================================
43 TCollection_AsciiString StdStorage::Version()
45 TCollection_AsciiString v("1.3");
49 //=======================================================================
51 // Reads data from a file
52 //=======================================================================
53 Storage_Error StdStorage::Read(const TCollection_AsciiString& theFileName,
54 Handle(StdStorage_Data)& theData)
56 // Create a driver appropriate for the given file
57 PCDM_BaseDriverPointer aDriverPtr;
58 if (PCDM::FileDriverType(theFileName, aDriverPtr) == PCDM_TOFD_Unknown)
59 return Storage_VSWrongFileDriver;
61 NCollection_Handle<Storage_BaseDriver> aDriver(aDriverPtr);
63 // Try to open the file
67 PCDM_ReadWriter::Open(*aDriver, theFileName, Storage_VSRead);
69 catch (Standard_Failure const&)
71 return Storage_VSOpenError;
74 return Read(*aDriver, theData);
77 //=======================================================================
79 // Reads data from a pre-opened for reading driver
80 //=======================================================================
81 Storage_Error StdStorage::Read(Storage_BaseDriver& theDriver,
82 Handle(StdStorage_Data)& theData)
85 theData = new StdStorage_Data;
89 Handle(StdStorage_HeaderData) aHeaderData = theData->HeaderData();
90 Handle(StdStorage_TypeData) aTypeData = theData->TypeData();
91 Handle(StdStorage_RootData) aRootData = theData->RootData();
93 // Read header section
94 if (!aHeaderData->Read(theDriver))
95 return aHeaderData->ErrorStatus();
98 if (!aTypeData->Read(theDriver))
99 return aTypeData->ErrorStatus();
101 // Select instantiators for the used types
102 NCollection_Array1<StdObjMgt_Persistent::Instantiator>
103 anInstantiators(1, aTypeData->NumberOfTypes());
104 for (Standard_Integer i = 1; i <= aTypeData->NumberOfTypes(); i++)
106 StdObjMgt_Persistent::Instantiator anInstantiator =
107 aTypeData->Instantiator(i);
109 anInstantiators(i) = anInstantiator;
111 return Storage_VSUnknownType;
115 if (!aRootData->Read(theDriver))
116 return aRootData->ErrorStatus();
118 Storage_Error anError;
120 // Read and parse reference section
121 StdObjMgt_ReadData aReadData(theDriver, aHeaderData->NumberOfObjects());
123 anError = theDriver.BeginReadRefSection();
124 if (anError != Storage_VSOk)
127 Standard_Integer aNbRefs = theDriver.RefSectionSize();
128 for (Standard_Integer i = 1; i <= aNbRefs; i++)
130 Standard_Integer aRef = 0, aType = 0;
134 theDriver.ReadReferenceType(aRef, aType);
135 anError = Storage_VSOk;
137 catch (Storage_StreamTypeMismatchError const&)
139 anError = Storage_VSTypeMismatch;
142 if (anError != Storage_VSOk)
145 aReadData.CreatePersistentObject(aRef, anInstantiators(aType));
148 anError = theDriver.EndReadRefSection();
149 if (anError != Storage_VSOk)
152 // Read and parse data section
153 anError = theDriver.BeginReadDataSection();
154 if (anError != Storage_VSOk)
157 for (Standard_Integer i = 1; i <= aHeaderData->NumberOfObjects(); i++)
162 aReadData.ReadPersistentObject(i);
163 anError = Storage_VSOk;
165 catch (Storage_StreamTypeMismatchError const&) { anError = Storage_VSTypeMismatch; }
166 catch (Storage_StreamFormatError const&) { anError = Storage_VSFormatError; }
167 catch (Storage_StreamReadError const&) { anError = Storage_VSFormatError; }
169 if (anError != Storage_VSOk)
173 anError = theDriver.EndReadDataSection();
174 if (anError != Storage_VSOk)
177 Handle(StdStorage_HSequenceOfRoots) aRoots = aRootData->Roots();
178 if (!aRoots.IsNull())
180 for (StdStorage_HSequenceOfRoots::Iterator anIt(*aRoots); anIt.More(); anIt.Next())
182 Handle(StdStorage_Root)& aRoot = anIt.ChangeValue();
183 aRoot->SetObject(aReadData.PersistentObject(aRoot->Reference()));
190 //=======================================================================
191 // StdStorage::currentDate
192 //=======================================================================
193 static TCollection_AsciiString currentDate()
197 char nowstr[SLENGTH];
199 struct tm *nowstruct;
200 if (time(&nowbin) != (time_t)-1)
202 nowstruct = localtime(&nowbin);
203 strftime(nowstr, SLENGTH, "%m/%d/%Y", nowstruct);
205 TCollection_AsciiString t(nowstr);
211 //=======================================================================
213 //=======================================================================
214 Storage_Error StdStorage::Write(Storage_BaseDriver& theDriver,
215 const Handle(StdStorage_Data)& theData)
217 Standard_NullObject_Raise_if(theData.IsNull(), "Null storage data");
219 Handle(StdStorage_HeaderData) aHeaderData = theData->HeaderData();
220 Handle(StdStorage_TypeData) aTypeData = theData->TypeData();
221 Handle(StdStorage_RootData) aRootData = theData->RootData();
223 aHeaderData->SetCreationDate(currentDate());
225 Handle(StdStorage_HSequenceOfRoots) aRoots = aRootData->Roots();
227 StdStorage_BucketOfPersistent aPObjs;
229 if (!aRoots.IsNull())
231 StdObjMgt_Persistent::SequenceOfPersistent aPQueue;
232 for (StdStorage_HSequenceOfRoots::Iterator anIt(*aRoots); anIt.More(); anIt.Next())
234 Handle(StdStorage_Root) aRoot = anIt.ChangeValue();
235 Handle(StdObjMgt_Persistent) aPObj = aRoot->Object();
236 if (!aPObj.IsNull()) {
237 aPQueue.Append(aPObj);
240 while (!aPQueue.IsEmpty())
242 StdObjMgt_Persistent::SequenceOfPersistent aPQueue1;
243 for (StdObjMgt_Persistent::SequenceOfPersistent::Iterator anIt(aPQueue); anIt.More(); anIt.Next())
245 Handle(StdObjMgt_Persistent)& aPObj = anIt.ChangeValue();
248 if (aPObj->TypeNum() == 0 && aPObj->RefNum() == 0)
250 aPObj->TypeNum(aTypeData->AddType(aPObj));
251 Standard_Integer anPObjId = aPObjs.Length() + 1;
252 aPObj->RefNum(anPObjId);
253 aPObjs.Append(aPObj);
254 aPObj->PChildren(aPQueue1);
258 aPQueue.Assign(aPQueue1);
262 aHeaderData->SetStorageVersion(StdStorage::Version());
263 aHeaderData->SetNumberOfObjects(aPObjs.Length());
266 // Write header section
267 if (!aHeaderData->Write(theDriver))
268 return aHeaderData->ErrorStatus();
270 // Write types section
271 if (!aTypeData->Write(theDriver))
272 return aTypeData->ErrorStatus();
274 // Write root section
275 if (!aRootData->Write(theDriver))
276 return aRootData->ErrorStatus();
278 Storage_Error anError;
280 // Write reference section
281 anError = theDriver.BeginWriteRefSection();
282 if (anError != Storage_VSOk)
285 theDriver.SetRefSectionSize(aPObjs.Length());
286 for (StdStorage_BucketIterator anIt(&aPObjs); anIt.More(); anIt.Next())
288 Handle(StdObjMgt_Persistent) aPObj = anIt.Value();
290 theDriver.WriteReferenceType(aPObj->RefNum(), aPObj->TypeNum());
293 anError = theDriver.EndWriteRefSection();
294 if (anError != Storage_VSOk)
297 // Write data section
298 anError = theDriver.BeginWriteDataSection();
299 if (anError != Storage_VSOk)
302 StdObjMgt_WriteData aWriteData(theDriver);
303 for (StdStorage_BucketIterator anIt(&aPObjs); anIt.More(); anIt.Next())
305 Handle(StdObjMgt_Persistent) aPObj = anIt.Value();
307 aWriteData.WritePersistentObject(aPObj);
310 anError = theDriver.EndWriteDataSection();
311 if (anError != Storage_VSOk)
314 catch (Storage_StreamWriteError const&) {
315 return Storage_VSWriteError;