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 template<> 71 class BinaryTree<Input> : public BinaryTreeBase<Input> 72 { 73 public: 74 typedef size_t size_type; 75 typedef ptrdiff_t difference_type; 76 typedef Input value_type; 77 typedef value_type* pointer; 78 typedef value_type& reference; 79 typedef const value_type* const_pointer; 80 typedef const value_type& const_reference; 81 82 typedef BinaryTree<Input> Self; 83 typedef TreeIterator<value_type, NonConstTraits<value_type> > iterator; 84 typedef TreeIterator<value_type, ConstTraits<value_type> > const_iterator; 85 86 typedef PolicyIterator<value_type, NonConstTraits<value_type>, DFSIterator> dfs_iterator; 87 typedef PolicyIterator<value_type, ConstTraits<value_type>, DFSIterator> const_dfs_iterator; 88 typedef PolicyIterator<value_type, NonConstTraits<value_type>, BFSIterator> bfs_iterator; 89 typedef PolicyIterator<value_type, ConstTraits<value_type>, BFSIterator> const_bfs_iterator; 90 91 protected: 92 typedef Node<value_type> node_type; 93 94 public: 95 // ----- constructors and destructor ----- // 96 BinaryTree() 97 : BinaryTreeBase<Input>() 98 { } 99 100 ~BinaryTree() { 101 } 102 103 // ----- iterators ----- // 104 bfs_iterator bfs_begin() 105 { 106 bfs_iterator it = bfs_iterator(BinaryTreeBase<Input>::m_Root.node.left); 107 if (it.isGroup()) 108 ++it; 109 return it; 110 } 111 112 bfs_iterator bfs_end() 113 { return bfs_iterator(BinaryTreeBase<Input>::m_Root.node.right); } 114 115 const_bfs_iterator bfs_begin() const 116 { 117 const_bfs_iterator it = 118 const_bfs_iterator(BinaryTreeBase<Input>::m_Root.node.left); 119 if (it.isGroup()) 120 ++it; 121 return it; 122 } 123 124 const_bfs_iterator bfs_end() const 125 { return const_bfs_iterator(BinaryTreeBase<Input>::m_Root.node.right); } 126 127 dfs_iterator dfs_begin() 128 { 129 dfs_iterator it = dfs_iterator(BinaryTreeBase<Input>::m_Root.node.left); 130 if (it.isGroup()) 131 ++it; 132 return it; 133 } 134 135 dfs_iterator dfs_end() 136 { return dfs_iterator(BinaryTreeBase<Input>::m_Root.node.right); } 137 138 const_dfs_iterator dfs_begin() const 139 { 140 const_dfs_iterator it = 141 const_dfs_iterator(BinaryTreeBase<Input>::m_Root.node.left); 142 if (it.isGroup()) 143 ++it; 144 return it; 145 } 146 147 const_dfs_iterator dfs_end() const 148 { return const_dfs_iterator(BinaryTreeBase<Input>::m_Root.node.right); } 149 150 iterator root() 151 { return iterator(&(BinaryTreeBase<Input>::m_Root.node)); } 152 153 const_iterator root() const 154 { 155 // FIXME: provide the iterater constructors for constant NodeBase instead of 156 // using const_cast 157 return const_iterator( 158 const_cast<NodeBase*>(&BinaryTreeBase<Input>::m_Root.node)); 159 } 160 161 iterator begin() 162 { 163 iterator it = iterator(BinaryTreeBase<Input>::m_Root.node.left); 164 return it; 165 } 166 167 iterator end() 168 { return iterator(BinaryTreeBase<Input>::m_Root.node.right); } 169 170 const_iterator begin() const 171 { 172 const_iterator it = const_iterator(BinaryTreeBase<Input>::m_Root.node.left); 173 return it; 174 } 175 176 const_iterator end() const 177 { return const_iterator(BinaryTreeBase<Input>::m_Root.node.right); } 178 179 // ----- modifiers ----- // 180 /// join - create a leaf node and merge it in the tree. 181 // This version of join determines the direction on compilation time. 182 // @param DIRECT the direction of the connecting edge of the parent node. 183 // @param position the parent node 184 // @param value the value being pushed. 185 template<size_t DIRECT, class Pos> 186 BinaryTree& join(Pos position, const Input& value) { 187 node_type *node = BinaryTreeBase<Input>::createNode(); 188 node->data = const_cast<Input*>(&value); 189 if (position.isRoot()) 190 proxy::hook<TreeIteratorBase::Leftward>(position.m_pNode, 191 const_cast<const node_type*>(node)); 192 else 193 proxy::hook<DIRECT>(position.m_pNode, 194 const_cast<const node_type*>(node)); 195 return *this; 196 } 197 198 /// merge - merge the tree 199 // @param DIRECT the direction of the connecting edge of the parent node. 200 // @param position the parent node 201 // @param the tree being joined. 202 // @return the joined tree 203 template<size_t DIRECT, class Pos> 204 BinaryTree& merge(Pos position, BinaryTree& pTree) { 205 if (this == &pTree) 206 return *this; 207 208 if (!pTree.empty()) { 209 proxy::hook<DIRECT>(position.m_pNode, 210 const_cast<const NodeBase*>(pTree.m_Root.node.left)); 211 BinaryTreeBase<Input>::m_Root.summon( 212 pTree.BinaryTreeBase<Input>::m_Root); 213 BinaryTreeBase<Input>::m_Root.delegate(pTree.m_Root); 214 pTree.m_Root.node.left = pTree.m_Root.node.right = &pTree.m_Root.node; 215 } 216 return *this; 217 } 218 }; 219 220 /** \class InputTree 221 * \brief InputTree is the input tree to contains all inputs from the 222 * command line. 223 * 224 * InputTree, of course, is uncopyable. 225 * 226 * @see Input 227 */ 228 class InputTree : public BinaryTree<Input> 229 { 230 private: 231 typedef BinaryTree<Input> BinTreeTy; 232 233 public: 234 enum Direction { 235 Inclusive = TreeIteratorBase::Leftward, 236 Positional = TreeIteratorBase::Rightward 237 }; 238 239 typedef BinaryTree<Input>::iterator iterator; 240 typedef BinaryTree<Input>::const_iterator const_iterator; 241 242 public: 243 /** \class Mover 244 * \brief Mover provides the interface for moving iterator forward. 245 * 246 * Mover is a function object (functor). @ref Mover::move moves 247 * iterator forward in certain direction. @ref Mover::connect 248 * connects two nodes of the given iterators togather. 249 */ 250 struct Mover { 251 virtual ~Mover() {} 252 virtual void connect(TreeIteratorBase& pFrom, const TreeIteratorBase& pTo) const = 0; 253 virtual void move(TreeIteratorBase& pNode) const = 0; 254 }; 255 256 /** \class Succeeder 257 * \brief class Succeeder moves the iterator afterward. 258 */ 259 struct Succeeder : public Mover { 260 virtual void connect(TreeIteratorBase& pFrom, const TreeIteratorBase& pTo) const { 261 proxy::hook<Positional>(pFrom.m_pNode, pTo.m_pNode); 262 } 263 264 virtual void move(TreeIteratorBase& pNode) const { 265 pNode.move<Positional>(); 266 } 267 }; 268 269 /** \class Includer 270 * \brief class Includer moves the iterator downward. 271 */ 272 struct Includer : public Mover { 273 virtual void connect(TreeIteratorBase& pFrom, const TreeIteratorBase& pTo) const { 274 proxy::hook<Inclusive>(pFrom.m_pNode, pTo.m_pNode); 275 } 276 277 virtual void move(TreeIteratorBase& pNode) const { 278 pNode.move<Inclusive>(); 279 } 280 }; 281 282 public: 283 static Succeeder Afterward; 284 static Includer Downward; 285 286 public: 287 288 using BinTreeTy::merge; 289 290 // ----- modify ----- // 291 template<size_t DIRECT> 292 InputTree& enterGroup(TreeIteratorBase pRoot); 293 294 template<size_t DIRECT> 295 InputTree& insert(TreeIteratorBase pRoot, 296 Input& pInput); 297 298 InputTree& merge(TreeIteratorBase pRoot, 299 const Mover& pMover, 300 InputTree& pTree); 301 302 InputTree& insert(TreeIteratorBase pRoot, 303 const Mover& pMover, 304 Input& pInput); 305 306 InputTree& enterGroup(TreeIteratorBase pRoot, 307 const Mover& pMover); 308 309 }; 310 311 bool isGroup(const InputTree::iterator& pos); 312 bool isGroup(const InputTree::const_iterator& pos); 313 bool isGroup(const InputTree::dfs_iterator& pos); 314 bool isGroup(const InputTree::const_dfs_iterator& pos); 315 bool isGroup(const InputTree::bfs_iterator& pos); 316 bool isGroup(const InputTree::const_bfs_iterator& pos); 317 318 } // namespace of mcld 319 320 //===----------------------------------------------------------------------===// 321 // template member functions 322 //===----------------------------------------------------------------------===// 323 template<size_t DIRECT> 324 mcld::InputTree& 325 mcld::InputTree::enterGroup(mcld::TreeIteratorBase pRoot) 326 { 327 BinTreeTy::node_type* node = createNode(); 328 if (pRoot.isRoot()) 329 proxy::hook<TreeIteratorBase::Leftward>(pRoot.m_pNode, 330 const_cast<const node_type*>(node)); 331 else 332 proxy::hook<DIRECT>(pRoot.m_pNode, 333 const_cast<const node_type*>(node)); 334 return *this; 335 } 336 337 template<size_t DIRECT> 338 mcld::InputTree& mcld::InputTree::insert(mcld::TreeIteratorBase pRoot, 339 mcld::Input& pInput) 340 { 341 BinTreeTy::node_type* node = createNode(); 342 node->data = &pInput; 343 if (pRoot.isRoot()) 344 proxy::hook<TreeIteratorBase::Leftward>(pRoot.m_pNode, 345 const_cast<const node_type*>(node)); 346 else 347 proxy::hook<DIRECT>(pRoot.m_pNode, 348 const_cast<const node_type*>(node)); 349 return *this; 350 } 351 352 #endif 353 354