]> OCCT Git - occt-copy.git/commitdiff
0031920: Application Framework - speed up methods of getting label by entry and vice...
authorvro <vladislav.romashko@opencascade.com>
Thu, 31 Dec 2020 12:34:42 +0000 (15:34 +0300)
committernds <nds@opencascade.com>
Tue, 13 Apr 2021 07:46:50 +0000 (10:46 +0300)
// A method TDF_Data::AddLabel() is set Standard_EXPORT.

(cherry picked from commit 8f2e87bddeffea13156ca6b0d7a1ae7619403844)

src/DDF/DDF_DataCommands.cxx
src/TDF/TDF_Data.cxx
src/TDF/TDF_Data.hxx
src/TDF/TDF_Label.cxx
src/TDF/TDF_Tool.cxx
tests/bugs/caf/bug31920 [new file with mode: 0644]

index f0e4391e02cb7f6ba66cfc9c7690c5c7f32b43f6..29658bc07f98f9d38d4f85f36988432e9ef47600 100644 (file)
@@ -371,11 +371,30 @@ static Standard_Integer  DDF_CheckLabel (Draw_Interpretor& di,Standard_Integer n
   return 1;    
 }
 
-
+//=======================================================================
+//function : DDF_SetAccessByEntry
+//purpose  : SetAccessByEntry DOC 1|0
+//=======================================================================
+static Standard_Integer DDF_SetAccessByEntry (Draw_Interpretor& di, Standard_Integer nb, const char** a)
+{
+  Standard_Integer aRet = 0;
+  if (nb != 3) {
+    di << "SetAccessByEntry DOC 1|0\n";
+    aRet = 1;
+  } else {
+    Handle(TDF_Data) aDF;
+    if (DDF::GetDF(a[1], aDF)) {
+      Standard_Boolean aSet = (Draw::Atoi (a[2]) == 1);
+      aDF->SetAccessByEntries (aSet);
+    } else {
+      aRet = 1;
+    }
+  }
+  return aRet;
+}
 
 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
-
 //=======================================================================
 //function : DataCommands
 //purpose  : 
@@ -415,10 +434,13 @@ void DDF::DataCommands (Draw_Interpretor& theCommands)
                    "CopyLabel (DOC, from, to)",
                   __FILE__, CopyLabel_SCopy, g);    
 
-  theCommands.Add("CheckAttrs","CheckAttrs DocName Lab1 Lab2 ",
+  theCommands.Add ("CheckAttrs","CheckAttrs DocName Lab1 Lab2 ",
                    __FILE__, DDF_CheckAttrs, g);
 
-  theCommands.Add("CheckLabel","CheckLabel DocName Label ",
+  theCommands.Add ("CheckLabel","CheckLabel DocName Label ",
                    __FILE__, DDF_CheckLabel, g);
 
+  theCommands.Add ("SetAccessByEntry", "SetAccessByEntry DOC 1|0",
+                   __FILE__, DDF_SetAccessByEntry, g);
+
 }
index 7cd8877047aba0dda45dc7644748c55893b10db9..96027493fb965ab550175cee0c1bd1411dab3502 100644 (file)
@@ -94,7 +94,8 @@ myTransaction           (0),
 myNbTouchedAtt          (0),
 myNotUndoMode           (Standard_True),
 myTime                  (0),
-myAllowModification     (Standard_True)
+myAllowModification     (Standard_True),
+myAccessByEntries       (Standard_False)
 {
   const Handle(NCollection_IncAllocator) anIncAllocator=
     new NCollection_IncAllocator (16000);
@@ -118,6 +119,7 @@ void TDF_Data::Destroy()
     Handle(TDF_Attribute) aFirst = myRoot->FirstAttribute();
     myRoot->RemoveAttribute(anEmpty, aFirst);
   }
+  myAccessByEntriesTable.Clear();
   myRoot->Destroy (myLabelNodeAllocator);
   myRoot = NULL;
 }
@@ -439,7 +441,66 @@ Handle(TDF_Delta) TDF_Data::Undo(const Handle(TDF_Delta)& aDelta,
   return newDelta;
 }
 
+//=======================================================================
+//function : SetAccessByEntries
+//purpose  : 
+//=======================================================================
+
+void TDF_Data::SetAccessByEntries(const Standard_Boolean aSet)
+{
+  myAccessByEntries = aSet;
+
+  myAccessByEntriesTable.Clear();
+  if (myAccessByEntries) {
+    // Add root label.
+    TCollection_AsciiString anEntry;
+    TDF_Tool::Entry(myRoot, anEntry);
+    myAccessByEntriesTable.Bind(anEntry, myRoot);
+
+    // Add all other labels.
+    TDF_ChildIterator itr(myRoot, Standard_True);
+    for (; itr.More(); itr.Next()) {
+      const TDF_Label aLabel = itr.Value();
+      TDF_Tool::Entry(aLabel, anEntry);
+      myAccessByEntriesTable.Bind(anEntry, aLabel);
+    }
+  }
+}
+
+//=======================================================================
+//function : IsAccessByEntries
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean TDF_Data::IsAccessByEntries() const
+{
+  return myAccessByEntries;
+}
+
+//=======================================================================
+//function : GetLabel
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean TDF_Data::GetLabel(const TCollection_AsciiString& anEntry, TDF_Label& aLabel)
+{
+  Standard_Boolean aResult = myAccessByEntriesTable.IsBound(anEntry);
+  if (aResult)
+    aLabel = myAccessByEntriesTable(anEntry);
+  return aResult;
+}
 
