0003513: There is no check for boundary of array in method Set for array attributes
[occt.git] / src / TDataStd / TDataStd_TreeNode.cxx
CommitLineData
b311480e 1// Created on: 1999-06-10
2// Created by: Vladislav ROMASHKO
3// Copyright (c) 1999-1999 Matra Datavision
4// Copyright (c) 1999-2012 OPEN CASCADE SAS
5//
6// The content of this file is subject to the Open CASCADE Technology Public
7// License Version 6.5 (the "License"). You may not use the content of this file
8// except in compliance with the License. Please obtain a copy of the License
9// at http://www.opencascade.org and read it completely before using this file.
10//
11// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13//
14// The Original Code and all software distributed under the License is
15// distributed on an "AS IS" basis, without warranty of any kind, and the
16// Initial Developer hereby disclaims all such warranties, including without
17// limitation, any warranties of merchantability, fitness for a particular
18// purpose or non-infringement. Please see the License for the specific terms
19// and conditions governing the rights and limitations under the License.
20
7fd59977 21
22
23#include <TDataStd_TreeNode.ixx>
24#include <TDF_Label.hxx>
25#include <Standard_DomainError.hxx>
26
27// This bug concerns the method IsDescendant():
28#define BUC60817
29
30// This bug concerns the method BeforeForget() - Forget/Resume, Undo/Redo behaviour of the attribute
31#define BUC60844
32
33//=======================================================================
34//function : Find
35//purpose :
36//=======================================================================
37
38Standard_Boolean TDataStd_TreeNode::Find(const TDF_Label& L,
39 Handle(TDataStd_TreeNode)& T)
40{
41 return L.FindAttribute(TDataStd_TreeNode::GetDefaultTreeID(), T);
42}
43
44//=======================================================================
45//TreeNode : GetDefaultTreeID
46//purpose : Static method to get the default ID of a TreeNode
47//=======================================================================
48
49const Standard_GUID& TDataStd_TreeNode::GetDefaultTreeID()
50{
51 static Standard_GUID TDataStd_TreeNodeID ("2a96b621-ec8b-11d0-bee7-080009dc3333");
52 return TDataStd_TreeNodeID;
53}
54
55//=======================================================================
56//TreeNode : Set
57//purpose : Finds or creates a TreeNode attribute with default ID
58//=======================================================================
59
60Handle(TDataStd_TreeNode) TDataStd_TreeNode::Set(const TDF_Label& L)
61{
62 Handle(TDataStd_TreeNode) TN;
63 if (!L.FindAttribute(TDataStd_TreeNode::GetDefaultTreeID(),TN)) {
64 TN = new TDataStd_TreeNode();
65 TN->SetTreeID(TDataStd_TreeNode::GetDefaultTreeID());
66 L.AddAttribute(TN);
67 }
68 return TN;
69}
70
71//=======================================================================
72//function : Set
73//purpose : Finds or creates a TreeNode attribute with explicit ID
74// : a driver for it
75//=======================================================================
76
77Handle(TDataStd_TreeNode) TDataStd_TreeNode::Set (const TDF_Label& L,
78 const Standard_GUID& explicitID)
79{
80 Handle(TDataStd_TreeNode) TN;
81 if (!L.FindAttribute(explicitID,TN)) {
82 TN = new TDataStd_TreeNode ();
83 TN->SetTreeID(explicitID);
84 L.AddAttribute(TN);
85 }
86 return TN;
87}
88
89//=======================================================================
90//TreeNode : ID
91//purpose : Returns GUID of the TreeNode
92//=======================================================================
93
94const Standard_GUID& TDataStd_TreeNode::ID() const
95{
96 return myTreeID;
97}
98
99//=======================================================================
100//TreeNode : TDataStd_TreeNode
101//purpose : Constructor
102//=======================================================================
103
104TDataStd_TreeNode::TDataStd_TreeNode () :
105 myFather(NULL), myPrevious(NULL), myNext(NULL), myFirst(NULL), myLast(NULL)
106{}
107
108
109//=======================================================================
110//function : Append
111//purpose : Add <TN> as last child of me
112//=======================================================================
113
114Standard_Boolean TDataStd_TreeNode::Append (const Handle(TDataStd_TreeNode)& TN)
115{
116 if (!(TN->ID() == myTreeID) )
117 Standard_DomainError::Raise("TDataStd_TreeNode::Append : uncompatible GUID");
118
119 Handle(TDataStd_TreeNode) bid;
120 TN->SetNext(bid); // Deconnects from next.
121
122 // Find the last
123 if (!HasFirst()) {
124 SetFirst(TN);
125 TN->SetPrevious(bid); // Deconnects from previous.
126 }
127 else
128 {
129 Handle(TDataStd_TreeNode) L = Last();
130 L->SetNext(TN);
131 TN->SetPrevious(L);
132 }
133 // Set Father
134 TN->SetFather(this);
135 myLast=TN.operator->();
136 return !TN.IsNull();
137}
138
139//=======================================================================
140//function : Prepend
141//purpose : Add <TN> as first child of me
142//=======================================================================
143
144Standard_Boolean TDataStd_TreeNode::Prepend (const Handle(TDataStd_TreeNode)& TN)
145{
146 if (!(TN->ID() == myTreeID) )
147 Standard_DomainError::Raise("TDataStd_TreeNode::Prepend : uncompatible GUID");
148
149 Handle(TDataStd_TreeNode) bid;
150 TN->SetPrevious(bid);
151 if (HasFirst()) {
152 TN->SetNext(First());
153 First()->SetPrevious(TN);
154 }
155 else {
156 TN->SetNext(bid);
157 SetLast(TN);
158 }
159 TN->SetFather(this);
160 SetFirst(TN);
161 return !TN.IsNull();
162}
163
164//=======================================================================
165//function : InsertBefore
166//purpose : Inserts the TreeNode <TN> before me
167//=======================================================================
168
169Standard_Boolean TDataStd_TreeNode::InsertBefore (const Handle(TDataStd_TreeNode)& TN)
170{
171 if (!(TN->ID() == myTreeID) )
172 Standard_DomainError::Raise("TDataStd_TreeNode::InsertBefore : uncompatible GUID");
173
174 TN->SetFather(Father());
175 TN->SetPrevious(Previous());
176 TN->SetNext(this);
177
178 if (!HasPrevious())
179 Father()->SetFirst(TN);
180 else
181 Previous()->SetNext(TN);
182
183 SetPrevious(TN);
184 return !TN.IsNull();
185}
186
187//=======================================================================
188//function : InsertAfter
189//purpose : Inserts the TreeNode <TN> after me
190//=======================================================================
191
192Standard_Boolean TDataStd_TreeNode::InsertAfter (const Handle(TDataStd_TreeNode)& TN)
193{
194 if (!(TN->ID() == myTreeID) )
195 Standard_DomainError::Raise("TDataStd_TreeNode::InsertAfter : uncompatible GUID");
196
197 if (HasFather() && !HasNext())
198 Father()->SetLast(TN);
199
200 TN->SetFather(Father());
201 TN->SetPrevious(this);
202 TN->SetNext(Next());
203
204 if (HasNext())
205 Next()->SetPrevious(TN);
206
207 SetNext(TN);
208 return !TN.IsNull();
209}
210
211//=======================================================================
212//function : Remove
213//purpose : Removees the function from the function tree
214//=======================================================================
215
216Standard_Boolean TDataStd_TreeNode::Remove ()
217{
218 if (IsRoot()) return Standard_True;
219
220 Handle(TDataStd_TreeNode) bid;
221 if (!HasPrevious())
222 Father()->SetFirst(Next());
223 else
224 Previous()->SetNext(Next());
225
226 if (HasNext()) {
227 if (HasPrevious()) Next()->SetPrevious(Previous());
228 else Next()->SetPrevious(bid);
229 }
230 else {
231 if (HasPrevious()) Previous()->SetNext(bid);
232 }
233
234 if (Father()->HasFirst()) {
235 if (Handle(TDataStd_TreeNode)::DownCast(this) == Father()->First()) {
236 if (HasNext()) {
237 Father()->SetFirst(Next());
238 }
239 else Father()->SetFirst(bid);
240 }
241 }
242
243 if(Father()->HasLast()) {
244 if (Handle(TDataStd_TreeNode)::DownCast(this) == Father()->Last()) {
245 if(HasPrevious()) {
246 Father()->SetLast(Previous());
247 }
248 else Father()->SetLast(bid);
249 }
250 }
251
252 SetFather(bid);
253 SetNext(bid);
254 SetPrevious(bid);
255 return Standard_True;
256}
257
258
259//=======================================================================
260//function : Depth
261//purpose :
262//=======================================================================
263
264Standard_Integer TDataStd_TreeNode::Depth () const
265{
266 Standard_Integer depth = 0;
267
268 TDataStd_TreeNode* O = (TDataStd_TreeNode*) this;
269 while (O->myFather != NULL)
270 {
271 depth++;
272 O = O->myFather;
273 }
274
275 return depth;
276}
277
278//=======================================================================
279//function : NbChildren
280//purpose : Returns the number of child nodes.
281// If <allLevels> is true, the method counts children of all levels
282// (children of children ...)
283//=======================================================================
284Standard_Integer TDataStd_TreeNode::NbChildren(const Standard_Boolean allLevels) const
285{
286 Standard_Integer nb = 0;
287 TDataStd_TreeNode* C = myFirst;
288 while (C != NULL)
289 {
290 if (allLevels &&
291 C->myFirst != NULL)
292 {
293 nb += C->NbChildren(allLevels);
294 }
295 nb++;
296 C = C->myNext;
297 }
298 return nb;
299}
300
301//=======================================================================
302//function : SetTreeID
303//purpose : Finds or creates a TreeNode attribute with explicit ID
304// : a driver for it
305//=======================================================================
306
307void TDataStd_TreeNode::SetTreeID (const Standard_GUID& explicitID)
308{
309 myTreeID = explicitID;
310}
311
312
313//=======================================================================
314//function : IsAscendant
315//purpose :
316//=======================================================================
317
318Standard_Boolean TDataStd_TreeNode::IsAscendant (const Handle(TDataStd_TreeNode)& ofTN) const
319{
320 return ofTN->IsDescendant(this);
321}
322
323
324//=======================================================================
325//function : IsDescendant
326//purpose :
327//=======================================================================
328
329Standard_Boolean TDataStd_TreeNode::IsDescendant (const Handle(TDataStd_TreeNode)& ofTN) const
330{
331#ifdef BUC60817
332
333 TDataStd_TreeNode* O = (TDataStd_TreeNode*) this;
334 while (O->myFather != NULL)
335 {
336 if (O->myFather == ofTN)
337 return Standard_True;
338 O = O->myFather;
339 }
340
341#else
342 Handle(TDataStd_TreeNode) current;
343 for (current = this; current = current->Father(); current->HasFather()) {
344 if (current == ofTN) return Standard_True;
345 }
346#endif
347 return Standard_False;
348}
349
350//=======================================================================
351//function : IsFather
352//purpose :
353//=======================================================================
354
355Standard_Boolean TDataStd_TreeNode::IsFather (const Handle(TDataStd_TreeNode)& ofTN) const
356{
357 return (ofTN->Father() == this);
358}
359
360
361//=======================================================================
362//function : IsChild
363//purpose :
364//=======================================================================
365
366Standard_Boolean TDataStd_TreeNode::IsChild (const Handle(TDataStd_TreeNode)& ofTN) const
367{
368 return (myFather == ofTN.operator->());
369}
370
371
372//=======================================================================
373//TreeNode : Father
374//purpose : Returns the Father of the TreeNode
375//=======================================================================
376
377Handle(TDataStd_TreeNode) TDataStd_TreeNode::Father() const
378{
379 Handle(TDataStd_TreeNode) O = myFather;
380 return O;
381}
382
383//=======================================================================
384//TreeNode : IsRoot
385//purpose : Returns Standard_True if the TreeNode is not attached to a
386// TreeNode tree or hasn't an Father.
387//=======================================================================
388
389Standard_Boolean TDataStd_TreeNode::IsRoot() const
390{
391 if (myFather == NULL &&
392 myPrevious == NULL &&
393 myNext == NULL)
394 return Standard_True;
395 return Standard_False;
396}
397
398//=======================================================================
399//TreeNode : Root
400//purpose : Returns the TreeNode which has no Father
401//=======================================================================
402
403Handle(TDataStd_TreeNode) TDataStd_TreeNode::Root() const
404{
405 TDataStd_TreeNode* O = (TDataStd_TreeNode*) this;
406 while (O->myFather != NULL)
407 {
408 O = O->myFather;
409 }
410 return O;
411}
412
413//=======================================================================
414//TreeNode : Next
415//purpose : Returns next (in the TreeNode tree) TreeNode
416//=======================================================================
417
418Handle(TDataStd_TreeNode) TDataStd_TreeNode::Next() const
419{
420 Handle(TDataStd_TreeNode) O = myNext;
421 return O;
422}
423
424//=======================================================================
425//TreeNode : Previous
426//purpose : Returns previous (in the TreeNode tree) TreeNode
427//=======================================================================
428
429Handle(TDataStd_TreeNode) TDataStd_TreeNode::Previous() const
430{
431 Handle(TDataStd_TreeNode) O = myPrevious;
432 return O;
433}
434
435//=======================================================================
436//TreeNode : First
437//purpose : Returns first child
438//=======================================================================
439
440Handle(TDataStd_TreeNode) TDataStd_TreeNode::First () const
441{
442 Handle(TDataStd_TreeNode) O = myFirst;
443 return O;
444}
445
446//=======================================================================
447//TreeNode : Last
448//purpose : Returns last child
449// Optimize an Append operation if it is called in a circle
450//=======================================================================
451
452Handle(TDataStd_TreeNode) TDataStd_TreeNode::Last ()
453{
454 if(myLast && !myLast->IsChild(this))
455 myLast=NULL;
456
457 if(myLast == NULL)
458 return FindLast();
459
460 return myLast;
461}
462
463//=======================================================================
464//TreeNode : FindLast
465//purpose : Returns last child
466// Optimizes an Append operation if it is called in a circle
467//=======================================================================
468Handle(TDataStd_TreeNode) TDataStd_TreeNode::FindLast ()
469{
470 if (myFirst == NULL)
471 return myFirst;
472 TDataStd_TreeNode* L = myFirst;
473 while (L->myNext != NULL)
474 {
475 L = L->myNext;
476 }
477 return L;
478}
479
480//=======================================================================
481//TreeNode : SetFather
482//purpose : Sets the TreeNode F as Father of me
483//=======================================================================
484
485void TDataStd_TreeNode::SetFather(const Handle(TDataStd_TreeNode)& F)
486{
487 Backup();
488 if (F.IsNull()) myFather = NULL;
489 else myFather = F.operator->();
490 myLast=NULL;
491}
492
493//=======================================================================
494//TreeNode : SetNext
495//purpose : Sets the TreeNode F next to me
496//=======================================================================
497
498void TDataStd_TreeNode::SetNext(const Handle(TDataStd_TreeNode)& F)
499{
500 Backup();
501 if (F.IsNull()) myNext = NULL;
502 else myNext = F.operator->();
503 myLast=NULL;
504}
505
506
507//=======================================================================
508//TreeNode : SetPrevious
509//purpose : Sets the TreeNode F previous to me
510//=======================================================================
511
512void TDataStd_TreeNode::SetPrevious(const Handle(TDataStd_TreeNode)& F)
513{
514 Backup();
515 if (F.IsNull()) myPrevious = NULL;
516 else myPrevious = F.operator->();
517 myLast=NULL;
518}
519
520//=======================================================================
521//TreeNode : SetFirst
522//purpose : Sets the TreeNode F as first in the TreeNode tree
523//=======================================================================
524
525void TDataStd_TreeNode::SetFirst(const Handle(TDataStd_TreeNode)& F)
526{
527 Backup();
528 if (F.IsNull()) myFirst = NULL;
529 else myFirst = F.operator->();
530 myLast=NULL;
531}
532
533//=======================================================================
534//TreeNode : SetLast
535//purpose : Sets the TreeNode F as last in the TreeNode tree
536//=======================================================================
537
538void TDataStd_TreeNode::SetLast(const Handle(TDataStd_TreeNode)& F)
539{
540 Backup();
541 if (F.IsNull()) myLast = NULL;
542 else myLast = F.operator->();
543}
544
545//=======================================================================
546//TreeNode : AfterAddition
547//purpose : Connects the TreeNode to the tree.
548// Backuped attribute must stay disconnected
549//=======================================================================
550
551void TDataStd_TreeNode::AfterAddition() {
552 if (!IsBackuped()) {
553 if (myPrevious)
554 myPrevious->SetNext(this);
555 else if (myFather)
556 myFather->SetFirst(this);
557 if (myNext)
558 myNext->SetPrevious(this);
559 }
560}
561
562//=======================================================================
563//TreeNode : BeforeForget
564//purpose : Disconnect the TreeNode from the tree.
565// Backuped attribute is normaly not concerned by such an operation
566//=======================================================================
567
568void TDataStd_TreeNode::BeforeForget() {
569#ifdef BUC60844
570 if (!IsBackuped()) {
571 Remove();
572 while (HasFirst()) First()->Remove();
573 }
574#else
575 if (!IsBackuped()) Remove();
576#endif
577}
578
579//=======================================================================
580//TreeNode : AfterResume
581//purpose : Connects the TreeNode to the tree
582//=======================================================================
583
584void TDataStd_TreeNode::AfterResume() {
585 AfterAddition();
586}
587
588//=======================================================================
589//TreeNode : BeforeUndo
590//purpose : Disconnect the TreeNode from the tree.
591//=======================================================================
592
593Standard_Boolean TDataStd_TreeNode::BeforeUndo(const Handle(TDF_AttributeDelta)& anAttDelta,
35e08fe8 594 const Standard_Boolean /*forceIt*/)
7fd59977 595{
596 if (anAttDelta->IsKind(STANDARD_TYPE(TDF_DeltaOnAddition))) BeforeForget(); // Disconnect.
597 return Standard_True;
598}
599
600//=======================================================================
601//TreeNode : AfterUndo
602//purpose : Connect the TreeNode from the tree.
603//=======================================================================
604
605Standard_Boolean TDataStd_TreeNode::AfterUndo(const Handle(TDF_AttributeDelta)& anAttDelta,
35e08fe8 606 const Standard_Boolean /*forceIt*/)
7fd59977 607{
608 if (anAttDelta->IsKind(STANDARD_TYPE(TDF_DeltaOnRemoval))) AfterAddition(); // Reconnect.
609 return Standard_True;
610}
611
612//=======================================================================
613//TreeNode : Restore
614//purpose :
615//=======================================================================
616
617void TDataStd_TreeNode::Restore(const Handle(TDF_Attribute)& other) {
618 Handle(TDataStd_TreeNode) F = Handle(TDataStd_TreeNode)::DownCast(other);
619 myFather = F->myFather;
620 myPrevious = F->myPrevious;
621 myNext = F->myNext;
622 myFirst = F->myFirst;
623 myTreeID = F->myTreeID;
624 myLast = NULL;
625}
626
627//=======================================================================
628//TreeNode : Paste
629//purpose : Method for Copy mechanism
630//=======================================================================
631
632void TDataStd_TreeNode::Paste(const Handle(TDF_Attribute)& into,
633 const Handle(TDF_RelocationTable)& RT) const
634{
635 Handle(TDataStd_TreeNode) intof = Handle(TDataStd_TreeNode)::DownCast(into);
636 Handle(TDataStd_TreeNode) func;
637 if (!RT->HasRelocation(myFather, func) && RT->AfterRelocate()) {
638 func.Nullify();
639 }
640 intof->SetFather(func);
641 if (!RT->HasRelocation(myNext, func) && RT->AfterRelocate()) {
642 func.Nullify();
643 }
644 intof->SetNext(func);
645 if (!RT->HasRelocation(myPrevious, func) && RT->AfterRelocate()) {
646 func.Nullify();
647 }
648 intof->SetPrevious(func);
649 if (!RT->HasRelocation(myFirst, func) && RT->AfterRelocate()) {
650 func.Nullify();
651 }
652
653 intof->SetFirst(func);
654 intof->SetTreeID(myTreeID);
655}
656
657//=======================================================================
658//TreeNode : NewEmpty
659//purpose : Returns new empty TreeNode attribute
660//=======================================================================
661
662Handle(TDF_Attribute) TDataStd_TreeNode::NewEmpty() const
663{
664 Handle(TDataStd_TreeNode) T = new TDataStd_TreeNode();
665 T->SetTreeID(myTreeID);
666 return T;
667}
668
669//=======================================================================
670//TreeNode : References
671//purpose : Collects the references
672//=======================================================================
673
674void TDataStd_TreeNode::References(const Handle(TDF_DataSet)& aDataSet) const
675{
676 TDataStd_TreeNode* fct = myFirst;
677 while (fct != NULL) {
678 aDataSet->AddAttribute(fct);
679 fct = fct->myNext;
680 }
681}
682
683//=======================================================================
684//TreeNode : Dump
685//purpose : Dump of the TreeNode
686//=======================================================================
687
688Standard_OStream& TDataStd_TreeNode::Dump (Standard_OStream& anOS) const
689{
690 TDF_Attribute::Dump (anOS);
691 if (myFather) {
692 anOS<<" Father=";
693 if (!myFather->Label().IsNull()) myFather->Label().EntryDump(anOS);
694 }
695 if (myPrevious) {
696 anOS<<" Previous=";
697 if (!myPrevious->Label().IsNull()) myPrevious->Label().EntryDump(anOS);
698 }
699 if (myNext) {
700 anOS<<" Next=";
701 if (!myNext->Label().IsNull()) myNext->Label().EntryDump(anOS);
702 }
703 if (myFirst) {
704 anOS<<" First=";
705 if (!myFirst->Label().IsNull()) myFirst->Label().EntryDump(anOS);
706 }
707 anOS<<endl;
708 return anOS;
709}