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