Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r70871 - in branches/quickbook-dev/tools/quickbook: src test/unit
From: dnljms_at_[hidden]
Date: 2011-04-02 13:45:11


Author: danieljames
Date: 2011-04-02 13:45:09 EDT (Sat, 02 Apr 2011)
New Revision: 70871
URL: http://svn.boost.org/trac/boost/changeset/70871

Log:
Quickbook: Alternative tst that's cheaper to copy.
Added:
   branches/quickbook-dev/tools/quickbook/src/symbols.hpp (contents, props changed)
   branches/quickbook-dev/tools/quickbook/test/unit/symbols_add_null.cpp (contents, props changed)
   branches/quickbook-dev/tools/quickbook/test/unit/symbols_find_null.cpp (contents, props changed)
   branches/quickbook-dev/tools/quickbook/test/unit/symbols_tests.cpp (contents, props changed)
Text files modified:
   branches/quickbook-dev/tools/quickbook/src/actions.cpp | 7 ++++---
   branches/quickbook-dev/tools/quickbook/src/actions.hpp | 3 +--
   branches/quickbook-dev/tools/quickbook/src/actions_class.cpp | 25 ++-----------------------
   branches/quickbook-dev/tools/quickbook/src/actions_class.hpp | 6 +-----
   branches/quickbook-dev/tools/quickbook/test/unit/Jamfile.v2 | 5 +++++
   5 files changed, 13 insertions(+), 33 deletions(-)

Modified: branches/quickbook-dev/tools/quickbook/src/actions.cpp
==============================================================================
--- branches/quickbook-dev/tools/quickbook/src/actions.cpp (original)
+++ branches/quickbook-dev/tools/quickbook/src/actions.cpp 2011-04-02 13:45:09 EDT (Sat, 02 Apr 2011)
@@ -899,7 +899,6 @@
         std::string phrase = values.consume().get_boostbook();
         values.finish();
 
