InputTree.h revision affc150dc44fab1911775a49636d0ce85333b634
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_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 24namespace mcld 25{ 26 27/** \class template<typename Traits, typename Iterator> PolicyIterator<mcld::Input> 28 * \brief PolicyIterator<mcld::Input> is a partially specific PolicyIterator 29 */ 30template<typename Traits, typename IteratorType> 31class PolicyIterator<mcld::Input, Traits, IteratorType> : public PolicyIteratorBase<Input, Traits, IteratorType> 32{ 33public: 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 39public: 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 */ 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(iterator& pFrom, const const_iterator& pTo) const = 0; 103 virtual void move(iterator& 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(iterator& pFrom, const const_iterator& pTo) const { 111 proxy::hook<Positional>(pFrom.m_pNode, pTo.m_pNode); 112 } 113 114 virtual void move(iterator& 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(iterator& pFrom, const const_iterator& pTo) const { 124 proxy::hook<Inclusive>(pFrom.m_pNode, pTo.m_pNode); 125 } 126 127 virtual void move(iterator& 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 InputTree(InputFactory& pInputFactory); 141 ~InputTree(); 142 143 // ----- modify ----- // 144 /// insert - create a leaf node and merge it in the tree. 145 // This version of join determines the direction at run time. 146 // @param pRoot position the parent node 147 // @param pMover the direction of the connecting edge of the parent node. 148 template<size_t DIRECT> 149 InputTree& insert(iterator pRoot, 150 const std::string& pNamespec, 151 const sys::fs::Path& pPath, 152 unsigned int pType = Input::Unknown); 153 154 template<size_t DIRECT> 155 InputTree& enterGroup(iterator pRoot); 156 157 template<size_t DIRECT> 158 InputTree& insert(iterator pRoot, 159 const Input& pInput); 160 161 InputTree& merge(iterator pRoot, 162 const Mover& pMover, 163 InputTree& pTree); 164 165 InputTree& insert(iterator pRoot, 166 const Mover& pMover, 167 const std::string& pNamespec, 168 const sys::fs::Path& pPath, 169 unsigned int pType = Input::Unknown); 170 171 InputTree& insert(iterator pRoot, 172 const Mover& pMover, 173 const Input& pInput); 174 175 InputTree& enterGroup(iterator pRoot, 176 const Mover& pMover); 177 178 // ----- observers ----- // 179 unsigned int numOfInputs() const 180 { return m_FileFactory.size(); } 181 182 bool hasInput() const 183 { return !m_FileFactory.empty(); } 184 185private: 186 InputFactory& m_FileFactory; 187 188}; 189 190bool isGroup(const InputTree::iterator& pos); 191bool isGroup(const InputTree::const_iterator& pos); 192bool isGroup(const InputTree::dfs_iterator& pos); 193bool isGroup(const InputTree::const_dfs_iterator& pos); 194bool isGroup(const InputTree::bfs_iterator& pos); 195bool isGroup(const InputTree::const_bfs_iterator& pos); 196 197} // namespace of mcld 198 199//===----------------------------------------------------------------------===// 200// template member functions 201template<size_t DIRECT> 202mcld::InputTree& 203mcld::InputTree::insert(mcld::InputTree::iterator pRoot, 204 const std::string& pNamespec, 205 const mcld::sys::fs::Path& pPath, 206 unsigned int pType) 207{ 208 BinTreeTy::node_type* node = createNode(); 209 node->data = m_FileFactory.produce(pNamespec, pPath, pType); 210 if (pRoot.isRoot()) 211 proxy::hook<TreeIteratorBase::Leftward>(pRoot.m_pNode, 212 const_cast<const node_type*>(node)); 213 else 214 proxy::hook<DIRECT>(pRoot.m_pNode, 215 const_cast<const node_type*>(node)); 216 return *this; 217} 218 219template<size_t DIRECT> 220mcld::InputTree& 221mcld::InputTree::enterGroup(mcld::InputTree::iterator pRoot) 222{ 223 BinTreeTy::node_type* node = createNode(); 224 if (pRoot.isRoot()) 225 proxy::hook<TreeIteratorBase::Leftward>(pRoot.m_pNode, 226 const_cast<const node_type*>(node)); 227 else 228 proxy::hook<DIRECT>(pRoot.m_pNode, 229 const_cast<const node_type*>(node)); 230 return *this; 231} 232 233template<size_t DIRECT> 234mcld::InputTree& mcld::InputTree::insert(mcld::InputTree::iterator pRoot, 235 const mcld::Input& pInput) 236{ 237 BinTreeTy::node_type* node = createNode(); 238 node->data = const_cast<mcld::Input*>(&pInput); 239 if (pRoot.isRoot()) 240 proxy::hook<TreeIteratorBase::Leftward>(pRoot.m_pNode, 241 const_cast<const node_type*>(node)); 242 else 243 proxy::hook<DIRECT>(pRoot.m_pNode, 244 const_cast<const node_type*>(node)); 245 return *this; 246} 247 248#endif 249 250