Home | History | Annotate | Download | only in mcld
      1 //===- InputTree.h --------------------------------------------------------===//
      2 //
      3 //                     The MCLinker Project
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 #ifndef MCLD_INPUTTREE_H
     10 #define MCLD_INPUTTREE_H
     11 
     12 #include <mcld/ADT/BinTree.h>
     13 #include <mcld/ADT/TypeTraits.h>
     14 #include <mcld/MC/Input.h>
     15 #include <mcld/Support/Path.h>
     16 
     17 #include <string>
     18 
     19 
     20 namespace mcld {
     21 
     22 /** \class template<typename Traits, typename Iterator> PolicyIterator<mcld::Input>
     23  *  \brief PolicyIterator<mcld::Input> is a partially specific PolicyIterator
     24  */
     25 template<typename Traits, typename IteratorType>
     26 class PolicyIterator<mcld::Input, Traits, IteratorType> : public PolicyIteratorBase<Input, Traits, IteratorType>
     27 {
     28 public:
     29   typedef PolicyIterator<Input, Traits, IteratorType> Self;
     30   typedef PolicyIteratorBase<Input, Traits, IteratorType> Base;
     31   typedef PolicyIterator<Input, typename Traits::nonconst_traits, IteratorType> iterator;
     32   typedef PolicyIterator<Input, typename Traits::const_traits, IteratorType>    const_iterator;
     33 
     34 public:
     35   PolicyIterator()
     36     : Base() {}
     37 
     38   PolicyIterator(const iterator &X)
     39     : Base(X.m_pNode) {}
     40 
     41   explicit PolicyIterator(NodeBase* X)
     42     : Base(X) {}
     43 
     44   virtual ~PolicyIterator() {}
     45 
     46   bool isGroup() const
     47   { return !Base::hasData() && !Base::isRoot(); }
     48 
     49   Self& operator++() {
     50     IteratorType::advance();
     51     // skip the Group node
     52     while (isGroup())
     53       IteratorType::advance();
     54     return *this;
     55   }
     56 
     57   Self operator++(int) {
     58     Self tmp(*this);
     59     IteratorType::advance();
     60     // skip the Group node
     61     while (isGroup())
     62       IteratorType::advance();
     63     return tmp;
     64   }
     65 };
     66 
     67 template<>
     68 class BinaryTree<Input> : public BinaryTreeBase<Input>
     69 {
     70 public:
     71   typedef size_t             size_type;
     72   typedef ptrdiff_t          difference_type;
     73   typedef Input              value_type;
     74   typedef value_type*        pointer;
     75   typedef value_type&        reference;
     76   typedef const value_type*  const_pointer;
     77   typedef const value_type&  const_reference;
     78 
     79   typedef BinaryTree<Input>  Self;
     80   typedef TreeIterator<value_type, NonConstTraits<value_type> > iterator;
     81   typedef TreeIterator<value_type, ConstTraits<value_type> >    const_iterator;
     82 
     83   typedef PolicyIterator<value_type, NonConstTraits<value_type>, DFSIterator> dfs_iterator;
     84   typedef PolicyIterator<value_type, ConstTraits<value_type>, DFSIterator>    const_dfs_iterator;
     85   typedef PolicyIterator<value_type, NonConstTraits<value_type>, BFSIterator> bfs_iterator;
     86   typedef PolicyIterator<value_type, ConstTraits<value_type>, BFSIterator>    const_bfs_iterator;
     87 
     88 protected:
     89   typedef Node<value_type> node_type;
     90 
     91 public:
     92   // -----  constructors and destructor  ----- //
     93   BinaryTree()
     94   : BinaryTreeBase<Input>()
     95   { }
     96 
     97   ~BinaryTree() {
     98   }
     99 
    100   // -----  iterators  ----- //
    101   bfs_iterator bfs_begin()
    102   {
    103      bfs_iterator it = bfs_iterator(BinaryTreeBase<Input>::m_Root.node.left);
    104      if (it.isGroup())
    105        ++it;
    106      return it;
    107   }
    108 
    109   bfs_iterator bfs_end()
    110   { return bfs_iterator(BinaryTreeBase<Input>::m_Root.node.right); }
    111 
    112   const_bfs_iterator bfs_begin() const
    113   {
    114      const_bfs_iterator it =
    115                     const_bfs_iterator(BinaryTreeBase<Input>::m_Root.node.left);
    116      if (it.isGroup())
    117        ++it;
    118      return it;
    119   }
    120 
    121   const_bfs_iterator bfs_end() const
    122   { return const_bfs_iterator(BinaryTreeBase<Input>::m_Root.node.right); }
    123 
    124   dfs_iterator dfs_begin()
    125   {
    126     dfs_iterator it = dfs_iterator(BinaryTreeBase<Input>::m_Root.node.left);
    127     if (it.isGroup())
    128       ++it;
    129     return it;
    130   }
    131 
    132   dfs_iterator dfs_end()
    133   { return dfs_iterator(BinaryTreeBase<Input>::m_Root.node.right); }
    134 
    135   const_dfs_iterator dfs_begin() const
    136   {
    137     const_dfs_iterator it =
    138                     const_dfs_iterator(BinaryTreeBase<Input>::m_Root.node.left);
    139     if (it.isGroup())
    140       ++it;
    141     return it;
    142   }
    143 
    144   const_dfs_iterator dfs_end() const
    145   { return const_dfs_iterator(BinaryTreeBase<Input>::m_Root.node.right); }
    146 
    147   iterator root()
    148   { return iterator(&(BinaryTreeBase<Input>::m_Root.node)); }
    149 
    150   const_iterator root() const
    151   {
    152     // FIXME: provide the iterater constructors for constant NodeBase instead of
    153     // using const_cast
    154     return const_iterator(
    155                     const_cast<NodeBase*>(&BinaryTreeBase<Input>::m_Root.node));
    156   }
    157 
    158   iterator begin()
    159   {
    160     iterator it = iterator(BinaryTreeBase<Input>::m_Root.node.left);
    161     return it;
    162   }
    163 
    164   iterator end()
    165   { return iterator(BinaryTreeBase<Input>::m_Root.node.right); }
    166 
    167   const_iterator begin() const
    168   {
    169     const_iterator it = const_iterator(BinaryTreeBase<Input>::m_Root.node.left);
    170     return it;
    171   }
    172 
    173   const_iterator end() const
    174   { return const_iterator(BinaryTreeBase<Input>::m_Root.node.right); }
    175 
    176   // ----- modifiers  ----- //
    177   /// join - create a leaf node and merge it in the tree.
    178   //  This version of join determines the direction on compilation time.
    179   //  @param DIRECT the direction of the connecting edge of the parent node.
    180   //  @param position the parent node
    181   //  @param value the value being pushed.
    182   template<size_t DIRECT>
    183   BinaryTree& join(TreeIteratorBase& pPosition, const Input& value) {
    184     node_type *node = BinaryTreeBase<Input>::createNode();
    185     node->data = const_cast<Input*>(&value);
    186 
    187     if (pPosition.isRoot())
    188       pPosition.hook<TreeIteratorBase::Leftward>(node);
    189     else
    190       pPosition.hook<DIRECT>(node);
    191 
    192     return *this;
    193   }
    194 
    195   /// merge - merge the tree
    196   //  @param DIRECT the direction of the connecting edge of the parent node.
    197   //  @param position the parent node
    198   //  @param the tree being joined.
    199   //  @return the joined tree
    200   template<size_t DIRECT>
    201   BinaryTree& merge(TreeIteratorBase& pPosition, BinaryTree& pTree) {
    202     if (this == &pTree)
    203       return *this;
    204 
    205     if (!pTree.empty()) {
    206       pPosition.hook<DIRECT>(pTree.m_Root.node.left);
    207       BinaryTreeBase<Input>::m_Root.summon(
    208                                    pTree.BinaryTreeBase<Input>::m_Root);
    209       BinaryTreeBase<Input>::m_Root.delegate(pTree.m_Root);
    210       pTree.m_Root.node.left = pTree.m_Root.node.right = &pTree.m_Root.node;
    211     }
    212     return *this;
    213   }
    214 };
    215 
    216 /** \class InputTree
    217  *  \brief InputTree is the input tree to contains all inputs from the
    218  *  command line.
    219  *
    220  *  InputTree, of course, is uncopyable.
    221  *
    222  *  @see Input
    223  */
    224 class InputTree : public BinaryTree<Input>
    225 {
    226 private:
    227   typedef BinaryTree<Input> BinTreeTy;
    228 
    229 public:
    230   enum Direction {
    231     Inclusive  = TreeIteratorBase::Leftward,
    232     Positional = TreeIteratorBase::Rightward
    233   };
    234 
    235   typedef BinaryTree<Input>::iterator       iterator;
    236   typedef BinaryTree<Input>::const_iterator const_iterator;
    237 
    238 public:
    239   /** \class Mover
    240    *  \brief Mover provides the interface for moving iterator forward.
    241    *
    242    *  Mover is a function object (functor). @ref Mover::move moves
    243    *  iterator forward in certain direction. @ref Mover::connect
    244    *  connects two nodes of the given iterators togather.
    245    */
    246   struct Mover {
    247     virtual void connect(TreeIteratorBase& pFrom, NodeBase* pTo) const = 0;
    248     virtual void move(TreeIteratorBase& pNode) const = 0;
    249     virtual ~Mover() { }
    250   };
    251 
    252   /** \class Succeeder
    253    *  \brief class Succeeder moves the iterator afterward.
    254    */
    255   struct Succeeder : public Mover {
    256     void connect(TreeIteratorBase& pFrom, NodeBase* pTo) const {
    257       pFrom.hook<Positional>(pTo);
    258     }
    259 
    260     void move(TreeIteratorBase& pNode) const {
    261       pNode.move<Positional>();
    262     }
    263   };
    264 
    265   /** \class Includer
    266    *  \brief class Includer moves the iterator downward.
    267    */
    268   struct Includer : public Mover {
    269     void connect(TreeIteratorBase& pFrom, NodeBase* pTo) const {
    270       pFrom.hook<Inclusive>(pTo);
    271     }
    272 
    273     void move(TreeIteratorBase& pNode) const {
    274       pNode.move<Inclusive>();
    275     }
    276   };
    277 
    278 public:
    279   static Succeeder Afterward;
    280   static Includer  Downward;
    281 
    282 public:
    283 
    284   using BinTreeTy::merge;
    285 
    286   // -----  modify  ----- //
    287   template<size_t DIRECT>
    288   InputTree& enterGroup(TreeIteratorBase pRoot);
    289 
    290   template<size_t DIRECT>
    291   InputTree& insert(TreeIteratorBase pRoot,
    292                     Input& pInput);
    293 
    294   InputTree& merge(TreeIteratorBase pRoot,
    295                    const Mover& pMover,
    296                    InputTree& pTree);
    297 
    298   InputTree& insert(TreeIteratorBase pRoot,
    299                     const Mover& pMover,
    300                     Input& pInput);
    301 
    302   InputTree& enterGroup(TreeIteratorBase pRoot,
    303                         const Mover& pMover);
    304 
    305 };
    306 
    307 bool isGroup(const InputTree::iterator& pos);
    308 bool isGroup(const InputTree::const_iterator& pos);
    309 bool isGroup(const InputTree::dfs_iterator& pos);
    310 bool isGroup(const InputTree::const_dfs_iterator& pos);
    311 bool isGroup(const InputTree::bfs_iterator& pos);
    312 bool isGroup(const InputTree::const_bfs_iterator& pos);
    313 
    314 } // namespace of mcld
    315 
    316 //===----------------------------------------------------------------------===//
    317 // template member functions
    318 //===----------------------------------------------------------------------===//
    319 template<size_t DIRECT>
    320 mcld::InputTree&
    321 mcld::InputTree::enterGroup(mcld::TreeIteratorBase pRoot)
    322 {
    323   BinTreeTy::node_type* node = createNode();
    324 
    325   if (pRoot.isRoot())
    326     pRoot.hook<TreeIteratorBase::Leftward>(node);
    327   else
    328     pRoot.hook<DIRECT>(node);
    329 
    330   return *this;
    331 }
    332 
    333 template<size_t DIRECT>
    334 mcld::InputTree& mcld::InputTree::insert(mcld::TreeIteratorBase pRoot,
    335 	                                 mcld::Input& pInput)
    336 {
    337   BinTreeTy::node_type* node = createNode();
    338   node->data = &pInput;
    339 
    340   if (pRoot.isRoot())
    341     pRoot.hook<TreeIteratorBase::Leftward>(node);
    342   else
    343     pRoot.hook<DIRECT>(node);
    344 
    345   return *this;
    346 }
    347 
    348 #endif
    349 
    350