[Kst] branches/work/kst/hierarchy/kst/src/libkst

Eli Fidler eli at staikos.net
Mon Nov 20 21:41:42 CET 2006


SVN commit 606565 by fidler:

Added KstObjectTree class to encapsulate naming tree and index
Added naming index for unique tags
Remove slashes in tag names
Clean up KstObjectTreeNodes properly

KstScalar: added setTagName(KstObjectTag), add to naming tree from setTagName
KstString: added setTagName(KstObjectTag), add to naming tree from setTagName



 M  +3 -1      kstdatacollection.cpp  
 M  +2 -1      kstdatacollection.h  
 M  +96 -13    kstobject.cpp  
 M  +19 -2     kstobject.h  
 M  +8 -4      kstscalar.cpp  
 M  +2 -0      kstscalar.h  
 M  +8 -1      kststring.cpp  
 M  +2 -0      kststring.h  


--- branches/work/kst/hierarchy/kst/src/libkst/kstdatacollection.cpp #606564:606565
@@ -36,10 +36,12 @@
 /** The list of Scalars which have been generated */
 KstScalarList KST::scalarList;
 /** Root of Scalar naming tree */
-KstObjectTreeNode *KST::scalarTree = new KstObjectTreeNode();
+KstObjectTree KST::scalarNameTree;
 
 /** The list of Strings */
 KstStringList KST::stringList;
