Home | History | Annotate | Download | only in MC
      1 //===- MCLDInputTree.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_INPUT_TREE_H
     10 #define MCLD_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/MC/InputFactory.h"
     19 #include "mcld/Support/FileSystem.h"
     20 
     21 #include <string>
     22 
     23 
     24 namespace mcld
     25 {
     26 
     27 /** \class template<typename Traits, typename Iterator> PolicyIterator<mcld::Input>
     28  *  \brief PolicyIterator<mcld::Input> is a partially specific PolicyIterator
     29  */
     30 template<typename Traits, typename IteratorType>
     31 class PolicyIterator<mcld::Input, Traits, IteratorType> : public PolicyIteratorBase<Input, Traits, IteratorType>
     32 {
     33 public:
     34   typedef PolicyIterator<Input, Traits, IteratorType> Self;
     35   typedef PolicyIteratorBase<Input, Traits, IteratorType> Base;
     36   typedef PolicyIterator<Input, typename Traits::nonconst_traits, IteratorType> iterator;
     37   typedef PolicyIterator<Input, typename Traits::const_traits, IteratorType>    const_iterator;
     38 
     39 public:
     40   PolicyIterator()
     41     : Base() {}
     42 
     43   PolicyIterator(const iterator &X)
     44     : Base(X.m_pNode) {}
     45 
     46   explicit PolicyIterator(NodeBase* X)
     47     : Base(X) {}
     48 
     49   virtual ~PolicyIterator() {}
     50 
     51   bool isGroup() const
     52   { return !Base::hasData(); }
     53 
     54   Self& operator++() {
     55     IteratorType::advance();
     56     if (isGroup())
     57       IteratorType::advance();
     58     return *this;
     59   }
     60 
     61   Self operator++(int) {
     62     Self tmp(*this);
     63     IteratorType::advance();
     64     if (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   struct Connector {
     94     virtual ~Connector() {}
     95     virtual void connect(iterator& pFrom, const const_iterator& pTo) const = 0;
     96     virtual void move(iterator& pNode) const = 0;
     97   };
     98 
     99   struct Succeeder : public Connector {
    100     virtual void connect(iterator& pFrom, const const_iterator& pTo) const {
    101       proxy::hook<Positional>(pFrom.m_pNode, pTo.m_pNode);
    102     }
    103 
    104     virtual void move(iterator& pNode) const {
    105       pNode.move<Positional>();
    106     }
    107   };
    108 
    109   struct Includer : public Connector {
    110     virtual void connect(iterator& pFrom, const const_iterator& pTo) const {
    111       proxy::hook<Inclusive>(pFrom.m_pNode, pTo.m_pNode);
    112     }
    113 
    114     virtual void move(iterator& pNode) const {
    115       pNode.move<Inclusive>();
    116     }
    117   };
    118 
    119 public:
    120   static Succeeder Afterward;
    121   static Includer  Downward;
    122 
    123 public:
    124 
    125   using BinTreeTy::merge;
    126 
    127   InputTree(InputFactory& pInputFactory);
    128   ~InputTree();
    129 
    130   // -----  modify  ----- //
    131   /// insert - create a leaf node and merge it in the tree.
    132   //  This version of join determines the direction at run time.
    133   //  @param position the parent node
    134   //  @param value the value being pushed.
    135   //  @param pConnector the direction of the connecting edge of the parent node.
    136   template<size_t DIRECT>
    137   InputTree& insert(iterator pPosition,
    138                     const std::string& pNamespec,
    139                     const sys::fs::Path& pPath,
    140                     unsigned int pType = Input::Unknown);
    141 
    142   template<size_t DIRECT>
    143   InputTree& enterGroup(iterator pPosition);
    144 
    145   template<size_t DIRECT>
    146   InputTree& insert(iterator pPosition,
    147                     const Input& pInput);
    148 
    149   InputTree& merge(iterator pPosition,
    150                    const Connector& pConnector,
    151                    InputTree& pTree);
    152 
    153   InputTree& insert(iterator pPosition,
    154                     const Connector& pConnector,
    155                     const std::string& pNamespec,
    156                     const sys::fs::Path& pPath,
    157                     unsigned int pType = Input::Unknown);
    158 
    159   InputTree& insert(iterator pPosition,
    160                     const Connector& pConnector,
    161                     const Input& pInput);
    162 
    163   InputTree& enterGroup(iterator pPosition,
    164                         const Connector& pConnector);
    165 
    166   // -----  observers  ----- //
    167   unsigned int numOfInputs() const
    168   { return m_FileFactory.size(); }
    169 
    170   bool hasInput() const
    171   { return !m_FileFactory.empty(); }
    172 
    173 private:
    174   InputFactory& m_FileFactory;
    175 
    176 };
    177 
    178 bool isGroup(const InputTree::iterator& pos);
    179 bool isGroup(const InputTree::const_iterator& pos);
    180 bool isGroup(const InputTree::dfs_iterator& pos);
    181 bool isGroup(const InputTree::const_dfs_iterator& pos);
    182 bool isGroup(const InputTree::bfs_iterator& pos);
    183 bool isGroup(const InputTree::const_bfs_iterator& pos);
    184 
    185 } // namespace of mcld
    186 
    187 //===----------------------------------------------------------------------===//
    188 // template member functions
    189 template<size_t DIRECT>
    190 mcld::InputTree&
    191 mcld::InputTree::insert(mcld::InputTree::iterator pPosition,
    192                         const std::string& pNamespec,
    193                         const mcld::sys::fs::Path& pPath,
    194                         unsigned int pType)
    195 {
    196   BinTreeTy::node_type* node = createNode();
    197   node->data = m_FileFactory.produce(pNamespec, pPath, pType);
    198   if (pPosition.isRoot())
    199     proxy::hook<TreeIteratorBase::Leftward>(pPosition.m_pNode,
    200         const_cast<const node_type*>(node));
    201   else
    202     proxy::hook<DIRECT>(pPosition.m_pNode,
    203         const_cast<const node_type*>(node));
    204   return *this;
    205 }
    206 
    207 template<size_t DIRECT>
    208 mcld::InputTree&
    209 mcld::InputTree::enterGroup(mcld::InputTree::iterator pPosition)
    210 {
    211   BinTreeTy::node_type* node = createNode();
    212   if (pPosition.isRoot())
    213     proxy::hook<TreeIteratorBase::Leftward>(pPosition.m_pNode,
    214         const_cast<const node_type*>(node));
    215   else
    216     proxy::hook<DIRECT>(pPosition.m_pNode,
    217         const_cast<const node_type*>(node));
    218   return *this;
    219 }
    220 
    221 template<size_t DIRECT>
    222 mcld::InputTree& mcld::InputTree::insert(mcld::InputTree::iterator pPosition,
    223 	                                 const mcld::Input& pInput)
    224 {
    225   BinTreeTy::node_type* node = createNode();
    226   node->data = const_cast<mcld::Input*>(&pInput);
    227   if (pPosition.isRoot())
    228     proxy::hook<TreeIteratorBase::Leftward>(pPosition.m_pNode,
    229                                          const_cast<const node_type*>(node));
    230   else
    231     proxy::hook<DIRECT>(pPosition.m_pNode,
    232                         const_cast<const node_type*>(node));
    233   return *this;
    234 }
    235 
    236 #endif
    237 
    238