+//=======================================================================
+//function : AddLabel
+//purpose  : 
+//=======================================================================
+
+void TDF_Data::AddLabel(const TDF_Label& aLabel)
+{
+  TCollection_AsciiString anEntry;
+  TDF_Tool::Entry(aLabel, anEntry);
+  myAccessByEntriesTable.Bind(anEntry, aLabel);
+}
 
 //=======================================================================
 //function : Dump
index 73a2341d3b6b4c9eaa9609bb12aa96cf30302807..17846c6fcad84edb2af46c049b0b47aea28d5c12 100644 (file)
 #include <Standard_Transient.hxx>
 #include <TDF_Label.hxx>
 #include <Standard_OStream.hxx>
+#include <NCollection_DataMap.hxx>
 class Standard_NoMoreObject;
 class TDF_Transaction;
 class TDF_LabelNode;
 class TDF_Delta;
 class TDF_Label;
 
-
 class TDF_Data;
 DEFINE_STANDARD_HANDLE(TDF_Data, Standard_Transient)
 
@@ -100,6 +100,27 @@ Standard_OStream& operator<< (Standard_OStream& anOS) const
   //! returns modification mode.
     Standard_Boolean IsModificationAllowed() const;
   
+  //! Initializes a mechanism for fast access to the labels by their entries.
+  //! The fast access is useful for large documents and often access to the labels 
+  //! via entries. Internally, a table of entry - label icreated, 
+  //! which allows to obtain a label by its entry in a very fast way.
+  //! If the mechanism is turned off, the internal table is cleaned.
+  //! New labels are added to the table, if the mechanism is on
+  //! (no need to re-initialize the mechanism).
+  Standard_EXPORT void SetAccessByEntries (const Standard_Boolean aSet);
+
+  //! Returns a status of mechanism for fast access to the labels via entries.
+  Standard_EXPORT Standard_Boolean IsAccessByEntries() const;
+
+  //! Returns a label by an entry.
+  //! Returns Standard_False, if such a label doesn't exist
+  //! or mechanism for fast access to the label by entry is not initialized.
+  Standard_EXPORT Standard_Boolean GetLabel (const TCollection_AsciiString& anEntry, TDF_Label& aLabel);
+
+  //! An internal method. It is used internally on creation of new labels.
+  //! It adds a new label into internal table for fast access to the labels by entry.
+  Standard_EXPORT void AddLabel (const TDF_Label& aLabel);
+
   //! Returns TDF_HAllocator, which is an
   //! incremental allocator used by
   //! TDF_LabelNode.
@@ -198,8 +219,8 @@ private:
   TColStd_ListOfInteger myTimes;
   TDF_HAllocator myLabelNodeAllocator;
   Standard_Boolean myAllowModification;
-
-
+  Standard_Boolean myAccessByEntries;
+  NCollection_DataMap<TCollection_AsciiString, TDF_Label> myAccessByEntriesTable;
 };
 
 
index 9fac8c344ff0c67dd017467e57f630dcf1ed7b81..b1b0cea3f8802c7c94d91c9b1087bd9be28c7e41 100644 (file)
@@ -345,6 +345,9 @@ TDF_LabelNode* TDF_Label::FindOrAddChild
       myLabelNode->myFirstChild = childLabelNode;
     else                 // ... somewhere.
       lastLnp->myBrother = childLabelNode;
+    // Update table for fast access to the labels.
+    if (myLabelNode->Data()->IsAccessByEntries())
+      myLabelNode->Data()->AddLabel (childLabelNode);
   }
 
   if (lastLnp)                               //agv 14.07.2010
index f587c69603f60895ca6599c17964d82cf1e803ed..efa6ae9328a2fcd6f503a44acb8cd17ca5edf852 100644 (file)
@@ -372,30 +372,43 @@ void TDF_Tool::RelocateLabel
 //purpose  : Returns the entry as an ascii string.
 //=======================================================================
 
