InputTree.h revision 22add6ff3426df1a85089fe6a6e1597ee3b6f300
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 23namespace mcld { 24 25/** \class template<typename Traits, typename Iterator> PolicyIterator<mcld::Input> 26 * \brief PolicyIterator<mcld::Input> is a partially specific PolicyIterator 27 */ 28template<typename Traits, typename IteratorType> 29class PolicyIterator<mcld::Input, Traits, IteratorType> : public PolicyIteratorBase<Input, Traits, IteratorType> 30{ 31public: 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 37public: 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 */ 78class InputTree : public BinaryTree<Input> 79{ 80private: 81 typedef BinaryTree<Input> BinTreeTy; 82 83public: 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 92public: 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 132public: 133 static Succeeder Afterward; 134 static Includer Downward; 135 136public: 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 161bool isGroup(const InputTree::iterator& pos); 162bool isGroup(const InputTree::const_iterator& pos); 163bool isGroup(const InputTree::dfs_iterator& pos); 164bool isGroup(const InputTree::const_dfs_iterator& pos); 165bool isGroup(const InputTree::bfs_iterator& pos); 166bool isGroup(const InputTree::const_bfs_iterator& pos); 167 168} // namespace of mcld 169 170//===----------------------------------------------------------------------===// 171// template member functions 172//===----------------------------------------------------------------------===// 173template<size_t DIRECT> 174mcld::InputTree& 175mcld::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 187template<size_t DIRECT> 188mcld::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