PageRenderTime 137ms CodeModel.GetById 19ms app.highlight 108ms RepoModel.GetById 1ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/spirit/home/support/utree/detail/utree_detail2.hpp

http://hadesmem.googlecode.com/
C++ Header | 1632 lines | 1359 code | 239 blank | 34 comment | 201 complexity | d3668eb17577ee94ff366a27d83b3303 MD5 | raw file
   1/*=============================================================================
   2    Copyright (c) 2001-2011 Joel de Guzman
   3    Copyright (c) 2001-2011 Hartmut Kaiser
   4    Copyright (c)      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_DETAIL2)
  10#define BOOST_SPIRIT_UTREE_DETAIL2
  11
  12#if defined(BOOST_MSVC)
  13# pragma warning(push)
  14# pragma warning(disable: 4800)
  15#endif
  16
  17#include <boost/type_traits/remove_pointer.hpp>
  18#include <boost/type_traits/is_pointer.hpp>
  19#include <boost/utility/enable_if.hpp>
  20#include <boost/throw_exception.hpp>
  21#include <boost/iterator/iterator_traits.hpp>
  22
  23namespace boost { namespace spirit { namespace detail
  24{
  25    inline char& fast_string::info()
  26    {
  27        return buff[small_string_size];
  28    }
  29
  30    inline char fast_string::info() const
  31    {
  32        return buff[small_string_size];
  33    }
  34
  35    inline int fast_string::get_type() const
  36    {
  37        return info() >> 1;
  38    }
  39
  40    inline void fast_string::set_type(int t)
  41    {
  42        info() = (t << 1) | (info() & 1);
  43    }
  44
  45    inline short fast_string::tag() const
  46    {
  47        return (int(buff[small_string_size-2]) << 8) + (unsigned char)buff[small_string_size-1];
  48    }
  49
  50    inline void fast_string::tag(short tag)
  51    {
  52        buff[small_string_size-2] = tag >> 8;
  53        buff[small_string_size-1] = tag & 0xff;
  54    }
  55
  56    inline bool fast_string::is_heap_allocated() const
  57    {
  58        return info() & 1;
  59    }
  60
  61    inline std::size_t fast_string::size() const
  62    {
  63        if (is_heap_allocated())
  64            return heap.size;
  65        else
  66            return max_string_len - buff[max_string_len];
  67    }
  68
  69    inline char const* fast_string::str() const
  70    {
  71        if (is_heap_allocated())
  72            return heap.str;
  73        else
  74            return buff;
  75    }
  76
  77    template <typename Iterator>
  78    inline void fast_string::construct(Iterator f, Iterator l)
  79    {
  80        unsigned const size = l-f;
  81        char* str;
  82        if (size < max_string_len)
  83        {
  84            // if it fits, store it in-situ; small_string_size minus the length
  85            // of the string is placed in buff[small_string_size - 1]
  86            str = buff;
  87            buff[max_string_len] = static_cast<char>(max_string_len - size);
  88            info() &= ~0x1;
  89        }
  90        else
  91        {
  92            // else, store it in the heap
  93            str = new char[size + 1]; // add one for the null char
  94            heap.str = str;
  95            heap.size = size;
  96            info() |= 0x1;
  97        }
  98        for (std::size_t i = 0; i != size; ++i)
  99        {
 100            *str++ = *f++;
 101        }
 102        *str = '\0'; // add the null char
 103    }
 104
 105    inline void fast_string::swap(fast_string& other)
 106    {
 107        std::swap(*this, other);
 108    }
 109
 110    inline void fast_string::free()
 111    {
 112        if (is_heap_allocated())
 113        {
 114            delete [] heap.str;
 115        }
 116    }
 117
 118    inline void fast_string::copy(fast_string const& other)
 119    {
 120        construct(other.str(), other.str() + other.size());
 121    }
 122
 123    inline void fast_string::initialize() 
 124    {
 125        for (std::size_t i = 0; i != buff_size / (sizeof(long)/sizeof(char)); ++i) 
 126            lbuff[i] = 0;
 127    }
 128
 129    struct list::node : boost::noncopyable
 130    {
 131        template <typename T>
 132        node(T const& val, node* next, node* prev)
 133          : val(val), next(next), prev(prev) {}
 134
 135        void unlink()
 136        {
 137            prev->next = next;
 138            next->prev = prev;
 139        }
 140
 141        utree val;
 142        node* next;
 143        node* prev;
 144    };
 145
 146    template <typename Value>
 147    class list::node_iterator
 148      : public boost::iterator_facade<
 149            node_iterator<Value>
 150          , Value
 151          , boost::bidirectional_traversal_tag>
 152    {
 153    public:
 154
 155        node_iterator()
 156          : node(0), prev(0) {}
 157
 158        node_iterator(list::node* node, list::node* prev)
 159          : node(node), prev(prev) {}
 160
 161    private:
 162
 163        friend class boost::iterator_core_access;
 164        friend class boost::spirit::utree;
 165        friend struct boost::spirit::detail::list;
 166
 167        void increment()
 168        {
 169            if (node != 0) // not at end
 170            {
 171                prev = node;
 172                node = node->next;
 173            }
 174        }
 175
 176        void decrement()
 177        {
 178            if (prev != 0) // not at begin
 179            {
 180                node = prev;
 181                prev = prev->prev;
 182            }
 183        }
 184
 185        bool equal(node_iterator const& other) const
 186        {
 187            return node == other.node;
 188        }
 189
 190        typename node_iterator::reference dereference() const
 191        {
 192            return node->val;
 193        }
 194
 195        list::node* node;
 196        list::node* prev;
 197    };
 198
 199    template <typename Value>
 200    class list::node_iterator<boost::reference_wrapper<Value> >
 201      : public boost::iterator_facade<
 202            node_iterator<boost::reference_wrapper<Value> >
 203          , boost::reference_wrapper<Value>
 204          , boost::bidirectional_traversal_tag>
 205    {
 206    public:
 207
 208        node_iterator()
 209          : node(0), prev(0), curr(nil_node) {}
 210
 211        node_iterator(list::node* node, list::node* prev)
 212          : node(node), prev(prev), curr(node ? node->val : nil_node) {}
 213
 214    private:
 215
 216        friend class boost::iterator_core_access;
 217        friend class boost::spirit::utree;
 218        friend struct boost::spirit::detail::list;
 219
 220        void increment()
 221        {
 222            if (node != 0) // not at end
 223            {
 224                prev = node;
 225                node = node->next;
 226                curr = boost::ref(node ? node->val : nil_node);
 227            }
 228        }
 229
 230        void decrement()
 231        {
 232            if (prev != 0) // not at begin
 233            {
 234                node = prev;
 235                prev = prev->prev;
 236                curr = boost::ref(node ? node->val : nil_node);
 237            }
 238        }
 239
 240        bool equal(node_iterator const& other) const
 241        {
 242            return node == other.node;
 243        }
 244
 245        typename node_iterator::reference dereference() const
 246        {
 247            return curr;
 248        }
 249
 250        list::node* node;
 251        list::node* prev;
 252
 253        static Value nil_node;
 254        mutable boost::reference_wrapper<Value> curr;
 255    };
 256
 257    template <typename Value>
 258    Value list::node_iterator<boost::reference_wrapper<Value> >::nil_node = Value();
 259
 260    inline void list::free()
 261    {
 262        node* p = first;
 263        while (p != 0)
 264        {
 265            node* next = p->next;
 266            delete p;
 267            p = next;
 268        }
 269    }
 270
 271    inline void list::copy(list const& other)
 272    {
 273        node* p = other.first;
 274        while (p != 0)
 275        {
 276            push_back(p->val);
 277            p = p->next;
 278        }
 279    }
 280
 281    inline void list::default_construct()
 282    {
 283        first = last = 0;
 284        size = 0;
 285    }
 286
 287    template <typename T, typename Iterator>
 288    inline void list::insert(T const& val, Iterator pos)
 289    {
 290        if (!pos.node)
 291        {
 292            push_back(val);
 293            return;
 294        }
 295
 296        detail::list::node* new_node = 
 297            new detail::list::node(val, pos.node, pos.node->prev);
 298
 299        if (pos.node->prev)
 300            pos.node->prev->next = new_node;
 301        else
 302            first = new_node;
 303
 304        pos.node->prev = new_node;
 305        ++size;
 306    }
 307
 308    template <typename T>
 309    inline void list::push_front(T const& val)
 310    {
 311        detail::list::node* new_node;
 312        if (first == 0)
 313        {
 314            new_node = new detail::list::node(val, 0, 0);
 315            first = last = new_node;
 316            ++size;
 317        }
 318        else
 319        {
 320            new_node = new detail::list::node(val, first, first->prev);
 321            first->prev = new_node;
 322            first = new_node;
 323            ++size;
 324        }
 325    }
 326
 327    template <typename T>
 328    inline void list::push_back(T const& val)
 329    {
 330        if (last == 0)
 331            push_front(val);
 332        else {
 333            detail::list::node* new_node = 
 334                new detail::list::node(val, last->next, last);
 335            last->next = new_node;
 336            last = new_node;
 337            ++size;
 338        }
 339    }
 340
 341    inline void list::pop_front()
 342    {
 343        BOOST_ASSERT(size != 0);
 344        if (first == last) // there's only one item
 345        {
 346            delete first;
 347            size = 0;
 348            first = last = 0;
 349        }
 350        else
 351        {
 352            node* np = first;
 353            first = first->next;
 354            first->prev = 0;
 355            delete np;
 356            --size;
 357        }
 358    }
 359
 360    inline void list::pop_back()
 361    {
 362        BOOST_ASSERT(size != 0);
 363        if (first == last) // there's only one item
 364        {
 365            delete first;
 366            size = 0;
 367            first = last = 0;
 368        }
 369        else
 370        {
 371            node* np = last;
 372            last = last->prev;
 373            last->next = 0;
 374            delete np;
 375            --size;
 376        }
 377    }
 378
 379    inline list::node* list::erase(node* pos)
 380    {
 381        BOOST_ASSERT(pos != 0);
 382        if (pos == first)
 383        {
 384            pop_front();
 385            return first;
 386        }
 387        else if (pos == last)
 388        {
 389            pop_back();
 390            return 0;
 391        }
 392        else
 393        {
 394            node* next(pos->next);
 395            pos->unlink();
 396            delete pos;
 397            --size;
 398            return next;
 399        }
 400    }
 401
 402    ///////////////////////////////////////////////////////////////////////////
 403    // simple binder for binary visitation (we don't want to bring in the big guns)
 404    template <typename F, typename X>
 405    struct bind_impl 
 406    {
 407        typedef typename F::result_type result_type;
 408        X& x; // always by reference
 409        F f;
 410        bind_impl(F f, X& x) : x(x), f(f) {}
 411
 412        template <typename Y>
 413        typename F::result_type operator()(Y& y) const
 414        {
 415            return f(x, y);
 416        }
 417
 418        template <typename Y>
 419        typename F::result_type operator()(Y const& y) const
 420        {
 421            return f(x, y);
 422        }
 423    };
 424
 425    template <typename F, typename X>
 426    bind_impl<F, X const> bind(F f, X const& x)
 427    {
 428        return bind_impl<F, X const>(f, x);
 429    }
 430
 431    template <typename F, typename X>
 432    bind_impl<F, X> bind(F f, X& x)
 433    {
 434        return bind_impl<F, X>(f, x);
 435    }
 436
 437    template <typename UTreeX, typename UTreeY = UTreeX>
 438    struct visit_impl
 439    {
 440        template <typename F>
 441        typename F::result_type
 442        static apply(UTreeX& x, F f) // single dispatch
 443        {
 444            typedef typename
 445                boost::mpl::if_<boost::is_const<UTreeX>,
 446                typename UTreeX::const_iterator,
 447                typename UTreeX::iterator>::type
 448            iterator;
 449
 450            typedef boost::iterator_range<iterator> list_range;
 451            typedef utree_type type;
 452
 453            switch (x.get_type())
 454            {
 455                default:
 456                    BOOST_THROW_EXCEPTION(
 457                        bad_type_exception("corrupt utree type", x.get_type()));
 458                    break;
 459
 460                case type::invalid_type:
 461                    return f(invalid);
 462
 463                case type::nil_type:
 464                    return f(nil);
 465
 466                case type::bool_type:
 467                    return f(x.b);
 468
 469                case type::int_type:
 470                    return f(x.i);
 471
 472                case type::double_type:
 473                    return f(x.d);
 474
 475                case type::list_type:
 476                    return f(list_range(iterator(x.l.first, 0), iterator(0, x.l.last)));
 477
 478                case type::range_type:
 479                    return f(list_range(iterator(x.r.first, 0), iterator(0, x.r.last)));
 480
 481                case type::string_type:
 482                    return f(utf8_string_range_type(x.s.str(), x.s.size()));
 483
 484                case type::string_range_type:
 485                    return f(utf8_string_range_type(x.sr.first, x.sr.last));
 486
 487                case type::symbol_type:
 488                    return f(utf8_symbol_range_type(x.s.str(), x.s.size()));
 489
 490                case type::binary_type:
 491                    return f(binary_range_type(x.s.str(), x.s.size()));
 492
 493                case type::reference_type:
 494                    return apply(*x.p, f);
 495
 496                case type::any_type:
 497                    return f(any_ptr(x.v.p, x.v.i));
 498
 499                case type::function_type:
 500                    return f(*x.pf);
 501            }
 502        }
 503
 504        template <typename F>
 505        typename F::result_type
 506        static apply(UTreeX& x, UTreeY& y, F f) // double dispatch
 507        {
 508            typedef typename
 509                boost::mpl::if_<boost::is_const<UTreeX>,
 510                typename UTreeX::const_iterator,
 511                typename UTreeX::iterator>::type
 512            iterator;
 513
 514            typedef boost::iterator_range<iterator> list_range;
 515            typedef utree_type type;
 516
 517            switch (x.get_type())
 518            {
 519                default:
 520                    BOOST_THROW_EXCEPTION(
 521                        bad_type_exception("corrupt utree type", x.get_type()));
 522                    break;
 523
 524                case type::invalid_type:
 525                    return visit_impl::apply(y, detail::bind(f, invalid));
 526
 527                case type::nil_type:
 528                    return visit_impl::apply(y, detail::bind(f, nil));
 529
 530                case type::bool_type:
 531                    return visit_impl::apply(y, detail::bind(f, x.b));
 532
 533                case type::int_type:
 534                    return visit_impl::apply(y, detail::bind(f, x.i));
 535
 536                case type::double_type:
 537                    return visit_impl::apply(y, detail::bind(f, x.d));
 538
 539                case type::list_type:
 540                    return visit_impl::apply(
 541                        y, detail::bind<F, list_range>(f,
 542                        list_range(iterator(x.l.first, 0), iterator(0, x.l.last))));
 543
 544                case type::range_type:
 545                    return visit_impl::apply(
 546                        y, detail::bind<F, list_range>(f,
 547                        list_range(iterator(x.r.first, 0), iterator(0, x.r.last))));
 548
 549                case type::string_type:
 550                    return visit_impl::apply(y, detail::bind(
 551                        f, utf8_string_range_type(x.s.str(), x.s.size())));
 552
 553                case type::string_range_type:
 554                    return visit_impl::apply(y, detail::bind(
 555                        f, utf8_string_range_type(x.sr.first, x.sr.last)));
 556
 557                case type::symbol_type:
 558                    return visit_impl::apply(y, detail::bind(
 559                        f, utf8_symbol_range_type(x.s.str(), x.s.size())));
 560
 561                case type::binary_type:
 562                    return visit_impl::apply(y, detail::bind(
 563                        f, binary_range_type(x.s.str(), x.s.size())));
 564
 565                case type::reference_type:
 566                    return apply(*x.p, y, f);
 567
 568                case type::any_type:
 569                    return visit_impl::apply(
 570                        y, detail::bind(f, any_ptr(x.v.p, x.v.i)));
 571
 572                case type::function_type:
 573                    return visit_impl::apply(y, detail::bind(f, *x.pf));
 574            }
 575        }
 576    };
 577
 578    struct index_impl
 579    {
 580        static utree& apply(utree& ut, std::size_t i)
 581        {
 582            switch (ut.get_type())
 583            {
 584                case utree_type::reference_type:
 585                    return apply(ut.deref(), i);
 586                case utree_type::range_type:
 587                    return apply(ut.r.first, i);
 588                case utree_type::list_type:
 589                    return apply(ut.l.first, i);
 590                default:
 591                    BOOST_THROW_EXCEPTION(
 592                        bad_type_exception
 593                            ("index operation performed on non-list utree type",
 594                             ut.get_type()));
 595            }
 596        }
 597
 598        static utree const& apply(utree const& ut, std::size_t i)
 599        {
 600            switch (ut.get_type())
 601            {
 602                case utree_type::reference_type:
 603                    return apply(ut.deref(), i);
 604                case utree_type::range_type:
 605                    return apply(ut.r.first, i);
 606                case utree_type::list_type:
 607                    return apply(ut.l.first, i);
 608                default:
 609                    BOOST_THROW_EXCEPTION(
 610                        bad_type_exception
 611                            ("index operation performed on non-list utree type",
 612                             ut.get_type()));
 613            }
 614        }
 615
 616        static utree& apply(list::node* node, std::size_t i)
 617        {
 618            for (; i > 0; --i)
 619                node = node->next;
 620            return node->val;
 621        }
 622
 623        static utree const& apply(list::node const* node, std::size_t i)
 624        {
 625            for (; i > 0; --i)
 626                node = node->next;
 627            return node->val;
 628        }
 629    };
 630}}}
 631
 632namespace boost { namespace spirit
 633{
 634    template <typename F>
 635    stored_function<F>::stored_function(F f)
 636      : f(f)
 637    {
 638    }
 639
 640    template <typename F>
 641    stored_function<F>::~stored_function()
 642    {
 643    }
 644
 645    template <typename F>
 646    utree stored_function<F>::operator()(utree const& env) const
 647    {
 648        return f(env);
 649    }
 650    
 651    template <typename F>
 652    utree stored_function<F>::operator()(utree& env) const 
 653    {
 654        return f(env);
 655    }
 656
 657    template <typename F>
 658    function_base*
 659    stored_function<F>::clone() const
 660    {
 661        return new stored_function<F>(f);
 662    }
 663    
 664    template <typename F>
 665    referenced_function<F>::referenced_function(F& f)
 666      : f(f)
 667    {
 668    }
 669
 670    template <typename F>
 671    referenced_function<F>::~referenced_function()
 672    {
 673    }
 674
 675    template <typename F>
 676    utree referenced_function<F>::operator()(utree const& env) const
 677    {
 678        return f(env);
 679    }
 680    
 681    template <typename F>
 682    utree referenced_function<F>::operator()(utree& env) const
 683    {
 684        return f(env);
 685    }
 686
 687    template <typename F>
 688    function_base*
 689    referenced_function<F>::clone() const
 690    {
 691        return new referenced_function<F>(f);
 692    }
 693
 694    inline utree::utree(utree::invalid_type)
 695    {
 696        s.initialize();
 697        set_type(type::invalid_type);
 698    }
 699
 700    inline utree::utree(utree::nil_type)
 701    {
 702        s.initialize();
 703        set_type(type::nil_type);
 704    }
 705    
 706    inline utree::utree(bool b_) 
 707    {
 708        s.initialize();
 709        b = b_;
 710        set_type(type::bool_type);
 711    }
 712
 713    inline utree::utree(char c)
 714    {
 715        s.initialize();
 716        // char constructs a single element string
 717        s.construct(&c, &c+1);
 718        set_type(type::string_type);
 719    }
 720
 721    inline utree::utree(unsigned int i_) 
 722    {
 723        s.initialize();
 724        i = i_;
 725        set_type(type::int_type);
 726    }
 727
 728    inline utree::utree(int i_) 
 729    {
 730        s.initialize();
 731        i = i_;
 732        set_type(type::int_type);
 733    }
 734
 735    inline utree::utree(double d_) 
 736    {
 737        s.initialize();
 738        d = d_;
 739        set_type(type::double_type);
 740    }
 741
 742    inline utree::utree(char const* str)
 743    {
 744        s.initialize();
 745        s.construct(str, str + strlen(str));
 746        set_type(type::string_type);
 747    }
 748
 749    inline utree::utree(char const* str, std::size_t len)
 750    {
 751        s.initialize();
 752        s.construct(str, str + len);
 753        set_type(type::string_type);
 754    }
 755
 756    inline utree::utree(std::string const& str)
 757    {
 758        s.initialize();
 759        s.construct(str.begin(), str.end());
 760        set_type(type::string_type);
 761    }
 762
 763    template <typename Base, utree_type::info type_>
 764    inline utree::utree(basic_string<Base, type_> const& bin)
 765    {
 766        s.initialize();
 767        s.construct(bin.begin(), bin.end());
 768        set_type(type_);
 769    }
 770
 771    inline utree::utree(boost::reference_wrapper<utree> ref)
 772    {
 773        s.initialize();
 774        p = ref.get_pointer();
 775        set_type(type::reference_type);
 776    }
 777
 778    inline utree::utree(any_ptr const& p)
 779    {
 780        s.initialize();
 781        v.p = p.p;
 782        v.i = p.i;
 783        set_type(type::any_type);
 784    }
 785
 786    inline utree::utree(function_base const& pf_)
 787    {
 788        s.initialize();
 789        pf = pf_.clone();
 790        set_type(type::function_type);
 791    }
 792    
 793    inline utree::utree(function_base* pf_)
 794    {
 795        s.initialize();
 796        pf = pf_;
 797        set_type(type::function_type);
 798    }
 799    
 800    template <typename Iter>
 801    inline utree::utree(boost::iterator_range<Iter> r)
 802    {
 803        s.initialize();
 804
 805        assign(r.begin(), r.end());
 806    }
 807
 808    inline utree::utree(range r, shallow_tag)
 809    {
 810        s.initialize();
 811        this->r.first = r.begin().node;
 812        this->r.last = r.end().prev;
 813        set_type(type::range_type);
 814    }
 815
 816    inline utree::utree(const_range r, shallow_tag)
 817    {
 818        s.initialize();
 819        this->r.first = r.begin().node;
 820        this->r.last = r.end().prev;
 821        set_type(type::range_type);
 822    }
 823
 824    inline utree::utree(utf8_string_range_type const& str, shallow_tag)
 825    {
 826        s.initialize();
 827        this->sr.first = str.begin();
 828        this->sr.last = str.end();
 829        set_type(type::string_range_type);
 830    }
 831
 832    inline utree::utree(utree const& other)
 833    {
 834        s.initialize();
 835        copy(other);
 836    }
 837
 838    inline utree::~utree()
 839    {
 840        free();
 841    }
 842
 843    inline utree& utree::operator=(utree const& other)
 844    {
 845        if (this != &other)
 846        {
 847            free();
 848            copy(other);
 849        }
 850        return *this;
 851    }
 852
 853    inline utree& utree::operator=(nil_type)
 854    {
 855        free();
 856        set_type(type::nil_type);
 857        return *this;
 858    }
 859
 860    inline utree& utree::operator=(bool b_)
 861    {
 862        free();
 863        b = b_;
 864        set_type(type::bool_type);
 865        return *this;
 866    }
 867
 868    inline utree& utree::operator=(char c)
 869    {
 870        // char constructs a single element string
 871        free();
 872        s.construct(&c, &c+1);
 873        set_type(type::string_type);
 874        return *this;
 875    }
 876
 877    inline utree& utree::operator=(unsigned int i_)
 878    {
 879        free();
 880        i = i_;
 881        set_type(type::int_type);
 882        return *this;
 883    }
 884
 885    inline utree& utree::operator=(int i_)
 886    {
 887        free();
 888        i = i_;
 889        set_type(type::int_type);
 890        return *this;
 891    }
 892
 893    inline utree& utree::operator=(double d_)
 894    {
 895        free();
 896        d = d_;
 897        set_type(type::double_type);
 898        return *this;
 899    }
 900
 901    inline utree& utree::operator=(char const* s_)
 902    {
 903        free();
 904        s.construct(s_, s_ + strlen(s_));
 905        set_type(type::string_type);
 906        return *this;
 907    }
 908
 909    inline utree& utree::operator=(std::string const& s_)
 910    {
 911        free();
 912        s.construct(s_.begin(), s_.end());
 913        set_type(type::string_type);
 914        return *this;
 915    }
 916
 917    template <typename Base, utree_type::info type_>
 918    inline utree& utree::operator=(basic_string<Base, type_> const& bin)
 919    {
 920        free();
 921        s.construct(bin.begin(), bin.end());
 922        set_type(type_);
 923        return *this;
 924    }
 925
 926    inline utree& utree::operator=(boost::reference_wrapper<utree> ref)
 927    {
 928        free();
 929        p = ref.get_pointer();
 930        set_type(type::reference_type);
 931        return *this;
 932    }
 933    
 934    inline utree& utree::operator=(any_ptr const& p)
 935    {
 936        free();
 937        v.p = p.p;
 938        v.i = p.i;
 939        set_type(type::any_type);
 940        return *this;
 941    }
 942    
 943    inline utree& utree::operator=(function_base const& pf_)
 944    {
 945        free();
 946        pf = pf_.clone();
 947        set_type(type::function_type);
 948        return *this;
 949    }
 950
 951    inline utree& utree::operator=(function_base* pf_)
 952    {
 953        free();
 954        pf = pf_;
 955        set_type(type::function_type);
 956        return *this;
 957    }
 958    
 959    template <typename Iter>
 960    inline utree& utree::operator=(boost::iterator_range<Iter> r)
 961    {
 962        free();
 963        assign(r.begin(), r.end());
 964        return *this;
 965    }
 966
 967    template <typename F>
 968    typename boost::result_of<F(utree const&)>::type
 969    inline utree::visit(utree const& x, F f)
 970    {
 971        return detail::visit_impl<utree const>::apply(x, f);
 972    }
 973
 974    template <typename F>
 975    typename boost::result_of<F(utree&)>::type
 976    inline utree::visit(utree& x, F f)
 977    {
 978        return detail::visit_impl<utree>::apply(x, f);
 979    }
 980
 981    template <typename F>
 982    typename boost::result_of<F(utree const&, utree const&)>::type
 983    inline utree::visit(utree const& x, utree const& y, F f)
 984    {
 985        return detail::visit_impl<utree const, utree const>::apply(x, y, f);
 986    }
 987
 988    template <typename F>
 989    typename boost::result_of<F(utree const&, utree&)>::type
 990    inline utree::visit(utree const& x, utree& y, F f)
 991    {
 992        return detail::visit_impl<utree const, utree>::apply(x, y, f);
 993    }
 994
 995    template <typename F>
 996    typename boost::result_of<F(utree&, utree const&)>::type
 997    inline utree::visit(utree& x, utree const& y, F f)
 998    {
 999        return detail::visit_impl<utree, utree const>::apply(x, y, f);
1000    }
1001
1002    template <typename F>
1003    typename boost::result_of<F(utree&, utree&)>::type
1004    inline utree::visit(utree& x, utree& y, F f)
1005    {
1006        return detail::visit_impl<utree, utree>::apply(x, y, f);
1007    }
1008
1009    inline utree::reference get(utree::reference ut, utree::size_type i)
1010    { return detail::index_impl::apply(ut, i); }
1011
1012    inline utree::const_reference
1013    get(utree::const_reference ut, utree::size_type i)
1014    { return detail::index_impl::apply(ut, i); }
1015
1016    template <typename T>
1017    inline void utree::push_front(T const& val)
1018    {
1019        if (get_type() == type::reference_type)
1020            return p->push_front(val);
1021
1022        ensure_list_type("push_front()");
1023        l.push_front(val);
1024    }
1025
1026    template <typename T>
1027    inline void utree::push_back(T const& val)
1028    {
1029        if (get_type() == type::reference_type)
1030            return p->push_back(val);
1031
1032        ensure_list_type("push_back()");
1033        l.push_back(val);
1034    }
1035
1036    template <typename T>
1037    inline utree::iterator utree::insert(iterator pos, T const& val)
1038    {
1039        if (get_type() == type::reference_type)
1040            return p->insert(pos, val);
1041
1042        ensure_list_type("insert()");
1043        if (!pos.node) 
1044        {
1045            l.push_back(val);
1046            return utree::iterator(l.first, 0); // begin();
1047        }
1048        l.insert(val, pos);
1049        return utree::iterator(pos.node->prev, pos.node->prev->prev);
1050    }
1051
1052    template <typename T>
1053    inline void utree::insert(iterator pos, std::size_t n, T const& val)
1054    {
1055        if (get_type() == type::reference_type)
1056            return p->insert(pos, n, val);
1057
1058        ensure_list_type("insert()");
1059        for (std::size_t i = 0; i != n; ++i)
1060            insert(pos, val);
1061    }
1062
1063    template <typename Iterator>
1064    inline void utree::insert(iterator pos, Iterator first, Iterator last)
1065    {
1066        if (get_type() == type::reference_type)
1067            return p->insert(pos, first, last);
1068
1069        ensure_list_type("insert()");
1070        while (first != last)
1071            insert(pos, *first++);
1072    }
1073
1074    template <typename Iterator>
1075    inline void utree::assign(Iterator first, Iterator last)
1076    {
1077        if (get_type() == type::reference_type)
1078            return p->assign(first, last);
1079
1080        clear();
1081        set_type(type::list_type);
1082
1083        while (first != last)
1084        {
1085            push_back(*first);
1086            ++first;
1087        }
1088    }
1089
1090    inline void utree::clear()
1091    {
1092        if (get_type() == type::reference_type)
1093            return p->clear();
1094
1095        // clear will always make this an invalid type
1096        free();
1097        set_type(type::invalid_type);
1098    }
1099
1100    inline void utree::pop_front()
1101    {
1102        if (get_type() == type::reference_type)
1103            return p->pop_front();
1104        if (get_type() != type::list_type)
1105            BOOST_THROW_EXCEPTION(
1106                bad_type_exception
1107                    ("pop_front() called on non-list utree type",
1108                     get_type()));
1109
1110        l.pop_front();
1111    }
1112
1113    inline void utree::pop_back()
1114    {
1115        if (get_type() == type::reference_type)
1116            return p->pop_back();
1117        if (get_type() != type::list_type)
1118            BOOST_THROW_EXCEPTION(
1119                bad_type_exception
1120                    ("pop_back() called on non-list utree type",
1121                     get_type()));
1122
1123        l.pop_back();
1124    }
1125
1126    inline utree::iterator utree::erase(iterator pos)
1127    {
1128        if (get_type() == type::reference_type)
1129            return p->erase(pos);
1130        if (get_type() != type::list_type)
1131            BOOST_THROW_EXCEPTION(
1132                bad_type_exception
1133                    ("erase() called on non-list utree type",
1134                     get_type()));
1135
1136        detail::list::node* np = l.erase(pos.node);
1137        return iterator(np, np?np->prev:l.last);
1138    }
1139
1140    inline utree::iterator utree::erase(iterator first, iterator last)
1141    {
1142        if (get_type() == type::reference_type)
1143            return p->erase(first, last);
1144
1145        if (get_type() != type::list_type)
1146            BOOST_THROW_EXCEPTION(
1147                bad_type_exception
1148                    ("erase() called on non-list utree type",
1149                     get_type()));
1150        while (first != last)
1151            erase(first++);
1152        return last;
1153    }
1154
1155    inline utree::iterator utree::begin()
1156    {
1157        if (get_type() == type::reference_type)
1158            return p->begin();
1159        else if (get_type() == type::range_type)
1160            return iterator(r.first, 0);
1161
1162        // otherwise...
1163        ensure_list_type("begin()");
1164        return iterator(l.first, 0);
1165    }
1166
1167    inline utree::iterator utree::end()
1168    {
1169        if (get_type() == type::reference_type)
1170            return p->end();
1171        else if (get_type() == type::range_type)
1172            return iterator(0, r.first);
1173
1174        // otherwise...
1175        ensure_list_type("end()");
1176        return iterator(0, l.last);
1177    }
1178
1179    inline utree::ref_iterator utree::ref_begin()
1180    {
1181        if (get_type() == type::reference_type)
1182            return p->ref_begin();
1183        else if (get_type() == type::range_type)
1184            return ref_iterator(r.first, 0);
1185
1186        // otherwise...
1187        ensure_list_type("ref_begin()");
1188        return ref_iterator(l.first, 0);
1189    }
1190
1191    inline utree::ref_iterator utree::ref_end()
1192    {
1193        if (get_type() == type::reference_type)
1194            return p->ref_end();
1195        else if (get_type() == type::range_type)
1196            return ref_iterator(0, r.first);
1197
1198        // otherwise...
1199        ensure_list_type("ref_end()");
1200        return ref_iterator(0, l.last);
1201    }
1202
1203    inline utree::const_iterator utree::begin() const
1204    {
1205        if (get_type() == type::reference_type)
1206            return ((utree const*)p)->begin();
1207        if (get_type() == type::range_type)
1208            return const_iterator(r.first, 0);
1209
1210        // otherwise...
1211        if (get_type() != type::list_type)
1212            BOOST_THROW_EXCEPTION(
1213                bad_type_exception
1214                    ("begin() called on non-list utree type",
1215                     get_type()));
1216
1217        return const_iterator(l.first, 0);
1218    }
1219
1220    inline utree::const_iterator utree::end() const
1221    {
1222        if (get_type() == type::reference_type)
1223            return ((utree const*)p)->end();
1224        if (get_type() == type::range_type)
1225            return const_iterator(0, r.first);
1226
1227        // otherwise...
1228        if (get_type() != type::list_type)
1229            BOOST_THROW_EXCEPTION(
1230                bad_type_exception
1231                    ("end() called on non-list utree type",
1232                     get_type()));
1233
1234        return const_iterator(0, l.last);
1235    }
1236
1237    inline bool utree::empty() const
1238    {
1239        type::info t = get_type();
1240        if (t == type::reference_type)
1241            return ((utree const*)p)->empty();
1242
1243        if (t == type::range_type)
1244            return r.first == 0;
1245        if (t == type::list_type)
1246            return l.size == 0;
1247
1248        return t == type::nil_type || t == type::invalid_type;
1249    }
1250
1251    inline std::size_t utree::size() const
1252    {
1253        type::info t = get_type();
1254        if (t == type::reference_type)
1255            return ((utree const*)p)->size();
1256
1257        if (t == type::range_type)
1258        {
1259            // FIXME: O(n), and we have the room to store the size of a range
1260            // in the union if we compute it when assigned/constructed.
1261            std::size_t size = 0;
1262            detail::list::node* n = r.first;
1263            while (n)
1264            {
1265                n = n->next;
1266                ++size;
1267            }
1268            return size;
1269        }
1270        if (t == type::list_type)
1271            return l.size;
1272
1273        if (t == type::string_type)
1274            return s.size();
1275
1276        if (t == type::symbol_type)
1277            return s.size();
1278        
1279        if (t == type::binary_type)
1280            return s.size();
1281        
1282        if (t == type::string_range_type)
1283            return sr.last - sr.first;
1284
1285        if (t != type::nil_type)
1286            BOOST_THROW_EXCEPTION(
1287                bad_type_exception
1288                    ("size() called on non-list and non-string utree type",
1289                     get_type()));
1290
1291        return 0;
1292    }
1293
1294    inline utree_type::info utree::which() const
1295    {
1296        return get_type();
1297    }
1298
1299    inline utree& utree::front()
1300    {
1301        if (get_type() == type::reference_type)
1302            return p->front();
1303        if (get_type() == type::range_type)
1304        {
1305            if (!r.first)
1306                BOOST_THROW_EXCEPTION(
1307                    empty_exception("front() called on empty utree range"));
1308            return r.first->val;
1309        }
1310
1311        // otherwise...
1312        if (get_type() != type::list_type)
1313            BOOST_THROW_EXCEPTION(
1314                bad_type_exception
1315                    ("front() called on non-list utree type", get_type()));
1316        else if (!l.first)
1317            BOOST_THROW_EXCEPTION(
1318                empty_exception("front() called on empty utree list"));
1319
1320        return l.first->val;
1321    }
1322
1323    inline utree& utree::back()
1324    {
1325        if (get_type() == type::reference_type)
1326            return p->back();
1327        if (get_type() == type::range_type)
1328        {
1329            if (!r.last)
1330                BOOST_THROW_EXCEPTION(
1331                    empty_exception("back() called on empty utree range"));
1332            return r.last->val;
1333        }
1334
1335        // otherwise...
1336        if (get_type() != type::list_type) 
1337            BOOST_THROW_EXCEPTION(
1338                bad_type_exception
1339                    ("back() called on non-list utree type", get_type()));
1340        else if (!l.last)
1341            BOOST_THROW_EXCEPTION(
1342                empty_exception("back() called on empty utree list"));
1343
1344        return l.last->val;
1345    }
1346
1347    inline utree const& utree::front() const
1348    {
1349        if (get_type() == type::reference_type)
1350            return ((utree const*)p)->front();
1351        if (get_type() == type::range_type)
1352        {
1353            if (!r.first)
1354                BOOST_THROW_EXCEPTION(
1355                    empty_exception("front() called on empty utree range"));
1356            return r.first->val;
1357        }
1358
1359        // otherwise...
1360        if (get_type() != type::list_type)
1361            BOOST_THROW_EXCEPTION(
1362                bad_type_exception
1363                    ("front() called on non-list utree type", get_type()));
1364        else if (!l.first)
1365            BOOST_THROW_EXCEPTION(
1366                empty_exception("front() called on empty utree list"));
1367
1368        return l.first->val;
1369    }
1370
1371    inline utree const& utree::back() const
1372    {
1373        if (get_type() == type::reference_type)
1374            return ((utree const*)p)->back();
1375        if (get_type() == type::range_type)
1376        {
1377            if (!r.last)
1378                BOOST_THROW_EXCEPTION(
1379                    empty_exception("back() called on empty utree range"));
1380            return r.last->val;
1381        }
1382
1383        // otherwise...
1384        if (get_type() != type::list_type) 
1385            BOOST_THROW_EXCEPTION(
1386                bad_type_exception
1387                    ("back() called on non-list utree type", get_type()));
1388        else if (!l.last)
1389            BOOST_THROW_EXCEPTION(
1390                empty_exception("back() called on empty utree list"));
1391
1392        return l.last->val;
1393    }
1394
1395    inline void utree::swap(utree& other)
1396    {
1397        s.swap(other.s);
1398    }
1399
1400    inline utree::type::info utree::get_type() const
1401    {
1402        // the fast string holds the type info
1403        return static_cast<utree::type::info>(s.get_type());
1404    }
1405
1406    inline void utree::set_type(type::info t)
1407    {
1408        // the fast string holds the type info
1409        s.set_type(t);
1410    }
1411
1412    inline void utree::ensure_list_type(char const* failed_in)
1413    {
1414        type::info t = get_type();
1415        if (t == type::invalid_type)
1416        {
1417            set_type(type::list_type);
1418            l.default_construct();
1419        }
1420        else if (get_type() != type::list_type)
1421        {
1422            std::string msg = failed_in;
1423            msg += "called on non-list and non-invalid utree type";
1424            BOOST_THROW_EXCEPTION(bad_type_exception(msg.c_str(), get_type()));
1425        }
1426    }
1427
1428    inline void utree::free()
1429    {
1430        switch (get_type())
1431        {
1432            case type::binary_type:
1433            case type::symbol_type:
1434            case type::string_type:
1435                s.free();
1436                break;
1437            case type::list_type:
1438                l.free();
1439                break;
1440            case type::function_type:
1441                delete pf;
1442                break;
1443            default:
1444                break;
1445        };
1446        s.initialize();
1447    }
1448
1449    inline void utree::copy(utree const& other)
1450    {
1451        set_type(other.get_type());
1452        switch (other.get_type())
1453        {
1454            default:
1455                BOOST_THROW_EXCEPTION(
1456                    bad_type_exception("corrupt utree type", other.get_type()));
1457                break;
1458            case type::invalid_type:
1459            case type::nil_type:
1460                s.tag(other.s.tag());
1461                break;
1462            case type::bool_type:
1463                b = other.b;
1464                s.tag(other.s.tag());
1465                break;
1466            case type::int_type:
1467                i = other.i;
1468                s.tag(other.s.tag());
1469                break;
1470            case type::double_type:
1471                d = other.d;
1472                s.tag(other.s.tag());
1473                break;
1474            case type::reference_type:
1475                p = other.p;
1476                s.tag(other.s.tag());
1477                break;
1478            case type::any_type:
1479                v = other.v;
1480                s.tag(other.s.tag());
1481                break;
1482            case type::range_type:
1483                r = other.r;
1484                s.tag(other.s.tag());
1485                break;
1486            case type::string_range_type:
1487                sr = other.sr;
1488                s.tag(other.s.tag());
1489                break;
1490            case type::function_type:
1491                pf = other.pf->clone();
1492                s.tag(other.s.tag());
1493                break;
1494            case type::string_type:
1495            case type::symbol_type:
1496            case type::binary_type:
1497                s.copy(other.s);
1498                s.tag(other.s.tag());
1499                break;
1500            case type::list_type:
1501                l.copy(other.l);
1502                s.tag(other.s.tag());
1503                break;
1504        }
1505    }
1506
1507    template <typename T>
1508    struct is_iterator_range
1509      : boost::mpl::false_
1510    {};
1511
1512    template <typename Iterator>
1513    struct is_iterator_range<boost::iterator_range<Iterator> >
1514      : boost::mpl::true_
1515    {};
1516
1517    template <typename To>
1518    struct utree_cast
1519    {
1520        typedef To result_type;
1521
1522        template <typename From>
1523        To dispatch(From const& val, boost::mpl::true_) const
1524        {
1525            return To(val); // From is convertible to To
1526        }
1527
1528        template <typename From>
1529        To dispatch(From const&, boost::mpl::false_) const
1530        {
1531            // From is NOT convertible to To !!!
1532            throw std::bad_cast();
1533            return To();
1534        }
1535
1536        template <typename From>
1537        To operator()(From const& val) const
1538        {
1539            // boost::iterator_range has a templated constructor, accepting
1540            // any argument and hence any type is 'convertible' to it.
1541            typedef typename boost::mpl::eval_if<
1542                is_iterator_range<To>
1543              , boost::is_same<From, To>, boost::is_convertible<From, To>
1544            >::type is_convertible;
1545            return dispatch(val, is_convertible());
1546        }
1547    };
1548
1549    template <typename T>
1550    struct utree_cast<T*>
1551    {
1552        typedef T* result_type;
1553
1554        template <typename From>
1555        T* operator()(From const&) const
1556        {
1557            // From is NOT convertible to T !!!
1558            throw std::bad_cast();
1559            return 0;
1560        }
1561
1562        T* operator()(any_ptr const& p) const
1563        {
1564            return p.get<T*>();
1565        }
1566    };
1567
1568    template <typename T>
1569    inline T utree::get() const
1570    {
1571        return utree::visit(*this, utree_cast<T>());
1572    }
1573
1574    inline utree& utree::deref()
1575    {
1576        return (get_type() == type::reference_type) ? *p : *this;
1577    }
1578
1579    inline utree const& utree::deref() const
1580    {
1581        return (get_type() == type::reference_type) ? *p : *this;
1582    }
1583
1584    inline short utree::tag() const
1585    {
1586        return s.tag();
1587    }
1588
1589    inline void utree::tag(short tag)
1590    {
1591        s.tag(tag);
1592    }
1593
1594    inline utree utree::eval(utree const& env) const
1595    {
1596        if (get_type() == type::reference_type)
1597            return deref().eval(env);
1598
1599        if (get_type() != type::function_type)
1600            BOOST_THROW_EXCEPTION(
1601                bad_type_exception(
1602                    "eval() called on non-function utree type", get_type()));
1603        return (*pf)(env);
1604    }
1605    
1606    inline utree utree::eval(utree& env) const
1607    {
1608        if (get_type() == type::reference_type)
1609            return deref().eval(env);
1610
1611        if (get_type() != type::function_type)
1612            BOOST_THROW_EXCEPTION(
1613                bad_type_exception(
1614                    "eval() called on non-function utree type", get_type()));
1615        return (*pf)(env);
1616    }
1617    
1618    inline utree utree::operator() (utree const& env) const
1619    {
1620        return eval(env);
1621    }
1622    
1623    inline utree utree::operator() (utree& env) const
1624    {
1625        return eval(env);
1626    }
1627}}
1628
1629#if defined(BOOST_MSVC)
1630# pragma warning(pop)
1631#endif
1632#endif