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