//===- InputTree.h --------------------------------------------------------===// // // The MCLinker Project // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef MCLD_MC_INPUT_TREE_H #define MCLD_MC_INPUT_TREE_H #ifdef ENABLE_UNITTEST #include <gtest.h> #endif #include <mcld/ADT/BinTree.h> #include <mcld/ADT/TypeTraits.h> #include <mcld/MC/MCLDInput.h> #include <mcld/Support/Path.h> #include <string> namespace mcld { /** \class template<typename Traits, typename Iterator> PolicyIterator<mcld::Input> * \brief PolicyIterator<mcld::Input> is a partially specific PolicyIterator */ template<typename Traits, typename IteratorType> class PolicyIterator<mcld::Input, Traits, IteratorType> : public PolicyIteratorBase<Input, Traits, IteratorType> { public: typedef PolicyIterator<Input, Traits, IteratorType> Self; typedef PolicyIteratorBase<Input, Traits, IteratorType> Base; typedef PolicyIterator<Input, typename Traits::nonconst_traits, IteratorType> iterator; typedef PolicyIterator<Input, typename Traits::const_traits, IteratorType> 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<Input> : public BinaryTreeBase<Input> { 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<Input> Self; typedef TreeIterator<value_type, NonConstTraits<value_type> > iterator; typedef TreeIterator<value_type, ConstTraits<value_type> > const_iterator; typedef PolicyIterator<value_type, NonConstTraits<value_type>, DFSIterator> dfs_iterator; typedef PolicyIterator<value_type, ConstTraits<value_type>, DFSIterator> const_dfs_iterator; typedef PolicyIterator<value_type, NonConstTraits<value_type>, BFSIterator> bfs_iterator; typedef PolicyIterator<value_type, ConstTraits<value_type>, BFSIterator> const_bfs_iterator; protected: typedef Node<value_type> node_type; public: // ----- constructors and destructor ----- // BinaryTree() : BinaryTreeBase<Input>() { } ~BinaryTree() { } // ----- iterators ----- // bfs_iterator bfs_begin() { bfs_iterator it = bfs_iterator(BinaryTreeBase<Input>::m_Root.node.left); if (it.isGroup()) ++it; return it; } bfs_iterator bfs_end() { return bfs_iterator(BinaryTreeBase<Input>::m_Root.node.right); } const_bfs_iterator bfs_begin() const { const_bfs_iterator it = const_bfs_iterator(BinaryTreeBase<Input>::m_Root.node.left); if (it.isGroup()) ++it; return it; } const_bfs_iterator bfs_end() const { return const_bfs_iterator(BinaryTreeBase<Input>::m_Root.node.right); } dfs_iterator dfs_begin() { dfs_iterator it = dfs_iterator(BinaryTreeBase<Input>::m_Root.node.left); if (it.isGroup()) ++it; return it; } dfs_iterator dfs_end() { return dfs_iterator(BinaryTreeBase<Input>::m_Root.node.right); } const_dfs_iterator dfs_begin() const { const_dfs_iterator it = const_dfs_iterator(BinaryTreeBase<Input>::m_Root.node.left); if (it.isGroup()) ++it; return it; } const_dfs_iterator dfs_end() const { return const_dfs_iterator(BinaryTreeBase<Input>::m_Root.node.right); } iterator root() { return iterator(&(BinaryTreeBase<Input>::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<NodeBase*>(&BinaryTreeBase<Input>::m_Root.node)); } iterator begin() { iterator it = iterator(BinaryTreeBase<Input>::m_Root.node.left); return it; } iterator end() { return iterator(BinaryTreeBase<Input>::m_Root.node.right); } const_iterator begin() const { const_iterator it = const_iterator(BinaryTreeBase<Input>::m_Root.node.left); return it; } const_iterator end() const { return const_iterator(BinaryTreeBase<Input>::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<size_t DIRECT, class Pos> BinaryTree& join(Pos position, const Input& value) { node_type *node = BinaryTreeBase<Input>::createNode(); node->data = const_cast<Input*>(&value); if (position.isRoot()) proxy::hook<TreeIteratorBase::Leftward>(position.m_pNode, const_cast<const node_type*>(node)); else proxy::hook<DIRECT>(position.m_pNode, const_cast<const node_type*>(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<size_t DIRECT, class Pos> BinaryTree& merge(Pos position, BinaryTree& pTree) { if (this == &pTree) return *this; if (!pTree.empty()) { proxy::hook<DIRECT>(position.m_pNode, const_cast<const NodeBase*>(pTree.m_Root.node.left)); BinaryTreeBase<Input>::m_Root.summon( pTree.BinaryTreeBase<Input>::m_Root); BinaryTreeBase<Input>::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<Input> { private: typedef BinaryTree<Input> BinTreeTy; public: enum Direction { Inclusive = TreeIteratorBase::Leftward, Positional = TreeIteratorBase::Rightward }; typedef BinaryTree<Input>::iterator iterator; typedef BinaryTree<Input>::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 ~Mover() {} virtual void connect(TreeIteratorBase& pFrom, const TreeIteratorBase& pTo) const = 0; virtual void move(TreeIteratorBase& pNode) const = 0; }; /** \class Succeeder * \brief class Succeeder moves the iterator afterward. */ struct Succeeder : public Mover { virtual void connect(TreeIteratorBase& pFrom, const TreeIteratorBase& pTo) const { proxy::hook<Positional>(pFrom.m_pNode, pTo.m_pNode); } virtual void move(TreeIteratorBase& pNode) const { pNode.move<Positional>(); } }; /** \class Includer * \brief class Includer moves the iterator downward. */ struct Includer : public Mover { virtual void connect(TreeIteratorBase& pFrom, const TreeIteratorBase& pTo) const { proxy::hook<Inclusive>(pFrom.m_pNode, pTo.m_pNode); } virtual void move(TreeIteratorBase& pNode) const { pNode.move<Inclusive>(); } }; public: static Succeeder Afterward; static Includer Downward; public: using BinTreeTy::merge; // ----- modify ----- // template<size_t DIRECT> InputTree& enterGroup(TreeIteratorBase pRoot); template<size_t DIRECT> 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 of mcld //===----------------------------------------------------------------------===// // template member functions //===----------------------------------------------------------------------===// template<size_t DIRECT> mcld::InputTree& mcld::InputTree::enterGroup(mcld::TreeIteratorBase pRoot) { BinTreeTy::node_type* node = createNode(); if (pRoot.isRoot()) proxy::hook<TreeIteratorBase::Leftward>(pRoot.m_pNode, const_cast<const node_type*>(node)); else proxy::hook<DIRECT>(pRoot.m_pNode, const_cast<const node_type*>(node)); return *this; } template<size_t DIRECT> mcld::InputTree& mcld::InputTree::insert(mcld::TreeIteratorBase pRoot, mcld::Input& pInput) { BinTreeTy::node_type* node = createNode(); node->data = &pInput; if (pRoot.isRoot()) proxy::hook<TreeIteratorBase::Leftward>(pRoot.m_pNode, const_cast<const node_type*>(node)); else proxy::hook<DIRECT>(pRoot.m_pNode, const_cast<const node_type*>(node)); return *this; } #endif