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_MC_INPUT_TREE_H
     10 #define MCLD_MC_INPUT_TREE_H
     11 #ifdef ENABLE_UNITTEST
     12 #include <gtest.h>
     13 #endif
     14 
     15 #include <mcld/ADT/BinTree.h>
     16 #include <mcld/ADT/TypeTraits.h>
     17 #include <mcld/MC/MCLDInput.h>
     18 #include <mcld/Support/Path.h>
     19 
     20 #include <string>
     21 
     22 
     23 namespace mcld {
     24 
     25 /** \class template<typename Traits, typename Iterator> PolicyIterator<mcld::Input>
     26  *  \brief PolicyIterator<mcld::Input> is a partially specific PolicyIterator
     27  */
     28 template<typename Traits, typename IteratorType>
     29 class PolicyIterator<mcld::Input, Traits, IteratorType> : public PolicyIteratorBase<Input, Traits, IteratorType>
     30 {
     31 public:
     32   typedef PolicyIterator<Input, Traits, IteratorType> Self;
     33   typedef PolicyIteratorBase<Input, Traits, IteratorType> Base;
     34   typedef PolicyIterator<Input, typename Traits::nonconst_traits, IteratorType> iterator;
     35   typedef PolicyIterator<Input, typename Traits::const_traits, IteratorType>    const_iterator;
     36 
     37 public:
     38   PolicyIterator()
     39     : Base() {}
     40 
     41   PolicyIterator(const iterator &X)
     42     : Base(X.m_pNode) {}
     43 
     44   explicit PolicyIterator(NodeBase* X)
     45     : Base(X) {}
     46 
     47   virtual ~PolicyIterator() {}
     48 
     49   bool isGroup() const
     50   { return !Base::hasData() && !Base::isRoot(); }
     51 
     52   Self& operator++() {
     53     IteratorType::advance();
     54     // skip the Group node
     55     while (isGroup())
     56       IteratorType::advance();
     57     return *this;
     58   }
     59 
     60   Self operator++(int) {
     61     Self tmp(*this);
     62     IteratorType::advance();
     63     // skip the Group node
     64     while (isGroup())
     65       IteratorType::advance();
     66     return tmp;
     67   }
     68 };
     69 
     70 /** \class InputTree
     71  *  \brief InputTree is the input tree to contains all inputs from the
     72  *  command line.
     73  *
     74  *  InputTree, of course, is uncopyable.
     75  *
     76  *  @see Input
     77  */
     78 class InputTree : public BinaryTree<Input>
     79 {
     80 private:
     81   typedef BinaryTree<Input> BinTreeTy;
     82 
     83 public:
     84   enum Direction {
     85     Inclusive  = TreeIteratorBase::Leftward,
     86     Positional = TreeIteratorBase::Rightward
     87   };
     88 
     89   typedef BinaryTree<Input>::iterator       iterator;
     90   typedef BinaryTree<Input>::const_iterator const_iterator;
     91 
     92 public:
     93   /** \class Mover
     94    *  \brief Mover provides the interface for moving iterator forward.
     95    *
     96    *  Mover is a function object (functor). @ref Mover::move moves
     97    *  iterator forward in certain direction. @ref Mover::connect
     98    *  connects two nodes of the given iterators togather.
     99    */
    100   struct Mover {
    101     virtual ~Mover() {}
    102     virtual void connect(TreeIteratorBase& pFrom, const TreeIteratorBase& pTo) const = 0;
    103     virtual void move(TreeIteratorBase& pNode) const = 0;
    104   };
    105 
    106   /** \class Succeeder
    107    *  \brief class Succeeder moves the iterator afterward.
    108    */
    109   struct Succeeder : public Mover {
    110     virtual void connect(TreeIteratorBase& pFrom, const TreeIteratorBase& pTo) const {
    111       proxy::hook<Positional>(pFrom.m_pNode, pTo.m_pNode);
    112     }
    113 
    114     virtual void move(TreeIteratorBase& pNode) const {
    115       pNode.move<Positional>();
    116     }
    117   };
    118 
    119   /** \class Includer
    120    *  \brief class Includer moves the iterator downward.
    121    */
    122   struct Includer : public Mover {
    123     virtual void connect(TreeIteratorBase& pFrom, const TreeIteratorBase& pTo) const {
    124       proxy::hook<Inclusive>(pFrom.m_pNode, pTo.m_pNode);
    125     }
    126 
    127     virtual void move(TreeIteratorBase& pNode) const {
    128       pNode.move<Inclusive>();
    129     }
    130   };
    131 
    132 public:
    133   static Succeeder Afterward;
    134   static Includer  Downward;
    135 
    136 public:
    137 
    138   using BinTreeTy::merge;
    139 
    140   // -----  modify  ----- //
    141   template<size_t DIRECT>
    142   InputTree& enterGroup(TreeIteratorBase pRoot);
    143 
    144   template<size_t DIRECT>
    145   InputTree& insert(TreeIteratorBase pRoot,
    146                     Input& pInput);
    147 
    148   InputTree& merge(TreeIteratorBase pRoot,
    149                    const Mover& pMover,
    150                    InputTree& pTree);
    151 
    152   InputTree& insert(TreeIteratorBase pRoot,
    153                     const Mover& pMover,
    154                     Input& pInput);
    155 
    156   InputTree& enterGroup(TreeIteratorBase pRoot,
    157                         const Mover& pMover);
    158 
    159 };
    160 
    161 bool isGroup(const InputTree::iterator& pos);
    162 bool isGroup(const InputTree::const_iterator& pos);
    163 bool isGroup(const InputTree::dfs_iterator& pos);
    164 bool isGroup(const InputTree::const_dfs_iterator& pos);
    165 bool isGroup(const InputTree::bfs_iterator& pos);
    166 bool isGroup(const InputTree::const_bfs_iterator& pos);
    167 
    168 } // namespace of mcld
    169 
    170 //===----------------------------------------------------------------------===//
    171 // template member functions
    172 //===----------------------------------------------------------------------===//
    173 template<size_t DIRECT>
    174 mcld::InputTree&
    175 mcld::InputTree::enterGroup(mcld::TreeIteratorBase pRoot)
    176 {
    177   BinTreeTy::node_type* node = createNode();
    178   if (pRoot.isRoot())
    179     proxy::hook<TreeIteratorBase::Leftward>(pRoot.m_pNode,
    180         const_cast<const node_type*>(node));
    181   else
    182     proxy::hook<DIRECT>(pRoot.m_pNode,
    183         const_cast<const node_type*>(node));
    184   return *this;
    185 }
    186 
    187 template<size_t DIRECT>
    188 mcld::InputTree& mcld::InputTree::insert(mcld::TreeIteratorBase pRoot,
    189 	                                 mcld::Input& pInput)
    190 {
    191   BinTreeTy::node_type* node = createNode();
    192   node->data = &pInput;
    193   if (pRoot.isRoot())
    194     proxy::hook<TreeIteratorBase::Leftward>(pRoot.m_pNode,
    195                                          const_cast<const node_type*>(node));
    196   else
    197     proxy::hook<DIRECT>(pRoot.m_pNode,
    198                         const_cast<const node_type*>(node));
    199   return *this;
    200 }
    201 
    202 #endif
    203 
    204