+/** Root of String naming tree */
+KstObjectTree KST::stringNameTree;
 
 void KST::addVectorToList(KstVectorPtr v) {
   KST::vectorList.lock().writeLock();
--- branches/work/kst/hierarchy/kst/src/libkst/kstdatacollection.h #606564:606565
@@ -78,10 +78,11 @@
 
     /** The list of Scalars which have been generated */
     KST_EXPORT extern KstScalarList scalarList;
-    KST_EXPORT extern KstObjectTreeNode *scalarTree;
+    KST_EXPORT extern KstObjectTree scalarNameTree;
 
     /** The list of Strings */
     KST_EXPORT extern KstStringList stringList;
+    KST_EXPORT extern KstObjectTree stringNameTree;
 
     /** The list of matrices that are being read */
     KST_EXPORT extern KstMatrixList matrixList;
--- branches/work/kst/hierarchy/kst/src/libkst/kstobject.cpp #606564:606565
@@ -65,9 +65,9 @@
 
 
 void KstObject::setTagName(KstObjectTag tag) {
-  if (tag.tag().contains('/')) {
-    kstdWarning() << "WARNING: setting KstObject tag name containing '/':\"" << tag.tag() << "\"" << endl;
-    // TODO: parse out slashes
+  if (tag.tag().contains(KstObjectTag::tagSeparator)) {
+    kstdWarning() << "WARNING: setting KstObject tag name containing " << KstObjectTag::tagSeparator << ":\"" << tag.tag() << "\"" << endl;
+    tag.setTag(tag.tag().replace(KstObjectTag::tagSeparator, "-"));
   }
 
   _tag = tag;
@@ -76,12 +76,13 @@
 
 
 void KstObject::setTagName(const QString& tag, QStringList context) {
-  if (tag.contains('/')) {
-    kstdWarning() << "WARNING: setting KstObject tag name containing '/':" << tag << endl;
-    // TODO: parse out slashes
+  _tag.setTag(tag, context);
+
+  if (tag.contains(KstObjectTag::tagSeparator)) {
+    kstdWarning() << "WARNING: setting KstObject tag name containing " << KstObjectTag::tagSeparator << ":\"" << tag << "\"" << endl;
+    _tag.setTag(_tag.tag().replace(KstObjectTag::tagSeparator, "-"));
   }
 
-  _tag.setTag(tag, context);
   setName(_tag.tagString().local8Bit().data());
 }
 
@@ -121,12 +122,21 @@
 }
 
 
+
 KstObjectTreeNode::KstObjectTreeNode(const QString& tag) : _tag(tag),
                                                            _object(NULL),
                                                            _parent(NULL)
 {
 }
 
+
+KstObjectTreeNode::~KstObjectTreeNode() {
+  for (QMapIterator<QString, KstObjectTreeNode*> i = _children.begin(); i != _children.end(); ++i) {
+    delete (i.data());
+  }
+}
+
+
 QStringList KstObjectTreeNode::fullTag() const {
   QStringList tag;
   const KstObjectTreeNode *p = this;
@@ -141,6 +151,7 @@
   return tag;
 }
 
+
 KstObjectTreeNode *KstObjectTreeNode::child(const QString& tag) const {
   if (_children.contains(tag)) {
     return _children[tag];
@@ -149,6 +160,7 @@
   }
 }
 
+
 KstObjectTreeNode *KstObjectTreeNode::descendant(QStringList tag) {
   KstObjectTreeNode *currNode = this;
   for (QStringList::ConstIterator i = tag.begin(); i != tag.end(); ++i) {
@@ -161,9 +173,10 @@
   return currNode;
 }
 
-bool KstObjectTreeNode::addDescendant(KstObject *o) {
+
+KstObjectTreeNode *KstObjectTreeNode::addDescendant(KstObject *o, KstObjectNameIndex *index) {
   if (!o) {
-    return false;
+    return NULL;
   }
 
   QStringList tag = o->tag().fullTag();
@@ -175,20 +188,25 @@
       nextNode = new KstObjectTreeNode(*i);
       nextNode->_parent = currNode;
       currNode->_children[*i] = nextNode;
+      if (index) {
+        (*index)[*i].append(nextNode);
+      }
     }
     currNode = nextNode;
   }
 
   if (currNode->_object) {
-    return false;
+    kstdDebug() << "Tried to add KstObject to naming tree:" << o->tag().tagString() << ", but there's already an object with that name" << endl;
+    return NULL;
   } else {
     currNode->_object = o;
     kstdDebug() << "Added KstObject to naming tree:" << o->tag().tagString() << endl;
-    return true;
+    return currNode;
   }
 }
 
-bool KstObjectTreeNode::removeDescendant(KstObject *o) {
+
+bool KstObjectTreeNode::removeDescendant(KstObject *o, KstObjectNameIndex *index) {
   if (!o) {
     return false;
   }
@@ -199,26 +217,91 @@
   for (QStringList::ConstIterator i = tag.begin(); i != tag.end(); ++i) {
     KstObjectTreeNode *nextNode = currNode->child(*i);
     if (!nextNode) {
+//      kstdDebug() << "Tried to remove KstObject from naming tree:" << o->tag().tagString() << ", but the node is not in the tree" << endl;
       return false;
     }
     currNode = nextNode;
   }
 
   if (currNode->_object != QGuardedPtr<KstObject>(o)) {
+//    kstdDebug() << "Tried to remove KstObject from naming tree:" << o->tag().tagString() << ", but the object is not in the tree" << endl;
     return false;
   } else {
     currNode->_object = NULL;
     QStringList::ConstIterator i = tag.end();
-    while (i != tag.begin() && currNode->_object.isNull()) {
+    while (i != tag.begin() && currNode->_object.isNull() && currNode->_children.isEmpty()) {
       --i;
       KstObjectTreeNode *lastNode = currNode->_parent;
       lastNode->_children.remove(*i);
+      kstdDebug() << "Removed naming tree node:" << currNode->fullTag().join(KstObjectTag::tagSeparator) << endl;
+      if (index) {
+        (*index)[*i].remove(currNode);
+        if ((*index)[*i].isEmpty()) {
+          (*index).remove(*i);
+        }
+      }
       delete currNode;
       currNode = lastNode;
     }
+    kstdDebug() << "Removed KstObject from naming tree:" << o->tag().tagString() << endl;
     return true;
   }
 }
 
 
+bool KstObjectTree::addObject(KstObject *o) {
+  KstObjectTreeNode *n = _root.addDescendant(o, &_index);
+  return (n != NULL);
+}
+
+
+bool KstObjectTree::removeObject(KstObject *o) {
+  bool ok = _root.removeDescendant(o, &_index);
+
+  return ok;
+}
+
+
+KstObject * KstObjectTree::retrieveObject(QStringList tag) {
+  kstdDebug() << "Retrieving object with tag: " << tag.join(KstObjectTag::tagSeparator) << endl;
+
+  if (tag.isEmpty()) {
+    return NULL;
+  }
+
+  if (_index.contains(tag.first()) && _index[tag.first()].count() == 1) {
+    // the first tag element is unique, so use the index
+    kstdDebug() << "  first tag element (" << tag.first() << ") is unique in index" << endl;
+
+    KstObjectTreeNode *n = _index[tag.first()].first();
+    if (n) {
+      tag.pop_front();
+      n = n->descendant(tag);
+    }
+    if (n) {
+      kstdDebug() << "  found node, returning object " << (void*) n->object() << endl;
+      return n->object();
+    }
+  }
+
+  // search through the tree
+  KstObjectTreeNode *n = _root.descendant(tag);
+  if (n) {
+    kstdDebug() << "  found node, returning object " << (void*) n->object() << endl;
+    return n->object();
+  } else {
+    kstdDebug() << "  node not found" << endl;
+    return NULL;
+  }
+}
+
+
+KstObject * KstObjectTree::retrieveObject(KstObjectTag tag) {
+  if (!tag.isValid()) {
+    return NULL;
+  }
+
+  return retrieveObject(tag.fullTag());
+}
+
 // vim: ts=2 sw=2 et
--- branches/work/kst/hierarchy/kst/src/libkst/kstobject.h #606564:606565
@@ -305,9 +305,13 @@
 
 
 /** KstObject Naming Tree */
+class KstObjectTreeNode;
+typedef QMap<QString, QValueList<KstObjectTreeNode *> > KstObjectNameIndex;
+
 class KstObjectTreeNode {
   public:
     KstObjectTreeNode(const QString& tag = QString::null);
+    ~KstObjectTreeNode();
 
     QString nodeTag() const { return _tag; }
     QStringList fullTag() const;
@@ -319,8 +323,8 @@
     QMap<QString, KstObjectTreeNode *> children() const { return _children; }
 
     KstObjectTreeNode *descendant(QStringList tag);
-    bool addDescendant(KstObject *o);
-    bool removeDescendant(KstObject *o);
+    KstObjectTreeNode *addDescendant(KstObject *o, KstObjectNameIndex *index = NULL);
+    bool removeDescendant(KstObject *o, KstObjectNameIndex *index = NULL);
 
     // TODO: locking
   private:
@@ -330,5 +334,18 @@
     QMap<QString, KstObjectTreeNode *> _children;
 };
 
+class KstObjectTree {
+  public:
+    bool addObject(KstObject *o);
+    bool removeObject(KstObject *o);
+
+    KstObject *retrieveObject(QStringList tag);
+    KstObject *retrieveObject(KstObjectTag tag);
+
+  private:
+    KstObjectTreeNode _root;
+    KstObjectNameIndex _index;
+};
+
 #endif
 // vim: ts=2 sw=2 et
--- branches/work/kst/hierarchy/kst/src/libkst/kstscalar.cpp #606564:606565
@@ -52,14 +52,13 @@
       _tag += '\'';
     }
   }
-  setTagName(_tag, in_tag.context());
+  setTagName(KstObjectTag(_tag, in_tag.context()));
 
   // FIXME: passing in a lock variable indicates a design problem
   if (doLock) {
     KST::scalarList.lock().writeLock();
   }
   KST::scalarList.append(this);
-  KST::scalarTree->addDescendant(this);
   if (doLock) {
     KST::scalarList.lock().unlock();
   }
@@ -77,7 +76,7 @@
     QDomElement e = n.toElement();
     if(!e.isNull()) {
       if (e.tagName() == "tag") {
-        setTagName(e.text(), QStringList());  // FIXME: use proper tag context
+        setTagName(KstObjectTag(e.text(), KstObjectTag::globalTagContext));  // FIXME: use proper tag context
       } else if (e.tagName() == "orphan") {
         _orphan = true;
       } else if (e.tagName() == "value") {
@@ -94,7 +93,6 @@
   }
 
   KST::scalarList.append(this);
-  KST::scalarTree->addDescendant(this);
 }
 
 
@@ -198,5 +196,11 @@
 }
 
 
+void KstScalar::setTagName(KstObjectTag newTag) {
+  KST::scalarNameTree.removeObject(this);
+  KstObject::setTagName(newTag);
+  KST::scalarNameTree.addObject(this);
+}
+
 #include "kstscalar.moc"
 // vim: et ts=2 sw=2
--- branches/work/kst/hierarchy/kst/src/libkst/kstscalar.h #606564:606565
@@ -34,6 +34,8 @@
     KstScalar(const QDomElement& e);
     virtual ~KstScalar();
 
+    void setTagName(KstObjectTag tag);
+
     /* return true if any scalars are dirty at the moment */
     static bool scalarsDirty();
     /* For use by the update thread */
--- branches/work/kst/hierarchy/kst/src/libkst/kststring.cpp #606564:606565
@@ -57,7 +57,7 @@
     QDomElement e = n.toElement();
     if (!e.isNull()) {
       if (e.tagName() == "tag") {
-        setTagName(e.text(), QStringList());  // FIXME: use proper tag context
+        setTagName(KstObjectTag(e.text(), KstObjectTag::globalTagContext));  // FIXME: use proper tag context
       } else if (e.tagName() == "orphan") {
         _orphan = true;
       } else if (e.tagName() == "value") {
@@ -74,6 +74,13 @@
 }
 
 
+void KstString::setTagName(KstObjectTag tag) {
+  KST::stringNameTree.removeObject(this);
+  KstObject::setTagName(tag);
+  KST::stringNameTree.addObject(this);
+}
+
+
 void KstString::save(QTextStream &ts, const QString& indent) {
   ts << indent << "<tag>" << QStyleSheet::escape(tagName()) << "</tag>" << endl;
   if (_orphan) {
--- branches/work/kst/hierarchy/kst/src/libkst/kststring.h #606564:606565
@@ -29,6 +29,8 @@
     KstString(QDomElement& e);
     ~KstString();
 
+    void setTagName(KstObjectTag tag);
+
     /** Save information */
     void save(QTextStream &ts, const QString& indent = QString::null);
 


More information about the Kst mailing list