#line 1 "/user/cvsspst/ees1cg/RAVL/RAVL-0.7/Core/Container/Trees/HashTree.hh" // This file is part of RAVL, Recognition And Vision Library // Copyright (C) 2001, University of Surrey // This code may be redistributed under the terms of the GNU Lesser // General Public License (LGPL). See the lgpl.licence file for details or // see http://www.gnu.org/copyleft/lesser.html // file-header-ends-here #ifndef RAVL_HASHTREE_HEADER #define RAVL_HASHTREE_HEADER 1 ////////////////////////////////////////////////////////////// //! rcsid="$Id: HashTree.hh,v 1.3 2002/01/31 14:55:30 craftit Exp $" //! author="Charles Galambos" //! docentry="Ravl.Core.Trees" //! lib=RavlCore //! file="Ravl/Core/Container/Trees/HashTree.hh" #include "Ravl/Hash.hh" #include "Ravl/HashIter.hh" #include "Ravl/DList.hh" namespace RavlN { template class HashTreeC; //! userlevel=Develop //: Base class for tree's. template class HashTreeNodeBodyC : public RCBodyVC { public: HashTreeNodeBodyC() {} //: Default constructor. HashTreeNodeBodyC(const DataT &ndata) : data(ndata) {} //: Constructor. DataT &Data() { return data; } //: Access data. const DataT &Data() const { return data; } //: Access data. virtual bool IsLeaf() const { return true; } //: Test if node is a leaf in the tree. virtual ostream &Dump(ostream &out,int level = 0) const { out << data; return out; } //: Dump in a easly readable format. protected: DataT data; }; //! userlevel=Advanced //: Base class for tree's. template class HashTreeNodeC : public RCHandleC > { public: HashTreeNodeC() {} //: Default constructor. // Creates an invalid handle. protected: HashTreeNodeC(HashTreeNodeBodyC &bod) : RCHandleC >(bod) {} //: Default constructor. HashTreeNodeBodyC &Body() { return RCHandleC >::Body(); } //: Access body. const HashTreeNodeBodyC &Body() const { return RCHandleC >::Body(); } //: Access body. public: DataT &Data() { return Body().Data(); } //: Access data. const DataT &Data() const { return Body().Data(); } //: Access data. bool IsLeaf() const { return Body().IsLeaf(); } //: Test if node is a leaf in the tree. ostream &Dump(ostream &out,int level = 0) const { return Body().Dump(out,level); } //: Dump in a easly readable format. }; //! userlevel=Develop //: Tree of hashtables. template class HashTreeBodyC : public HashTreeNodeBodyC { public: HashTreeBodyC(const DataT &dat) : HashTreeNodeBodyC(dat) {} //: Constructor. HashTreeBodyC() {} //: Default constructor. HashTreeNodeC &Node(const KeyT &key) { return children[key]; } //: Access child node. virtual bool IsLeaf() const { return children.IsEmpty(); } //: Test if node is a leaf in the tree. HashTreeNodeC Follow(const DListC &lst); //: Follow list of keys to a node. // If node is not found then an invalid handle is returned. bool Child(const KeyT &key,HashTreeNodeC &child) { return children.Lookup(key,child); } //: lookup child in tree. // Returns true and updates 'child' if child is found. bool Add(const KeyT &key,const DataT &data); //: Add a child with given key and data. // returns false if child exists. bool Add(const KeyT &key,const HashTreeC &subtree); //: Add a sub tree // returns false if child exists. HashC > &Children() { return children; } //: Access table of children. const HashC > &Children() const { return children; } //: Access table of children. virtual ostream &Dump(ostream &out,int level = 0) const { out << data << "\n"; for(HashIterC > it(children);it;it++){ out << it.Key() << " "; it.Data().Dump(out,level+1) << "\n"; } return out; } //: Dump in a easly readable format. // This is a little poor at the moment, its really expecting a derived // class to provide a better function. protected: HashC > children; }; //! userlevel=Normal //: Tree of hashtables. template class HashTreeC : public HashTreeNodeC { public: HashTreeC() {} //: Default constructor. // creates an invalid handle. HashTreeC(bool) : HashTreeNodeC(*new HashTreeBodyC()) {} //: Constructor. // Creates an empty tree HashTreeC(HashTreeNodeC &base) : HashTreeNodeC(base) { if(dynamic_cast * >(&HashTreeNodeC::Body() ) == 0) Invalidate(); } //: Base class constructor. HashTreeC(const DataT &data) : HashTreeNodeC(*new HashTreeBodyC(data)) {} protected: HashTreeC(HashTreeBodyC &bod) : HashTreeNodeC(bod) {} //: Body constructor. HashTreeBodyC &Body() { return static_cast & >(HashTreeNodeC::Body()); } //: Access body. const HashTreeBodyC &Body() const { return static_cast & >(HashTreeNodeC::Body()); } //: Access body. public: HashTreeNodeC Follow(const DListC &lst) { return Body().Follow(lst); } //: Follow list of keys to a node. // If node is not found then an invalid handle is returned. bool Child(const KeyT &key,HashTreeNodeC &child) { return Body().Child(key,child); } //: lookup child in tree. // Returns true and updates 'child' if child is found. bool Add(const KeyT &key,const DataT &data) { return Body().Add(key,data); } //: Add a child with given key and data. // returns false if child exists. bool Add(const KeyT &key,const HashTreeC &subtree) { return Body().Add(key,subtree); } //: Add a sub tree // returns false if child exists. HashC > &Children() { return Body().Children(); } //: Access table of children. const HashC > &Children() const { return Body().Children(); } //: Access table of children. friend class HashTreeBodyC; }; //! userlevel=Normal //: Iterate through a tree. template class HashTreeIterC : public HashIterC > { public: HashTreeIterC() {} //: Default constructor. HashTreeIterC(const HashTreeC &tree) : HashIterC >(tree.Children()) {} //: Constructor from tree. HashTreeC Tree() { return HashTreeC(Data()); } //: Access current node as tree. bool Go() { HashTreeC tree(Data()); if(!tree.IsValid()) return false; HashIterC >::operator=(tree.Children()); return true; } //: Go down the current node in the tree. }; template ostream &operator<<(ostream &s,const HashTreeC &tree) { if(!tree.IsValid()) { DataT dummy; HashC > tab; s << dummy << ' ' << tab; } else s << tree.Data() << ' ' << tree.Children(); return s; } template istream &operator>>(istream &s,HashTreeC &tree) { s >> tree.Data() >> tree.Children(); return s; } template ostream &operator<<(ostream &s,const HashTreeNodeC &node) { HashTreeC tree(const_cast & >(node)); // Always save nodes as full hash tree's if(tree.IsValid()) return s << tree; if(node.IsValid()) s << node.Data(); else { DataT dummy; s << dummy; } static HashC > empty; // Empty tree. s << ' ' << empty; return s; } template istream &operator>>(istream &s,HashTreeNodeC &tree) { HashTreeC ht; // Always read in as a full HashTree. s >> ht; tree = ht; return s; } //: Add a child with given key and data. // returns false if child exists. template bool HashTreeBodyC::Add(const KeyT &key,const DataT &data) { HashTreeNodeC &child = children[key]; if(child.IsValid()) return false; // it already exits! child = HashTreeC(data); return true; } //: Add a child with given key and data. // returns false if child exists. template bool HashTreeBodyC::Add(const KeyT &key,const HashTreeC &data) { HashTreeNodeC &child = children[key]; if(child.IsValid()) return false; // it already exits! child = data; return true; } //: Follow list of keys to a node. // If node is not found then an invalid handle is returned. template HashTreeNodeC HashTreeBodyC::Follow(const DListC &lst) { HashTreeNodeC ret; HashTreeC at(*this); DLIterC it(lst); for(;it && at.IsValid();it++) { if(!at.Child(*it,ret)) return HashTreeNodeC(); // Child not found. at = HashTreeC(ret); } if(it) // Did we reach the end of the path ? return HashTreeNodeC(); // Child not found. return ret; } } #endif