0027232: Configuration - fix mblen missing building issue on Android
[occt.git] / src / TDF / TDF_Data.cxx
CommitLineData
b311480e 1// Created by: DAUTRY Philippe
2// Copyright (c) 1997-1999 Matra Datavision
973c2be1 3// Copyright (c) 1999-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.
b311480e 15
7fd59977 16
42cf5bc1 17#include <NCollection_IncAllocator.hxx>
18#include <Standard_NoMoreObject.hxx>
19#include <Standard_NullObject.hxx>
20#include <Standard_Type.hxx>
7fd59977 21#include <TCollection_AsciiString.hxx>
7fd59977 22#include <TDF_Attribute.hxx>
42cf5bc1 23#include <TDF_AttributeDelta.hxx>
7fd59977 24#include <TDF_AttributeIndexedMap.hxx>
42cf5bc1 25#include <TDF_AttributeIterator.hxx>
7fd59977 26#include <TDF_ChildIterator.hxx>
42cf5bc1 27#include <TDF_Data.hxx>
7fd59977 28#include <TDF_Delta.hxx>
7fd59977 29#include <TDF_DeltaOnAddition.hxx>
30#include <TDF_DeltaOnForget.hxx>
31#include <TDF_DeltaOnModification.hxx>
32#include <TDF_DeltaOnRemoval.hxx>
33#include <TDF_DeltaOnResume.hxx>
34#include <TDF_Label.hxx>
35#include <TDF_LabelNode.hxx>
36#include <TDF_LabelNodePtr.hxx>
37#include <TDF_Tool.hxx>
42cf5bc1 38#include <TDF_Transaction.hxx>
60d4560d 39
92efcf78 40IMPLEMENT_STANDARD_RTTIEXT(TDF_Data,MMgt_TShared)
41
7fd59977 42#undef DEB_DELTA_CREATION
43#undef TDF_DATA_COMMIT_OPTIMIZED
44
0797d9d3 45#ifdef OCCT_DEBUG_DELTA
7fd59977 46#define TDF_Data_DebugModified(ACTION) \
47 cout<<"After "<<ACTION<<" #"<<myTransaction+1<<", DF "<<this<<" had "<<myNbTouchedAtt<<" attribute(s) touched. Time = "<<myTime<<endl; \
48if (!myTransaction) { \
49 TCollection_AsciiString entry; \
50 for (TDF_ChildIterator itr(Root(),Standard_True); itr.More(); itr.Next()) { \
51 const TDF_LabelNode* lnp = itr.Value().myLabelNode; \
52 if (lnp->AttributesModified() || lnp->MayBeModified()) { \
53 TDF_Tool::Entry(itr.Value(),entry); \
54 cout<<ACTION<<" on "<<entry<<" : flag(s) "; \
55 if (lnp->AttributesModified()) cout<<"AttributesModified "; \
56 if (lnp->MayBeModified()) cout<<"MayBeModified already set in transaction 0! Please contact TDF developer."; \
57 cout<<endl; \
58 cout<<itr.Value()<<endl; \
59 entry.Clear(); \
60 }}}
61#else
62#define TDF_Data_DebugModified(ACTION)
63#endif
64
0797d9d3 65#ifdef OCCT_DEBUG_DELTA_CREATION
7fd59977 66#define TDF_DataDebugDeltaCreation(DELTATYPE) \
67{ \
68TCollection_AsciiString entry; \
69TDF_Tool::Entry(currentAtt->Label(),entry); \
70cout<<"Creation of a DeltaOn"<<DELTATYPE<<" \tat "<<entry<<" \ton "<<currentAtt->DynamicType()<<endl; \
71}
72#else
73#define TDF_DataDebugDeltaCreation(DELTATYPE)
74#endif
75
76#define TDF_Data_DeltaCreation(DELTACOMMENT,DELTACREATION) \
77if (withDelta) { \
78 TDF_DataDebugDeltaCreation(DELTACOMMENT); \
79 aDelta->AddAttributeDelta(DELTACREATION); \
80}
81
7fd59977 82//=======================================================================
83//function : TDF_Data
84//purpose : empty constructor
85//=======================================================================
86
87TDF_Data::TDF_Data() :
88myTransaction (0),
89myNbTouchedAtt (0),
90myNotUndoMode (Standard_True),
91myTime (0),
92myAllowModification (Standard_True)
93{
94 const Handle(NCollection_IncAllocator) anIncAllocator=
95 new NCollection_IncAllocator (16000);
96 myLabelNodeAllocator = anIncAllocator;
97 myRoot = new (anIncAllocator) TDF_LabelNode (this);
98}
99
7fd59977 100//=======================================================================
101//function : Destroy
102//purpose : Used to implement the destructor ~.
103//=======================================================================
104
105void TDF_Data::Destroy()
106{
107 AbortUntilTransaction(1);
60d4560d 108 myRoot->Destroy (myLabelNodeAllocator);
109 myRoot = NULL;
7fd59977 110}
111
112
113//=======================================================================
114//function : OpenTransaction
115//purpose :
116//=======================================================================
117
118Standard_Integer TDF_Data::OpenTransaction()
119{
6af4fe1c 120 myTimes.Prepend(myTime);
7fd59977 121 return ++myTransaction;
122}
123
124
125//=======================================================================
126//function : CommitTransaction
127//purpose : Commits the current transaction.
128//=======================================================================
129
130Handle(TDF_Delta) TDF_Data::CommitTransaction
131(const Standard_Boolean withDelta)
132{
133 Handle(TDF_Delta) delta;
134 if (myTransaction>0) {
135 if (withDelta) delta = new TDF_Delta();
0797d9d3 136#ifdef OCCT_DEBUG_DELTA
7fd59977 137 cout<<"TDF_Data::Begin Commit #"<<myTransaction<<endl;
138#endif
139#ifdef TDF_DATA_COMMIT_OPTIMIZED
140 myNbTouchedAtt = 0;
141 if (Root().myLabelNode->MayBeModified())
142#endif
143 myNbTouchedAtt =
144 TDF_Data::CommitTransaction(Root(),delta,withDelta);
145
146 if (myNbTouchedAtt && !(withDelta && delta->IsEmpty())) ++myTime;
147 --myTransaction;
148 if (withDelta) {
149 if (!delta->IsEmpty()) {
6af4fe1c 150 delta->Validity(myTimes.First(),myTime);
0797d9d3 151#ifdef OCCT_DEBUG_DELTA
7fd59977 152 if (myTransaction == 0) {
153 cout<<"TDF_Data::Commit generated this delta in t=0:"<<endl;
154 delta->Dump(cout);
155 }
156#endif
157 }
0797d9d3 158#ifdef OCCT_DEBUG_DELTA
7fd59977 159 else {
160 if (myTransaction == 0)
161 cout<<"TDF_Data::Commit generated NO delta."<<endl;
162 }
163#endif
164 }
6af4fe1c 165 myTimes.RemoveFirst();
7fd59977 166 }
167 TDF_Data_DebugModified("COMMIT");
168 return delta;
169}
170
171
172//=======================================================================
173//function : CommitUntilTransaction
174//purpose : Commits the transactions until AND including
175// the given transaction index.
176//=======================================================================
177
178Handle(TDF_Delta) TDF_Data::CommitUntilTransaction
179(const Standard_Integer untilTransaction,
180 const Standard_Boolean withDelta)
181{
182 Handle(TDF_Delta) delta;
183 if ((untilTransaction>0) && (myTransaction >= untilTransaction)) {
184 while (myTransaction > untilTransaction) {
185 delta = TDF_Data::CommitTransaction(Standard_False);
186 }
187 delta = TDF_Data::CommitTransaction(withDelta);
188 }
189 return delta;
190}
191
192
193//=======================================================================
194//function : CommitTransaction
195//purpose : Recursive method used to implement the commit action.
196//=======================================================================
197
198Standard_Integer TDF_Data::CommitTransaction
199(const TDF_Label& aLabel,
200 const Handle(TDF_Delta)& aDelta,
201 const Standard_Boolean withDelta)
202{
203 aLabel.myLabelNode->MayBeModified(Standard_False);
204 Standard_Integer nbTouchedAtt = 0;
205#ifdef TDF_DATA_COMMIT_OPTIMIZED
206 Standard_Boolean attMod = aLabel.myLabelNode->AttributesModified();
207#else
208 Standard_Boolean attMod = Standard_True;
209#endif
210
211 if (attMod) {
212 Handle(TDF_Attribute) lastAtt;
213 Handle(TDF_Attribute) backupAtt;
214 Standard_Boolean currentIsRemoved = Standard_False;
215 attMod = Standard_False;
216
217 TDF_AttributeIterator itr1(aLabel, Standard_False);
218 while (itr1.More()) {
219 TDF_Attribute * aPtrCurrentAtt = itr1.Value();
220 itr1.Next();
221 // currentAtt = itr1.Value();
222
7fd59977 223 // A callback:
224 aPtrCurrentAtt->BeforeCommitTransaction();
7fd59977 225
226 backupAtt = aPtrCurrentAtt->myBackup;
227
228 if (aPtrCurrentAtt->myTransaction == myTransaction) {
229 ++nbTouchedAtt;
230 --(aPtrCurrentAtt->myTransaction);
231
232 // ------------------------------------------------------- Forgotten
233 if (aPtrCurrentAtt->IsForgotten()) {
234 if (aPtrCurrentAtt->mySavedTransaction >=
235 aPtrCurrentAtt->myTransaction)
236 {
237 const Handle(TDF_Attribute) currentAtt = aPtrCurrentAtt;
238 // Collision with a not forgotten version.
239 if (backupAtt.IsNull()) {
240 TDF_Data_DeltaCreation
241 ("Removal(1)",
242 currentAtt->DeltaOnRemoval());
243 if (myNotUndoMode) currentAtt->BeforeRemoval();
244 aLabel.myLabelNode->RemoveAttribute(lastAtt,currentAtt);
245 currentIsRemoved = Standard_True;
246 attMod = Standard_True;
247 }
248 else {
249 // Modified then Forgotten...
250 // Forgotten flag spreading?
251 currentAtt->Resume();
252 currentAtt->Restore(backupAtt);
253 currentAtt->myTransaction = backupAtt->myTransaction;
254 currentAtt->RemoveBackup();
255 backupAtt = currentAtt->myBackup;
256 if (myTransaction == 1) {
257 TDF_Data_DeltaCreation
258 ("Removal(2)",
259 currentAtt->DeltaOnRemoval());
260 if (myNotUndoMode) currentAtt->BeforeRemoval();
261 aLabel.myLabelNode->RemoveAttribute(lastAtt,currentAtt);
262 currentIsRemoved = Standard_True;
263 }
264 else {
265 // BeforeForget has already been called once.
266 // if (myNotUndoMode) currentAtt->BeforeForget();
267 currentAtt->Forget(myTransaction-1);
268 TDF_Data_DeltaCreation
269 ("Forget(1)",
270 currentAtt->DeltaOnForget());
271 attMod = Standard_True;
272 }
273 }
274 }
275 else {
276 // Forgotten in lower transaction than the current one.
277 TDF_Data_DeltaCreation
278 ("Forget(2)",
279 aPtrCurrentAtt->DeltaOnForget());
280 }
281 }
282 // ---------------------------------------------------------- Resumed.
283 else if (aPtrCurrentAtt->mySavedTransaction < 0) {
284 TDF_Data_DeltaCreation
285 ("Resume",
286 aPtrCurrentAtt->DeltaOnResume());
287 aPtrCurrentAtt->mySavedTransaction = 0;
288 attMod = attMod || (aPtrCurrentAtt->myTransaction > 0);
289 }
290
291 // ------------------------------------------------------------ Added.
292 else if (backupAtt.IsNull()) {
293 TDF_Data_DeltaCreation
294 ("Addition",
295 aPtrCurrentAtt->DeltaOnAddition());
296 attMod = attMod || (aPtrCurrentAtt->myTransaction > 0);
297 }
298 // --------------------------------------------------------- Modified.
299 else {
543a9964 300 const TDF_Attribute* anAttrPtr = aPtrCurrentAtt; // to avoid ambiguity
7fd59977 301 TDF_Data_DeltaCreation
302 ("Modification",
543a9964 303 anAttrPtr->DeltaOnModification(backupAtt));
7fd59977 304 if (aPtrCurrentAtt->myTransaction == backupAtt->myTransaction)
305 aPtrCurrentAtt->RemoveBackup();
306 attMod = attMod || (aPtrCurrentAtt->myTransaction > 0);
307 }
308
309 }
310 else attMod = attMod || (aPtrCurrentAtt->myTransaction > 0);
311
312 if (currentIsRemoved) currentIsRemoved = Standard_False;
313 else lastAtt = aPtrCurrentAtt;
314 }
315 aLabel.myLabelNode->AttributesModified(attMod);
316 }
317
318 // Iteration on the children to do the same!
319 //------------------------------------------
320 for (TDF_ChildIterator itr2(aLabel); itr2.More(); itr2.Next()) {
321#ifdef TDF_DATA_COMMIT_OPTIMIZED
322 if (itr2.Value().myLabelNode->MayBeModified())
323#endif
324 nbTouchedAtt +=
325 TDF_Data::CommitTransaction(itr2.Value(),aDelta,withDelta);
326 }
327
328 return nbTouchedAtt;
329}
330
331
332//=======================================================================
333//function : AbortTransaction
334//purpose : Aborts the current transaction.
335//=======================================================================
336
337void TDF_Data::AbortTransaction()
338{
339 if (myTransaction>0)
340 Undo(TDF_Data::CommitTransaction(Standard_True),Standard_False);
341 TDF_Data_DebugModified("New ABORT");
342}
343
344
345//=======================================================================
346//function : AbortUntilTransaction
347//purpose : Aborts the transactions until AND including the given index.
348//=======================================================================
349
350void TDF_Data::AbortUntilTransaction(const Standard_Integer untilTransaction)
351{
352 if (untilTransaction>0)
353 Undo(TDF_Data::CommitUntilTransaction(untilTransaction,Standard_True),Standard_False);
354}
355
356
357//=======================================================================
358//function : IsApplicable
359//purpose :
360//=======================================================================
361
362Standard_Boolean TDF_Data::IsApplicable
363(const Handle(TDF_Delta)& aDelta) const
364{
365 return !aDelta.IsNull() && aDelta->IsApplicable(myTime);
366}
367
368
369//=======================================================================
370//function : Undo
371//purpose : Applies a delta to undo actions.
372//=======================================================================
373
374Handle(TDF_Delta) TDF_Data::Undo
375(const Handle(TDF_Delta)& aDelta,
376 const Standard_Boolean withDelta)
377{
378 Handle(TDF_Delta) newDelta;
379 if (!aDelta.IsNull ()) {
380 if (aDelta->IsApplicable(myTime)) {
381 if (withDelta) OpenTransaction();
0797d9d3 382#ifdef OCCT_DEBUG_DELTA
7fd59977 383 cout<<"TDF_Data::Undo applies this delta:"<<endl;
384 aDelta->Dump(cout);
385#endif
386 aDelta->BeforeOrAfterApply(Standard_True);
387 myNotUndoMode = Standard_False;
388 aDelta->Apply ();
389 myNotUndoMode = Standard_True;
390 if (withDelta) {
391 newDelta = CommitTransaction(Standard_True);
392 newDelta->Validity(aDelta->EndTime(),aDelta->BeginTime());
0797d9d3 393#ifdef OCCT_DEBUG_DELTA
7fd59977 394 cout<<"TDF_Data::Undo, after validity correction, Delta is now available from time \t#"<<newDelta->BeginTime()<<" to time \t#"<<newDelta->EndTime()<<endl;
395#endif
396 }
397 myTime = aDelta->BeginTime();
398 aDelta->BeforeOrAfterApply(Standard_False);
399 }
400 }
401 return newDelta;
402}
403
404
405
406//=======================================================================
407//function : Dump
408//purpose :
409//=======================================================================
410
411Standard_OStream& TDF_Data::Dump(Standard_OStream& anOS) const
412{
413 anOS<<"Dump of a TDF_Data."<<endl;
414 anOS<<"Current transaction: "<<myTransaction;
415 anOS<<"; Current tick: "<<myTime<<";"<<endl;
416 return anOS;
417}