1 /*=============================================================================
2 Copyright (c) 2001-2003 Joel de Guzman
3 http://spirit.sourceforge.net/
5 Use, modification and distribution is subject to the Boost Software
6 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7 http://www.boost.org/LICENSE_1_0.txt)
8 =============================================================================*/
9 #ifndef BOOST_SPIRIT_TST_IPP
10 #define BOOST_SPIRIT_TST_IPP
12 ///////////////////////////////////////////////////////////////////////////////
13 #include <boost/move/unique_ptr.hpp>
14 #include <boost/spirit/home/classic/core/assert.hpp>
16 ///////////////////////////////////////////////////////////////////////////////
17 namespace boost { namespace spirit {
19 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
24 ///////////////////////////////////////////////////////////////////////////////
28 // Ternary Search Tree implementation. The data structure is faster than
29 // hashing for many typical search problems especially when the search
30 // interface is iterator based. Searching for a string of length k in a
31 // ternary search tree with n strings will require at most O(log n+k)
32 // character comparisons. TSTs are many times faster than hash tables
33 // for unsuccessful searches since mismatches are discovered earlier
34 // after examining only a few characters. Hash tables always examine an
35 // entire key when searching.
37 // For details see http://www.cs.princeton.edu/~rs/strings/.
39 // *** This is a low level class and is
40 // not meant for public consumption ***
42 ///////////////////////////////////////////////////////////////////////////////
43 template <typename T, typename CharT>
46 tst_node(CharT value_)
65 boost::movelib::unique_ptr<tst_node> copy(new tst_node(value));
68 copy->left = left->clone();
70 copy->right = right->clone();
72 if (value && middle.link)
74 copy->middle.link = middle.link->clone();
78 boost::movelib::unique_ptr<T> mid_data(new T(*middle.data));
79 copy->middle.data = mid_data.release();
82 return copy.release();
97 ///////////////////////////////////////////////////////////////////////////
98 template <typename T, typename CharT>
112 tst(tst const& other)
113 : root(other.root ? other.root->clone() : 0) {}
119 operator=(tst const& other)
123 node_t* new_root = other.root ? other.root->clone() : 0;
130 template <typename IteratorT>
131 T* add(IteratorT first, IteratorT const& last, T const& data)
139 BOOST_SPIRIT_ASSERT((first == last || ch != 0)
140 && "Won't add string containing null character");
144 if (*np == 0 || ch == 0)
149 *np = new node_t(ch);
151 (**np).right = right;
154 if (ch < (**np).value)
160 if (ch == (**np).value)
164 if ((**np).middle.data == 0)
166 (**np).middle.data = new T(data);
167 return (**np).middle.data;
171 // re-addition is disallowed
176 ch = (first == last) ? CharT(0) : *first;
177 BOOST_SPIRIT_ASSERT((first == last || ch != 0)
178 && "Won't add string containing null character");
179 np = &(**np).middle.link;
189 template <typename ScannerT>
190 search_info find(ScannerT const& scan) const
192 search_info result = { 0, 0 };
197 typedef typename ScannerT::iterator_t iterator_t;
200 iterator_t save = scan.first;
201 iterator_t latest = scan.first;
202 std::size_t latest_len = 0;
207 if (ch < np->value) // => go left!
211 result.data = np->middle.data;
215 latest_len = result.length;
221 else if (ch == np->value) // => go middle!
223 // Matching the null character is not allowed.
226 result.data = np->middle.data;
230 latest_len = result.length;
236 ch = scan.at_end() ? CharT(0) : *scan;
237 np = np->middle.link;
240 else // (ch > np->value) => go right!
244 result.data = np->middle.data;
248 latest_len = result.length;
256 if (result.data == 0)
263 result.length = latest_len;
270 typedef tst_node<T, CharT> node_t;
274 ///////////////////////////////////////////////////////////////////////////////
277 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
279 }} // namespace boost::spirit