//===- InputTree.h --------------------------------------------------------===// // // The MCLinker Project // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef MCLD_INPUTTREE_H_ #define MCLD_INPUTTREE_H_ #include "mcld/ADT/BinTree.h" #include "mcld/ADT/TypeTraits.h" #include "mcld/MC/Input.h" #include "mcld/Support/Path.h" #include namespace mcld { /** \class template * PolicyIterator * \brief PolicyIterator is a partially specific PolicyIterator */ template class PolicyIterator : public PolicyIteratorBase { public: typedef PolicyIterator Self; typedef PolicyIteratorBase Base; typedef PolicyIterator iterator; typedef PolicyIterator const_iterator; public: PolicyIterator() : Base() {} PolicyIterator(const iterator& X) : Base(X.m_pNode) {} explicit PolicyIterator(NodeBase* X) : Base(X) {} virtual ~PolicyIterator() {} bool isGroup() const { return !Base::hasData() && !Base::isRoot(); } Self& operator++() { IteratorType::advance(); // skip the Group node while (isGroup()) IteratorType::advance(); return *this; } Self operator++(int) { Self tmp(*this); IteratorType::advance(); // skip the Group node while (isGroup()) IteratorType::advance(); return tmp; } }; template <> class BinaryTree : public BinaryTreeBase { public: typedef size_t size_type; typedef ptrdiff_t difference_type; typedef Input value_type; typedef value_type* pointer; typedef value_type& reference; typedef const value_type* const_pointer; typedef const value_type& const_reference; typedef BinaryTree Self; typedef TreeIterator > iterator; typedef TreeIterator > const_iterator; typedef PolicyIterator, DFSIterator> dfs_iterator; typedef PolicyIterator, DFSIterator> const_dfs_iterator; typedef PolicyIterator, BFSIterator> bfs_iterator; typedef PolicyIterator, BFSIterator> const_bfs_iterator; protected: typedef Node node_type; public: // ----- constructors and destructor ----- // BinaryTree() : BinaryTreeBase() {} ~BinaryTree() {} // ----- iterators ----- // bfs_iterator bfs_begin() { bfs_iterator it = bfs_iterator(BinaryTreeBase::m_Root.node.left); if (it.isGroup()) ++it; return it; } bfs_iterator bfs_end() { return bfs_iterator(BinaryTreeBase::m_Root.node.right); } const_bfs_iterator bfs_begin() const { const_bfs_iterator it = const_bfs_iterator(BinaryTreeBase::m_Root.node.left); if (it.isGroup()) ++it; return it; } const_bfs_iterator bfs_end() const { return const_bfs_iterator(BinaryTreeBase::m_Root.node.right); } dfs_iterator dfs_begin() { dfs_iterator it = dfs_iterator(BinaryTreeBase::m_Root.node.left); if (it.isGroup()) ++it; return it; } dfs_iterator dfs_end() { return dfs_iterator(BinaryTreeBase::m_Root.node.right); } const_dfs_iterator dfs_begin() const { const_dfs_iterator it = const_dfs_iterator(BinaryTreeBase::m_Root.node.left); if (it.isGroup()) ++it; return it; } const_dfs_iterator dfs_end() const { return const_dfs_iterator(BinaryTreeBase::m_Root.node.right); } iterator root() { return iterator(&(BinaryTreeBase::m_Root.node)); } const_iterator root() const { // FIXME: provide the iterater constructors for constant NodeBase instead of // using const_cast return const_iterator( const_cast(&BinaryTreeBase::m_Root.node)); } iterator begin() { iterator it = iterator(BinaryTreeBase::m_Root.node.left); return it; } iterator end() { return iterator(BinaryTreeBase::m_Root.node.right); } const_iterator begin() const { return const_iterator(BinaryTreeBase::m_Root.node.left); } const_iterator end() const { return const_iterator(BinaryTreeBase::m_Root.node.right); } // ----- modifiers ----- // /// join - create a leaf node and merge it in the tree. // This version of join determines the direction on compilation time. // @param DIRECT the direction of the connecting edge of the parent node. // @param position the parent node // @param value the value being pushed. template BinaryTree& join(TreeIteratorBase& pPosition, const Input& value) { node_type* node = BinaryTreeBase::createNode(); node->data = const_cast(&value); if (pPosition.isRoot()) pPosition.hook(node); else pPosition.hook(node); return *this; } /// merge - merge the tree // @param DIRECT the direction of the connecting edge of the parent node. // @param position the parent node // @param the tree being joined. // @return the joined tree template BinaryTree& merge(TreeIteratorBase& pPosition, BinaryTree& pTree) { if (this == &pTree) return *this; if (!pTree.empty()) { pPosition.hook(pTree.m_Root.node.left); BinaryTreeBase::m_Root.summon(pTree.BinaryTreeBase::m_Root); BinaryTreeBase::m_Root.delegate(pTree.m_Root); pTree.m_Root.node.left = pTree.m_Root.node.right = &pTree.m_Root.node; } return *this; } }; /** \class InputTree * \brief InputTree is the input tree to contains all inputs from the * command line. * * InputTree, of course, is uncopyable. * * @see Input */ class InputTree : public BinaryTree { private: typedef BinaryTree BinTreeTy; public: enum Direction { Inclusive = TreeIteratorBase::Leftward, Positional = TreeIteratorBase::Rightward }; typedef BinaryTree::iterator iterator; typedef BinaryTree::const_iterator const_iterator; public: /** \class Mover * \brief Mover provides the interface for moving iterator forward. * * Mover is a function object (functor). @ref Mover::move moves * iterator forward in certain direction. @ref Mover::connect * connects two nodes of the given iterators togather. */ struct Mover { virtual void connect(TreeIteratorBase& pFrom, NodeBase* pTo) const = 0; virtual void move(TreeIteratorBase& pNode) const = 0; virtual ~Mover() {} }; /** \class Succeeder * \brief class Succeeder moves the iterator afterward. */ struct Succeeder : public Mover { void connect(TreeIteratorBase& pFrom, NodeBase* pTo) const { pFrom.hook(pTo); } void move(TreeIteratorBase& pNode) const { pNode.move(); } }; /** \class Includer * \brief class Includer moves the iterator downward. */ struct Includer : public Mover { void connect(TreeIteratorBase& pFrom, NodeBase* pTo) const { pFrom.hook(pTo); } void move(TreeIteratorBase& pNode) const { pNode.move(); } }; public: static Succeeder Afterward; static Includer Downward; public: using BinTreeTy::merge; // ----- modify ----- // template InputTree& enterGroup(TreeIteratorBase pRoot); template InputTree& insert(TreeIteratorBase pRoot, Input& pInput); InputTree& merge(TreeIteratorBase pRoot, const Mover& pMover, InputTree& pTree); InputTree& insert(TreeIteratorBase pRoot, const Mover& pMover, Input& pInput); InputTree& enterGroup(TreeIteratorBase pRoot, const Mover& pMover); }; bool isGroup(const InputTree::iterator& pos); bool isGroup(const InputTree::const_iterator& pos); bool isGroup(const InputTree::dfs_iterator& pos); bool isGroup(const InputTree::const_dfs_iterator& pos); bool isGroup(const InputTree::bfs_iterator& pos); bool isGroup(const InputTree::const_bfs_iterator& pos); } // namespace mcld //===----------------------------------------------------------------------===// // template member functions //===----------------------------------------------------------------------===// template mcld::InputTree& mcld::InputTree::enterGroup(mcld::TreeIteratorBase pRoot) { BinTreeTy::node_type* node = createNode(); if (pRoot.isRoot()) pRoot.hook(node); else pRoot.hook(node); return *this; } template mcld::InputTree& mcld::InputTree::insert(mcld::TreeIteratorBase pRoot, mcld::Input& pInput) { BinTreeTy::node_type* node = createNode(); node->data = &pInput; if (pRoot.isRoot()) pRoot.hook(node); else pRoot.hook(node); return *this; } #endif // MCLD_INPUTTREE_H_