diff options
author | Shih-wei Liao <sliao@google.com> | 2012-12-15 17:21:00 -0800 |
---|---|---|
committer | Shih-wei Liao <sliao@google.com> | 2012-12-15 17:21:00 -0800 |
commit | 22add6ff3426df1a85089fe6a6e1597ee3b6f300 (patch) | |
tree | c58763780e7b965179d9cdce45f1fc5a5268932d /include/mcld/InputTree.h | |
parent | c842fe71ef087c982cc03d0ea73eeaf455d932d3 (diff) | |
download | mclinker-22add6ff3426df1a85089fe6a6e1597ee3b6f300.tar.gz |
MCLinker upstream commit 0459e386785c.
Change-Id: Ide6790f5a354b7fcc03d812d6c8cf43b1e309ba3
Diffstat (limited to 'include/mcld/InputTree.h')
-rw-r--r-- | include/mcld/InputTree.h | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/include/mcld/InputTree.h b/include/mcld/InputTree.h new file mode 100644 index 0000000..2981ebe --- /dev/null +++ b/include/mcld/InputTree.h @@ -0,0 +1,203 @@ +//===- 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; + } +}; + +/** \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 + |