]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/tools/quickbook/src/values.cpp
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / boost / tools / quickbook / src / values.cpp
CommitLineData
7c673cae
FG
1/*=============================================================================
2 Copyright (c) 2010-2011 Daniel James
3
4 Use, modification and distribution is subject to the Boost Software
5 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6 http://www.boost.org/LICENSE_1_0.txt)
7=============================================================================*/
8
9#include "values.hpp"
7c673cae
FG
10#include <boost/current_function.hpp>
11#include <boost/lexical_cast.hpp>
11fdf7f2 12#include "files.hpp"
7c673cae 13
11fdf7f2
TL
14#define UNDEFINED_ERROR() \
15 throw value_undefined_method( \
16 std::string(BOOST_CURRENT_FUNCTION) + " not defined for " + \
17 this->type_name() + " values.");
7c673cae
FG
18
19namespace quickbook
20{
21 ////////////////////////////////////////////////////////////////////////////
22 // Value Error
11fdf7f2 23
7c673cae
FG
24 struct value_undefined_method : value_error
25 {
26 value_undefined_method(std::string const&);
27 };
11fdf7f2
TL
28
29 value_error::value_error(std::string const& x) : std::logic_error(x) {}
7c673cae
FG
30
31 value_undefined_method::value_undefined_method(std::string const& x)
11fdf7f2
TL
32 : value_error(x)
33 {
34 }
7c673cae
FG
35
36 ////////////////////////////////////////////////////////////////////////////
37 // Node
38
39 namespace detail
40 {
11fdf7f2
TL
41 value_node::value_node(tag_type t) : ref_count_(0), tag_(t), next_() {}
42
43 value_node::~value_node() {}
44
7c673cae
FG
45 file_ptr value_node::get_file() const { UNDEFINED_ERROR(); }
46 string_iterator value_node::get_position() const { UNDEFINED_ERROR(); }
47 int value_node::get_int() const { UNDEFINED_ERROR(); }
11fdf7f2
TL
48 quickbook::string_view value_node::get_quickbook() const
49 {
50 UNDEFINED_ERROR();
51 }
7c673cae
FG
52 std::string value_node::get_encoded() const { UNDEFINED_ERROR(); }
53 value_node* value_node::get_list() const { UNDEFINED_ERROR(); }
54
55 bool value_node::empty() const { return false; }
56 bool value_node::check() const { return true; }
57 bool value_node::is_list() const { return false; }
58 bool value_node::is_encoded() const { return false; }
59 bool value_node::equals(value_node*) const { UNDEFINED_ERROR(); }
60 }
61
62 ////////////////////////////////////////////////////////////////////////////
63 // List end value
64 //
65 // A special value for marking the end of lists.
66
67 namespace detail
68 {
69 struct value_list_end_impl : public value_node
70 {
71 static value_list_end_impl instance;
11fdf7f2
TL
72
73 private:
74 value_list_end_impl() : value_node(value::default_tag)
7c673cae
FG
75 {
76 intrusive_ptr_add_ref(&instance);
77 next_ = this;
78 }
79
80 virtual char const* type_name() const { return "list end"; }
81 virtual value_node* clone() const { UNDEFINED_ERROR(); }
82
83 virtual bool equals(value_node* other) const
11fdf7f2
TL
84 {
85 return this == other;
86 }
7c673cae
FG
87
88 bool empty() const { UNDEFINED_ERROR(); }
89 bool check() const { UNDEFINED_ERROR(); }
90 bool is_list() const { UNDEFINED_ERROR(); }
91 bool is_encoded() const { UNDEFINED_ERROR(); }
92 };
93
94 value_list_end_impl value_list_end_impl::instance;
95 }
11fdf7f2 96
7c673cae
FG
97 ////////////////////////////////////////////////////////////////////////////
98 // Empty/nil values
99 //
100 // (nil is just a special case of empty, don't be mislead by the name
101 // the type is not important).
102
103 namespace detail
104 {
105 struct empty_value_impl : public value_node
106 {
107 static value_node* new_(value::tag_type t);
108
11fdf7f2
TL
109 protected:
110 explicit empty_value_impl(value::tag_type t) : value_node(t) {}
7c673cae 111
11fdf7f2 112 private:
7c673cae 113 char const* type_name() const { return "empty"; }
11fdf7f2 114
7c673cae 115 virtual value_node* clone() const
11fdf7f2
TL
116 {
117 return new empty_value_impl(tag_);
118 }
7c673cae 119
11fdf7f2 120 virtual bool empty() const { return true; }
7c673cae 121
11fdf7f2 122 virtual bool check() const { return false; }
7c673cae
FG
123
124 virtual bool equals(value_node* other) const
11fdf7f2
TL
125 {
126 return !other->check();
127 }
128
7c673cae
FG
129 friend value quickbook::empty_value(value::tag_type);
130 };
11fdf7f2 131
7c673cae
FG
132 struct value_nil_impl : public empty_value_impl
133 {
134 static value_nil_impl instance;
11fdf7f2
TL
135
136 private:
137 value_nil_impl() : empty_value_impl(value::default_tag)
7c673cae
FG
138 {
139 intrusive_ptr_add_ref(&instance);
140 next_ = &value_list_end_impl::instance;
141 }
142 };
143
144 value_nil_impl value_nil_impl::instance;
145
11fdf7f2
TL
146 value_node* empty_value_impl::new_(value::tag_type t)
147 {
7c673cae
FG
148 // The return value from this function is always placed in an
149 // intrusive_ptr which will manage the memory correctly.
150 // Note that value_nil_impl increments its reference count
151 // in its constructor, so that it will never be deleted by the
152 // intrusive pointer.
153
154 if (t == value::default_tag)
155 return &value_nil_impl::instance;
156 else
157 return new empty_value_impl(t);
158 }
159 }
160
161 value empty_value(value::tag_type t)
162 {
163 return value(detail::empty_value_impl::new_(t));
164 }
165
166 ////////////////////////////////////////////////////////////////////////////
167 // value_counted
168
169 namespace detail
170 {
11fdf7f2 171 value_counted::value_counted() : value_base(&value_nil_impl::instance)
7c673cae
FG
172 {
173 // Even though empty is not on the heap, its reference
174 // counter needs to be incremented so that the destructor
175 // doesn't try to delete it.
176
177 intrusive_ptr_add_ref(value_);
178 }
11fdf7f2
TL
179
180 value_counted::value_counted(value_counted const& x) : value_base(x)
7c673cae
FG
181 {
182 intrusive_ptr_add_ref(value_);
183 }
11fdf7f2
TL
184
185 value_counted::value_counted(value_base const& x) : value_base(x)
7c673cae
FG
186 {
187 intrusive_ptr_add_ref(value_);
188 }
11fdf7f2
TL
189
190 value_counted::value_counted(value_node* x) : value_base(x)
7c673cae
FG
191 {
192 intrusive_ptr_add_ref(value_);
193 }
11fdf7f2
TL
194
195 value_counted::~value_counted() { intrusive_ptr_release(value_); }
7c673cae 196 }
11fdf7f2 197
7c673cae
FG
198 ////////////////////////////////////////////////////////////////////////////
199 // value
200
11fdf7f2 201 value::value() : detail::value_counted() {}
7c673cae 202
11fdf7f2 203 value::value(value const& x) : detail::value_counted(x) {}
7c673cae 204
11fdf7f2 205 value::value(detail::value_base const& x) : detail::value_counted(x) {}
7c673cae 206
11fdf7f2 207 value::value(detail::value_node* x) : detail::value_counted(x) {}
7c673cae
FG
208
209 value& value::operator=(value x)
210 {
211 swap(x);
212 return *this;
213 }
214
215 ////////////////////////////////////////////////////////////////////////////
216 // Integers
217
218 namespace detail
219 {
220 struct int_value_impl : public value_node
221 {
11fdf7f2 222 public:
7c673cae 223 explicit int_value_impl(int, value::tag_type);
11fdf7f2
TL
224
225 private:
7c673cae
FG
226 char const* type_name() const { return "integer"; }
227 virtual value_node* clone() const;
228 virtual int get_int() const;
229 virtual std::string get_encoded() const;
230 virtual bool empty() const;
231 virtual bool is_encoded() const;
232 virtual bool equals(value_node*) const;
233
234 int value_;
235 };
236
237 int_value_impl::int_value_impl(int v, value::tag_type t)
11fdf7f2
TL
238 : value_node(t), value_(v)
239 {
240 }
7c673cae
FG
241
242 value_node* int_value_impl::clone() const
243 {
244 return new int_value_impl(value_, tag_);
245 }
246
11fdf7f2 247 int int_value_impl::get_int() const { return value_; }
7c673cae
FG
248
249 std::string int_value_impl::get_encoded() const
250 {
251 return boost::lexical_cast<std::string>(value_);
252 }
253
11fdf7f2 254 bool int_value_impl::empty() const { return false; }
7c673cae 255
11fdf7f2 256 bool int_value_impl::is_encoded() const { return true; }
7c673cae 257
11fdf7f2
TL
258 bool int_value_impl::equals(value_node* other) const
259 {
7c673cae
FG
260 try {
261 return value_ == other->get_int();
11fdf7f2 262 } catch (value_undefined_method&) {
7c673cae
FG
263 return false;
264 }
265 }
266 }
267
268 value int_value(int v, value::tag_type t)
269 {
270 return value(new detail::int_value_impl(v, t));
271 }
272
273 ////////////////////////////////////////////////////////////////////////////
274 // Strings
275
276 namespace detail
277 {
278 struct encoded_value_impl : public value_node
279 {
11fdf7f2 280 public:
7c673cae 281 explicit encoded_value_impl(std::string const&, value::tag_type);
11fdf7f2
TL
282
283 private:
7c673cae
FG
284 char const* type_name() const { return "encoded text"; }
285
286 virtual ~encoded_value_impl();
287 virtual value_node* clone() const;
288 virtual std::string get_encoded() const;
289 virtual bool empty() const;
290 virtual bool is_encoded() const;
291 virtual bool equals(value_node*) const;
292
293 std::string value_;
294 };
11fdf7f2 295
7c673cae
FG
296 struct qbk_value_impl : public value_node
297 {
11fdf7f2 298 public:
7c673cae 299 explicit qbk_value_impl(
11fdf7f2
TL
300 file_ptr const&,
301 string_iterator begin,
302 string_iterator end,
303 value::tag_type);
304
305 private:
7c673cae
FG
306 char const* type_name() const { return "quickbook"; }
307
308 virtual ~qbk_value_impl();
309 virtual value_node* clone() const;
310 virtual file_ptr get_file() const;
311 virtual string_iterator get_position() const;
b32b8144 312 virtual quickbook::string_view get_quickbook() const;
7c673cae
FG
313 virtual bool empty() const;
314 virtual bool equals(value_node*) const;
315
316 file_ptr file_;
317 string_iterator begin_;
318 string_iterator end_;
319 };
11fdf7f2 320
7c673cae
FG
321 struct encoded_qbk_value_impl : public value_node
322 {
11fdf7f2
TL
323 private:
324 char const* type_name() const
325 {
326 return "encoded text with quickbook reference";
327 }
328
329 encoded_qbk_value_impl(
330 file_ptr const&,
331 string_iterator,
332 string_iterator,
333 std::string const&,
334 value::tag_type);
7c673cae 335
7c673cae
FG
336 virtual ~encoded_qbk_value_impl();
337 virtual value_node* clone() const;
338 virtual file_ptr get_file() const;
339 virtual string_iterator get_position() const;
b32b8144 340 virtual quickbook::string_view get_quickbook() const;
7c673cae
FG
341 virtual std::string get_encoded() const;
342 virtual bool empty() const;
343 virtual bool is_encoded() const;
344 virtual bool equals(value_node*) const;
345
346 file_ptr file_;
347 string_iterator begin_;
348 string_iterator end_;
349 std::string encoded_value_;
11fdf7f2 350
7c673cae 351 friend quickbook::value quickbook::encoded_qbk_value(
11fdf7f2
TL
352 file_ptr const&,
353 string_iterator,
354 string_iterator,
355 std::string const&,
356 quickbook::value::tag_type);
7c673cae
FG
357 };
358
359 // encoded_value_impl
11fdf7f2 360
7c673cae 361 encoded_value_impl::encoded_value_impl(
11fdf7f2 362 std::string const& val, value::tag_type tag)
7c673cae
FG
363 : value_node(tag), value_(val)
364 {
365 }
11fdf7f2
TL
366
367 encoded_value_impl::~encoded_value_impl() {}
7c673cae
FG
368
369 value_node* encoded_value_impl::clone() const
370 {
371 return new encoded_value_impl(value_, tag_);
372 }
7c673cae 373
11fdf7f2
TL
374 std::string encoded_value_impl::get_encoded() const { return value_; }
375
376 bool encoded_value_impl::empty() const { return value_.empty(); }
7c673cae 377
11fdf7f2 378 bool encoded_value_impl::is_encoded() const { return true; }
7c673cae 379
11fdf7f2
TL
380 bool encoded_value_impl::equals(value_node* other) const
381 {
7c673cae
FG
382 try {
383 return value_ == other->get_encoded();
11fdf7f2 384 } catch (value_undefined_method&) {
7c673cae
FG
385 return false;
386 }
387 }
388
389 // qbk_value_impl
11fdf7f2 390
7c673cae 391 qbk_value_impl::qbk_value_impl(
11fdf7f2
TL
392 file_ptr const& f,
393 string_iterator begin,
394 string_iterator end,
395 value::tag_type tag)
396 : value_node(tag), file_(f), begin_(begin), end_(end)
7c673cae
FG
397 {
398 }
11fdf7f2
TL
399
400 qbk_value_impl::~qbk_value_impl() {}
401
7c673cae
FG
402 value_node* qbk_value_impl::clone() const
403 {
404 return new qbk_value_impl(file_, begin_, end_, tag_);
405 }
406
11fdf7f2 407 file_ptr qbk_value_impl::get_file() const { return file_; }
7c673cae 408
11fdf7f2 409 string_iterator qbk_value_impl::get_position() const { return begin_; }
7c673cae 410
b32b8144 411 quickbook::string_view qbk_value_impl::get_quickbook() const
11fdf7f2
TL
412 {
413 return quickbook::string_view(begin_, end_ - begin_);
414 }
7c673cae 415
11fdf7f2
TL
416 bool qbk_value_impl::empty() const { return begin_ == end_; }
417
418 bool qbk_value_impl::equals(value_node* other) const
419 {
7c673cae
FG
420 try {
421 return this->get_quickbook() == other->get_quickbook();
11fdf7f2 422 } catch (value_undefined_method&) {
7c673cae
FG
423 return false;
424 }
425 }
426
427 // encoded_qbk_value_impl
11fdf7f2 428
7c673cae 429 encoded_qbk_value_impl::encoded_qbk_value_impl(
11fdf7f2
TL
430 file_ptr const& f,
431 string_iterator begin,
432 string_iterator end,
433 std::string const& encoded,
434 value::tag_type tag)
7c673cae
FG
435 : value_node(tag)
436 , file_(f)
437 , begin_(begin)
438 , end_(end)
439 , encoded_value_(encoded)
11fdf7f2 440
7c673cae
FG
441 {
442 }
443
11fdf7f2
TL
444 encoded_qbk_value_impl::~encoded_qbk_value_impl() {}
445
7c673cae
FG
446 value_node* encoded_qbk_value_impl::clone() const
447 {
448 return new encoded_qbk_value_impl(
11fdf7f2 449 file_, begin_, end_, encoded_value_, tag_);
7c673cae
FG
450 }
451
11fdf7f2 452 file_ptr encoded_qbk_value_impl::get_file() const { return file_; }
7c673cae
FG
453
454 string_iterator encoded_qbk_value_impl::get_position() const
11fdf7f2
TL
455 {
456 return begin_;
457 }
7c673cae 458
b32b8144 459 quickbook::string_view encoded_qbk_value_impl::get_quickbook() const
11fdf7f2
TL
460 {
461 return quickbook::string_view(begin_, end_ - begin_);
462 }
7c673cae
FG
463
464 std::string encoded_qbk_value_impl::get_encoded() const
11fdf7f2
TL
465 {
466 return encoded_value_;
467 }
7c673cae
FG
468
469 // Should this test the quickbook, the boostbook or both?
470 bool encoded_qbk_value_impl::empty() const
11fdf7f2
TL
471 {
472 return encoded_value_.empty();
473 }
7c673cae 474
11fdf7f2 475 bool encoded_qbk_value_impl::is_encoded() const { return true; }
7c673cae 476
11fdf7f2
TL
477 bool encoded_qbk_value_impl::equals(value_node* other) const
478 {
7c673cae
FG
479 try {
480 return this->get_quickbook() == other->get_quickbook();
11fdf7f2 481 } catch (value_undefined_method&) {
7c673cae 482 }
7c673cae
FG
483
484 try {
485 return this->get_encoded() == other->get_encoded();
11fdf7f2 486 } catch (value_undefined_method&) {
7c673cae 487 }
7c673cae
FG
488
489 return false;
490 }
491 }
492
11fdf7f2
TL
493 value qbk_value(
494 file_ptr const& f,
495 string_iterator x,
496 string_iterator y,
497 value::tag_type t)
7c673cae
FG
498 {
499 return value(new detail::qbk_value_impl(f, x, y, t));
500 }
501
502 value encoded_value(std::string const& x, value::tag_type t)
503 {
504 return value(new detail::encoded_value_impl(x, t));
505 }
506
507 value encoded_qbk_value(
11fdf7f2
TL
508 file_ptr const& f,
509 string_iterator x,
510 string_iterator y,
511 std::string const& z,
512 value::tag_type t)
7c673cae 513 {
11fdf7f2 514 return value(new detail::encoded_qbk_value_impl(f, x, y, z, t));
7c673cae
FG
515 }
516
517 //////////////////////////////////////////////////////////////////////////
518 // List methods
11fdf7f2 519
7c673cae
FG
520 namespace detail
521 {
11fdf7f2
TL
522 namespace
523 {
524 value_node** list_ref_back(value_node**);
525 void list_ref(value_node*);
526 void list_unref(value_node*);
527 value_node** merge_sort(value_node**);
528 value_node** merge_sort(value_node**, int);
529 value_node** merge(value_node**, value_node**, value_node**);
530 void rotate(value_node**, value_node**, value_node**);
531
532 value_node** list_ref_back(value_node** back)
533 {
534 while (*back != &value_list_end_impl::instance) {
535 intrusive_ptr_add_ref(*back);
536 back = &(*back)->next_;
537 }
538
539 return back;
7c673cae 540 }
7c673cae 541
11fdf7f2
TL
542 void list_ref(value_node* ptr)
543 {
544 while (ptr != &value_list_end_impl::instance) {
545 intrusive_ptr_add_ref(ptr);
546 ptr = ptr->next_;
547 }
7c673cae 548 }
7c673cae 549
11fdf7f2
TL
550 void list_unref(value_node* ptr)
551 {
552 while (ptr != &value_list_end_impl::instance) {
553 value_node* next = ptr->next_;
554 intrusive_ptr_release(ptr);
555 ptr = next;
556 }
7c673cae 557 }
7c673cae 558
11fdf7f2
TL
559 value_node** merge_sort(value_node** l)
560 {
561 if (*l == &value_list_end_impl::instance)
562 return l;
563 else
564 return merge_sort(l, 9999);
565 }
7c673cae 566
11fdf7f2 567 value_node** merge_sort(value_node** l, int recurse_limit)
7c673cae 568 {
11fdf7f2
TL
569 value_node** p = &(*l)->next_;
570 for (int count = 0; count < recurse_limit &&
571 *p != &value_list_end_impl::instance;
572 ++count) {
573 p = merge(l, p, merge_sort(p, count));
574 }
575 return p;
7c673cae 576 }
11fdf7f2
TL
577
578 value_node** merge(
7c673cae 579 value_node** first, value_node** second, value_node** third)
11fdf7f2
TL
580 {
581 for (;;) {
582 for (;;) {
583 if (first == second) return third;
584 if ((*second)->tag_ < (*first)->tag_) break;
585 first = &(*first)->next_;
586 }
587
588 rotate(first, second, third);
7c673cae 589 first = &(*first)->next_;
11fdf7f2
TL
590
591 // Since the two ranges were just swapped, the order is now:
592 // first...third...second
593 //
594 // Also, that since the second section of the list was
595 // originally before the first, if the heads are equal
596 // we need to swap to maintain the order.
597
598 for (;;) {
599 if (first == third) return second;
600 if ((*third)->tag_ <= (*first)->tag_) break;
601 first = &(*first)->next_;
602 }
603
604 rotate(first, third, second);
7c673cae
FG
605 first = &(*first)->next_;
606 }
7c673cae 607 }
7c673cae 608
11fdf7f2
TL
609 void rotate(
610 value_node** first, value_node** second, value_node** third)
611 {
612 value_node* tmp = *first;
613 *first = *second;
614 *second = *third;
615 *third = tmp;
616 // if(*second != &value_list_end_impl::instance) back = second;
617 }
7c673cae
FG
618 }
619 }
7c673cae
FG
620
621 //////////////////////////////////////////////////////////////////////////
622 // Lists
11fdf7f2 623
7c673cae
FG
624 namespace detail
625 {
626 struct value_list_impl : public value_node
627 {
628 value_list_impl(value::tag_type);
629 value_list_impl(value_list_builder&, value::tag_type);
11fdf7f2
TL
630
631 private:
7c673cae
FG
632 value_list_impl(value_list_impl const&);
633
634 char const* type_name() const { return "list"; }
635
636 virtual ~value_list_impl();
637 virtual value_node* clone() const;
638 virtual bool empty() const;
639 virtual bool equals(value_node*) const;
640
641 virtual bool is_list() const;
642 virtual value_node* get_list() const;
11fdf7f2 643
7c673cae
FG
644 value_node* head_;
645 };
11fdf7f2 646
7c673cae
FG
647 value_list_impl::value_list_impl(value::tag_type tag)
648 : value_node(tag), head_(&value_list_end_impl::instance)
11fdf7f2
TL
649 {
650 }
651
652 value_list_impl::value_list_impl(
653 value_list_builder& builder, value::tag_type tag)
7c673cae
FG
654 : value_node(tag), head_(builder.release())
655 {
656 }
657
658 value_list_impl::value_list_impl(value_list_impl const& x)
659 : value_node(x.tag_), head_(x.head_)
660 {
661 list_ref(head_);
662 }
11fdf7f2
TL
663
664 value_list_impl::~value_list_impl() { list_unref(head_); }
7c673cae
FG
665
666 value_node* value_list_impl::clone() const
667 {
668 return new value_list_impl(*this);
669 }
670
671 bool value_list_impl::empty() const
672 {
673 return head_ == &value_list_end_impl::instance;
674 }
7c673cae 675
11fdf7f2
TL
676 bool value_list_impl::is_list() const { return true; }
677
678 value_node* value_list_impl::get_list() const { return head_; }
679
680 bool value_list_impl::equals(value_node* other) const
681 {
7c673cae
FG
682 value_node* x1;
683
684 try {
11fdf7f2
TL
685 x1 = other->get_list();
686 } catch (value_undefined_method&) {
7c673cae
FG
687 return false;
688 }
689
11fdf7f2
TL
690 for (value_node *x2 = head_; x1 != x2;
691 x1 = x1->next_, x2 = x2->next_) {
692 if (x2 == &value_list_end_impl::instance || !x1->equals(x2))
693 return false;
7c673cae 694 }
11fdf7f2 695
7c673cae
FG
696 return true;
697 }
698 }
699
700 //////////////////////////////////////////////////////////////////////////
701 // List builder
11fdf7f2 702
7c673cae
FG
703 namespace detail
704 {
705 // value_list_builder
11fdf7f2 706
7c673cae 707 value_list_builder::value_list_builder()
11fdf7f2
TL
708 : head_(&value_list_end_impl::instance), back_(&head_)
709 {
710 }
7c673cae
FG
711
712 value_list_builder::value_list_builder(value_node* ptr)
11fdf7f2 713 : head_(ptr), back_(list_ref_back(&head_))
7c673cae 714 {
7c673cae
FG
715 }
716
11fdf7f2
TL
717 value_list_builder::~value_list_builder() { list_unref(head_); }
718
719 void value_list_builder::swap(value_list_builder& other)
720 {
7c673cae
FG
721 std::swap(head_, other.head_);
722 std::swap(back_, other.back_);
11fdf7f2
TL
723 if (back_ == &other.head_) back_ = &head_;
724 if (other.back_ == &head_) other.back_ = &other.head_;
7c673cae
FG
725 }
726
11fdf7f2
TL
727 value_node* value_list_builder::release()
728 {
7c673cae
FG
729 value_node* r = head_;
730 head_ = &value_list_end_impl::instance;
731 back_ = &head_;
732 return r;
733 }
11fdf7f2 734
7c673cae
FG
735 void value_list_builder::append(value_node* item)
736 {
11fdf7f2 737 if (item->next_) item = item->clone();
7c673cae
FG
738 intrusive_ptr_add_ref(item);
739 item->next_ = *back_;
740 *back_ = item;
741 back_ = &item->next_;
742 }
11fdf7f2 743
7c673cae
FG
744 void value_list_builder::sort()
745 {
746 back_ = merge_sort(&head_);
747 assert(*back_ == &value_list_end_impl::instance);
748 }
749
750 bool value_list_builder::empty() const
751 {
752 return head_ == &value_list_end_impl::instance;
753 }
754 }
755
756 //////////////////////////////////////////////////////////////////////////
757 // Value builder
11fdf7f2 758
7c673cae 759 value_builder::value_builder()
11fdf7f2 760 : current(), list_tag(value::default_tag), saved()
7c673cae
FG
761 {
762 }
11fdf7f2
TL
763
764 void value_builder::swap(value_builder& other)
765 {
7c673cae
FG
766 current.swap(other.current);
767 std::swap(list_tag, other.list_tag);
768 saved.swap(other.saved);
769 }
11fdf7f2
TL
770
771 void value_builder::save()
772 {
7c673cae
FG
773 boost::scoped_ptr<value_builder> store(new value_builder);
774 swap(*store);
775 saved.swap(store);
776 }
777
11fdf7f2
TL
778 void value_builder::restore()
779 {
7c673cae
FG
780 boost::scoped_ptr<value_builder> store;
781 store.swap(saved);
782 swap(*store);
783 }
784
11fdf7f2
TL
785 value value_builder::release()
786 {
7c673cae
FG
787 return value(new detail::value_list_impl(current, list_tag));
788 }
789
11fdf7f2
TL
790 void value_builder::insert(value const& item)
791 {
7c673cae
FG
792 current.append(item.value_);
793 }
794
11fdf7f2
TL
795 void value_builder::extend(value const& list)
796 {
7c673cae 797 for (value::iterator begin = list.begin(), end = list.end();
11fdf7f2 798 begin != end; ++begin) {
7c673cae
FG
799 insert(*begin);
800 }
801 }
802
11fdf7f2
TL
803 void value_builder::start_list(value::tag_type tag)
804 {
7c673cae
FG
805 save();
806 list_tag = tag;
807 }
808
11fdf7f2
TL
809 void value_builder::finish_list()
810 {
7c673cae
FG
811 value list = release();
812 restore();
813 insert(list);
814 }
815
11fdf7f2 816 void value_builder::clear_list() { restore(); }
7c673cae 817
11fdf7f2 818 void value_builder::sort_list() { current.sort(); }
7c673cae 819
11fdf7f2 820 bool value_builder::empty() const { return current.empty(); }
7c673cae
FG
821
822 ////////////////////////////////////////////////////////////////////////////
823 // Iterator
824
825 namespace detail
826 {
11fdf7f2 827 value::iterator::iterator() : ptr_(&value_list_end_impl::instance) {}
7c673cae
FG
828 }
829}