|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r70565 - in trunk/tools/quickbook: src test/unit
From: dnljms_at_[hidden]
Date: 2011-03-26 07:13:09
Author: danieljames
Date: 2011-03-26 07:13:07 EDT (Sat, 26 Mar 2011)
New Revision: 70565
URL: http://svn.boost.org/trac/boost/changeset/70565
Log:
Quickbook: Iterator tests. Equality operator for values.
The equality operator is pretty inefficient. Just for testing really.
Added:
trunk/tools/quickbook/test/unit/iterator_tests.cpp (contents, props changed)
Text files modified:
trunk/tools/quickbook/src/doc_info_grammar.cpp | 10
trunk/tools/quickbook/src/values.cpp | 204 +++++++++++++++++++++++++++++++--------
trunk/tools/quickbook/src/values.hpp | 6 +
trunk/tools/quickbook/test/unit/Jamfile.v2 | 1
trunk/tools/quickbook/test/unit/values_test.cpp | 29 +++++
5 files changed, 203 insertions(+), 47 deletions(-)
Modified: trunk/tools/quickbook/src/doc_info_grammar.cpp
==============================================================================
--- trunk/tools/quickbook/src/doc_info_grammar.cpp (original)
+++ trunk/tools/quickbook/src/doc_info_grammar.cpp 2011-03-26 07:13:07 EDT (Sat, 26 Mar 2011)
@@ -248,11 +248,11 @@
[cl::chset<>("0-9a-fA-F")]
[actions.escape_unicode]
| ("'''" >> !eol)
- >> actions.values.save()
- [ (*(cl::anychar_p - "'''"))
- [actions.values.entry(ph::arg1, ph::arg2, phrase_tags::escape)]
- >> cl::str_p("'''") [actions.element]
- ]
+ >> actions.values.save()
+ [ (*(cl::anychar_p - "'''"))
+ [actions.values.entry(ph::arg1, ph::arg2, phrase_tags::escape)]
+ >> cl::str_p("'''") [actions.element]
+ ]
| cl::anychar_p [actions.plain_char]
;
}
Modified: trunk/tools/quickbook/src/values.cpp
==============================================================================
--- trunk/tools/quickbook/src/values.cpp (original)
+++ trunk/tools/quickbook/src/values.cpp 2011-03-26 07:13:07 EDT (Sat, 26 Mar 2011)
@@ -12,7 +12,7 @@
#include <boost/lexical_cast.hpp>
#define UNDEFINED_ERROR() \
- throw value_error( \
+ throw value_undefined_method( \
std::string(BOOST_CURRENT_FUNCTION) +\
" not defined for " + \
this->type_name() + \
@@ -24,9 +24,17 @@
////////////////////////////////////////////////////////////////////////////
// Value Error
+ struct value_undefined_method : value_error
+ {
+ value_undefined_method(std::string const&);
+ };
+
value_error::value_error(std::string const& x)
: std::logic_error(x) {}
-
+
+ value_undefined_method::value_undefined_method(std::string const& x)
+ : value_error(x) {}
+
////////////////////////////////////////////////////////////////////////////
// Node
@@ -45,16 +53,50 @@
int value_node::get_int() const { UNDEFINED_ERROR(); }
std::string value_node::get_quickbook() const { UNDEFINED_ERROR(); }
value_node::qbk_range value_node::get_quickbook_range() const { UNDEFINED_ERROR(); }
- std::string value_node::get_boostbook() const { UNDEFINED_ERROR(); }
- value_node* value_node::get_list() const { UNDEFINED_ERROR(); }
+ std::string value_node::get_boostbook() const { UNDEFINED_ERROR(); }
+ value_node* value_node::get_list() const { UNDEFINED_ERROR(); }
bool value_node::empty() const { return false; }
bool value_node::check() const { return true; }
bool value_node::is_list() const { return false; }
bool value_node::is_string() const { return false; }
+ bool value_node::equals(value_node*) const { UNDEFINED_ERROR(); }
}
////////////////////////////////////////////////////////////////////////////
+ // List end value
+ //
+ // A special value for marking the end of lists.
+
+ namespace detail
+ {
+ struct value_list_end_impl : public value_node
+ {
+ static value_list_end_impl instance;
+ private:
+ value_list_end_impl()
+ : value_node(value::default_tag)
+ {
+ intrusive_ptr_add_ref(&instance);
+ next_ = this;
+ }
+
+ virtual char const* type_name() const { return "list end"; }
+ virtual value_node* clone() const { UNDEFINED_ERROR(); }
+
+ virtual bool equals(value_node* other) const
+ { return this == other; }
+
+ bool empty() const { UNDEFINED_ERROR(); }
+ bool check() const { UNDEFINED_ERROR(); }
+ bool is_list() const { UNDEFINED_ERROR(); }
+ bool is_string() const { UNDEFINED_ERROR(); }
+ };
+
+ value_list_end_impl value_list_end_impl::instance;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
// Empty/nil values
//
// (nil is just a special case of empty, don't be mislead by the name
@@ -81,6 +123,9 @@
virtual bool check() const
{ return false; }
+
+ virtual bool equals(value_node* other) const
+ { return !other->check(); }
friend value quickbook::empty_value(value::tag_type);
};
@@ -93,9 +138,10 @@
: value_empty_impl(value::default_tag)
{
intrusive_ptr_add_ref(&instance);
+ next_ = &value_list_end_impl::instance;
}
};
-
+
value_nil_impl value_nil_impl::instance;
value_node* value_empty_impl::new_(value::tag_type t) {
@@ -112,6 +158,11 @@
}
}
+ value empty_value(value::tag_type t)
+ {
+ return value(detail::value_empty_impl::new_(t));
+ }
+
////////////////////////////////////////////////////////////////////////////
// value_counted
@@ -205,20 +256,6 @@
}
////////////////////////////////////////////////////////////////////////////
- // Iterator
-
- namespace detail
- {
- value::iterator::iterator()
- : ptr_(&value_nil_impl::instance) {}
- }
-
- value empty_value(value::tag_type t)
- {
- return value(detail::value_empty_impl::new_(t));
- }
-
- ////////////////////////////////////////////////////////////////////////////
// Integers
namespace detail
@@ -234,7 +271,8 @@
virtual std::string get_quickbook() const;
virtual std::string get_boostbook() const;
virtual bool empty() const;
-
+ virtual bool equals(value_node*) const;
+
int value_;
};
@@ -267,6 +305,15 @@
{
return false;
}
+
+ bool value_int_impl::equals(value_node* other) const {
+ try {
+ return value_ == other->get_int();
+ }
+ catch(value_undefined_method&) {
+ return false;
+ }
+ }
}
value int_value(int v, value::tag_type t)
@@ -291,7 +338,8 @@
virtual std::string get_boostbook() const;
virtual bool is_string() const;
virtual bool empty() const;
-
+ virtual bool equals(value_node*) const;
+
std::string value_;
};
@@ -313,6 +361,7 @@
qbk_range get_quickbook_range() const;
virtual bool is_string() const;
virtual bool empty() const;
+ virtual bool equals(value_node*) const;
std::string value_;
file_position position_;
@@ -333,7 +382,8 @@
qbk_range get_quickbook_range() const;
virtual bool is_string() const;
virtual bool empty() const;
-
+ virtual bool equals(value_node*) const;
+
quickbook::iterator begin_;
quickbook::iterator end_;
};
@@ -359,6 +409,7 @@
virtual std::string get_boostbook() const;
virtual bool is_string() const;
virtual bool empty() const;
+ virtual bool equals(value_node*) const;
std::string qbk_value_;
std::string bbk_value_;
@@ -399,6 +450,15 @@
bool value_string_impl::empty() const
{ return value_.empty(); }
+ bool value_string_impl::equals(value_node* other) const {
+ try {
+ return value_ == other->get_boostbook();
+ }
+ catch(value_undefined_method&) {
+ return false;
+ }
+ }
+
// value_qbk_string_impl
value_qbk_string_impl::value_qbk_string_impl(
@@ -442,7 +502,16 @@
bool value_qbk_string_impl::empty() const
{ return value_.empty(); }
-
+
+ bool value_qbk_string_impl::equals(value_node* other) const {
+ try {
+ return value_ == other->get_quickbook();
+ }
+ catch(value_undefined_method&) {
+ return false;
+ }
+ }
+
// value_qbk_ref_impl
value_qbk_ref_impl::value_qbk_ref_impl(
@@ -481,6 +550,15 @@
bool value_qbk_ref_impl::empty() const
{ return begin_ == end_; }
+ bool value_qbk_ref_impl::equals(value_node* other) const {
+ try {
+ return this->get_quickbook() == other->get_quickbook();
+ }
+ catch(value_undefined_method&) {
+ return false;
+ }
+ }
+
// value_qbk_bbk_impl
value_qbk_bbk_impl::value_qbk_bbk_impl(
@@ -549,6 +627,20 @@
// Should this test the quickbook, the boostbook or both?
bool value_qbk_bbk_impl::empty() const
{ return bbk_value_.empty(); }
+
+ bool value_qbk_bbk_impl::equals(value_node* other) const {
+ try {
+ return this->get_quickbook() == other->get_quickbook();
+ }
+ catch(value_undefined_method&) {}
+
+ try {
+ return this->get_boostbook() == other->get_boostbook();
+ }
+ catch(value_undefined_method&) {}
+
+ return false;
+ }
}
value qbk_value(iterator x, iterator y, value::tag_type t)
@@ -594,7 +686,7 @@
value_node** list_ref_back(value_node** back)
{
- while(*back != &value_nil_impl::instance) {
+ while(*back != &value_list_end_impl::instance) {
intrusive_ptr_add_ref(*back);
back = &(*back)->next_;
}
@@ -604,7 +696,7 @@
void list_ref(value_node* ptr)
{
- while(ptr != &value_nil_impl::instance) {
+ while(ptr != &value_list_end_impl::instance) {
intrusive_ptr_add_ref(ptr);
ptr = ptr->next_;
}
@@ -612,7 +704,7 @@
void list_unref(value_node* ptr)
{
- while(ptr != &value_nil_impl::instance) {
+ while(ptr != &value_list_end_impl::instance) {
value_node* next = ptr->next_;
intrusive_ptr_release(ptr);
ptr = next;
@@ -621,7 +713,7 @@
value_node** merge_sort(value_node** l)
{
- if(*l == &value_nil_impl::instance)
+ if(*l == &value_list_end_impl::instance)
return l;
else
return merge_sort(l, 9999);
@@ -631,7 +723,7 @@
{
value_node** p = &(*l)->next_;
for(int count = 0;
- count < recurse_limit && *p != &value_nil_impl::instance;
+ count < recurse_limit && *p != &value_list_end_impl::instance;
++count)
{
p = merge(l, p, merge_sort(p, count));
@@ -676,7 +768,7 @@
*first = *second;
*second = *third;
*third = tmp;
- //if(*second != &value_nil_impl::instance) back = second;
+ //if(*second != &value_list_end_impl::instance) back = second;
}
}
}
@@ -699,19 +791,20 @@
virtual value_node* clone() const;
virtual value_node* store();
virtual bool empty() const;
+ virtual bool equals(value_node*) const;
+
virtual bool is_list() const;
-
virtual value_node* get_list() const;
value_node* head_;
};
-
+
value_list_impl::value_list_impl(value::tag_type tag)
- : value_node(tag), head_(&value_nil_impl::instance)
+ : value_node(tag), head_(&value_list_end_impl::instance)
{}
value_list_impl::value_list_impl(value_list_builder& builder,
- value::tag_type tag)
+ value::tag_type tag)
: value_node(tag), head_(builder.release())
{
}
@@ -738,7 +831,7 @@
boost::intrusive_ptr<value_node> new_node;
for(;;) {
- if(pos == &value_nil_impl::instance)
+ if(pos == &value_list_end_impl::instance)
return this;
new_node = pos->store();
if(new_node.get() != pos) break;
@@ -755,16 +848,15 @@
build.append(new_node.get());
pos2 = pos2->next_;
- for(;pos2 != &value_nil_impl::instance; pos2 = pos2->next_)
+ for(;pos2 != &value_list_end_impl::instance; pos2 = pos2->next_)
build.append(pos2->store());
return new value_list_impl(build, tag_);
}
-
bool value_list_impl::empty() const
{
- return head_ == &value_nil_impl::instance;
+ return head_ == &value_list_end_impl::instance;
}
bool value_list_impl::is_list() const
@@ -776,6 +868,25 @@
{
return head_;
}
+
+ bool value_list_impl::equals(value_node* other) const {
+ value_node* x1;
+
+ try {
+ x1 = other->get_list();
+ }
+ catch(value_undefined_method&) {
+ return false;
+ }
+
+ for(value_node *x2 = head_; x1 != x2; x1 = x1->next_, x2 = x2->next_)
+ {
+ if (x2 == &value_list_end_impl::instance ||
+ !x1->equals(x2)) return false;
+ }
+
+ return true;
+ }
}
//////////////////////////////////////////////////////////////////////////
@@ -786,7 +897,7 @@
// value_list_builder
value_list_builder::value_list_builder()
- : head_(&value_nil_impl::instance)
+ : head_(&value_list_end_impl::instance)
, back_(&head_)
{}
@@ -808,9 +919,9 @@
}
value_node* value_list_builder::release() {
- value_node* r = head_;
- head_ = &value_nil_impl::instance;
- back_ = &head_;
+ value_node* r = head_;
+ head_ = &value_list_end_impl::instance;
+ back_ = &head_;
return r;
}
@@ -826,7 +937,7 @@
void value_list_builder::sort()
{
back_ = merge_sort(&head_);
- assert(*back_ == &value_nil_impl::instance);
+ assert(*back_ == &value_list_end_impl::instance);
}
}
@@ -900,4 +1011,13 @@
{
current.sort();
}
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Iterator
+
+ namespace detail
+ {
+ value::iterator::iterator()
+ : ptr_(&value_list_end_impl::instance) {}
+ }
}
Modified: trunk/tools/quickbook/src/values.hpp
==============================================================================
--- trunk/tools/quickbook/src/values.hpp (original)
+++ trunk/tools/quickbook/src/values.hpp 2011-03-26 07:13:07 EDT (Sat, 26 Mar 2011)
@@ -61,6 +61,7 @@
virtual bool empty() const;
virtual bool is_list() const;
virtual bool is_string() const;
+ virtual bool equals(value_node*) const;
virtual value_node* get_list() const;
@@ -122,6 +123,11 @@
int get_int() const
{ return value_->get_int(); }
+ // Equality is pretty inefficient. Not really designed for anything
+ // more than testing purposes.
+ friend bool operator==(value_base const& x, value_base const& y)
+ { return x.value_->equals(y.value_); }
+
protected:
value_node* value_;
Modified: trunk/tools/quickbook/test/unit/Jamfile.v2
==============================================================================
--- trunk/tools/quickbook/test/unit/Jamfile.v2 (original)
+++ trunk/tools/quickbook/test/unit/Jamfile.v2 2011-03-26 07:13:07 EDT (Sat, 26 Mar 2011)
@@ -6,3 +6,4 @@
run values_test.cpp ../../src/values.cpp ;
run post_process_test.cpp ../../src/post_process.cpp ;
+run iterator_tests.cpp ../../src/values.cpp ;
Added: trunk/tools/quickbook/test/unit/iterator_tests.cpp
==============================================================================
--- (empty file)
+++ trunk/tools/quickbook/test/unit/iterator_tests.cpp 2011-03-26 07:13:07 EDT (Sat, 26 Mar 2011)
@@ -0,0 +1,71 @@
+/*=============================================================================
+ Copyright (c) 2011 Daniel James
+
+ Use, modification and distribution is subject to the Boost Software
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+// Use boost's iterator concept tests for our iterators.
+
+#include "fwd.hpp"
+#include "values.hpp"
+#include <boost/iterator/new_iterator_tests.hpp>
+#include <boost/iterator/iterator_concepts.hpp>
+#include <boost/concept_check.hpp>
+
+void iterator_concept_checks()
+{
+ typedef quickbook::iterator Iter;
+ boost::function_requires< boost::ForwardIterator<Iter> >();
+ boost::function_requires< boost_concepts::ReadableIteratorConcept<Iter> >();
+ boost::function_requires< boost_concepts::LvalueIteratorConcept<Iter> >();
+ boost::function_requires< boost_concepts::ForwardTraversalConcept<Iter> >();
+}
+
+void value_iterator_concept_checks()
+{
+ typedef quickbook::value::iterator Iter;
+ boost::function_requires< boost::ForwardIterator<Iter> >();
+ boost::function_requires< boost_concepts::ReadableIteratorConcept<Iter> >();
+ boost::function_requires< boost_concepts::ForwardTraversalConcept<Iter> >();
+}
+
+void iterator_runtime_checks()
+{
+ std::string x = "Hello World";
+
+ quickbook::iterator i1(x.begin(), quickbook::file_position(10, 5));
+ quickbook::iterator i2(++x.begin(), quickbook::file_position(10, 6));
+
+ boost::forward_readable_iterator_test(i1, i2, 'H', 'e');
+ boost::constant_lvalue_iterator_test(i1, 'H');
+}
+
+void value_iterator_runtime_checks()
+{
+ quickbook::value v1 = quickbook::bbk_value("a", 10);
+ quickbook::value v2 = quickbook::int_value(25, 32);
+
+ quickbook::value_builder b;
+ b.insert(v1);
+ b.insert(v2);
+ quickbook::value x = b.release();
+
+ quickbook::value::iterator i1 = x.begin();
+ quickbook::value::iterator i2 = ++x.begin();
+
+ boost::forward_readable_iterator_test(i1, i2, v1, v2);
+}
+
+int main()
+{
+ // I know I don't have to run the concept checks.
+ // I'm a bit irrational like that.
+ iterator_concept_checks();
+ value_iterator_concept_checks();
+ iterator_runtime_checks();
+ value_iterator_runtime_checks();
+
+ return boost::report_errors();
+}
Modified: trunk/tools/quickbook/test/unit/values_test.cpp
==============================================================================
--- trunk/tools/quickbook/test/unit/values_test.cpp (original)
+++ trunk/tools/quickbook/test/unit/values_test.cpp 2011-03-26 07:13:07 EDT (Sat, 26 Mar 2011)
@@ -11,6 +11,7 @@
#include <boost/detail/lightweight_test.hpp>
#include <boost/range/algorithm/equal.hpp>
+#include <vector>
#include "values.hpp"
void empty_tests()
@@ -131,6 +132,33 @@
store_test2_check(q);
}
+void equality_tests()
+{
+ std::vector<quickbook::value> distinct_values;
+
+ quickbook::value_builder builder;
+ quickbook::value nil;
+
+ // 0: nil
+ distinct_values.push_back(nil);
+
+ // 1: []
+ distinct_values.push_back(builder.release());
+
+ // 2: [nil]
+ builder.insert(nil);
+ distinct_values.push_back(builder.release());
+
+ for(int i = 0; i < distinct_values.size(); ++i)
+ for(int j = 0; j < distinct_values.size(); ++j)
+ if ((i == j) != (distinct_values[i] == distinct_values[j]))
+ {
+ BOOST_ERROR("Value mismatch.");
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM
+ << "\tat " << i << ", " << j << std::endl;
+ }
+}
+
int main()
{
empty_tests();
@@ -139,6 +167,7 @@
multiple_list_test();
store_test1();
store_test2();
+ equality_tests();
return boost::report_errors();
}
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk