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