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