- actions.copy_macros_for_write();
         actions.macro.add(
             macro_id.begin()
           , macro_id.end()
@@ -1805,7 +1804,6 @@
 
         // scope the macros
         string_symbols macro = actions.macro;
- std::size_t macro_change_depth = actions.macro_change_depth;
         // scope the templates
         //~ template_symbols templates = actions.templates; $$$ fixme $$$
 
@@ -1837,9 +1835,12 @@
 
         // restore the macros
         actions.macro = macro;
- actions.macro_change_depth = macro_change_depth;
         // restore the templates
         //~ actions.templates = templates; $$$ fixme $$$
+
+ // restore the __FILENAME__ macro
+ *boost::spirit::classic::find(actions.macro, "__FILENAME__")
+ = detail::path_to_generic(actions.filename_relative);
     }
 
     void phrase_to_docinfo_action_impl::operator()(iterator first, iterator last,

Modified: branches/quickbook-dev/tools/quickbook/src/actions.hpp
==============================================================================
--- branches/quickbook-dev/tools/quickbook/src/actions.hpp (original)
+++ branches/quickbook-dev/tools/quickbook/src/actions.hpp 2011-04-02 13:45:09 EDT (Sat, 02 Apr 2011)
@@ -19,6 +19,7 @@
 #include "utils.hpp"
 #include "values.hpp"
 #include "scoped.hpp"
+#include "symbols.hpp"
 
 namespace quickbook
 {
@@ -51,8 +52,6 @@
         return quickbook_range(0, max_);
     }
 
- typedef cl::symbols<std::string> string_symbols;
-
     int load_snippets(std::string const& file, std::vector<template_symbol>& storage,
         std::string const& extension);
     std::string syntax_highlight(

Modified: branches/quickbook-dev/tools/quickbook/src/actions_class.cpp
==============================================================================
--- branches/quickbook-dev/tools/quickbook/src/actions_class.cpp (original)
+++ branches/quickbook-dev/tools/quickbook/src/actions_class.cpp 2011-04-02 13:45:09 EDT (Sat, 02 Apr 2011)
@@ -47,7 +47,6 @@
         , filename(filein_)
         , filename_relative(filein_.filename())
         , xinclude_base(xinclude_base_)
- , macro_change_depth(0)
         , macro()
         , section_level(0)
         , min_section_level(0)
@@ -101,7 +100,7 @@
             boost::make_tuple(
                 filename
               , xinclude_base
- , macro_change_depth
+ , macro
               , section_level
               , min_section_level
               , section_id
@@ -116,32 +115,12 @@
         values.builder.save();
     }
     
- // Pushing and popping the macro symbol table is pretty expensive, so
- // instead implement a sort of 'stack on write'. Call this whenever a
- // change is made to the macro table, and it'll stack the current macros
- // if necessary. Would probably be better to implement macros in a less
- // expensive manner.
- void actions::copy_macros_for_write()
- {
- if(macro_change_depth != state_stack.size())
- {
- macro_stack.push(macro);
- macro_change_depth = state_stack.size();
- }
- }
-
     void actions::pop()
     {
- if(macro_change_depth == state_stack.size())
- {
- macro = macro_stack.top();
- macro_stack.pop();
- }
-
         boost::tie(
             filename
           , xinclude_base
- , macro_change_depth
+ , macro
           , section_level
           , min_section_level
           , section_id

Modified: branches/quickbook-dev/tools/quickbook/src/actions_class.hpp
==============================================================================
--- branches/quickbook-dev/tools/quickbook/src/actions_class.hpp (original)
+++ branches/quickbook-dev/tools/quickbook/src/actions_class.hpp 2011-04-02 13:45:09 EDT (Sat, 02 Apr 2011)
@@ -71,7 +71,6 @@
                                                     // (relative to the original file
                                                     // or include path).
         fs::path xinclude_base;
- std::size_t macro_change_depth;
         string_symbols macro;
         int section_level;
         int min_section_level;
@@ -82,7 +81,7 @@
         typedef boost::tuple<
             fs::path
           , fs::path
- , std::size_t
+ , string_symbols
           , int
           , int
           , std::string
@@ -91,8 +90,6 @@
         state_tuple;
 
         std::stack<state_tuple> state_stack;
- // Stack macros separately as copying macros is expensive.
- std::stack<string_symbols> macro_stack;
 
     // temporary or global state
         int template_depth;
@@ -105,7 +102,6 @@
         int context;
 
     // push/pop the states and the streams
- void copy_macros_for_write();
         void push();
         void pop();
         quickbook_grammar& grammar() const;

Added: branches/quickbook-dev/tools/quickbook/src/symbols.hpp
==============================================================================
--- (empty file)
+++ branches/quickbook-dev/tools/quickbook/src/symbols.hpp 2011-04-02 13:45:09 EDT (Sat, 02 Apr 2011)
@@ -0,0 +1,279 @@
+/*=============================================================================
+ Copyright (c) 2001-2003 Joel de Guzman
+ Copyright (c) 2011 Daniel James
+ http://spirit.sourceforge.net/
+
+ 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)
+=============================================================================*/
+#ifndef QUICKBOOK_SYMBOLS_IPP
+#define QUICKBOOK_SYMBOLS_IPP
+
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/spirit/home/classic/symbols.hpp>
+#include <boost/spirit/home/classic/core/assert.hpp>
+#include <boost/intrusive_ptr.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+namespace quickbook
+{
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// tst class
+//
+// This it the Ternary Search Tree from
+// <boost/spirit/home/classic/symbols/impl/tst.ipp> adapted to be cheap
+// to copy.
+//
+// Ternary Search Tree implementation. The data structure is faster than
+// hashing for many typical search problems especially when the search
+// interface is iterator based. Searching for a string of length k in a
+// ternary search tree with n strings will require at most O(log n+k)
+// character comparisons. TSTs are many times faster than hash tables
+// for unsuccessful searches since mismatches are discovered earlier
+// after examining only a few characters. Hash tables always examine an
+// entire key when searching.
+//
+// For details see http://www.cs.princeton.edu/~rs/strings/.
+//
+// *** This is a low level class and is
+// not meant for public consumption ***
+//
+///////////////////////////////////////////////////////////////////////////////
+
+ template <typename T, typename CharT>
+ struct tst_node
+ {
+ tst_node(CharT value_)
+ : reference_count(0)
+ , value(value_)
+ , data(0)
+ {
+ }
+
+ tst_node(tst_node const& other)
+ : reference_count(0)
+ , value(other.value)
+ , left(other.left)
+ , middle(other.middle)
+ , right(other.right)
+ , data(0)
+ {
+ if (other.data)
+ data = new T(*other.data);
+ }
+
+ tst_node& operator=(tst_node other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ ~tst_node()
+ {
+ delete data;
+ }
+
+ void swap(tst_node& x, tst_node& y)
+ {
+ boost::swap(x.reference_count, y.reference_count);
+ boost::swap(x.value, y.value);
+ boost::swap(x.left, y.left);
+ boost::swap(x.middle, y.middle);
+ boost::swap(x.right, y.right);
+ boost::swap(x.data, y.data);
+ }
+
+ short reference_count;
+ CharT value;
+ boost::intrusive_ptr<tst_node> left;
+ boost::intrusive_ptr<tst_node> middle;
+ boost::intrusive_ptr<tst_node> right;
+ T* data;
+ };
+
+ template <typename T, typename CharT>
+ void intrusive_ptr_add_ref(tst_node<T, CharT>* ptr)
+ { ++ptr->reference_count; }
+
+ template <typename T, typename CharT>
+ void intrusive_ptr_release(tst_node<T, CharT>* ptr)
+ { if(--ptr->reference_count == 0) delete ptr; }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename T, typename CharT>
+ class tst
+ {
+ public:
+
+ struct search_info
+ {
+ T* data;
+ std::size_t length;
+ };
+
+ void swap(tst& other)
+ {
+ root.swap(other.root);
+ }
+
+ // TODO: Make sure you check for readdition.
+ template <typename IteratorT>
+ T* add(IteratorT first, IteratorT const& last, T const& data)
+ {
+ if (first == last)
+ return 0;
+
+ node_ptr* np = &root;
+ CharT ch = *first;
+
+ BOOST_SPIRIT_ASSERT((first == last || ch != 0)
+ && "Won't add string containing null character");
+
+ for (;;)
+ {
+ if (!*np || ch == 0)
+ {
+ node_ptr right = *np;
+ *np = new node_t(ch);
+ if (right)
+ (*np)->right = right;
+ }
+ else if ((*np)->reference_count > 1)
+ {
+ *np = new node_t(**np);
+ }
+
+ if (ch < (*np)->value)
+ {
+ np = &(*np)->left;
+ }
+ else
+ {
+ if (ch == (*np)->value)
+ {
+ if (ch == 0)
+ {
+ if ((*np)->data == 0)
+ {
+ (*np)->data = new T(data);
+ return (*np)->data;
+ }
+ else
+ {
+ // re-addition is disallowed
+ return 0;
+ }
+ }
+ ++first;
+ ch = (first == last) ? CharT(0) : *first;
+ BOOST_SPIRIT_ASSERT((first == last || ch != 0)
+ && "Won't add string containing null character");
+ np = &(*np)->middle;
+ }
+ else
+ {
+ np = &(*np)->right;
+ }
+ }
+ }
+ }
+
+ template <typename ScannerT>
+ search_info find(ScannerT const& scan) const
+ {
+ search_info result = { 0, 0 };
+ if (scan.at_end()) {
+ return result;
+ }
+
+ typedef typename ScannerT::iterator_t iterator_t;
+ node_ptr np = root;
+ CharT ch = *scan;
+ iterator_t save = scan.first;
+ iterator_t latest = scan.first;
+ std::size_t latest_len = 0;
+
+ while (np)
+ {
+
+ if (ch < np->value) // => go left!
+ {
+ if (np->value == 0)
+ {
+ result.data = np->data;
+ if (result.data)
+ {
+ latest = scan.first;
+ latest_len = result.length;
+ }
+ }
+
+ np = np->left;
+ }
+ else if (ch == np->value) // => go middle!
+ {
+ // Matching the null character is not allowed.
+ if (np->value == 0)
+ {
+ result.data = np->data;
+ if (result.data)
+ {
+ latest = scan.first;
+ latest_len = result.length;
+ }
+ break;
+ }
+
+ ++scan;
+ ch = scan.at_end() ? CharT(0) : *scan;
+ np = np->middle;
+ ++result.length;
+ }
+ else // (ch > np->value) => go right!
+ {
+ if (np->value == 0)
+ {
+ result.data = np->data;
+ if (result.data)
+ {
+ latest = scan.first;
+ latest_len = result.length;
+ }
+ }
+
+ np = np->right;
+ }
+ }
+
+ if (result.data == 0)
+ {
+ scan.first = save;
+ }
+ else
+ {
+ scan.first = latest;
+ result.length = latest_len;
+ }
+ return result;
+ }
+
+ private:
+
+ typedef tst_node<T, CharT> node_t;
+ typedef boost::intrusive_ptr<node_t> node_ptr;
+ node_ptr root;
+ };
+
+ typedef boost::spirit::classic::symbols<
+ std::string,
+ char,
+ quickbook::tst<std::string, char>
+ > string_symbols;
+} // namespace quickbook
+
+#endif

Modified: branches/quickbook-dev/tools/quickbook/test/unit/Jamfile.v2
==============================================================================
--- branches/quickbook-dev/tools/quickbook/test/unit/Jamfile.v2 (original)
+++ branches/quickbook-dev/tools/quickbook/test/unit/Jamfile.v2 2011-04-02 13:45:09 EDT (Sat, 02 Apr 2011)
@@ -7,3 +7,8 @@
 run values_test.cpp ../../src/values.cpp ;
 run post_process_test.cpp ../../src/post_process.cpp ;
 run iterator_tests.cpp ../../src/values.cpp ;
+
+# Copied from spirit
+run symbols_tests.cpp ;
+run symbols_add_null.cpp ;
+run symbols_find_null.cpp ;
\ No newline at end of file

Added: branches/quickbook-dev/tools/quickbook/test/unit/symbols_add_null.cpp
==============================================================================
--- (empty file)
+++ branches/quickbook-dev/tools/quickbook/test/unit/symbols_add_null.cpp 2011-04-02 13:45:09 EDT (Sat, 02 Apr 2011)
@@ -0,0 +1,79 @@
+/*=============================================================================
+ Copyright (c) 2004 Joao Abecasis
+ http://spirit.sourceforge.net/
+
+ 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)
+=============================================================================*/
+
+// This test requires NDEBUG to be undefined, because it depends on
+// BOOST_SPIRIT_ASSERT throwing an exception.
+#ifdef NDEBUG
+# undef NDEBUG
+#endif
+
+#include <stdexcept>
+
+#define BOOST_SPIRIT_ASSERT_EXCEPTION ::spirit_exception
+
+struct spirit_exception : std::exception
+{
+ spirit_exception(char const * msg)
+ : message(msg)
+ {
+ }
+ ~spirit_exception() throw() {}
+
+ char const* what() const throw() { return message; }
+
+ char const * message;
+};
+
+#include <boost/spirit/include/classic_scanner.hpp>
+#include <boost/utility/addressof.hpp>
+#include "symbols.hpp"
+
+#include <boost/detail/lightweight_test.hpp>
+
+typedef char char_type;
+typedef char const * iterator;
+
+char_type data_[] = "whatever";
+
+iterator begin = data_;
+iterator end = data_
+ + sizeof(data_)/sizeof(char_type); // Yes, this is an intentional bug ;)
+
+char_type data2_[] = "\0something";
+iterator begin2 = data2_;
+iterator end2 = data2_ + sizeof(data2_)/sizeof(char_type) - 1;
+
+int main()
+{
+ typedef BOOST_SPIRIT_CLASSIC_NS::scanner<> scanner;
+ typedef quickbook::tst<void *, char_type> symbols;
+
+ symbols symbols_;
+
+ try
+ {
+ // It is not ok to add strings containing the null character.
+ symbols_.add(begin, end, (void*) boost::addressof(symbols_));
+ BOOST_TEST(0);
+ }
+ catch (spirit_exception &/*e*/)
+ {
+ }
+
+ try
+ {
+ // It is not ok to add strings containing the null character.
+ symbols_.add(begin2, end2, (void*) boost::addressof(symbols_));
+ BOOST_TEST(0);
+ }
+ catch (spirit_exception &/*e*/)
+ {
+ }
+ return boost::report_errors();
+}

Added: branches/quickbook-dev/tools/quickbook/test/unit/symbols_find_null.cpp
==============================================================================
--- (empty file)
+++ branches/quickbook-dev/tools/quickbook/test/unit/symbols_find_null.cpp 2011-04-02 13:45:09 EDT (Sat, 02 Apr 2011)
@@ -0,0 +1,35 @@
+/*=============================================================================
+ Copyright (c) 2004 Joao Abecasis
+ http://spirit.sourceforge.net/
+
+ 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)
+=============================================================================*/
+
+#include <boost/spirit/include/classic_scanner.hpp>
+#include <boost/utility/addressof.hpp>
+#include "symbols.hpp"
+
+typedef char char_type;
+typedef char const * iterator;
+
+char_type data_[] = "whatever";
+
+iterator begin = data_;
+iterator end = data_
+ + sizeof(data_)/sizeof(char_type); // Yes, this is an intentional bug ;)
+
+int main()
+{
+ typedef BOOST_SPIRIT_CLASSIC_NS::scanner<> scanner;
+ typedef quickbook::tst<void *, char_type> symbols;
+
+ symbols symbols_;
+
+ symbols_.add(begin, end - 1, (void*) boost::addressof(symbols_));
+
+ // The symbol table parser should not choke on input containing the null
+ // character.
+ symbols_.find(scanner(begin, end));
+}

Added: branches/quickbook-dev/tools/quickbook/test/unit/symbols_tests.cpp
==============================================================================
--- (empty file)
+++ branches/quickbook-dev/tools/quickbook/test/unit/symbols_tests.cpp 2011-04-02 13:45:09 EDT (Sat, 02 Apr 2011)
@@ -0,0 +1,356 @@
+/*=============================================================================
+ Copyright (c) 1998-2003 Joel de Guzman
+ Copyright (c) 2003 Martin Wille
+ http://spirit.sourceforge.net/
+
+ 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)
+=============================================================================*/
+#include <iostream>
+#include <string>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/classic_core.hpp>
+#include <boost/spirit/include/classic_symbols.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/swap.hpp>
+#include "symbols.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+using namespace std;
+using namespace BOOST_SPIRIT_CLASSIC_NS;
+
+///////////////////////////////////////////////////////////////////////////////
+
+template <typename IteratorT>
+bool
+equal(IteratorT p, IteratorT q)
+{
+ while (*p && *p == *q)
+ {
+ ++p;
+ ++q;
+ }
+ return *p == *q;
+}
+
+template <class SymbolsT, typename CharT>
+void
+docheck
+(
+ SymbolsT const &sym,
+ CharT const *candidate,
+ bool hit,
+ CharT const *result,
+ int length
+)
+{
+ parse_info<CharT const*> info = parse(candidate, sym);
+
+#define correctly_matched hit == info.hit
+#define correct_match_length unsigned(length) == info.length
+#define correct_tail equal(candidate + (hit?1:0)*length, result)
+
+ BOOST_TEST(correctly_matched);
+
+ if (hit)
+ {
+ BOOST_TEST(correct_match_length);
+ BOOST_TEST(correct_tail);
+ }
+ else
+ {
+ BOOST_TEST(correct_tail);
+ }
+}
+
+template <typename T>
+struct store_action
+{
+ store_action(T const &v) : value(v) {}
+ void operator()(T &v) const { v = value; }
+private:
+ T const value;
+};
+
+template <typename T>
+store_action<T>
+store(T const &v)
+{
+ return v;
+}
+
+template <typename T>
+struct check_action
+{
+ check_action(T const &v) : value(v) {}
+
+#define correct_value_stored (v==value)
+ void operator()(T const &v) const { BOOST_TEST(correct_value_stored); }
+private:
+ T const value;
+};
+
+template <typename T>
+check_action<T>
+docheck(T const &v)
+{
+ return v;
+}
+
+static void
+default_constructible()
+{ // this actually a compile time test
+ symbols<int, char, quickbook::tst<int, char> > ns1;
+ symbols<int, wchar_t, quickbook::tst<int, wchar_t> > ws1;
+ symbols<std::string, char, quickbook::tst<std::string, char> > ns2;
+ symbols<std::string, wchar_t, quickbook::tst<std::string, wchar_t> > ws2;
+
+ (void)ns1; (void)ws1; (void)ns2; (void)ws2;
+}
+
+typedef symbols<int, char, quickbook::tst<int, char> > nsymbols;
+typedef symbols<int, wchar_t, quickbook::tst<int, wchar_t> > wsymbols;
+
+static void
+narrow_match_tests()
+{
+ nsymbols sym;
+ sym = "pineapple", "orange", "banana", "applepie", "apple";
+
+ docheck(sym, "pineapple", true, "", 9);
+ docheck(sym, "orange", true, "", 6);
+ docheck(sym, "banana", true, "", 6);
+ docheck(sym, "apple", true, "", 5);
+ docheck(sym, "pizza", false, "pizza", -1);
+ docheck(sym, "steak", false, "steak", -1);
+ docheck(sym, "applepie", true, "", 8);
+ docheck(sym, "bananarama", true, "rama", 6);
+ docheck(sym, "applet", true, "t", 5);
+ docheck(sym, "applepi", true, "pi", 5);
+ docheck(sym, "appl", false, "appl", -1);
+
+ docheck(sym, "pineapplez", true, "z", 9);
+ docheck(sym, "orangez", true, "z", 6);
+ docheck(sym, "bananaz", true, "z", 6);
+ docheck(sym, "applez", true, "z", 5);
+ docheck(sym, "pizzaz", false, "pizzaz", -1);
+ docheck(sym, "steakz", false, "steakz", -1);
+ docheck(sym, "applepiez", true, "z", 8);
+ docheck(sym, "bananaramaz", true, "ramaz", 6);
+ docheck(sym, "appletz", true, "tz", 5);
+ docheck(sym, "applepix", true, "pix", 5);
+}
+
+static void
+narrow_copy_ctor_tests()
+{
+ nsymbols sym;
+ sym = "pineapple", "orange", "banana", "applepie", "apple";
+
+ nsymbols sym2(sym);
+ docheck(sym2, "pineapple", true, "", 9);
+ docheck(sym2, "pizza", false, "pizza", -1);
+ docheck(sym2, "bananarama", true, "rama", 6);
+}
+
+static void
+narrow_assigment_operator_tests()
+{
+ nsymbols sym;
+ sym = "pineapple", "orange", "banana", "applepie", "apple";
+
+ nsymbols sym2;
+ sym2 = sym;
+
+ docheck(sym2, "pineapple", true, "", 9);
+ docheck(sym2, "pizza", false, "pizza", -1);
+ docheck(sym2, "bananarama", true, "rama", 6);
+}
+
+static void
+narrow_swap_tests()
+{
+ nsymbols sym, sym2;
+ sym = "pineapple", "orange", "banana", "applepie", "apple";
+ sym2 = "potato", "cucumber", "cauliflower", "carrot";
+
+ boost::swap(sym, sym2);
+
+ docheck(sym2, "pineapple", true, "", 9);
+ docheck(sym2, "pizza", false, "pizza", -1);
+ docheck(sym2, "bananarama", true, "rama", 6);
+ docheck(sym, "potatoe", true, "e", 6);
+ docheck(sym, "cauliflour", false, "cauliflour", -1);
+}
+
+static void
+narrow_value_tests()
+{ // also tests the add member functions
+ nsymbols sym;
+
+ sym = "orange", "banana";
+ sym.add("pineapple",1234);
+ sym.add("lemon");
+
+ parse("orange", sym[store(12345)]);
+ parse("orange", sym[docheck(12345)]);
+ parse("pineapple", sym[docheck(1234)]);
+ parse("banana", sym[docheck(int())]);
+ parse("lemon", sym[docheck(int())]);
+}
+
+static void
+narrow_free_functions_tests()
+{
+ nsymbols sym;
+
+#define add_returned_non_null_value (res!=0)
+#define add_returned_null (res==0)
+#define find_returned_non_null_value (res!=0)
+#define find_returned_null (res==0)
+
+ int *res = add(sym,"pineapple");
+ BOOST_TEST(add_returned_non_null_value);
+ res = add(sym,"pineapple");
+ BOOST_TEST(add_returned_null);
+
+ res = find(sym, "pineapple");
+ BOOST_TEST(find_returned_non_null_value);
+ res = find(sym, "banana");
+ BOOST_TEST(find_returned_null);
+}
+
+static void
+wide_match_tests()
+{
+ wsymbols sym;
+ sym = L"pineapple", L"orange", L"banana", L"applepie", L"apple";
+
+ docheck(sym, L"pineapple", true, L"", 9);
+ docheck(sym, L"orange", true, L"", 6);
+ docheck(sym, L"banana", true, L"", 6);
+ docheck(sym, L"apple", true, L"", 5);
+ docheck(sym, L"pizza", false, L"pizza", -1);
+ docheck(sym, L"steak", false, L"steak", -1);
+ docheck(sym, L"applepie", true, L"", 8);
+ docheck(sym, L"bananarama", true, L"rama", 6);
+ docheck(sym, L"applet", true, L"t", 5);
+ docheck(sym, L"applepi", true, L"pi", 5);
+ docheck(sym, L"appl", false, L"appl", -1);
+
+ docheck(sym, L"pineapplez", true, L"z", 9);
+ docheck(sym, L"orangez", true, L"z", 6);
+ docheck(sym, L"bananaz", true, L"z", 6);
+ docheck(sym, L"applez", true, L"z", 5);
+ docheck(sym, L"pizzaz", false, L"pizzaz", -1);
+ docheck(sym, L"steakz", false, L"steakz", -1);
+ docheck(sym, L"applepiez", true, L"z", 8);
+ docheck(sym, L"bananaramaz", true, L"ramaz", 6);
+ docheck(sym, L"appletz", true, L"tz", 5);
+ docheck(sym, L"applepix", true, L"pix", 5);
+}
+
+static void
+wide_copy_ctor_tests()
+{
+ wsymbols sym;
+ sym = L"pineapple", L"orange", L"banana", L"applepie", L"apple";
+
+ wsymbols sym2(sym);
+ docheck(sym2, L"pineapple", true, L"", 9);
+ docheck(sym2, L"pizza", false, L"pizza", -1);
+ docheck(sym2, L"bananarama", true, L"rama", 6);
+}
+
+static void
+wide_assigment_operator_tests()
+{
+ wsymbols sym;
+ sym = L"pineapple", L"orange", L"banana", L"applepie", L"apple";
+
+ wsymbols sym2;
+ sym2 = sym;
+
+ docheck(sym2, L"pineapple", true, L"", 9);
+ docheck(sym2, L"pizza", false, L"pizza", -1);
+ docheck(sym2, L"bananarama", true, L"rama", 6);
+}
+
+static void
+wide_swap_tests()
+{
+ wsymbols sym, sym2;
+ sym = L"pineapple", L"orange", L"banana", L"applepie", L"apple";
+ sym2 = L"potato", L"cucumber", L"cauliflower", L"carrot";
+
+ boost::swap(sym, sym2);
+
+ docheck(sym2, L"pineapple", true, L"", 9);
+ docheck(sym2, L"pizza", false, L"pizza", -1);
+ docheck(sym2, L"bananarama", true, L"rama", 6);
+ docheck(sym, L"potatoe", true, L"e", 6);
+ docheck(sym, L"cauliflour", false, L"cauliflour", -1);
+}
+
+static void
+wide_value_tests()
+{ // also tests the add member functions
+ wsymbols sym;
+
+ sym = L"orange", L"banana";
+ sym.add(L"pineapple",1234);
+ sym.add(L"lemon");
+
+ parse(L"orange", sym[store(12345)]);
+ parse(L"orange", sym[docheck(12345)]);
+ parse(L"pineapple", sym[docheck(1234)]);
+ parse(L"banana", sym[docheck(int())]);
+ parse(L"lemon", sym[docheck(int())]);
+}
+
+static void
+wide_free_functions_tests()
+{
+ wsymbols sym;
+
+ int *res = add(sym,L"pineapple");
+ BOOST_TEST(add_returned_non_null_value);
+ res = add(sym,L"pineapple");
+ BOOST_TEST(add_returned_null);
+
+ res = find(sym, L"pineapple");
+ BOOST_TEST(find_returned_non_null_value);
+ res = find(sym, L"banana");
+ BOOST_TEST(find_returned_null);
+}
+
+static
+void free_add_find_functions_tests()
+{
+ nsymbols sym;
+ BOOST_TEST(*add(sym, "a", 0) == 0);
+ BOOST_TEST(*add(sym, "a2", 1) == 1);
+ BOOST_TEST(find(sym, "a2"));
+ BOOST_TEST(find(sym, "a"));
+}
+
+int
+main()
+{
+ default_constructible();
+ narrow_match_tests();
+ narrow_copy_ctor_tests();
+ narrow_assigment_operator_tests();
+ narrow_swap_tests();
+ narrow_value_tests();
+ narrow_free_functions_tests();
+ wide_match_tests();
+ wide_copy_ctor_tests();
+ wide_assigment_operator_tests();
+ wide_swap_tests();
+ wide_value_tests();
+ wide_free_functions_tests();
+ free_add_find_functions_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