You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
327 lines
9.3 KiB
327 lines
9.3 KiB
//===- 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 <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 {
|
|
return const_iterator(BinaryTreeBase<Input>::m_Root.node.left);
|
|
}
|
|
|
|
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>
|
|
BinaryTree& join(TreeIteratorBase& pPosition, const Input& value) {
|
|
node_type* node = BinaryTreeBase<Input>::createNode();
|
|
node->data = const_cast<Input*>(&value);
|
|
|
|
if (pPosition.isRoot())
|
|
pPosition.hook<TreeIteratorBase::Leftward>(node);
|
|
else
|
|
pPosition.hook<DIRECT>(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>
|
|
BinaryTree& merge(TreeIteratorBase& pPosition, BinaryTree& pTree) {
|
|
if (this == &pTree)
|
|
return *this;
|
|
|
|
if (!pTree.empty()) {
|
|
pPosition.hook<DIRECT>(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 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<Positional>(pTo);
|
|
}
|
|
|
|
void move(TreeIteratorBase& pNode) const { pNode.move<Positional>(); }
|
|
};
|
|
|
|
/** \class Includer
|
|
* \brief class Includer moves the iterator downward.
|
|
*/
|
|
struct Includer : public Mover {
|
|
void connect(TreeIteratorBase& pFrom, NodeBase* pTo) const {
|
|
pFrom.hook<Inclusive>(pTo);
|
|
}
|
|
|
|
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 mcld
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// template member functions
|
|
//===----------------------------------------------------------------------===//
|
|
template <size_t DIRECT>
|
|
mcld::InputTree& mcld::InputTree::enterGroup(mcld::TreeIteratorBase pRoot) {
|
|
BinTreeTy::node_type* node = createNode();
|
|
|
|
if (pRoot.isRoot())
|
|
pRoot.hook<TreeIteratorBase::Leftward>(node);
|
|
else
|
|
pRoot.hook<DIRECT>(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())
|
|
pRoot.hook<TreeIteratorBase::Leftward>(node);
|
|
else
|
|
pRoot.hook<DIRECT>(node);
|
|
|
|
return *this;
|
|
}
|
|
|
|
#endif // MCLD_INPUTTREE_H_
|