-void TDF_Tool::Entry
-(const TDF_Label& aLabel,
- TCollection_AsciiString& anEntry)
+void TDF_Tool::Entry (const TDF_Label& aLabel, TCollection_AsciiString& anEntry)
 {
-  anEntry.Clear();
   if (!aLabel.IsNull()) {
-    TColStd_ListOfInteger Tags;
-    TDF_Tool::TagList(aLabel, Tags);
-    anEntry += TCollection_AsciiString(Tags.First());
-    Tags.RemoveFirst();
-    if (Tags.IsEmpty()) {
-      anEntry += TDF_TagSeparator; // It must be the root label case.
+    int aStrLen = 1; // initial "0" of a root label
+    TDF_Label aLab = aLabel;
+    for (; !aLab.IsRoot(); aLab = aLab.Father())
+    {
+      for (int aTag = aLab.Tag(); aTag > 9; aTag /= 10)
+        ++aStrLen;
+      aStrLen += 2; // one digit and separator
     }
-    else {
-      while (!Tags.IsEmpty()) {
-       anEntry += TDF_TagSeparator;
-       anEntry += TCollection_AsciiString(Tags.First());
-       Tags.RemoveFirst();
-      }
+        
+    if (aStrLen == 1)
+    {
+      // an exceptional case for the root label, it ends with separator
+      static const TCollection_AsciiString THE_ROOT_ENTRY = TCollection_AsciiString ('0') + TDF_TagSeparator;
+      anEntry = THE_ROOT_ENTRY;
+    }
+    else
+    {
+      anEntry = TCollection_AsciiString (aStrLen, TDF_TagSeparator);
+      Standard_Character* aPtr = const_cast<Standard_Character*>(anEntry.ToCString() + aStrLen - 1);
+      for (aLab = aLabel; !aLab.IsRoot(); aLab = aLab.Father())
+      {
+        int aTag = aLab.Tag();
+        for (; aTag > 9; --aPtr, aTag /= 10)
+          *aPtr = Standard_Character (aTag % 10) + '0';
+        *aPtr = Standard_Character (aTag) + '0';
+        aPtr -= 2;
+      }        
+      *aPtr = '0';
     }
   }
+  else
+    anEntry.Clear();
 }
 
-
 //=======================================================================
 //function : TagList
 //purpose  : Returns the entry of a label as a list of integers.
@@ -452,12 +465,18 @@ void TDF_Tool::TagList
 //purpose  : Returns the label expressed by <anEntry>.
 //=======================================================================
 
-void TDF_Tool::Label
-(const Handle(TDF_Data)& aDF,
- const TCollection_AsciiString& anEntry,
- TDF_Label& aLabel,
- const Standard_Boolean create) 
-{ TDF_Tool::Label(aDF,anEntry.ToCString(),aLabel,create); }
+void TDF_Tool::Label (const Handle(TDF_Data)& aDF,
+                      const TCollection_AsciiString& anEntry,
+                      TDF_Label& aLabel,
+                      const Standard_Boolean create) 
+{
+  Standard_Boolean isFound = Standard_False;
+  if (aDF->IsAccessByEntries())
+    isFound = aDF->GetLabel (anEntry, aLabel);
+
+  if (!isFound)
+    TDF_Tool::Label (aDF, anEntry.ToCString(), aLabel, create);
+}
 
 
 //=======================================================================
@@ -466,15 +485,20 @@ void TDF_Tool::Label
 //           and creates it if <create> is true.
 //=======================================================================
 
-void TDF_Tool::Label
-(const Handle(TDF_Data)& aDF,
- const Standard_CString  anEntry,
- TDF_Label&              aLabel,
- const Standard_Boolean  create) 
+void TDF_Tool::Label (const Handle(TDF_Data)& aDF,
+                      const Standard_CString  anEntry,
+                      TDF_Label&              aLabel,
+                      const Standard_Boolean  create) 
 {
-  TColStd_ListOfInteger tagList;
-  TDF_Tool::TagList(anEntry,tagList);
-  TDF_Tool::Label(aDF,tagList,aLabel,create);
+  Standard_Boolean isFound = Standard_False;
+  if (aDF->IsAccessByEntries())
+    isFound = aDF->GetLabel (anEntry, aLabel);
+
+  if (!isFound) {
+    TColStd_ListOfInteger tagList;
+    TDF_Tool::TagList (anEntry, tagList);
+    TDF_Tool::Label (aDF, tagList, aLabel, create);
+  }
 }
 
 
diff --git a/tests/bugs/caf/bug31920 b/tests/bugs/caf/bug31920
new file mode 100644 (file)
index 0000000..9d5a19c
--- /dev/null
@@ -0,0 +1,22 @@
+puts "==========="
+puts "0031920: Application Framework - speed up methods of getting label by entry and vice versa"
+puts "==========="
+
+NewDocument D
+set entry 0:2
+set value 5
+SetInteger D $entry 5
+set checkvalue1 [GetInteger D $entry]
+if { $value != $checkvalue1 } {
+  puts "Set a value of TDataStd_Integer attribute: Error"
+  return
+}
+
+SetAccessByEntry D 1
+set checkvalue2 [GetInteger D $entry]
+if { $value != $checkvalue2 } {
+  puts "Fast access to label by entry: Error"
+  return
+}
+
+puts "Fast access to label by entry: OK"