Program Listing for File TreeImpl.h

Program Listing for File TreeImpl.h#

Return to documentation for file (src/util/support/TreeImpl.h)

#ifndef TREE_IMPL_H
#define TREE_IMPL_H

#include <iostream>
#include <DoublyLinkedList.h>
#include <mlog.h>

template<class T>
class TreeNodeImpl
{
  T* parent;
  DoublyLinkedListWrap<T*> children;
  typedef DoublyLinkedEntryWrap<T*> HolderType;
  HolderType *holder;

 protected:
  void Unlink()
    { if (holder != 0) {
          parent->children.Delete(holder); holder = 0; parent = 0;
      }
    }

 public:
  TreeNodeImpl() : parent(0), holder(0) {}
  virtual ~TreeNodeImpl()
    { for (iterator p = ChildrenIterator(); !p.ReachEnd(); ++p) {
         TreeNodeImpl<T>* n = (*p);
         n->holder = 0;
         delete n;
      }
      Unlink();
    }
  typedef typename DoublyLinkedListWrap<T*>::iterator iterator;
  typedef typename DoublyLinkedListWrap<T*>::const_iterator const_iterator;

  typedef enum {AsFirstChild,AsLastChild, AsPrevSibling, AsNextSibling} LinkOption;

  T* Parent() const { return parent; }
  T* FirstChild() const { return (ChildCount() > 0)? children.First()->GetEntry() : 0; }
  T* LastChild() const { return (ChildCount() > 0)? children.Last()->GetEntry() : 0; }
  iterator ChildrenIterator() { return iterator(children); }
  const_iterator ChildrenIterator() const { return const_iterator(children); }
  T* NextSibling() const {  HolderType *h = (holder==0)? 0 : parent->children.Next(holder);
                            return (h != 0)? h->GetEntry() : 0; }
  T* PrevSibling() const { HolderType *h = (holder==0)? 0 : parent->children.Prev(holder);
                           return (h != 0)? h->GetEntry() : 0; }
  unsigned ChildCount() const { return children.NumberOfEntries(); }

  void Link(T* pos, LinkOption opt)
     { ASSERT_require(holder == 0);
       T* entry = static_cast<T*>(this);
       switch (opt) {
       case AsFirstChild:
           parent = pos; holder = pos->children.PushFirst(entry); break;
       case AsLastChild:
           parent = pos; holder = pos->children.AppendLast(entry); break;
       case AsPrevSibling:
           parent = pos->parent;
           holder = parent->children.InsertBefore(entry, pos->holder);
           break;
       case AsNextSibling:
           parent = pos->parent;
           holder = parent->children.InsertAfter(entry, pos->holder);
           break;
       default:
           ROSE_ABORT();
       }
     }
  virtual void write(std::ostream& out) const {
      for (const_iterator p = ChildrenIterator(); !p.ReachEnd(); ++p)
         (*p)->write(out);
      if (ChildCount() > 0)
        out << "endtree\n";
  }
  void write() const
    { write(std::cerr); }
};

template <class T>
class TreeTraverse
{
 public:
  typedef enum {PreOrder, PostOrder, ChildrenOnly} TraversalOpt;
  static T* FirstNode(T *n, TraversalOpt opt=PreOrder)
    { switch (opt) {
       case PreOrder: return n;
       case PostOrder:
          while (n->FirstChild() != 0)
             n = n->FirstChild();
          return n;
       case ChildrenOnly:
          return n->FirstChild();
       default:
          ROSE_ABORT();
      }
    }
  static T* LastNode( T *n, TraversalOpt opt=PreOrder)
   { switch (opt) {
      case PostOrder: return n;
      case PreOrder:
         while (n->LastChild() != 0)
             n = n->LastChild();
         return n;
      case ChildrenOnly: return n->LastChild();
      default:
         ROSE_ABORT();
      }
   }
  static T* PrevNode( T *n, TraversalOpt opt=PreOrder)
   { T *result = 0;
     switch (opt ) {
      case PreOrder:
          result = n->PrevSibling();
          if ( result != 0)
              return LastNode( result, PreOrder );
          else
              return n->Parent();
      case PostOrder:
          result = n->LastChild();
          if ( result == 0) {
             for ( result = n->PrevSibling(); result == 0;
                   result = n->PrevSibling()) {
                n = n->Parent();
               if (n == 0)
                  break;
             }
          }
          return result;
      case ChildrenOnly:
          return n->PrevSibling();
      default:
          ROSE_ABORT();
     }
   }
  static T* NextNode( T *n, TraversalOpt opt=PreOrder)
   { T *result = 0;
     switch (opt ) {
      case PostOrder:
         result = n->NextSibling();
         if ( result != 0)
            return FirstNode( result, PostOrder );
         else
            return n->Parent();
      case PreOrder:
         result = n->FirstChild();
         if ( result == 0) {
            for ( result = n->NextSibling(); result == 0;
                  result = n->NextSibling()) {
                n = n->Parent();
                if (n == 0)
                  break;
            }
         }
         return result;
     case ChildrenOnly:
          return n->NextSibling();
     default:
          ROSE_ABORT();
     }
   }
};

#endif