0022627: Change OCCT memory management defaults
[occt.git] / src / MDF / MDF_Tool.cxx
1 // File:        MDF_Tool.cxx
2 //              --------------
3 // Author:      DAUTRY Philippe
4 //              <fid@fox.paris1.matra-dtv.fr>
5 // Copyright:   Matra Datavision 1997
6
7 // Version:     0.0
8 // History:     Version Date            Purpose
9 //              0.0     Mar 13 1997     Creation
10
11
12
13 #include <MDF_Tool.ixx>
14
15 #include <MDF_ARDriver.hxx>
16 #include <MDF_ASDriver.hxx>
17 #include <MDF_RRelocationTable.hxx>
18 #include <MDF_SRelocationTable.hxx>
19
20 #include <PDF_Attribute.hxx>
21 #include <PDF_HAttributeArray1.hxx>
22
23 #include <TDF_Attribute.hxx>
24 #include <TDF_AttributeIterator.hxx>
25 #include <TDF_ListIteratorOfAttributeList.hxx>
26 #include <TDF_AttributeList.hxx>
27 #include <TDF_ChildIterator.hxx>
28 #include <TDF_Label.hxx>
29 #include <TDF_Tool.hxx>
30
31 #include <TColStd_HArray1OfInteger.hxx>
32
33 #include <PTColStd_DataMapIteratorOfPersistentTransientMap.hxx>
34 #include <PTColStd_DataMapIteratorOfTransientPersistentMap.hxx>
35 #include <PTColStd_PersistentTransientMap.hxx>
36 #include <PTColStd_TransientPersistentMap.hxx>
37
38 #include <Standard_GUID.hxx>
39
40 #ifdef DEB
41 #include <Standard_ConstructionError.hxx>
42 #endif
43
44 #define DeclareAndSpeedCast(V,T,Vdown) Handle(T) Vdown = *((Handle(T)*)& V)
45 #define DeclareConstAndSpeedCast(V,T,Vdown) const Handle(T)& Vdown = (Handle(T)&) V
46 #define SpeedCast(V,T,Vdown) Vdown = *((Handle(T)*)& V)
47
48 #undef DEB_MDF_TOOL
49
50 // Persistent structure:
51 //
52 // Label Array Item
53 //
54 // (Tag; NbOfAttributes; NbOfChildren)
55 //
56 // The attributes are stored sequencially in the Attribute Array.
57 // The children of a label are stored recursively after the label item itself.
58
59
60 //      W       W  RRRRR   III  TTTTT  EEEEE
61 //      W       W  R    R   I     T    E
62 //       W     W   R    R   I     T    E
63 //       W  W  W   RRRRR    I     T    EEE
64 //        WW WW    R  R     I     T    E
65 //        W   W    R   R   III    T    EEEEE
66
67
68 //=======================================================================
69 //function : MDF_NbAttributesWithDriver
70 //purpose  : 
71 //=======================================================================
72
73 static Standard_Integer MDF_NbAttributesWithDriver
74 (const TDF_Label& aLabel,
75  const MDF_TypeASDriverMap& aDriverMap)
76 {
77   Standard_Integer n = 0;
78   for (TDF_AttributeIterator itr1(aLabel); itr1.More(); itr1.Next())
79     if (aDriverMap.IsBound(itr1.Value()->DynamicType())) ++n;
80   for (TDF_ChildIterator itr2(aLabel); itr2.More(); itr2.Next())
81     n += MDF_NbAttributesWithDriver(itr2.Value(),aDriverMap);
82   return n;
83 }
84
85
86 //=======================================================================
87 //function : WriteLabels
88 //purpose  : TRANSIENT -> PERSISTENT;
89 //           writes the arrays contents with empty attributes.
90 //=======================================================================
91
92 void MDF_Tool::WriteLabels
93 (const Handle(TDF_Data)& aSource,
94  const Handle(PDF_Data)& aTarget,
95  const MDF_TypeASDriverMap& aDriverMap,
96  const Handle(MDF_SRelocationTable)& aReloc)
97 {
98   TDF_Label aSourceLab = aSource->Root();
99
100   // Label array sizing.
101   Handle(PColStd_HArray1OfInteger) theLabels;
102   Standard_Integer nbLab = TDF_Tool::NbLabels(aSourceLab);
103   if (nbLab) {
104     theLabels = new PColStd_HArray1OfInteger(1,nbLab*3);
105     aTarget->Labels(theLabels);
106   }
107   // In fact, some labels whithout attributes attached to themselves
108   // nor to their descendants will not be kept.
109
110   // Attribute array sizing.
111   Handle(PDF_HAttributeArray1) theAttributes;
112   Standard_Integer nbAtt = 0;
113   if (nbLab) {
114     nbAtt = MDF_NbAttributesWithDriver(aSourceLab,aDriverMap);
115     if (nbAtt) {
116       theAttributes = new PDF_HAttributeArray1(1,nbAtt);
117       aTarget->Attributes(theAttributes);
118     }
119     // In fact, some attributes will not be kept by the filter.
120   }
121
122   if (nbLab && nbAtt) {
123     // labAlloc & attAlloc content the last used cell address.
124     Standard_Integer labAlloc = 0;
125     Standard_Integer attAlloc = 0;
126     MDF_Tool::WriteLabels(aSourceLab, aTarget->Labels(), aTarget->Attributes(),
127                           aDriverMap, aReloc, labAlloc, attAlloc);
128
129     // Label array REsizing.
130     if (labAlloc < theLabels->Upper()) {
131 #ifdef DEB
132       cout<<"MDF_Tool::WriteLabels LABEL array resizing from "<<theLabels->Upper()<<" to "<<labAlloc<<endl;
133 #endif
134       Handle(PColStd_HArray1OfInteger) newLabels =
135         new PColStd_HArray1OfInteger(1,labAlloc);
136       for (Standard_Integer i = 1; i <= labAlloc; ++i)
137         newLabels->SetValue(i,theLabels->Value(i));
138       aTarget->Labels(newLabels);
139     }
140
141
142     // Attribute array REsizing.
143     if (attAlloc < theAttributes->Upper()) {
144 #ifdef DEB
145       cout<<"MDF_Tool::WriteLabels ATTRIBUTES array resizing from "<<theAttributes->Upper()<<" to "<<attAlloc<<endl;
146 #endif
147       Handle(PDF_HAttributeArray1) newAttributes =
148         new PDF_HAttributeArray1(1,attAlloc);
149       for (Standard_Integer i = 1; i <= attAlloc; ++i)
150         newAttributes->SetValue(i,theAttributes->Value(i));
151       aTarget->Attributes(newAttributes);
152     }
153   }
154 }
155
156
157 //=======================================================================
158 //function : WriteLabels
159 //purpose  : TRANSIENT -> PERSISTENT;
160 //           writes the arrays contents with empty attributes.
161 //=======================================================================
162
163 void MDF_Tool::WriteLabels
164 (const TDF_Label& aSourceLab,
165  const Handle(PColStd_HArray1OfInteger)& theLabels,
166  const Handle(PDF_HAttributeArray1)& theAttributes,
167  const MDF_TypeASDriverMap& aDriverMap,
168  const Handle(MDF_SRelocationTable)& aReloc,
169  Standard_Integer& labAlloc,
170  Standard_Integer& attAlloc)
171 {
172   // Cells allocation.
173   Standard_Integer labIndex = labAlloc;
174   labAlloc += 3;
175   Standard_Integer attIndex = attAlloc; // Backup the value.
176
177   // Tag.
178   theLabels->SetValue(++labIndex,aSourceLab.Tag());
179
180   Standard_Integer count = 0;
181
182   // Attributes.
183   Handle(PDF_Attribute) pAtt;
184   TDF_AttributeIterator itr1(aSourceLab);
185   for ( ; itr1.More(); itr1.Next()) {
186     const Handle(TDF_Attribute)& tAtt = itr1.Value();
187     const Handle(Standard_Type)& type = tAtt->DynamicType();
188     if (aDriverMap.IsBound(type)) {
189       ++count;
190       const Handle(MDF_ASDriver)& driver = aDriverMap.Find(type);
191       pAtt = driver->NewEmpty();
192       theAttributes->SetValue(++attAlloc,pAtt);
193       aReloc->SetRelocation(tAtt,pAtt);
194     }
195   }
196   theLabels->SetValue(++labIndex,count); // Nb Attributes.
197   count = 0;
198
199   // Label Children.
200   Standard_Integer childLabIndex;
201   TDF_ChildIterator itr2(aSourceLab);
202   for ( ; itr2.More(); itr2.Next()) {
203     childLabIndex = labAlloc;
204     const TDF_Label& label = itr2.Value();
205     MDF_Tool::WriteLabels(label, theLabels, theAttributes,
206                           aDriverMap, aReloc, labAlloc, attAlloc);
207     if (childLabIndex < labAlloc) ++count;
208   }
209
210 #ifdef DEB_MDF_TOOL
211   aSourceLab.EntryDump(cout);
212   cout<<" Count="<<count<<" attIndex="<<attIndex<<" attAlloc="<<attAlloc;
213 #endif
214   if (attIndex < attAlloc) { // At least one attribute has been stored.
215     theLabels->SetValue(++labIndex,count); // Nb Children.
216   }
217   else {
218     labAlloc -= 2;
219     theLabels->SetValue(labAlloc--,0); // To clean the tag value.
220 #ifdef DEB_MDF_TOOL
221     cout<<"    <== Cleared";
222 #endif
223   }
224 #ifdef DEB_MDF_TOOL
225   cout<<endl;
226 #endif
227 }
228
229
230 //=======================================================================
231 //function : WriteAttributes
232 //purpose  : TRANSIENT -> PERSISTENT
233 //           writes the persistent attributes content.
234 //=======================================================================
235
236 void MDF_Tool::WriteAttributes
237 (const MDF_TypeASDriverMap& aDriverMap,
238  const Handle(MDF_SRelocationTable)& aReloc) 
239 {
240   // Iterer sur la map pour traduire si target.IsNull().
241   const PTColStd_TransientPersistentMap& attMap = aReloc->AttributeTable();
242   PTColStd_DataMapIteratorOfTransientPersistentMap itr(attMap);
243   Handle(PDF_Attribute) pAtt;
244   for ( ; itr.More(); itr.Next()) {
245     DeclareConstAndSpeedCast(itr.Key(),TDF_Attribute,tAtt);
246     const Handle(Standard_Type)& type = tAtt->DynamicType();
247     if (aDriverMap.IsBound(type)) {
248       SpeedCast(itr.Value(),PDF_Attribute,pAtt);
249       const Handle(MDF_ASDriver)& driver = aDriverMap.Find(type);
250       driver->Paste(tAtt, pAtt, aReloc);
251     }
252   }
253 }
254
255
256
257 //      RRRRR   EEEEE    A    DDDD
258 //      R    R  E       A A   D   D
259 //      R    R  E      A   A  D   D
260 //      RRRRR   EEE    AAAAA  D   D
261 //      R  R    E      A   A  D   D
262 //      R   R   EEEEE  A   A  DDDD
263
264 //=======================================================================
265 //function : ReadLabels
266 //purpose  : PERSISTENT -> TRANSIENT;
267 //           reads the arrays contents and build the objects
268 //           with empty attributes.
269 //=======================================================================
270
271 void MDF_Tool::ReadLabels
272 (const Handle(PDF_Data)& aSource,
273  const Handle(TDF_Data)& aTarget,
274  const MDF_TypeARDriverMap& aDriverMap,
275  const Handle(MDF_RRelocationTable)& aReloc)
276 {
277   // Root label creation.
278   //TDF_Insertor ins(aTarget->Root());
279   TDF_Label ins = aTarget->Root();
280
281   // labAlloc & attAlloc content the last used cell address.
282   Standard_Integer labRead = 1; // Root already used above.
283   Standard_Integer attRead = 0;
284   MDF_Tool::ReadLabels(ins, aSource->Labels(), aSource->Attributes(),
285                        aDriverMap, aReloc, labRead, attRead);
286 }
287
288
289 //=======================================================================
290 //function : ReadLabels
291 //purpose  : PERSISTENT -> TRANSIENT;
292 //           Reads the arrays contents and build the objects
293 //           with empty attributes.
294 //=======================================================================
295
296 void MDF_Tool::ReadLabels
297 (TDF_Label& anIns,
298  const Handle(PColStd_HArray1OfInteger)& theLabels,
299  const Handle(PDF_HAttributeArray1)& theAttributes,
300  const MDF_TypeARDriverMap& aDriverMap,
301  const Handle(MDF_RRelocationTable)& aReloc,
302  Standard_Integer& labRead,
303  Standard_Integer& attRead)
304 {
305   // Empty attributes creation.
306   Handle(TDF_Attribute) tAtt;
307   // Number of attributes.
308   Standard_Integer nbAtt = theLabels->Value(++labRead);
309   for (Standard_Integer iAtt = 1 ; iAtt <= nbAtt; iAtt++) {
310     const Handle(PDF_Attribute)& pAtt = theAttributes->Value(++attRead);
311     if (pAtt.IsNull()) {
312       // This case occurs only if somebody modified manually the file.
313       tAtt.Nullify();
314     }
315     else {
316       const Standard_GUID anEmptyID;
317       Handle(MDF_RRelocationTable) anEmptyRelocaTable = new MDF_RRelocationTable(Standard_True);
318       const Handle(Standard_Type)& type = pAtt->DynamicType();
319       if (aDriverMap.IsBound(type)) {
320         const Handle(MDF_ARDriver)& driver = aDriverMap.Find(type);
321         tAtt = driver->NewEmpty();
322         if (tAtt->ID() == anEmptyID) driver->Paste(pAtt, tAtt, anEmptyRelocaTable);
323         anIns.AddAttribute(tAtt);
324       }
325       aReloc->SetRelocation(pAtt,tAtt);
326     }
327   }
328
329   // Label Children creation.
330   Standard_Integer tag;
331   // Number of labels.
332   Standard_Integer nbLab = theLabels->Value(++labRead);
333   for (Standard_Integer iLab = 1 ; iLab <= nbLab; iLab++) {
334     // Label creation.
335     tag = theLabels->Value(++labRead);
336
337
338     //TDF_Insertor ins(anIns,tag);
339     TDF_Label ins = anIns.FindChild(tag,Standard_True);
340
341     MDF_Tool::ReadLabels(ins, theLabels, theAttributes,
342                          aDriverMap, aReloc, labRead, attRead);
343   }
344 }
345
346
347 //=======================================================================
348 //function : ReadAttributes
349 //purpose  : PERSISTENT -> TRANSIENT
350 //           Reads the persistent attributes content.
351 //=======================================================================
352
353 void MDF_Tool::ReadAttributes
354 (const MDF_TypeARDriverMap& aDriverMap,
355  const Handle(MDF_RRelocationTable)& aReloc) 
356 {
357 //  cout<<"MDF_Tool::ReadAttributes ..."<<endl;
358   // Iterer sur la map pour traduire si target.IsNull().
359   const PTColStd_PersistentTransientMap& attMap = aReloc->AttributeTable();
360   PTColStd_DataMapIteratorOfPersistentTransientMap itr(attMap);
361   Handle(TDF_Attribute) tAtt;
362   for ( ; itr.More(); itr.Next()) {
363     DeclareConstAndSpeedCast(itr.Key(),PDF_Attribute,pAtt);
364     if (!pAtt.IsNull()) { // See above...
365       const Handle(Standard_Type)& type = pAtt->DynamicType();
366       if (aDriverMap.IsBound(type)) {
367         SpeedCast(itr.Value(),TDF_Attribute,tAtt);
368         const Handle(MDF_ARDriver)& driver = aDriverMap.Find(type);
369         driver->Paste(pAtt, tAtt, aReloc);
370       }
371     }
372   }
373
374   TDF_AttributeList attList;
375   for (itr.Initialize(attMap); itr.More(); itr.Next()) {
376     SpeedCast(itr.Value(),TDF_Attribute,tAtt);
377     attList.Append(tAtt);
378   }
379
380   TDF_ListIteratorOfAttributeList itr2;
381   Standard_Boolean noDeadLock = Standard_True;
382   Standard_Integer nbAtt = attList.Extent();
383   while (noDeadLock && (nbAtt != 0)) {
384     itr2.Initialize(attList);
385     while (itr2.More()) {
386       if (!itr2.Value()->AfterRetrieval())
387         itr2.Next();
388       else
389         attList.Remove(itr2);
390     }
391     noDeadLock = (nbAtt > attList.Extent());
392     nbAtt = attList.Extent();
393   }
394
395   if (!noDeadLock) {
396 #ifdef DEB
397     cout<<"AfterRetrieval(): dead lock between these attributes:"<<endl;
398     for (itr2.Initialize(attList); itr2.More(); itr2.Next())
399       cout<<"Attribute type = "<<itr2.Value()->DynamicType()->Name()<<endl;;
400     Standard_ConstructionError::Raise("AfterRetrieval: dead lock.");
401 #endif
402     for (itr2.Initialize(attList); itr2.More(); itr2.Next())
403       itr2.Value()->AfterRetrieval(Standard_True);
404   }
405 }