Mercurial > hg > vamp-build-and-test
diff DEPENDENCIES/generic/include/boost/xpressive/detail/utility/symbols.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children | c530137014c0 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DEPENDENCIES/generic/include/boost/xpressive/detail/utility/symbols.hpp Tue Aug 05 11:11:38 2014 +0100 @@ -0,0 +1,284 @@ +/////////////////////////////////////////////////////////////////////////////// +/// \file symbols.hpp +/// Contains the Ternary Search Trie implementation. +/// Based on the following papers: +/// J. Bentley and R. Sedgewick. (1998) Ternary search trees. Dr. Dobbs Journal +/// G. Badr and B.J. Oommen. (2005) Self-Adjusting of Ternary Search Tries Using +/// Conditional Rotations and Randomized Heuristics +// +// Copyright 2007 David Jenkins. +// Copyright 2007 Eric Niebler. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_XPRESSIVE_DETAIL_SYMBOLS_HPP_DRJ_06_11_2007 +#define BOOST_XPRESSIVE_DETAIL_SYMBOLS_HPP_DRJ_06_11_2007 + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include <boost/noncopyable.hpp> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/value_type.hpp> +#include <boost/range/const_iterator.hpp> +#include <boost/shared_ptr.hpp> + +namespace boost { namespace xpressive { namespace detail +{ + + /////////////////////////////////////////////////////////////////////////////// + // symbols (using a ternary search trie) + // + template<typename Map> + struct symbols + { + typedef typename range_value<Map>::type::first_type key_type; + typedef typename range_value<Map>::type::second_type value_type; + typedef typename range_value<key_type>::type char_type; + typedef typename range_const_iterator<Map>::type iterator; + typedef typename range_const_iterator<key_type>::type key_iterator; + typedef value_type const *result_type; + + // copies of this symbol table share the TST + + template<typename Trans> + void load(Map const &map, Trans trans) + { + iterator begin = boost::begin(map); + iterator end = boost::end(map); + node* root_p = this->root.get(); + for(; begin != end; ++begin) + { + key_iterator kbegin = boost::begin(begin->first); + key_iterator kend = boost::end(begin->first); + root_p = this->insert(root_p, kbegin, kend, &begin->second, trans); + } + this->root.reset(root_p); + } + + template<typename BidiIter, typename Trans> + result_type operator ()(BidiIter &begin, BidiIter end, Trans trans) const + { + return this->search(begin, end, trans, this->root.get()); + } + + template<typename Sink> + void peek(Sink const &sink) const + { + this->peek_(this->root.get(), sink); + } + + private: + /////////////////////////////////////////////////////////////////////////////// + // struct node : a node in the TST. + // The "eq" field stores the result pointer when ch is zero. + // + struct node + : boost::noncopyable + { + node(char_type c) + : ch(c) + , lo(0) + , eq(0) + , hi(0) + #ifdef BOOST_DISABLE_THREADS + , tau(0) + #endif + {} + + ~node() + { + delete lo; + if (ch) + delete eq; + delete hi; + } + + void swap(node& that) + { + std::swap(ch, that.ch); + std::swap(lo, that.lo); + std::swap(eq, that.eq); + std::swap(hi, that.hi); + #ifdef BOOST_DISABLE_THREADS + std::swap(tau, that.tau); + #endif + } + + char_type ch; + node* lo; + union + { + node* eq; + result_type result; + }; + node* hi; + #ifdef BOOST_DISABLE_THREADS + long tau; + #endif + }; + + /////////////////////////////////////////////////////////////////////////////// + // insert : insert a string into the TST + // + template<typename Trans> + node* insert(node* p, key_iterator &begin, key_iterator end, result_type r, Trans trans) const + { + char_type c1 = 0; + + if(begin != end) + { + c1 = trans(*begin); + } + + if(!p) + { + p = new node(c1); + } + + if(c1 < p->ch) + { + p->lo = this->insert(p->lo, begin, end, r, trans); + } + else if(c1 == p->ch) + { + if(0 == c1) + { + p->result = r; + } + else + { + p->eq = this->insert(p->eq, ++begin, end, r, trans); + } + } + else + { + p->hi = this->insert(p->hi, begin, end, r, trans); + } + + return p; + } + + #ifdef BOOST_DISABLE_THREADS + /////////////////////////////////////////////////////////////////////////////// + // conditional rotation : the goal is to minimize the overall + // weighted path length of each binary search tree + // + bool cond_rotation(bool left, node* const i, node* const j) const + { + // don't rotate top node in binary search tree + if (i == j) + return false; + // calculate psi (the rotation condition) + node* const k = (left ? i->hi : i->lo); + long psi = 2*i->tau - j->tau - (k ? k->tau : 0); + if (psi <= 0) + return false; + + // recalculate the tau values + j->tau += -i->tau + (k ? k->tau : 0); + i->tau += j->tau - (k ? k->tau : 0); + // fixup links and swap nodes + if (left) + { + j->lo = k; + i->hi = i; + } + else + { + j->hi = k; + i->lo = i; + } + (*i).swap(*j); + return true; + } + #endif + + /////////////////////////////////////////////////////////////////////////////// + // search : find a string in the TST + // + template<typename BidiIter, typename Trans> + result_type search(BidiIter &begin, BidiIter end, Trans trans, node* p) const + { + result_type r = 0; + #ifdef BOOST_DISABLE_THREADS + node* p2 = p; + bool left = false; + #endif + char_type c1 = (begin != end ? trans(*begin) : 0); + while(p) + { + #ifdef BOOST_DISABLE_THREADS + ++p->tau; + #endif + if(c1 == p->ch) + { + // conditional rotation test + #ifdef BOOST_DISABLE_THREADS + if (this->cond_rotation(left, p, p2)) + p = p2; + #endif + if (0 == p->ch) + { + // it's a match! + r = p->result; + } + if(begin == end) + break; + ++begin; + p = p->eq; + // search for the longest match first + r = search(begin,end,trans,p); + if (0 == r) + { + // search for a match ending here + r = search(end,end,trans,p); + if (0 == r) + { + --begin; + } + } + break; + } + else if(c1 < p->ch) + { + #ifdef BOOST_DISABLE_THREADS + left = true; + p2 = p; + #endif + p = p->lo; + } + else // (c1 > p->ch) + { + #ifdef BOOST_DISABLE_THREADS + left = false; + p2 = p; + #endif + p = p->hi; + } + } + return r; + } + + template<typename Sink> + void peek_(node const *const &p, Sink const &sink) const + { + if(p) + { + sink(p->ch); + this->peek_(p->lo, sink); + this->peek_(p->hi, sink); + } + } + + boost::shared_ptr<node> root; + }; + +}}} // namespace boost::xpressive::detail + +#endif