• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
PolicyIterator()40   PolicyIterator()
41     : Base() {}
42 
PolicyIterator(const iterator & X)43   PolicyIterator(const iterator &X)
44     : Base(X.m_pNode) {}
45 
PolicyIterator(NodeBase * X)46   explicit PolicyIterator(NodeBase* X)
47     : Base(X) {}
48 
~PolicyIterator()49   virtual ~PolicyIterator() {}
50 
isGroup()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 {
~ConnectorConnector94     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 {
connectSucceeder100     virtual void connect(iterator& pFrom, const const_iterator& pTo) const {
101       proxy::hook<Positional>(pFrom.m_pNode, pTo.m_pNode);
102     }
103 
moveSucceeder104     virtual void move(iterator& pNode) const {
105       pNode.move<Positional>();
106     }
107   };
108 
109   struct Includer : public Connector {
connectIncluder110     virtual void connect(iterator& pFrom, const const_iterator& pTo) const {
111       proxy::hook<Inclusive>(pFrom.m_pNode, pTo.m_pNode);
112     }
113 
moveIncluder114     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  ----- //
numOfInputs()167   unsigned int numOfInputs() const
168   { return m_FileFactory.size(); }
169 
hasInput()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&
insert(mcld::InputTree::iterator pPosition,const std::string & pNamespec,const mcld::sys::fs::Path & pPath,unsigned int pType)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&
enterGroup(mcld::InputTree::iterator pPosition)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>
insert(mcld::InputTree::iterator pPosition,const mcld::Input & pInput)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