0023799: Crash on copying a label
[occt.git] / src / TDF / TDF_Tool.cxx
1 // Created by: DAUTRY Philippe
2 // Copyright (c) 1997-1999 Matra Datavision
3 // Copyright (c) 1999-2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20 //              ------------
21
22 // Version:     0.0
23 //Version       Date            Purpose
24 //              0.0     Mar 13 1997     Creation
25
26
27
28 #include <TDF_Tool.ixx>
29
30 #include <TDF_MapIteratorOfLabelMap.hxx>
31 #include <TDF_MapIteratorOfAttributeMap.hxx>
32 #include <TDF_AttributeIterator.hxx>
33 #include <TDF_AttributeIndexedMap.hxx>
34 #include <TDF_ChildIterator.hxx>
35 #include <TDF_DataSet.hxx>
36 #include <TDF_ListIteratorOfLabelList.hxx>
37
38 #include <TColStd_ListOfInteger.hxx>
39 #include <TColStd_ListIteratorOfListOfInteger.hxx>
40
41 #define TDF_TagSeparator ':'
42
43 static void TDF_Tool_ExtendedDeepDump(Standard_OStream& anOS, 
44                                       const TDF_Label& aLabel, 
45                                       const TDF_IDFilter& aFilter,
46                                       TDF_AttributeIndexedMap& aMap);
47
48 static Standard_Boolean TDF_Tool_DescendantRef(const TDF_Label& aRefLabel, 
49                                                const TDF_Label& aLabel,
50                                                const TDF_IDFilter& aFilter, 
51                                                const Handle(TDF_DataSet)& ds);
52
53 static void TDF_Tool_OutReferers(const TDF_Label& aRefLabel, 
54                                  const TDF_Label& aLabel,
55                                  TDF_AttributeMap& atts,  
56                                  const TDF_IDFilter& aFilterForReferers,
57                                  const TDF_IDFilter& aFilterForReferences,
58                                  const Handle(TDF_DataSet)& ds);
59
60 static void TDF_Tool_OutReferences(const TDF_Label& aRefLabel,
61                                    const TDF_Label& aLabel,
62                                    TDF_AttributeMap& atts,  
63                                    const TDF_IDFilter& aFilterForReferers,
64                                    const TDF_IDFilter& aFilterForReferences,
65                                    const Handle(TDF_DataSet)& ds);
66
67 //=======================================================================
68 //function : NbLabels
69 //purpose  : Returns the numbers of labels of the tree.
70 //=======================================================================
71
72 Standard_Integer TDF_Tool::NbLabels(const TDF_Label& aLabel)
73 {
74   Standard_Integer n = 1;
75   for (TDF_ChildIterator itr(aLabel,Standard_True); itr.More(); itr.Next())
76     ++n;
77   return n;
78 }
79
80
81 //=======================================================================
82 //function : NbAttributes
83 //purpose  : Returns the number of attributes of the tree.
84 //=======================================================================
85
86 Standard_Integer TDF_Tool::NbAttributes(const TDF_Label& aLabel)
87 {
88   Standard_Integer n = aLabel.NbAttributes();
89   for (TDF_ChildIterator itr(aLabel,Standard_True); itr.More(); itr.Next())
90     n += itr.Value().NbAttributes();
91   return n;
92 }
93
94
95 //=======================================================================
96 //function : NbAttributes
97 //purpose  : Returns the number of attributes of the tree,
98 //           selected by an IDFilter.
99 //=======================================================================
100
101 Standard_Integer TDF_Tool::NbAttributes
102 (const TDF_Label& aLabel,
103  const TDF_IDFilter& aFilter)
104 {
105   Standard_Integer n = 0;
106   TDF_AttributeIterator it2;
107   for (it2.Initialize(aLabel,Standard_True);it2.More();it2.Next())
108     if (aFilter.IsKept(it2.Value())) ++n;
109   for (TDF_ChildIterator it1(aLabel,Standard_True); it1.More(); it1.Next())
110     for (it2.Initialize(it1.Value(),Standard_True);it2.More();it2.Next())
111       if (aFilter.IsKept(it2.Value())) ++n;
112   return n;
113 }
114
115
116 //=======================================================================
117 //function : IsSelfContained
118 //purpose  : 
119 //=======================================================================
120
121 Standard_Boolean TDF_Tool::IsSelfContained(const TDF_Label& aLabel)
122 {
123   TDF_IDFilter filter(Standard_False); // Keep all.
124   return IsSelfContained(aLabel,filter);
125 }
126
127 //=======================================================================
128 //function : IsSelfContained
129 //purpose  : 
130 //=======================================================================
131
132 Standard_Boolean TDF_Tool::IsSelfContained
133 (const TDF_Label& aLabel,
134  const TDF_IDFilter& aFilter)
135 {
136   Handle(TDF_DataSet) ds = new TDF_DataSet();
137
138   if (!TDF_Tool_DescendantRef(aLabel,aLabel,aFilter,ds))
139     return Standard_False;
140
141   for (TDF_ChildIterator itr(aLabel,Standard_True);
142        itr.More();
143        itr.Next()) {
144     if (!TDF_Tool_DescendantRef(aLabel,itr.Value(),aFilter,ds))
145       return Standard_False;
146   }
147   return Standard_True;
148 }
149
150
151 //=======================================================================
152 //function : TDF_Tool_DescendantRef
153 //purpose  : 
154 //=======================================================================
155
156 static Standard_Boolean TDF_Tool_DescendantRef
157 (const TDF_Label& aRefLabel,
158  const TDF_Label& aLabel,
159  const TDF_IDFilter& aFilter,
160  const Handle(TDF_DataSet)& ds)
161 {
162   for (TDF_AttributeIterator itr(aLabel); itr.More(); itr.Next()) {
163     // CLE
164     // const Handle(TDF_Attribute)& labAtt = itr.Value();
165     Handle(TDF_Attribute) labAtt = itr.Value();
166     // ENDCLE
167     if (aFilter.IsKept(labAtt)) {
168       labAtt->References(ds);
169       // First of all, the referenced labels.
170       const TDF_LabelMap& labMap = ds->Labels();
171
172       for (TDF_MapIteratorOfLabelMap labMItr(labMap);
173            labMItr.More(); labMItr.Next()) {
174         if (!labMItr.Key().IsDescendant(aRefLabel))
175           return Standard_False;
176       }
177       // Then the referenced attributes.
178       const TDF_AttributeMap& attMap = ds->Attributes();
179       for (TDF_MapIteratorOfAttributeMap attMItr(attMap);
180            attMItr.More(); attMItr.Next()) {
181         // CLE
182         // const Handle(TDF_Attribute)& att = attMItr.Key();
183         Handle(TDF_Attribute) att = attMItr.Key();
184         if (!att.IsNull() && !att->Label().IsNull())
185         {
186           // ENDCLE
187           if (aFilter.IsKept(att) && !att->Label().IsDescendant(aRefLabel))
188             return Standard_False;
189         }
190       }
191       ds->Clear();
192     }
193   }
194   return Standard_True;
195 }
196
197
198 //=======================================================================
199 //function : OutReferers
200 //purpose  : 
201 //=======================================================================
202
203 void TDF_Tool::OutReferers(const TDF_Label& aLabel,
204                            TDF_AttributeMap& atts)
205 {
206   TDF_IDFilter filter(Standard_False); // Keep all.
207   OutReferers(aLabel,filter,filter,atts);
208 }
209
210
211 //=======================================================================
212 //function : OutReferers
213 //purpose  : 
214 //=======================================================================
215
216 void TDF_Tool::OutReferers(const TDF_Label& aLabel,
217                            const TDF_IDFilter& aFilterForReferers,
218                            const TDF_IDFilter& aFilterForReferences,
219                            TDF_AttributeMap& atts)
220 {
221   Handle(TDF_DataSet) ds = new TDF_DataSet();
222   TDF_Tool_OutReferers(aLabel,aLabel,atts,aFilterForReferers,aFilterForReferences,ds);
223   for (TDF_ChildIterator itr(aLabel,Standard_True);itr.More();itr.Next()) {
224     TDF_Tool_OutReferers(aLabel,itr.Value(),atts,aFilterForReferers,aFilterForReferences,ds);
225   }
226 }
227
228
229 //=======================================================================
230 //function : TDF_Tool_OutReferers
231 //purpose  : 
232 //=======================================================================
233
234 static void TDF_Tool_OutReferers(const TDF_Label& aRefLabel,
235                                  const TDF_Label& aLabel,
236                                  TDF_AttributeMap& atts,
237                                  const TDF_IDFilter& aFilterForReferers,
238                                  const TDF_IDFilter& aFilterForReferences,
239                                  const Handle(TDF_DataSet)& ds)
240 {
241   Standard_Boolean outRefFound = Standard_False;
242
243   for (TDF_AttributeIterator itr(aLabel); itr.More(); itr.Next()) {
244
245     if (!aFilterForReferers.IsKept(itr.Value())) continue;
246     itr.Value()->References(ds);
247
248     const TDF_AttributeMap& attMap = ds->Attributes();
249     for (TDF_MapIteratorOfAttributeMap attMItr(attMap);
250          attMItr.More(); attMItr.Next()) {
251       // CLE
252       // const Handle(TDF_Attribute)& att = attMItr.Key();
253       Handle(TDF_Attribute) att = attMItr.Key();
254       // ENDCLE
255       if (aFilterForReferences.IsKept(att) && !att->Label().IsDescendant(aRefLabel)) {
256         atts.Add(itr.Value());
257         outRefFound = Standard_True;
258         break;
259       }
260     }
261
262     if (!outRefFound) {
263       const TDF_LabelMap& labMap = ds->Labels();
264       for (TDF_MapIteratorOfLabelMap labMItr(labMap);
265            labMItr.More(); labMItr.Next()) {
266         if (!labMItr.Key().IsDescendant(aRefLabel)) {
267           atts.Add(itr.Value());
268           break;
269         }
270       }
271     }
272
273     outRefFound = Standard_False;
274     ds->Clear();
275   }
276 }
277
278 //=======================================================================
279 //function : OutReferences
280 //purpose  : 
281 //=======================================================================
282
283 void TDF_Tool::OutReferences(const TDF_Label& aLabel,
284                              TDF_AttributeMap& atts)
285 {
286   TDF_IDFilter filter(Standard_False); // Keep all.
287   OutReferences(aLabel,filter,filter,atts);
288 }
289
290 //=======================================================================
291 //function : OutReferences
292 //purpose  : 
293 //=======================================================================
294
295 void TDF_Tool::OutReferences(const TDF_Label& aLabel,
296                              const TDF_IDFilter& aFilterForReferers,
297                              const TDF_IDFilter& aFilterForReferences,
298                              TDF_AttributeMap& atts)
299 {
300   Handle(TDF_DataSet) ds = new TDF_DataSet();
301   TDF_Tool_OutReferences(aLabel,aLabel,atts,aFilterForReferers,aFilterForReferences,ds);
302   for (TDF_ChildIterator itr(aLabel,Standard_True);itr.More();itr.Next()) {
303     TDF_Tool_OutReferences(aLabel,itr.Value(),atts,aFilterForReferers,aFilterForReferences,ds);
304   }
305 }
306
307 //=======================================================================
308 //function : TDF_Tool_OutReferences
309 //purpose  : 
310 //=======================================================================
311
312 static void TDF_Tool_OutReferences(const TDF_Label& aRefLabel,
313                                    const TDF_Label& aLabel,
314                                    TDF_AttributeMap& atts,
315                                    const TDF_IDFilter& aFilterForReferers,
316                                    const TDF_IDFilter& aFilterForReferences,
317                                    const Handle(TDF_DataSet)& ds)
318 {
319   for (TDF_AttributeIterator itr(aLabel); itr.More(); itr.Next()) {
320     if (!aFilterForReferers.IsKept(itr.Value())) continue;
321     itr.Value()->References(ds);
322     const TDF_AttributeMap& attMap = ds->Attributes();
323     for (TDF_MapIteratorOfAttributeMap attMItr(attMap);attMItr.More();attMItr.Next()) {
324       Handle(TDF_Attribute) att = attMItr.Key();
325       if (aFilterForReferences.IsKept(att) && !att->Label().IsDescendant(aRefLabel)) {
326         atts.Add(att);
327       }
328     }
329     const TDF_LabelMap& labMap = ds->Labels();
330     for (TDF_MapIteratorOfLabelMap labMItr(labMap);labMItr.More();labMItr.Next()) {
331       if (!labMItr.Key().IsDescendant(aRefLabel)) {
332         TDF_AttributeIterator itra(labMItr.Key());
333         for (; itra.More(); itra.Next()) {
334           if (aFilterForReferences.IsKept(itra.Value())) {
335             atts.Add(itra.Value());
336           }
337         }
338       }
339     }
340   }
341   ds->Clear();
342 }
343
344 //=======================================================================
345 //function : RelocateLabel
346 //purpose  : 
347 //=======================================================================
348
349 void TDF_Tool::RelocateLabel
350 (const TDF_Label& aSourceLabel,
351  const TDF_Label& fromRoot,
352  const TDF_Label& toRoot,
353  TDF_Label& aTargetLabel,
354  const Standard_Boolean create)
355 {
356   if (!aSourceLabel.IsDescendant(fromRoot)) return;
357   aTargetLabel.Nullify();
358   TColStd_ListOfInteger labelTags;
359   TDF_Tool::TagList(aSourceLabel,labelTags);
360   TColStd_ListOfInteger toTags;
361   TDF_Tool::TagList(toRoot,toTags);
362   for (Standard_Integer i = fromRoot.Depth(); i >= 0; --i)
363     labelTags.RemoveFirst();
364   labelTags.Prepend(toTags);
365   TDF_Tool::Label(toRoot.Data(),labelTags,aTargetLabel,create);
366 }
367
368
369 //=======================================================================
370 //function : Entry
371 //purpose  : Returns the entry as an ascii string.
372 //=======================================================================
373
374 void TDF_Tool::Entry
375 (const TDF_Label& aLabel,
376  TCollection_AsciiString& anEntry)
377 {
378   anEntry.Clear();
379   if (!aLabel.IsNull()) {
380     TColStd_ListOfInteger Tags;
381     TDF_Tool::TagList(aLabel, Tags);
382     anEntry += TCollection_AsciiString(Tags.First());
383     Tags.RemoveFirst();
384     if (Tags.IsEmpty()) {
385       anEntry += TDF_TagSeparator; // It must be the root label case.
386     }
387     else {
388       while (!Tags.IsEmpty()) {
389         anEntry += TDF_TagSeparator;
390         anEntry += TCollection_AsciiString(Tags.First());
391         Tags.RemoveFirst();
392       }
393     }
394   }
395 }
396
397
398 //=======================================================================
399 //function : TagList
400 //purpose  : Returns the entry of a label as a list of integers.
401 //=======================================================================
402
403 void TDF_Tool::TagList
404 (const TDF_Label& aLabel,
405  TColStd_ListOfInteger& aTagList)
406 {
407   aTagList.Clear();
408   if (!aLabel.IsNull()) {
409     TDF_Label Label = aLabel;
410     for (;;) {
411       aTagList.Prepend(Label.Tag());
412       if (Label.IsRoot()) break;
413       Label = Label.Father();
414     }
415   }
416 }
417
418
419 //=======================================================================
420 //function : TagList
421 //purpose  : Returns the entry expressed as a string as a list of integers.
422 //=======================================================================
423
424 void TDF_Tool::TagList
425 (const TCollection_AsciiString& anEntry,
426  TColStd_ListOfInteger& aTagList)
427 {
428   char* cc = (char *)anEntry.ToCString();
429   Standard_Integer n = 0;
430   aTagList.Clear();
431   while (*cc != '\0') {
432     while ( *cc >= '0' && *cc <= '9') {
433       n = 10*n + (*cc - '0');
434       ++cc;
435     }
436     if (*cc == TDF_TagSeparator || *cc == '\0') {
437       aTagList.Append(n);
438       n = 0;
439       if (*cc != '\0') ++cc;
440     }
441     else { // Not an entry!
442       aTagList.Clear();
443       break;
444     }
445   }
446 }
447
448
449 //=======================================================================
450 //function : Label
451 //purpose  : Returns the label expressed by <anEntry>.
452 //=======================================================================
453
454 void TDF_Tool::Label
455 (const Handle(TDF_Data)& aDF,
456  const TCollection_AsciiString& anEntry,
457  TDF_Label& aLabel,
458  const Standard_Boolean create) 
459 { TDF_Tool::Label(aDF,anEntry.ToCString(),aLabel,create); }
460
461
462 //=======================================================================
463 //function : Label
464 //purpose  : Returns the label expressed by <anEntry>,
465 //           and creates it if <create> is true.
466 //=======================================================================
467
468 void TDF_Tool::Label
469 (const Handle(TDF_Data)& aDF,
470  const Standard_CString  anEntry,
471  TDF_Label&              aLabel,
472  const Standard_Boolean  create) 
473 {
474   TColStd_ListOfInteger tagList;
475   TDF_Tool::TagList(anEntry,tagList);
476   TDF_Tool::Label(aDF,tagList,aLabel,create);
477 }
478
479
480 //=======================================================================
481 //function : Label
482 //purpose  : Returns the label expressed by <anEntry>,
483 //           and creates it if <create> is true.
484 //=======================================================================
485
486 void TDF_Tool::Label
487 (const Handle(TDF_Data)& aDF,
488  const TColStd_ListOfInteger& aTagList,
489  TDF_Label& aLabel,
490  const Standard_Boolean create) 
491 {
492   if (aTagList.Extent() == 0) {
493     aLabel.Nullify();
494   }
495   else {
496     aLabel = aDF->Root();
497     if (aTagList.Extent() == 1 && aTagList.First() == 0) return;
498     else {
499       TColStd_ListIteratorOfListOfInteger tagItr (aTagList);
500       tagItr.Next(); // Suppresses root tag.
501       for (; !aLabel.IsNull() && tagItr.More(); tagItr.Next()) {
502         aLabel = aLabel.FindChild(tagItr.Value(),create);
503       }
504     }
505   }
506 }
507
508
509 //=======================================================================
510 //function : CountLabels
511 //purpose  : 
512 //=======================================================================
513
514 void TDF_Tool::CountLabels
515 (TDF_LabelList& aLabelList,
516  TDF_LabelIntegerMap& aLabelMap)
517 {
518   if (aLabelList.IsEmpty()) return;
519   Standard_Boolean next = Standard_True;
520   TDF_ListIteratorOfLabelList itr(aLabelList);
521   while (itr.More()) {
522     const TDF_Label& lab = itr.Value();
523     if (aLabelMap.IsBound(lab)) {
524       aLabelMap(lab) += 1;
525       aLabelList.Remove(itr);
526       next = Standard_False;
527     }
528     else {
529       aLabelMap.Bind(lab,1);
530       next = itr.More();
531     }
532     if (next && !aLabelList.IsEmpty()) itr.Next();
533   }
534 }
535
536
537 //=======================================================================
538 //function : DeductLabels
539 //purpose  : 
540 //=======================================================================
541
542 void TDF_Tool::DeductLabels
543 (TDF_LabelList& aLabelList,
544  TDF_LabelIntegerMap& aLabelMap)
545 {
546   if (aLabelList.IsEmpty()) return;
547   Standard_Boolean next = Standard_True;
548   TDF_ListIteratorOfLabelList itr(aLabelList);
549   while (itr.More()) {
550     const TDF_Label& lab = itr.Value();
551     if (aLabelMap.IsBound(lab)) {
552       aLabelMap(lab) -= 1;
553       if (aLabelMap(lab) == 0) {
554         aLabelMap.UnBind(lab);
555         aLabelList.Remove(itr);
556         next = Standard_False;
557       }
558     }
559     else next = itr.More();
560     if (next && !aLabelList.IsEmpty()) itr.Next();
561   }
562 }
563
564
565 //=======================================================================
566 //function : DeepDump
567 //purpose  : Deep dump of a DF.
568 //=======================================================================
569
570 void TDF_Tool::DeepDump
571 (Standard_OStream& anOS,
572  const Handle(TDF_Data)& aDF)
573 {
574   anOS<<aDF;
575   TDF_Tool::DeepDump(anOS,aDF->Root());
576 }
577
578
579 //=======================================================================
580 //function : ExtendedDeepDump
581 //purpose  : Extended deep dump of a DF.
582 //=======================================================================
583
584 void TDF_Tool::ExtendedDeepDump
585 (Standard_OStream& anOS,
586  const Handle(TDF_Data)& aDF,
587  const TDF_IDFilter& aFilter)
588 {
589   anOS<<aDF;
590   TDF_Tool::ExtendedDeepDump(anOS,aDF->Root(),aFilter);
591 }
592
593
594 //=======================================================================
595 //function : DeepDump
596 //purpose  : Deep dump of a label.
597 //=======================================================================
598
599 void TDF_Tool::DeepDump
600 (Standard_OStream& anOS,
601  const TDF_Label& aLabel)
602 {
603   // Dumps the label.
604   anOS<<aLabel;
605   // Its children
606   for (TDF_ChildIterator ChildIt(aLabel); ChildIt.More (); ChildIt.Next ()) {
607     TDF_Tool::DeepDump(anOS,ChildIt.Value());
608   }
609 }
610
611
612 //=======================================================================
613 //function : ExtendedDeepDump
614 //purpose  : Extended deep dump of a label.
615 //=======================================================================
616
617 void TDF_Tool::ExtendedDeepDump
618 (Standard_OStream& anOS,
619  const TDF_Label& aLabel,
620  const TDF_IDFilter& aFilter)
621 {
622   TDF_AttributeIndexedMap map;
623   TDF_Tool_ExtendedDeepDump(anOS,aLabel,aFilter,map);
624
625   anOS<<map.Extent()<<" attribute"; if (map.Extent()>1) anOS<<"s";
626   anOS<<" referenced by the label structure."<<endl;
627
628   anOS<<endl<<"Extended dump of filtered attribute(s):"<<endl;
629   Standard_Integer nba = 0;
630   TCollection_AsciiString entry;
631   Standard_Integer i ;
632   for ( i = 1; i<= map.Extent(); ++i) {
633     const Handle(TDF_Attribute)& att = map.FindKey(i);
634     if (aFilter.IsKept(att)) {
635       ++nba;
636       anOS<<"# "<<i;
637       if (att->Label().IsNull()) {
638         anOS<<" (no label)"<<endl;
639       }
640       else {
641         TDF_Tool::Entry(att->Label(),entry);
642         anOS<<" (label: "<<entry<<")"<<endl;
643       }
644       att->ExtendedDump(anOS,aFilter,map); anOS<<endl;
645     }
646   }
647   anOS<<endl<<nba<<" attribute";
648   if (nba>1) anOS<<"s";
649   anOS<<" dumped between "<<--i<<endl;
650 }
651
652
653 //=======================================================================
654 //function : ExtendedDeepDump
655 //purpose  : Internal method.
656 //=======================================================================
657
658 static void TDF_Tool_ExtendedDeepDump
659 (Standard_OStream& anOS,
660  const TDF_Label& aLabel,
661  const TDF_IDFilter& aFilter,
662  TDF_AttributeIndexedMap& aMap)
663 {
664   // Dumps the label.
665   aLabel.ExtendedDump(anOS,aFilter,aMap);
666   // Its children
667   for (TDF_ChildIterator ChildIt(aLabel); ChildIt.More (); ChildIt.Next ()) {
668     TDF_Tool_ExtendedDeepDump(anOS,ChildIt.Value(),aFilter,aMap);
669   }
670 }