Chris@16
|
1 /*=============================================================================
|
Chris@16
|
2 Copyright (c) 2001-2011 Joel de Guzman
|
Chris@16
|
3 Copyright (c) 2001-2011 Hartmut Kaiser
|
Chris@16
|
4 Copyright (c) 2010-2011 Bryce Lelbach
|
Chris@16
|
5
|
Chris@16
|
6 Distributed under the Boost Software License, Version 1.0. (See accompanying
|
Chris@16
|
7 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
8 =============================================================================*/
|
Chris@16
|
9 #if !defined(BOOST_SPIRIT_UTREE)
|
Chris@16
|
10 #define BOOST_SPIRIT_UTREE
|
Chris@16
|
11
|
Chris@16
|
12 #include <cstddef>
|
Chris@16
|
13 #include <algorithm>
|
Chris@16
|
14 #include <string>
|
Chris@16
|
15 #include <iostream>
|
Chris@16
|
16 #include <ios>
|
Chris@16
|
17 #include <sstream>
|
Chris@16
|
18 #include <typeinfo>
|
Chris@16
|
19
|
Chris@16
|
20 #include <boost/io/ios_state.hpp>
|
Chris@16
|
21 #include <boost/integer.hpp>
|
Chris@16
|
22 #include <boost/throw_exception.hpp>
|
Chris@16
|
23 #include <boost/assert.hpp>
|
Chris@16
|
24 #include <boost/noncopyable.hpp>
|
Chris@16
|
25 #include <boost/iterator/iterator_facade.hpp>
|
Chris@16
|
26 #include <boost/range/iterator_range.hpp>
|
Chris@16
|
27 #include <boost/type_traits/remove_pointer.hpp>
|
Chris@16
|
28 #include <boost/type_traits/is_polymorphic.hpp>
|
Chris@16
|
29 #include <boost/utility/enable_if.hpp>
|
Chris@16
|
30 #include <boost/utility/result_of.hpp>
|
Chris@16
|
31 #include <boost/ref.hpp>
|
Chris@16
|
32
|
Chris@16
|
33 #include <boost/spirit/home/support/utree/detail/utree_detail1.hpp>
|
Chris@16
|
34
|
Chris@16
|
35 #if defined(BOOST_MSVC)
|
Chris@16
|
36 # pragma warning(push)
|
Chris@16
|
37 # pragma warning(disable: 4804)
|
Chris@16
|
38 # pragma warning(disable: 4805)
|
Chris@16
|
39 # pragma warning(disable: 4244)
|
Chris@16
|
40 #endif
|
Chris@16
|
41
|
Chris@16
|
42 namespace boost { namespace spirit
|
Chris@16
|
43 {
|
Chris@16
|
44 //[utree_exceptions
|
Chris@16
|
45 /*` All exceptions thrown by utree are derived from utree_exception. */
|
Chris@16
|
46 struct utree_exception : std::exception {};
|
Chris@16
|
47
|
Chris@16
|
48 /*`The `bad_type_exception` is thrown whenever somebody calls a member
|
Chris@16
|
49 function, which applies to certain stored utree_type's only, but this
|
Chris@16
|
50 precondition is violated as the `utree` instance holds some other type.
|
Chris@16
|
51 */
|
Chris@16
|
52 struct bad_type_exception /*: utree_exception*/;
|
Chris@16
|
53
|
Chris@16
|
54 /*`The `empty_exception` is thrown whenever a precondition of a list
|
Chris@16
|
55 or range utree method is violated due to the list or range being empty.
|
Chris@16
|
56 */
|
Chris@16
|
57 struct empty_exception /*: utree_exception*/;
|
Chris@16
|
58 //]
|
Chris@16
|
59
|
Chris@16
|
60 //[utree_types
|
Chris@16
|
61 /*`Each instance of an `utree` data structure can store exactly one of the
|
Chris@16
|
62 following data types at a time:
|
Chris@16
|
63 */
|
Chris@16
|
64 struct utree_type
|
Chris@16
|
65 {
|
Chris@16
|
66 enum info
|
Chris@16
|
67 {
|
Chris@16
|
68 invalid_type, // the utree has not been initialized (it's
|
Chris@16
|
69 // default constructed)
|
Chris@16
|
70 nil_type, // nil is the sentinel (empty) utree type.
|
Chris@16
|
71 list_type, // A doubly linked list of utrees.
|
Chris@16
|
72 range_type, // A range of list::iterators.
|
Chris@16
|
73 reference_type, // A reference to another utree.
|
Chris@16
|
74 any_type, // A pointer or reference to any C++ type.
|
Chris@16
|
75 function_type, // A utree holding a stored_function<F> object,
|
Chris@16
|
76 // where F is an unary function object taking a
|
Chris@16
|
77 // utree as it's parameter and returning a
|
Chris@16
|
78 // utree.
|
Chris@16
|
79
|
Chris@16
|
80 // numeric atoms
|
Chris@16
|
81 bool_type, // An utree holding a boolean value
|
Chris@16
|
82 int_type, // An utree holding a integer (int) value
|
Chris@16
|
83 double_type, // An utree holding a floating point (double) value
|
Chris@16
|
84
|
Chris@16
|
85 // text atoms (utf8)
|
Chris@16
|
86 string_type, // An UTF-8 string
|
Chris@16
|
87 string_range_type, // A pair of iterators into an UTF-8 string
|
Chris@16
|
88 symbol_type, // An UTF-8 symbol name
|
Chris@16
|
89
|
Chris@16
|
90 binary_type // Arbitrary binary data
|
Chris@16
|
91 };
|
Chris@16
|
92 typedef boost::uint_t<sizeof(info)*8>::exact exact_integral_type;
|
Chris@16
|
93 typedef boost::uint_t<sizeof(info)*8>::fast fast_integral_type;
|
Chris@16
|
94 };
|
Chris@16
|
95 //]
|
Chris@16
|
96
|
Chris@16
|
97 // streaming operator for utree types - essential for diagnostics
|
Chris@16
|
98 inline std::ostream& operator<<(std::ostream& out, utree_type::info t)
|
Chris@16
|
99 {
|
Chris@16
|
100 boost::io::ios_all_saver saver(out);
|
Chris@16
|
101 switch (t) {
|
Chris@16
|
102 case utree_type::invalid_type: { out << "invalid"; break; }
|
Chris@16
|
103 case utree_type::nil_type: { out << "nil"; break; }
|
Chris@16
|
104 case utree_type::list_type: { out << "list"; break; }
|
Chris@16
|
105 case utree_type::range_type: { out << "range"; break; }
|
Chris@16
|
106 case utree_type::reference_type: { out << "reference"; break; }
|
Chris@16
|
107 case utree_type::any_type: { out << "any"; break; }
|
Chris@16
|
108 case utree_type::function_type: { out << "function"; break; }
|
Chris@16
|
109 case utree_type::bool_type: { out << "bool"; break; }
|
Chris@16
|
110 case utree_type::int_type: { out << "int"; break; }
|
Chris@16
|
111 case utree_type::double_type: { out << "double"; break; }
|
Chris@16
|
112 case utree_type::string_type: { out << "string"; break; }
|
Chris@16
|
113 case utree_type::string_range_type: { out << "string_range"; break; }
|
Chris@16
|
114 case utree_type::symbol_type: { out << "symbol"; break; }
|
Chris@16
|
115 case utree_type::binary_type: { out << "binary"; break; }
|
Chris@16
|
116 default: { out << "unknown"; break; }
|
Chris@16
|
117 }
|
Chris@16
|
118 out << std::hex << "[0x"
|
Chris@16
|
119 << static_cast<utree_type::fast_integral_type>(t) << "]";
|
Chris@16
|
120 return out;
|
Chris@16
|
121 }
|
Chris@16
|
122
|
Chris@16
|
123 struct bad_type_exception : utree_exception
|
Chris@16
|
124 {
|
Chris@16
|
125 std::string msg;
|
Chris@16
|
126
|
Chris@16
|
127 bad_type_exception(char const* error, utree_type::info got)
|
Chris@16
|
128 : msg()
|
Chris@16
|
129 {
|
Chris@16
|
130 std::ostringstream oss;
|
Chris@16
|
131 oss << "utree: " << error
|
Chris@16
|
132 << " (got utree type '" << got << "')";
|
Chris@16
|
133 msg = oss.str();
|
Chris@16
|
134 }
|
Chris@16
|
135
|
Chris@16
|
136 bad_type_exception(char const* error, utree_type::info got1,
|
Chris@16
|
137 utree_type::info got2)
|
Chris@16
|
138 : msg()
|
Chris@16
|
139 {
|
Chris@16
|
140 std::ostringstream oss;
|
Chris@16
|
141 oss << "utree: " << error
|
Chris@16
|
142 << " (got utree types '" << got1 << "' and '" << got2 << "')";
|
Chris@16
|
143 msg = oss.str();
|
Chris@16
|
144 }
|
Chris@16
|
145
|
Chris@16
|
146 virtual ~bad_type_exception() throw() {}
|
Chris@16
|
147
|
Chris@16
|
148 virtual char const* what() const throw()
|
Chris@16
|
149 { return msg.c_str(); }
|
Chris@16
|
150 };
|
Chris@16
|
151
|
Chris@16
|
152 struct empty_exception : utree_exception
|
Chris@16
|
153 {
|
Chris@16
|
154 char const* msg;
|
Chris@16
|
155
|
Chris@16
|
156 empty_exception(char const* error) : msg(error) {}
|
Chris@16
|
157
|
Chris@16
|
158 virtual ~empty_exception() throw() {}
|
Chris@16
|
159
|
Chris@16
|
160 virtual char const* what() const throw()
|
Chris@16
|
161 { return msg; }
|
Chris@16
|
162 };
|
Chris@16
|
163
|
Chris@16
|
164 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
165 // A typed string with parametric Base storage. The storage can be any
|
Chris@16
|
166 // range or (stl container) of chars.
|
Chris@16
|
167 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
168 template <typename Base, utree_type::info type_>
|
Chris@16
|
169 struct basic_string : Base
|
Chris@16
|
170 {
|
Chris@16
|
171 static utree_type::info const type = type_;
|
Chris@16
|
172
|
Chris@16
|
173 basic_string()
|
Chris@16
|
174 : Base() {}
|
Chris@16
|
175
|
Chris@16
|
176 basic_string(Base const& base)
|
Chris@16
|
177 : Base(base) {}
|
Chris@16
|
178
|
Chris@16
|
179 template <typename Iterator>
|
Chris@16
|
180 basic_string(Iterator bits, std::size_t len)
|
Chris@16
|
181 : Base(bits, bits + len) {}
|
Chris@16
|
182
|
Chris@16
|
183 template <typename Iterator>
|
Chris@16
|
184 basic_string(Iterator first, Iterator last)
|
Chris@16
|
185 : Base(first, last) {}
|
Chris@16
|
186
|
Chris@16
|
187 basic_string& operator=(basic_string const& other)
|
Chris@16
|
188 {
|
Chris@16
|
189 Base::operator=(other);
|
Chris@16
|
190 return *this;
|
Chris@16
|
191 }
|
Chris@16
|
192
|
Chris@16
|
193 basic_string& operator=(Base const& other)
|
Chris@16
|
194 {
|
Chris@16
|
195 Base::operator=(other);
|
Chris@16
|
196 return *this;
|
Chris@16
|
197 }
|
Chris@16
|
198 };
|
Chris@16
|
199
|
Chris@16
|
200 //[utree_strings
|
Chris@16
|
201 /*`The `utree` string types described below are used by the `utree` API
|
Chris@16
|
202 only. These are not used to store information in the `utree` itself.
|
Chris@16
|
203 Their purpose is to refer to different internal `utree` node types
|
Chris@16
|
204 only. For instance, creating a `utree` from a binary data type will
|
Chris@16
|
205 create a `binary_type` utree node (see above).
|
Chris@16
|
206 */
|
Chris@16
|
207 /*`The binary data type can be represented either verbatim as a sequence
|
Chris@16
|
208 of bytes or as a pair of iterators into some other stored binary data
|
Chris@16
|
209 sequence. Use this string type to access/create a `binary_type` `utree`.
|
Chris@16
|
210 */
|
Chris@16
|
211 typedef basic_string<
|
Chris@16
|
212 boost::iterator_range<char const*>, utree_type::binary_type
|
Chris@16
|
213 > binary_range_type;
|
Chris@16
|
214 typedef basic_string<
|
Chris@16
|
215 std::string, utree_type::binary_type
|
Chris@16
|
216 > binary_string_type;
|
Chris@16
|
217
|
Chris@16
|
218 /*`The UTF-8 string can be represented either verbatim as a sequence of
|
Chris@16
|
219 characters or as a pair of iterators into some other stored binary data
|
Chris@16
|
220 sequence. Use this string type to access/create a `string_type` `utree`.
|
Chris@16
|
221 */
|
Chris@16
|
222 typedef basic_string<
|
Chris@16
|
223 boost::iterator_range<char const*>, utree_type::string_type
|
Chris@16
|
224 > utf8_string_range_type;
|
Chris@16
|
225 typedef basic_string<
|
Chris@16
|
226 std::string, utree_type::string_type
|
Chris@16
|
227 > utf8_string_type;
|
Chris@16
|
228
|
Chris@16
|
229 /*`The UTF-8 symbol can be represented either verbatim as a sequence of
|
Chris@16
|
230 characters or as a pair of iterators into some other stored binary data
|
Chris@16
|
231 sequence. Use this string type to access/create a `symbol_type` `utree`.
|
Chris@16
|
232 */
|
Chris@16
|
233 typedef basic_string<
|
Chris@16
|
234 boost::iterator_range<char const*>, utree_type::symbol_type
|
Chris@16
|
235 > utf8_symbol_range_type;
|
Chris@16
|
236 typedef basic_string<
|
Chris@16
|
237 std::string, utree_type::symbol_type
|
Chris@16
|
238 > utf8_symbol_type;
|
Chris@16
|
239 //]
|
Chris@16
|
240
|
Chris@16
|
241 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
242 // Our function type
|
Chris@16
|
243 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
244 class utree;
|
Chris@16
|
245
|
Chris@16
|
246 //[utree_function_object_interface
|
Chris@16
|
247 struct function_base
|
Chris@16
|
248 {
|
Chris@16
|
249 virtual ~function_base() {}
|
Chris@16
|
250 virtual utree operator()(utree const& env) const = 0;
|
Chris@16
|
251 virtual utree operator()(utree& env) const = 0;
|
Chris@16
|
252
|
Chris@16
|
253 // Calling f.clone() must return a newly allocated function_base
|
Chris@16
|
254 // instance that is equal to f.
|
Chris@16
|
255 virtual function_base* clone() const = 0;
|
Chris@16
|
256 };
|
Chris@16
|
257
|
Chris@16
|
258 template <typename F>
|
Chris@16
|
259 struct stored_function : function_base
|
Chris@16
|
260 {
|
Chris@16
|
261 F f;
|
Chris@16
|
262 stored_function(F f = F());
|
Chris@16
|
263 virtual ~stored_function();
|
Chris@16
|
264 virtual utree operator()(utree const& env) const;
|
Chris@16
|
265 virtual utree operator()(utree& env) const;
|
Chris@16
|
266 virtual function_base* clone() const;
|
Chris@16
|
267 };
|
Chris@16
|
268
|
Chris@16
|
269 template <typename F>
|
Chris@16
|
270 struct referenced_function : function_base
|
Chris@16
|
271 {
|
Chris@16
|
272 F& f;
|
Chris@16
|
273 referenced_function(F& f);
|
Chris@16
|
274 virtual ~referenced_function();
|
Chris@16
|
275 virtual utree operator()(utree const& env) const;
|
Chris@16
|
276 virtual utree operator()(utree& env) const;
|
Chris@16
|
277 virtual function_base* clone() const;
|
Chris@16
|
278 };
|
Chris@16
|
279 //]
|
Chris@16
|
280
|
Chris@16
|
281 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
282 // Shallow tag. Instructs utree to hold an iterator_range
|
Chris@16
|
283 // as-is without deep copying the range.
|
Chris@16
|
284 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
285 struct shallow_tag {};
|
Chris@16
|
286 shallow_tag const shallow = {};
|
Chris@16
|
287
|
Chris@16
|
288 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
289 // A void* plus type_info
|
Chris@16
|
290 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
291 class any_ptr
|
Chris@16
|
292 {
|
Chris@16
|
293 public:
|
Chris@16
|
294 template <typename Ptr>
|
Chris@16
|
295 typename boost::disable_if<
|
Chris@16
|
296 boost::is_polymorphic<
|
Chris@16
|
297 typename boost::remove_pointer<Ptr>::type>,
|
Chris@16
|
298 Ptr>::type
|
Chris@16
|
299 get() const
|
Chris@16
|
300 {
|
Chris@16
|
301 if (*i == typeid(Ptr))
|
Chris@16
|
302 {
|
Chris@16
|
303 return static_cast<Ptr>(p);
|
Chris@16
|
304 }
|
Chris@16
|
305 boost::throw_exception(std::bad_cast());
|
Chris@16
|
306 }
|
Chris@16
|
307
|
Chris@16
|
308 template <typename T>
|
Chris@16
|
309 any_ptr(T* p)
|
Chris@16
|
310 : p(p), i(&typeid(T*))
|
Chris@16
|
311 {}
|
Chris@16
|
312
|
Chris@16
|
313 friend bool operator==(any_ptr const& a, any_ptr const& b)
|
Chris@16
|
314 {
|
Chris@16
|
315 return (a.p == b.p) && (*a.i == *b.i);
|
Chris@16
|
316 }
|
Chris@16
|
317
|
Chris@16
|
318 private:
|
Chris@16
|
319 // constructor is private
|
Chris@16
|
320 any_ptr(void* p, std::type_info const* i)
|
Chris@16
|
321 : p(p), i(i) {}
|
Chris@16
|
322
|
Chris@16
|
323 template <typename UTreeX, typename UTreeY>
|
Chris@16
|
324 friend struct detail::visit_impl;
|
Chris@16
|
325
|
Chris@16
|
326 friend class utree;
|
Chris@16
|
327
|
Chris@16
|
328 void* p;
|
Chris@16
|
329 std::type_info const* i;
|
Chris@16
|
330 };
|
Chris@16
|
331
|
Chris@16
|
332 //[utree
|
Chris@16
|
333 class utree {
|
Chris@16
|
334 public:
|
Chris@16
|
335 ///////////////////////////////////////////////////////////////////////
|
Chris@16
|
336 // The invalid type
|
Chris@16
|
337 struct invalid_type {};
|
Chris@16
|
338
|
Chris@16
|
339 ///////////////////////////////////////////////////////////////////////
|
Chris@16
|
340 // The nil type
|
Chris@16
|
341 struct nil_type {};
|
Chris@16
|
342
|
Chris@16
|
343 ///////////////////////////////////////////////////////////////////////
|
Chris@16
|
344 // The list type, this can be used to initialize an utree to hold an
|
Chris@16
|
345 // empty list
|
Chris@16
|
346 struct list_type;
|
Chris@16
|
347
|
Chris@16
|
348 //[utree_container_types
|
Chris@16
|
349 typedef utree value_type;
|
Chris@16
|
350 typedef utree& reference;
|
Chris@16
|
351 typedef utree const& const_reference;
|
Chris@16
|
352 typedef std::ptrdiff_t difference_type;
|
Chris@16
|
353 typedef std::size_t size_type;
|
Chris@16
|
354
|
Chris@16
|
355 typedef detail::list::node_iterator<utree> iterator;
|
Chris@16
|
356 typedef detail::list::node_iterator<utree const> const_iterator;
|
Chris@16
|
357 //]
|
Chris@16
|
358
|
Chris@16
|
359 typedef detail::list::node_iterator<boost::reference_wrapper<utree> >
|
Chris@16
|
360 ref_iterator;
|
Chris@16
|
361
|
Chris@16
|
362 typedef boost::iterator_range<iterator> range;
|
Chris@16
|
363 typedef boost::iterator_range<const_iterator> const_range;
|
Chris@16
|
364
|
Chris@16
|
365 // dtor
|
Chris@16
|
366 ~utree();
|
Chris@16
|
367
|
Chris@16
|
368 ////////////////////////////////////////////////////////////////////////
|
Chris@16
|
369 //[utree_initialization
|
Chris@16
|
370 /*`A `utree` can be constructed or initialized from a wide range of
|
Chris@16
|
371 data types, allowing to create `utree` instances for every
|
Chris@16
|
372 possible node type (see the description of `utree_type::info` above).
|
Chris@16
|
373 For this reason it exposes a constructor and an assignment operator
|
Chris@16
|
374 for each of the allowed node types as shown below. All constructors
|
Chris@16
|
375 are non-explicit on purpose, allowing to use an utree instance as
|
Chris@16
|
376 the attribute to almost any Qi parser.
|
Chris@16
|
377 */
|
Chris@16
|
378 // This constructs an `invalid_type` node. When used in places
|
Chris@16
|
379 // where a boost::optional is expected (i.e. as an attribute for the
|
Chris@16
|
380 // optional component), this represents the 'empty' state.
|
Chris@16
|
381 utree(invalid_type = invalid_type());
|
Chris@16
|
382
|
Chris@16
|
383 // This initializes a `nil_type` node, which represents a valid,
|
Chris@16
|
384 // 'initialized empty' utree (different from invalid_type!).
|
Chris@16
|
385 utree(nil_type);
|
Chris@16
|
386 reference operator=(nil_type);
|
Chris@16
|
387
|
Chris@16
|
388 // This initializes a `boolean_type` node, which can hold 'true' or
|
Chris@16
|
389 // 'false' only.
|
Chris@16
|
390 explicit utree(bool);
|
Chris@16
|
391 reference operator=(bool);
|
Chris@16
|
392
|
Chris@16
|
393 // This initializes an `integer_type` node, which can hold arbitrary
|
Chris@16
|
394 // integers. For convenience these functions are overloaded for signed
|
Chris@16
|
395 // and unsigned integer types.
|
Chris@16
|
396 utree(unsigned int);
|
Chris@16
|
397 utree(int);
|
Chris@16
|
398 reference operator=(unsigned int);
|
Chris@16
|
399 reference operator=(int);
|
Chris@16
|
400
|
Chris@16
|
401 // This initializes a `double_type` node, which can hold arbitrary
|
Chris@16
|
402 // floating point (double) values.
|
Chris@16
|
403 utree(double);
|
Chris@16
|
404 reference operator=(double);
|
Chris@16
|
405
|
Chris@16
|
406 // This initializes a `string_type` node, which can hold a narrow
|
Chris@16
|
407 // character sequence (usually an UTF-8 string).
|
Chris@16
|
408 utree(char);
|
Chris@16
|
409 utree(char const*);
|
Chris@16
|
410 utree(char const*, std::size_t);
|
Chris@16
|
411 utree(std::string const&);
|
Chris@16
|
412 reference operator=(char);
|
Chris@16
|
413 reference operator=(char const*);
|
Chris@16
|
414 reference operator=(std::string const&);
|
Chris@16
|
415
|
Chris@16
|
416 // This constructs a `string_range_type` node, which does not copy the
|
Chris@16
|
417 // data but stores the iterator range to the character sequence the
|
Chris@16
|
418 // range has been initialized from.
|
Chris@16
|
419 utree(utf8_string_range_type const&, shallow_tag);
|
Chris@16
|
420
|
Chris@16
|
421 // This initializes a `reference_type` node, which holds a reference to
|
Chris@16
|
422 // another utree node. All operations on such a node are automatically
|
Chris@16
|
423 // forwarded to the referenced utree instance.
|
Chris@16
|
424 utree(boost::reference_wrapper<utree>);
|
Chris@16
|
425 reference operator=(boost::reference_wrapper<utree>);
|
Chris@16
|
426
|
Chris@16
|
427 // This initializes an `any_type` node, which can hold a pointer to an
|
Chris@16
|
428 // instance of any type together with the typeid of that type. When
|
Chris@16
|
429 // accessing that pointer the typeid will be checked, causing a
|
Chris@16
|
430 // std::bad_cast to be thrown if the typeids do not match.
|
Chris@16
|
431 utree(any_ptr const&);
|
Chris@16
|
432 reference operator=(any_ptr const&);
|
Chris@16
|
433
|
Chris@16
|
434 // This initializes a `range_type` node, which holds an utree list node
|
Chris@16
|
435 // the elements of which are copy constructed (assigned) from the
|
Chris@16
|
436 // elements referenced by the given range of iterators.
|
Chris@16
|
437 template <class Iterator>
|
Chris@16
|
438 utree(boost::iterator_range<Iterator>);
|
Chris@16
|
439 template <class Iterator>
|
Chris@16
|
440 reference operator=(boost::iterator_range<Iterator>);
|
Chris@16
|
441
|
Chris@16
|
442 // This initializes a `function_type` node from a polymorphic function
|
Chris@16
|
443 // object pointer (takes ownership) or reference.
|
Chris@16
|
444 utree(function_base const&);
|
Chris@16
|
445 reference operator=(function_base const&);
|
Chris@16
|
446 utree(function_base*);
|
Chris@16
|
447 reference operator=(function_base*);
|
Chris@16
|
448
|
Chris@16
|
449 // This initializes either a `string_type`, a `symbol_type`, or a
|
Chris@16
|
450 // `binary_type` node (depending on the template parameter `type_`),
|
Chris@16
|
451 // which will hold the corresponding narrow character sequence (usually
|
Chris@16
|
452 // an UTF-8 string).
|
Chris@16
|
453 template <class Base, utree_type::info type_>
|
Chris@16
|
454 utree(basic_string<Base, type_> const&);
|
Chris@16
|
455 template <class Base, utree_type::info type_>
|
Chris@16
|
456 reference operator=(basic_string<Base, type_> const&);
|
Chris@16
|
457 //]
|
Chris@16
|
458
|
Chris@16
|
459 // copy
|
Chris@16
|
460 utree(const_reference);
|
Chris@16
|
461 reference operator=(const_reference);
|
Chris@16
|
462
|
Chris@16
|
463 // range
|
Chris@16
|
464 utree(range, shallow_tag);
|
Chris@16
|
465 utree(const_range, shallow_tag);
|
Chris@16
|
466
|
Chris@16
|
467 // assign dispatch
|
Chris@16
|
468 template <class Iterator>
|
Chris@16
|
469 void assign(Iterator, Iterator);
|
Chris@16
|
470
|
Chris@16
|
471 ////////////////////////////////////////////////////////////////////////
|
Chris@16
|
472
|
Chris@16
|
473 ////////////////////////////////////////////////////////////////////////
|
Chris@16
|
474 // function object visitation interface
|
Chris@16
|
475
|
Chris@16
|
476 // single dispatch
|
Chris@16
|
477 template <class F>
|
Chris@16
|
478 typename boost::result_of<F(utree const&)>::type
|
Chris@16
|
479 static visit(utree const&, F);
|
Chris@16
|
480
|
Chris@16
|
481 template <class F>
|
Chris@16
|
482 typename boost::result_of<F(utree&)>::type
|
Chris@16
|
483 static visit(utree&, F);
|
Chris@16
|
484
|
Chris@16
|
485 // double dispatch
|
Chris@16
|
486 template <class F>
|
Chris@16
|
487 typename boost::result_of<F(utree const&, utree const&)>::type
|
Chris@16
|
488 static visit(utree const&, utree const&, F);
|
Chris@16
|
489
|
Chris@16
|
490 template <class F>
|
Chris@16
|
491 typename boost::result_of<F(utree&, utree const&)>::type
|
Chris@16
|
492 static visit(utree&, utree const&, F);
|
Chris@16
|
493
|
Chris@16
|
494 template <class F>
|
Chris@16
|
495 typename boost::result_of<F(utree const&, utree&)>::type
|
Chris@16
|
496 static visit(utree const&, utree&, F);
|
Chris@16
|
497
|
Chris@16
|
498 template <class F>
|
Chris@16
|
499 typename boost::result_of<F(utree&, utree&)>::type
|
Chris@16
|
500 static visit(utree&, utree&, F);
|
Chris@16
|
501
|
Chris@16
|
502 ////////////////////////////////////////////////////////////////////////
|
Chris@16
|
503
|
Chris@16
|
504 ///////////////////////////////////////////////////////////////////////
|
Chris@16
|
505 //[utree_container_functions
|
Chris@16
|
506 // STL Container interface
|
Chris@16
|
507
|
Chris@16
|
508 // insertion
|
Chris@16
|
509 template <class T>
|
Chris@16
|
510 void push_back(T const&);
|
Chris@16
|
511 template <class T>
|
Chris@16
|
512 void push_front(T const&);
|
Chris@16
|
513 template <class T>
|
Chris@16
|
514 iterator insert(iterator, T const&);
|
Chris@16
|
515 template <class T>
|
Chris@16
|
516 void insert(iterator, std::size_t, T const&);
|
Chris@16
|
517 template <class Iterator>
|
Chris@16
|
518 void insert(iterator, Iterator, Iterator);
|
Chris@16
|
519
|
Chris@16
|
520 // erasure
|
Chris@16
|
521 void pop_front();
|
Chris@16
|
522 void pop_back();
|
Chris@16
|
523 iterator erase(iterator);
|
Chris@16
|
524 iterator erase(iterator, iterator);
|
Chris@16
|
525
|
Chris@16
|
526 // front access
|
Chris@16
|
527 reference front();
|
Chris@16
|
528 const_reference front() const;
|
Chris@16
|
529 iterator begin();
|
Chris@16
|
530 const_iterator begin() const;
|
Chris@16
|
531 ref_iterator ref_begin();
|
Chris@16
|
532
|
Chris@16
|
533 // back access
|
Chris@16
|
534 reference back();
|
Chris@16
|
535 const_reference back() const;
|
Chris@16
|
536 iterator end();
|
Chris@16
|
537 const_iterator end() const;
|
Chris@16
|
538 ref_iterator ref_end();
|
Chris@16
|
539 //]
|
Chris@16
|
540
|
Chris@16
|
541 // This clears the utree instance and resets its type to `invalid_type`
|
Chris@16
|
542 void clear();
|
Chris@16
|
543
|
Chris@16
|
544 void swap(utree&);
|
Chris@16
|
545
|
Chris@16
|
546 bool empty() const;
|
Chris@16
|
547
|
Chris@16
|
548 size_type size() const;
|
Chris@16
|
549 /*`[warning `size()` has O(n) complexity on `utree` ranges. On utree
|
Chris@16
|
550 lists, it has O(1) complexity.]`*/
|
Chris@16
|
551
|
Chris@16
|
552 ////////////////////////////////////////////////////////////////////////
|
Chris@16
|
553
|
Chris@16
|
554 //[utree_variant_functions
|
Chris@16
|
555 // return the data type (`utree_type::info`) of the currently stored
|
Chris@16
|
556 // data item
|
Chris@16
|
557 utree_type::info which() const;
|
Chris@16
|
558
|
Chris@16
|
559 // access the currently stored data in a type safe manner, this will
|
Chris@16
|
560 // throw a `std::bad_cast()` if the currently stored data item is not
|
Chris@16
|
561 // default convertible to `T`.
|
Chris@16
|
562 template <class T>
|
Chris@16
|
563 T get() const;
|
Chris@16
|
564 //]
|
Chris@16
|
565
|
Chris@16
|
566 reference deref();
|
Chris@16
|
567 const_reference deref() const;
|
Chris@16
|
568
|
Chris@16
|
569 short tag() const;
|
Chris@16
|
570 void tag(short);
|
Chris@16
|
571
|
Chris@16
|
572 utree eval(utree const&) const;
|
Chris@16
|
573 utree eval(utree&) const;
|
Chris@16
|
574
|
Chris@16
|
575 utree operator() (utree const&) const;
|
Chris@16
|
576 utree operator() (utree&) const;
|
Chris@16
|
577 //<-
|
Chris@16
|
578 protected:
|
Chris@16
|
579 void ensure_list_type(char const* failed_in = "ensure_list_type()");
|
Chris@16
|
580
|
Chris@16
|
581 private:
|
Chris@16
|
582 typedef utree_type type;
|
Chris@16
|
583
|
Chris@16
|
584 template <class UTreeX, class UTreeY>
|
Chris@16
|
585 friend struct detail::visit_impl;
|
Chris@16
|
586 friend struct detail::index_impl;
|
Chris@16
|
587
|
Chris@16
|
588 type::info get_type() const;
|
Chris@16
|
589 void set_type(type::info);
|
Chris@16
|
590 void free();
|
Chris@16
|
591 void copy(const_reference);
|
Chris@16
|
592
|
Chris@16
|
593 union {
|
Chris@16
|
594 detail::fast_string s;
|
Chris@16
|
595 detail::list l;
|
Chris@16
|
596 detail::range r;
|
Chris@16
|
597 detail::string_range sr;
|
Chris@16
|
598 detail::void_ptr v;
|
Chris@16
|
599 bool b;
|
Chris@16
|
600 int i;
|
Chris@16
|
601 double d;
|
Chris@16
|
602 utree* p;
|
Chris@16
|
603 function_base* pf;
|
Chris@16
|
604 };
|
Chris@16
|
605 //->
|
Chris@16
|
606 };
|
Chris@16
|
607 //]
|
Chris@16
|
608
|
Chris@16
|
609 //[utree_tuple_interface
|
Chris@16
|
610 /*<-*/inline/*->*/
|
Chris@16
|
611 utree::reference get(utree::reference, utree::size_type);
|
Chris@16
|
612 /*<-*/inline/*->*/
|
Chris@16
|
613 utree::const_reference get(utree::const_reference, utree::size_type);
|
Chris@16
|
614 /*`[warning `get()` has O(n) complexity.]`*/
|
Chris@16
|
615 //]
|
Chris@16
|
616
|
Chris@16
|
617 struct utree::list_type : utree
|
Chris@16
|
618 {
|
Chris@16
|
619 using utree::operator=;
|
Chris@16
|
620
|
Chris@16
|
621 list_type() : utree() { ensure_list_type("list_type()"); }
|
Chris@16
|
622
|
Chris@16
|
623 template <typename T0>
|
Chris@16
|
624 list_type(T0 t0) : utree(t0) {}
|
Chris@16
|
625
|
Chris@16
|
626 template <typename T0, typename T1>
|
Chris@16
|
627 list_type(T0 t0, T1 t1) : utree(t0, t1) {}
|
Chris@16
|
628 };
|
Chris@16
|
629
|
Chris@16
|
630 ///////////////////////////////////////////////////////////////////////////
|
Chris@16
|
631 // predefined instances for singular types
|
Chris@16
|
632 utree::invalid_type const invalid = {};
|
Chris@16
|
633 utree::nil_type const nil = {};
|
Chris@16
|
634 utree::list_type const empty_list = utree::list_type();
|
Chris@16
|
635 }}
|
Chris@16
|
636
|
Chris@16
|
637 #if defined(BOOST_MSVC)
|
Chris@16
|
638 #pragma warning(pop)
|
Chris@16
|
639 #endif
|
Chris@16
|
640
|
Chris@16
|
641 #endif
|
Chris@16
|
642
|