$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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();
 }