/tools/quickbook/src/values.cpp

https://github.com/eile/boost-svn · C++ · 1023 lines · 770 code · 192 blank · 61 comment · 52 complexity · 4dd4729f00e3cdc098a7a4080c39d5c6 MD5 · raw file

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