| //===- InputTree.h --------------------------------------------------------===// |
| // |
| // The MCLinker Project |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| #ifndef MCLD_INPUT_TREE_H |
| #define MCLD_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/MC/InputFactory.h" |
| #include "mcld/Support/FileSystem.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(); } |
| |
| Self& operator++() { |
| IteratorType::advance(); |
| if (isGroup()) |
| IteratorType::advance(); |
| return *this; |
| } |
| |
| Self operator++(int) { |
| Self tmp(*this); |
| IteratorType::advance(); |
| if (isGroup()) |
| IteratorType::advance(); |
| return tmp; |
| } |
| }; |
| |
| /** \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; |
| |
| InputTree(InputFactory& pInputFactory); |
| ~InputTree(); |
| |
| // ----- modify ----- // |
| /// insert - create a leaf node and merge it in the tree. |
| // This version of join determines the direction at run time. |
| // @param pRoot position the parent node |
| // @param pMover the direction of the connecting edge of the parent node. |
| template<size_t DIRECT> |
| InputTree& insert(TreeIteratorBase pRoot, |
| const std::string& pNamespec, |
| const sys::fs::Path& pPath, |
| unsigned int pType = Input::Unknown); |
| |
| template<size_t DIRECT> |
| InputTree& enterGroup(TreeIteratorBase pRoot); |
| |
| template<size_t DIRECT> |
| InputTree& insert(TreeIteratorBase pRoot, |
| const Input& pInput); |
| |
| InputTree& merge(TreeIteratorBase pRoot, |
| const Mover& pMover, |
| InputTree& pTree); |
| |
| InputTree& insert(TreeIteratorBase pRoot, |
| const Mover& pMover, |
| const std::string& pNamespec, |
| const sys::fs::Path& pPath, |
| unsigned int pType = Input::Unknown); |
| |
| InputTree& insert(TreeIteratorBase pRoot, |
| const Mover& pMover, |
| const Input& pInput); |
| |
| InputTree& enterGroup(TreeIteratorBase pRoot, |
| const Mover& pMover); |
| |
| // ----- observers ----- // |
| unsigned int numOfInputs() const |
| { return m_FileFactory.size(); } |
| |
| bool hasInput() const |
| { return !m_FileFactory.empty(); } |
| |
| private: |
| InputFactory& m_FileFactory; |
| |
| }; |
| |
| 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::insert(mcld::TreeIteratorBase pRoot, |
| const std::string& pNamespec, |
| const mcld::sys::fs::Path& pPath, |
| unsigned int pType) |
| { |
| BinTreeTy::node_type* node = createNode(); |
| node->data = m_FileFactory.produce(pNamespec, pPath, pType); |
| 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::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, |
| const mcld::Input& pInput) |
| { |
| BinTreeTy::node_type* node = createNode(); |
| node->data = const_cast<mcld::Input*>(&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 |
| |