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