Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r53115 - in sandbox/pinhole: boost boost/pinhole boost/pinhole/detail libs/pinhole/test
From: jmcintyre_at_[hidden]
Date: 2009-05-19 15:30:29


Author: jared
Date: 2009-05-19 15:30:22 EDT (Tue, 19 May 2009)
New Revision: 53115
URL: http://svn.boost.org/trac/boost/changeset/53115

Log:
pinhole - add depth-first iterator, path-filtered iterator, get_path_filtered_nodes(), set_single_value(), set_all_values()
Added:
   sandbox/pinhole/boost/pinhole/category_iterator.hpp (contents, props changed)
   sandbox/pinhole/boost/pinhole/depth_first_iterator.hpp (contents, props changed)
   sandbox/pinhole/boost/pinhole/detail/
   sandbox/pinhole/boost/pinhole/detail/depth_first_iterator_base.hpp (contents, props changed)
   sandbox/pinhole/boost/pinhole/detail/path.hpp (contents, props changed)
   sandbox/pinhole/boost/pinhole/detail/tokenizer.hpp (contents, props changed)
   sandbox/pinhole/boost/pinhole/path_filtered_iterator.hpp (contents, props changed)
   sandbox/pinhole/boost/pinhole/value.hpp (contents, props changed)
   sandbox/pinhole/libs/pinhole/test/test_category_iterator.cpp (contents, props changed)
   sandbox/pinhole/libs/pinhole/test/test_depth_first_iterator.cpp (contents, props changed)
   sandbox/pinhole/libs/pinhole/test/test_path_filtered_iterator.cpp (contents, props changed)
   sandbox/pinhole/libs/pinhole/test/test_tokenizer.cpp (contents, props changed)
Text files modified:
   sandbox/pinhole/boost/pinhole.hpp | 2
   sandbox/pinhole/boost/pinhole/find.hpp | 140 ++++++-------
   sandbox/pinhole/boost/pinhole/main.cpp | 4
   sandbox/pinhole/boost/pinhole/property_group.hpp | 78 +++++--
   sandbox/pinhole/boost/pinhole/property_manager.hpp | 168 ++++++++--------
   sandbox/pinhole/libs/pinhole/test/Jamfile.v2 | 6
   sandbox/pinhole/libs/pinhole/test/test_find.cpp | 394 ++++++++++++++++++++++++++++++++++++++-
   sandbox/pinhole/libs/pinhole/test/test_property_groups.cpp | 35 ++-
   sandbox/pinhole/libs/pinhole/test/test_string_properties.cpp | 2
   9 files changed, 607 insertions(+), 222 deletions(-)

Modified: sandbox/pinhole/boost/pinhole.hpp
==============================================================================
--- sandbox/pinhole/boost/pinhole.hpp (original)
+++ sandbox/pinhole/boost/pinhole.hpp 2009-05-19 15:30:22 EDT (Tue, 19 May 2009)
@@ -10,6 +10,6 @@
 
 #include "pinhole/config.hpp"
 #include "pinhole/property_group.hpp"
-#include "pinhole/find.hpp"
+#include "pinhole/value.hpp"
 
 #endif //BOOST_PROPERTY_PINHOLE
\ No newline at end of file

Added: sandbox/pinhole/boost/pinhole/category_iterator.hpp
==============================================================================
--- (empty file)
+++ sandbox/pinhole/boost/pinhole/category_iterator.hpp 2009-05-19 15:30:22 EDT (Tue, 19 May 2009)
@@ -0,0 +1,101 @@
+// Pinhole category_iterator.hpp file
+//
+// Copyright Jared McIntyre 2009.
+// Distributed under 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 BOOST_CATEGORY_ITERATOR
+#define BOOST_CATEGORY_ITERATOR
+
+#include <exception>
+#include <stdexcept>
+#include <string>
+#include <boost/../../boost_sandbox/pinhole/boost/pinhole/property_group.hpp>
+
+#if defined(BOOST_MSVC)
+ #pragma warning(push)
+ #pragma warning(disable: 4561 4996)
+#endif
+#include <boost/iterator.hpp>
+#include <boost/iterator/iterator_adaptor.hpp>
+#include <boost/iterator/iterator_categories.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/type_traits/is_pointer.hpp>
+#include <boost/static_assert.hpp>
+#if defined(BOOST_MSVC)
+ #pragma warning(pop)
+#endif
+
+namespace boost { namespace pinhole
+{
+ /** @todo: comment */
+ template <class Iterator>
+ class category_iterator
+ : public boost::iterator_adaptor<
+ category_iterator<Iterator>
+ , Iterator
+ >
+ {
+ private:
+
+ /** Required by boost::iterator_adaptor. */
+ friend class boost::iterator_core_access;
+
+ /** Required by boost::iterator_adaptor. */
+ struct enabler {}; // a private type avoids misuse
+
+ /** Required by boost::iterator_adaptor. */
+ category_iterator() :
+ category_iterator::iterator_adaptor_() { }
+
+ public:
+
+ explicit category_iterator( const std::string& category, Iterator x, Iterator end ) :
+ category_iterator::iterator_adaptor_(x), search_category(category), current_end(end) { MoveIteratorToValidPosition(); }
+
+ /** Required by boost::iterator_adaptor. Allows for proper conversion between otherwise incompatible iterator types. */
+ template <class other_iterator>
+ category_iterator(
+ category_iterator<other_iterator> const& other
+ , typename boost::enable_if<
+ boost::is_convertible<other_iterator*, Iterator*>
+ , enabler
+ >::type = enabler()
+ )
+ : category_iterator::iterator_adaptor_(other.base()) {}
+
+ private:
+
+ void MoveIteratorToValidPosition()
+ {
+ while( current_end != this->base_reference() )
+ {
+ const boost::pinhole::category_collection& categories = (*this->base_reference())->get_category_collection();
+ if( categories.end() != std::find(categories.begin(), categories.end(), search_category) )
+ {
+ break;
+ }
+ ++(this->base_reference());
+ }
+ }
+
+ void increment()
+ {
+ ++(this->base_reference());
+
+ MoveIteratorToValidPosition();
+ }
+
+ const std::string search_category;
+ Iterator current_end;
+ };
+
+ template <class Iterator>
+ category_iterator<Iterator> make_category_iterator(const std::string& category, Iterator x, Iterator end)
+ {
+ return category_iterator<Iterator>(category, x, end);
+ }
+}}
+
+#endif // include guard
\ No newline at end of file

Added: sandbox/pinhole/boost/pinhole/depth_first_iterator.hpp
==============================================================================
--- (empty file)
+++ sandbox/pinhole/boost/pinhole/depth_first_iterator.hpp 2009-05-19 15:30:22 EDT (Tue, 19 May 2009)
@@ -0,0 +1,59 @@
+// Pinhole depth_first_iterator.hpp file
+//
+// Copyright Jared McIntyre 2009.
+// Distributed under 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 BOOST_DEPTH_FIRST_ITERATOR
+#define BOOST_DEPTH_FIRST_ITERATOR
+
+#include <string>
+#include <boost/../../boost_sandbox/pinhole/boost/pinhole/detail/depth_first_iterator_base.hpp>
+
+namespace boost { namespace pinhole
+{
+ template<class Iterator>
+ struct no_filter : public detail::depth_first_iterator_base<Iterator, no_filter<Iterator> >
+ {
+ typedef detail::depth_first_iterator_base< Iterator, no_filter<Iterator> > base_type;
+
+ explicit no_filter( Iterator end ) :
+ base_type(end, end)
+ {
+ }
+
+ explicit no_filter( Iterator x, Iterator end ) :
+ base_type(x, end)
+ {
+ // required call by depth_first_iterator_base
+ MoveIteratorToValidPosition();
+ }
+
+ inline bool visit_children(property_group* property)
+ {
+ return true;
+ }
+
+ inline bool is_valid(property_group* property)
+ {
+ return true;
+ }
+
+ inline void move_up()
+ {
+
+ }
+
+ private:
+
+ no_filter() :
+ base_type() { }
+ };
+
+ /** Iterates over all the keys in a map. */
+ typedef no_filter<children_collection::iterator> depth_first_iterator;
+ typedef no_filter<children_collection::const_iterator> const_depth_first_iterator;
+}}
+
+#endif // include guard
\ No newline at end of file

Added: sandbox/pinhole/boost/pinhole/detail/depth_first_iterator_base.hpp
==============================================================================
--- (empty file)
+++ sandbox/pinhole/boost/pinhole/detail/depth_first_iterator_base.hpp 2009-05-19 15:30:22 EDT (Tue, 19 May 2009)
@@ -0,0 +1,142 @@
+// Pinhole depth_first_iterator_base.hpp file
+//
+// Copyright Jared McIntyre 2009.
+// Distributed under 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 BOOST_DETAIL_DEPTH_FIRST_ITERATOR_BASE
+#define BOOST_DETAIL_DEPTH_FIRST_ITERATOR_BASE
+
+#include <exception>
+#include <stdexcept>
+#include <string>
+#include <boost/../../boost_sandbox/pinhole/boost/pinhole/property_group.hpp>
+
+#if defined(BOOST_MSVC)
+ #pragma warning(push)
+ #pragma warning(disable: 4561 4996)
+#endif
+#include <boost/iterator.hpp>
+#include <boost/iterator/iterator_adaptor.hpp>
+#include <boost/iterator/iterator_categories.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/type_traits/is_pointer.hpp>
+#include <boost/static_assert.hpp>
+#if defined(BOOST_MSVC)
+ #pragma warning(pop)
+#endif
+
+namespace boost { namespace pinhole { namespace detail
+{
+ template<class Iterator, class filter>
+ class depth_first_iterator_base
+ : public boost::iterator_adaptor<
+ depth_first_iterator_base<Iterator, filter>
+ , Iterator
+ >
+ {
+ private:
+
+ /** Required by boost::iterator_adaptor. */
+ friend class boost::iterator_core_access;
+
+ /** Required by boost::iterator_adaptor. */
+ struct enabler {}; // a private type avoids misuse
+
+ typedef std::pair<Iterator,Iterator> past_state_type;
+
+ public:
+ depth_first_iterator_base() :
+ depth_first_iterator_base::iterator_adaptor_() { }
+
+ explicit depth_first_iterator_base( Iterator x, Iterator end ) :
+ depth_first_iterator_base::iterator_adaptor_(x), current_end(end) { }
+
+ depth_first_iterator_base( const depth_first_iterator_base& other ) :
+ depth_first_iterator_base::iterator_adaptor_(other)
+ {
+ stack = other.stack;
+ current_end = other.current_end;
+ }
+
+ /** Required by boost::iterator_adaptor. */
+ template <class other_iterator>
+ depth_first_iterator_base(
+ category_iterator<other_iterator> const& other
+ , typename boost::enable_if<
+ boost::is_convertible<other_iterator*, Iterator*>
+ , enabler
+ >::type = enabler()
+ )
+ : depth_first_iterator_base::iterator_adaptor_(other.base()) {}
+
+ protected:
+
+ void MoveIteratorToValidPosition()
+ {
+ bool bContinue = false;
+
+ do
+ {
+ if( this->base_reference() == current_end )
+ {
+ if( false == stack.empty() )
+ {
+ past_state_type& previous_par = stack.back();
+
+ this->base_reference() = previous_par.first;
+ current_end = previous_par.second;
+
+ stack.pop_back();
+
+ static_cast<filter*>(this)->move_up();
+ }
+ }
+ else
+ {
+ while( false == (*this->base_reference())->get_children_collection().empty() && static_cast<filter*>(this)->visit_children(*this->base_reference()) )
+ {
+ stack.push_back( past_state_type(this->base_reference(), current_end) );
+
+ boost::pinhole::children_collection& children = (*this->base_reference())->get_children_collection();
+ this->base_reference() = children.begin();
+ current_end = children.end();
+ }
+ }
+
+ if( this->base_reference() != current_end && false == static_cast<filter*>(this)->is_valid(*this->base_reference()) )
+ {
+ bContinue = true;
+ ++(this->base_reference());
+ }
+ else
+ {
+ bContinue = false;
+ }
+ } while( bContinue );
+ }
+
+ private:
+
+ #if defined(BOOST_MSVC) // work around for extra MS secure library checks
+ bool equal(iterator_adaptor_ const& x) const
+ {
+ return static_cast<const depth_first_iterator_base*>(&x)->stack == stack &&
+ static_cast<const depth_first_iterator_base*>(&x)->base_reference() == this->base_reference();
+ }
+ #endif
+
+ void increment()
+ {
+ ++(this->base_reference());
+
+ MoveIteratorToValidPosition();
+ }
+
+ std::deque< past_state_type > stack;
+ Iterator current_end;
+ };
+}}}
+
+#endif // include guard
\ No newline at end of file

Added: sandbox/pinhole/boost/pinhole/detail/path.hpp
==============================================================================
--- (empty file)
+++ sandbox/pinhole/boost/pinhole/detail/path.hpp 2009-05-19 15:30:22 EDT (Tue, 19 May 2009)
@@ -0,0 +1,84 @@
+// Pinhole Find.hpp file
+//
+// Copyright Jared McIntyre 2007-2009.
+// Distributed under 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 BOOST_PINHOLE_PATH
+#define BOOST_PINHOLE_PATH
+
+#include <vector>
+
+namespace boost { namespace pinhole
+{
+ namespace detail
+ {
+ inline
+ boost::pinhole::property_group*
+ search_single_property_group_based_on_name( boost::pinhole::children_collection::iterator itr,
+ boost::pinhole::children_collection::iterator itrEnd,
+ const std::string& property_group_name)
+ {
+ boost::pinhole::property_group* property_group_found = 0;
+ for( ; itr != itrEnd; ++itr)
+ {
+ boost::pinhole::property_group* current_property_group = *itr;
+ if(current_property_group->get_name() == property_group_name)
+ {
+ if(property_group_found != 0)
+ {
+ std::string strError = "Multiple " + property_group_name + " are found in property_manager::selectSingleNode";
+ throw multiple_property_groups(strError.c_str());
+ }
+ property_group_found = current_property_group;
+ }
+ }
+ if(property_group_found == 0)
+ {
+ throw no_metadata_defined_error();
+ }
+ return property_group_found;
+ }
+
+ inline
+ boost::pinhole::property_group*
+ search_single_property_group_based_on_property_value( boost::pinhole::children_collection::iterator itr,
+ boost::pinhole::children_collection::iterator itrEnd,
+ const std::string& property_group_name,
+ const std::string& property_name,
+ const std::string& property_value )
+ {
+ boost::pinhole::property_group* property_group_found = 0;
+ for(; itr != itrEnd; ++itr)
+ {
+ boost::pinhole::property_group* current_property_group = *itr;
+ if((current_property_group->get_name() == property_group_name) && (current_property_group->get_as_string(property_name) == property_value))
+ {
+ if(property_group_found != 0)
+ {
+ std::string strError = "Multiple " + property_group_name + "." + property_name + "=" + property_value + " are found in property_manager::selectSingleNode";
+ throw multiple_property_groups(strError.c_str());
+ }
+ property_group_found = current_property_group;
+ }
+ }
+ if(property_group_found == 0)
+ {
+ throw no_metadata_defined_error();
+ }
+ return property_group_found;
+ }
+
+ inline
+ void ThrowIfPathIsRelative(const std::string& path)
+ {
+ if( path.length() > 0 && path[0] != '/' )
+ {
+ throw boost::pinhole::invalid_path("A relative path was requested, but no property_group to search from was given.");
+ }
+ }
+ }
+}}
+
+#endif // include guard
\ No newline at end of file

Added: sandbox/pinhole/boost/pinhole/detail/tokenizer.hpp
==============================================================================
--- (empty file)
+++ sandbox/pinhole/boost/pinhole/detail/tokenizer.hpp 2009-05-19 15:30:22 EDT (Tue, 19 May 2009)
@@ -0,0 +1,120 @@
+// Pinhole tokenizer.hpp file
+//
+// Copyright Jared McIntyre 2009.
+// Distributed under 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 BOOST_PINHOLE_TOKENIZER
+#define BOOST_PINHOLE_TOKENIZER
+
+#include <vector>
+#include <boost/../../boost_sandbox/pinhole/boost/pinhole/exceptions.hpp>
+#include <boost/algorithm/string/find.hpp>
+
+namespace boost { namespace pinhole
+{
+ namespace detail
+ {
+ struct token_path
+ {
+ struct token
+ {
+ std::string name;
+ std::string property;
+ std::string value;
+ };
+
+ typedef std::list<token> token_list;
+ typedef token_list::iterator iterator;
+ typedef token_list::const_iterator const_iterator;
+
+
+ token_list tokens;
+ bool relative_path;
+ };
+
+ inline size_t process_path( const std::string& string_path, boost::pinhole::detail::token_path& processed_path )
+ {
+ typedef std::vector<std::string> split_vector_type;
+ typedef boost::split_iterator<std::string::const_iterator> string_split_iterator;
+ typedef boost::iterator_range<std::string::const_iterator> string_range;
+
+ processed_path.relative_path = false;
+ processed_path.tokens.clear();
+
+ if( string_path.empty() )
+ {
+ return 0;
+ }
+
+ std::string::const_iterator itr( string_path.begin() );
+ std::string::const_iterator itrEnd( string_path.end() );
+
+ if( *itr == '/' )
+ {
+ ++itr;
+ }
+ else
+ {
+ processed_path.relative_path = true;
+ }
+
+ size_t itemCount = 0;
+
+ string_split_iterator splitItr= boost::make_split_iterator( std::make_pair(itr, itrEnd), boost::first_finder("/", is_equal()));
+ while( splitItr!=string_split_iterator() )
+ {
+ boost::pinhole::detail::token_path::token newToken;
+ const std::string strSubToken( copy_range<std::string>(*splitItr) );
+ ++splitItr;
+
+ if( strSubToken.empty() )
+ {
+ if( false == splitItr.eof() )
+ {
+ throw invalid_path("part of the path was empty");
+ }
+ }
+ else
+ {
+ string_range dot_delim = boost::find_first( strSubToken, "." );
+ if( dot_delim )
+ {
+ string_range equal_delim = boost::find_first( string_range(dot_delim.end(), strSubToken.end()), "=" );
+ if( equal_delim )
+ {
+ if( dot_delim.end() == equal_delim.begin() )
+ {
+ throw invalid_path(".= found (no property name defined)");
+ }
+
+ newToken.name.assign(strSubToken.begin(), dot_delim.begin());
+ newToken.property.assign(dot_delim.end(), equal_delim.begin());
+ newToken.value.assign(equal_delim.end(), strSubToken.end());
+ }
+ else
+ {
+ throw invalid_path(". delimeter found with no matchind =");
+ }
+ }
+ else if( boost::find_first( strSubToken, "=" ) )
+ {
+ throw invalid_path("= delimeter found with no matchind .");
+ }
+ else
+ {
+ newToken.name = strSubToken;
+ }
+
+ processed_path.tokens.push_back( newToken );
+ ++itemCount;
+ }
+ }
+
+ return itemCount;
+ }
+ }
+}}
+
+#endif // include guard
\ No newline at end of file

Modified: sandbox/pinhole/boost/pinhole/find.hpp
==============================================================================
--- sandbox/pinhole/boost/pinhole/find.hpp (original)
+++ sandbox/pinhole/boost/pinhole/find.hpp 2009-05-19 15:30:22 EDT (Tue, 19 May 2009)
@@ -1,74 +1,20 @@
 // Pinhole Find.hpp file
 //
-// Copyright Jared McIntyre 2007-2008.
+// Copyright Jared McIntyre 2007-2009.
 // Distributed under 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 BOOST_FIND
-#define BOOST_FIND
+#ifndef BOOST_PINHOLE_FIND
+#define BOOST_PINHOLE_FIND
 
 #include <vector>
+#include <boost\..\..\boost_sandbox\pinhole\boost\pinhole\detail\path.hpp>
+#include <boost\..\..\boost_sandbox\pinhole\boost\pinhole\detail\tokenizer.hpp>
+#include <boost\..\..\boost_sandbox\pinhole\boost\pinhole\path_filtered_iterator.hpp>
 
 namespace boost { namespace pinhole
 {
- namespace detail
- {
- inline
- boost::pinhole::property_group*
- search_single_property_group_based_on_name( boost::pinhole::children_collection* current_property_group_collection,
- const std::string& property_group_name)
- {
- boost::pinhole::property_group* property_group_found = 0;
- for( children_collection::iterator iter = current_property_group_collection->begin(); iter != current_property_group_collection->end(); iter++)
- {
- boost::pinhole::property_group* current_property_group = *iter;
- if(current_property_group->get_name() == property_group_name)
- {
- if(property_group_found != 0)
- {
- std::string strError = "Multiple " + property_group_name + " are found in property_manager::selectSingleNode";
- throw multiple_property_groups(strError.c_str());
- }
- property_group_found = current_property_group;
- }
- }
- if(property_group_found == 0)
- {
- throw no_metadata_defined_error();
- }
- return property_group_found;
- }
-
- inline
- boost::pinhole::property_group*
- search_single_property_group_based_on_property_value( boost::pinhole::children_collection* current_property_group_collection,
- const std::string& property_group_name,
- const std::string& property_name,
- const std::string& property_value )
- {
- boost::pinhole::property_group* property_group_found = 0;
- for(boost::pinhole::children_collection::iterator iter = current_property_group_collection->begin(); iter != current_property_group_collection->end(); iter++)
- {
- boost::pinhole::property_group* current_property_group = *iter;
- if((current_property_group->get_name() == property_group_name) && (current_property_group->get_as_string(property_name) == property_value))
- {
- if(property_group_found != 0)
- {
- std::string strError = "Multiple " + property_group_name + "." + property_name + "=" + property_value + " are found in property_manager::selectSingleNode";
- throw multiple_property_groups(strError.c_str());
- }
- property_group_found = current_property_group;
- }
- }
- if(property_group_found == 0)
- {
- throw no_metadata_defined_error();
- }
- return property_group_found;
- }
- }
-
     /**
      * Returns a property_group based on a path that describes where that property_group
      * exists within the property group hierarchy. This path can either be from the
@@ -99,14 +45,16 @@
      */
     inline boost::pinhole::property_group* select_single_node(boost::pinhole::property_group* current_property_group, const std::string& path)
     {
- boost::pinhole::children_collection* current_property_group_collection = NULL;
+ std::pair<boost::pinhole::children_collection::iterator,boost::pinhole::children_collection::iterator> range;
+
         if( NULL != current_property_group )
         {
- current_property_group_collection = &current_property_group->get_children_collection();
+ range.first = current_property_group->get_children_collection().begin();
+ range.second = current_property_group->get_children_collection().end();
         }
- else if( path.length() > 0 && path[0] != '/' )
+ else
         {
- throw boost::pinhole::invalid_path("A relative path was requested, but no property_group to search from was given.");
+ detail::ThrowIfPathIsRelative(path);
         }
         boost::pinhole::children_collection* root_property_group_collection = 0; //The root collection might not be needed if it is not referred.
         
@@ -133,21 +81,17 @@
                         if(strItem.empty()) //It is "/"
                         {
                             boost::pinhole::property_manager::instance_type manager = boost::pinhole::property_manager::instance();
- root_property_group_collection = new boost::pinhole::children_collection();
- boost::pinhole::property_manager::iterator iter = manager->begin();
- boost::pinhole::property_manager::iterator iterEnd = manager->end();
- for( ; iter != iterEnd; iter++)
- {
- root_property_group_collection->push_back(*iter);
- }
- current_property_group_collection = root_property_group_collection; //From now on, we only care about current_property_group_collection.
+ range.first = manager->begin();
+ range.second = manager->end();
                         }
                         else
                         {
                             //strItem here must be a property group name.
                             //If multiple or none is found ,exception will be thrown.
- current_property_group = detail::search_single_property_group_based_on_name(current_property_group_collection, strItem);
- current_property_group_collection = &current_property_group->get_children_collection();
+ current_property_group = detail::search_single_property_group_based_on_name(range.first, range.second, strItem);
+
+ range.first = current_property_group->get_children_collection().begin();
+ range.second = current_property_group->get_children_collection().end();
                         }
                     }
                         break;
@@ -161,8 +105,10 @@
                         
                         std::string property_value = properties[2];
                         boost::trim(property_value);
- current_property_group = detail::search_single_property_group_based_on_property_value(current_property_group_collection, property_group_name, property_name, property_value);
- current_property_group_collection = &current_property_group->get_children_collection();
+ current_property_group = detail::search_single_property_group_based_on_property_value(range.first, range.second, property_group_name, property_name, property_value);
+
+ range.first = current_property_group->get_children_collection().begin();
+ range.second = current_property_group->get_children_collection().end();
                     }
                         break;
                     default:
@@ -210,6 +156,48 @@
     {
         return select_single_node(NULL, path);
     }
+
+ typedef boost::iterator_range< boost::pinhole::path_filtered_iterator > path_filtered_range;
+ typedef boost::iterator_range< boost::pinhole::const_path_filtered_iterator > const_path_filtered_range;
+
+ inline path_filtered_range get_path_filtered_range(const std::string& path)
+ {
+ detail::ThrowIfPathIsRelative(path);
+
+ return path_filtered_range( path_filtered_iterator( path, property_manager::instance()->begin(), property_manager::instance()->end() ),
+ path_filtered_iterator( property_manager::instance()->end() ) );
+ }
+
+ inline const_path_filtered_range get_const_path_filtered_range(const std::string& path)
+ {
+
+ detail::ThrowIfPathIsRelative(path);
+
+ return const_path_filtered_range( const_path_filtered_iterator( path, property_manager::instance()->begin(), property_manager::instance()->end() ),
+ const_path_filtered_iterator( property_manager::instance()->end() ) );
+ }
+
+ inline path_filtered_range get_path_filtered_range(const std::string& path, property_group& group)
+ {
+ if( path.length() > 0 && path[0] == '/' )
+ {
+ return get_path_filtered_range(path);
+ }
+
+ return path_filtered_range( path_filtered_iterator( path, group.get_children_collection().begin(), group.get_children_collection().end() ),
+ path_filtered_iterator( group.get_children_collection().end() ) );
+ }
+
+ inline const_path_filtered_range get_const_path_filtered_range(const std::string& path, property_group& group)
+ {
+ if( path.length() > 0 && path[0] == '/' )
+ {
+ return get_const_path_filtered_range(path);
+ }
+
+ return const_path_filtered_range( const_path_filtered_iterator( path, group.get_children_collection().begin(), group.get_children_collection().end() ),
+ const_path_filtered_iterator( group.get_children_collection().end() ) );
+ }
 }}
 
 #endif // include guard
\ No newline at end of file

Modified: sandbox/pinhole/boost/pinhole/main.cpp
==============================================================================
--- sandbox/pinhole/boost/pinhole/main.cpp (original)
+++ sandbox/pinhole/boost/pinhole/main.cpp 2009-05-19 15:30:22 EDT (Tue, 19 May 2009)
@@ -14,6 +14,10 @@
 using namespace std;
 using namespace boost;
 using namespace boost::pinhole;
+
+// I can hide these two line if I don't do everything in headers
+shared_ptr<property_manager> property_manager::m_instance(new property_manager);
+event_source* event_source::m_instance = 0;
 
 class SubGroup : public property_group
 {

Added: sandbox/pinhole/boost/pinhole/path_filtered_iterator.hpp
==============================================================================
--- (empty file)
+++ sandbox/pinhole/boost/pinhole/path_filtered_iterator.hpp 2009-05-19 15:30:22 EDT (Tue, 19 May 2009)
@@ -0,0 +1,104 @@
+// Pinhole path_filtered_iterator.hpp file
+//
+// Copyright Jared McIntyre 2009.
+// Distributed under 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 BOOST_PATH_FILTERED_ITERATOR
+#define BOOST_PATH_FILTERED_ITERATOR
+
+#include <string>
+#include <boost/../../boost_sandbox/pinhole/boost/pinhole/detail/depth_first_iterator_base.hpp>
+#include <boost/../../boost_sandbox/pinhole/boost/pinhole/detail/tokenizer.hpp>
+
+namespace boost { namespace pinhole
+{
+ namespace detail
+ {
+ template<class Iterator>
+ struct path_filter : depth_first_iterator_base<Iterator, path_filter<Iterator> >
+ {
+ typedef depth_first_iterator_base<Iterator, path_filter<Iterator> > base_type;
+
+ explicit path_filter( Iterator end ) :
+ base_type(end, end)
+ {
+ current_token = token_path.tokens.begin();
+ end_token = token_path.tokens.end();
+
+ // required call by depth_first_iterator_base
+ MoveIteratorToValidPosition();
+ }
+
+ explicit path_filter( std::string path, Iterator x, Iterator end ) :
+ base_type(x, end)
+ {
+ process_path( path, token_path );
+ current_token = token_path.tokens.begin();
+ end_token = token_path.tokens.end();
+
+ // required call by depth_first_iterator_base
+ MoveIteratorToValidPosition();
+ }
+
+ path_filter( const path_filter& other ) :
+ base_type(other)
+ {
+ token_path = other.token_path;
+ current_token = token_path.tokens.begin();
+ detail::token_path::token_list::difference_type position = std::distance(other.token_path.tokens.begin(), other.current_token);
+ for( ; position != 0; --position )
+ {
+ ++current_token;
+ }
+ end_token = token_path.tokens.end();
+ }
+
+ inline bool validity_test(property_group* property)
+ {
+ return current_token->name == property->get_name() &&
+ (true == current_token->property.empty() ||
+ (property->is_valid_property(current_token->property) && current_token->value == property->get_as_string(current_token->property)) );
+ }
+
+ inline bool visit_children(property_group* property)
+ {
+ if( false == validity_test(property) || ++detail::token_path::const_iterator(current_token) == end_token)
+ {
+ return false;
+ }
+
+ ++current_token;
+
+ return true;
+ }
+
+ inline bool is_valid(property_group* property)
+ {
+ // Looking for only leaf nodes
+ return ++detail::token_path::const_iterator(current_token) == end_token && validity_test(property);
+ }
+
+ inline void move_up()
+ {
+ --current_token;
+ }
+
+ private:
+
+ path_filter() :
+ base_type() { }
+
+ detail::token_path token_path;
+ detail::token_path::const_iterator current_token;
+ detail::token_path::const_iterator end_token;
+ };
+ }
+
+ /** Iterates over all the keys in a map. */
+ typedef detail::path_filter<children_collection::iterator> path_filtered_iterator;
+ typedef detail::path_filter<children_collection::const_iterator> const_path_filtered_iterator;
+}}
+
+#endif // include guard
\ No newline at end of file

Modified: sandbox/pinhole/boost/pinhole/property_group.hpp
==============================================================================
--- sandbox/pinhole/boost/pinhole/property_group.hpp (original)
+++ sandbox/pinhole/boost/pinhole/property_group.hpp 2009-05-19 15:30:22 EDT (Tue, 19 May 2009)
@@ -1,6 +1,6 @@
 // Pinhole property_group.hpp file
 //
-// Copyright Jared McIntyre 2007.
+// Copyright Jared McIntyre 2007-2009.
 // Distributed under 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)
@@ -29,20 +29,20 @@
     #pragma warning(pop)
 #endif
 
-#define BOOST_SETTER(c) boost::bind(c, this, _1)
+#define BOOST_SETTER(c) std::tr1::bind(c, this, std::tr1::placeholders::_1)
 #if defined(BOOST_MSVC) && (_MSC_VER > 1310) && (_MSC_VER <= 1400)
- #define BOOST_GETTER(c) boost::bind(boost::mem_fn(c), this)
+ #define BOOST_GETTER(c) std::tr1::bind(std::tr1::mem_fn(c), this)
 #else
- #define BOOST_GETTER(c) boost::bind(c, this)
+ #define BOOST_GETTER(c) std::tr1::bind(c, this)
 #endif
-#define BOOST_ACTION(c) boost::bind(c, this)
+#define BOOST_ACTION(c) std::tr1::bind(c, this)
 
 namespace boost { namespace pinhole
 {
     template<typename T>
     struct property_system_var_setter
     {
- typedef T result_type;
+ typedef void result_type;
         
         property_system_var_setter(T &t) : var(t){}
             
@@ -57,7 +57,7 @@
     template<typename T>
     inline std::tr1::function<void (const T&)> property_system_var_setter_builder(T &t)
     {
- return std::tr1::bind<void>(property_system_var_setter<T>(t), _1);
+ return std::tr1::bind<void>(property_system_var_setter<T>(t), std::tr1::placeholders::_1);
     }
 
     #define BOOST_SETTER_VAR(c) boost::pinhole::property_system_var_setter_builder(c)
@@ -141,11 +141,15 @@
             {
                 m_parent->remove_child(this);
             }
+ else if( m_manager != NULL )
+ {
+ m_manager->remove_property_group(this);
+ }
             
             if ( m_manager != NULL )
             {
                 // Unregister this group with this property manager...
- m_manager->unregister_property_group( this, m_category_collection );
+ m_manager->unregister_property_group( this );
             }
             
             // cleanup all the property_manager classes
@@ -191,18 +195,22 @@
         */
         void set_parent(property_group* new_parent)
         {
+ if ( NULL != m_parent )
+ {
+ m_parent->remove_child(this);
+ }
+ else if( m_manager != NULL )
+ {
+ m_manager->remove_property_group(this);
+ }
+
             if( m_manager )
             {
                 // Register this group with this property manager...
- m_manager->unregister_property_group(this, m_category_collection);
+ m_manager->unregister_property_group(this);
                 m_manager.reset();
             }
             
- if ( NULL != m_parent )
- {
- m_parent->remove_child(this);
- }
-
             m_parent = new_parent;
             
             
@@ -218,6 +226,7 @@
             else
             {
                 m_manager = property_manager::instance();
+ m_manager->add_property_group(this);
             }
 
             if( m_manager )
@@ -303,6 +312,16 @@
             }
 
             /**
+ * Returns whether the property exists.
+ * @retval true Property exists.
+ * @retval false Property does not exist.
+ */
+ bool is_valid_property( const std::string &property ) const
+ {
+ return m_properties.find(property) != m_properties.end();
+ }
+
+ /**
              * Gets a property's value by it's type.
              * @param property The name of the property.
              * @return The value of the property.
@@ -315,7 +334,7 @@
             {
                 // The system does not allow you to use pointers as property
                 // types due to the ambiguity of their use.
- BOOST_STATIC_ASSERT(false == boost::is_pointer<Return_Type>::value);
+ BOOST_STATIC_ASSERT(false == std::tr1::is_pointer<Return_Type>::value);
                 
                 property_collection::const_iterator itemItr = m_properties.find(property);
                 
@@ -351,7 +370,7 @@
             {
                 // The system does not allow you to use pointers as property
                 // types due to the ambiguity of their use.
- BOOST_STATIC_ASSERT(false == boost::is_pointer<Set_Type>::value);
+ BOOST_STATIC_ASSERT(false == std::tr1::is_pointer<Set_Type>::value);
                 
                 property_collection::const_iterator itemItr = m_properties.find(property);
                 
@@ -590,6 +609,16 @@
             }
 
             /**
+ * Returns whether the action exists.
+ * @retval true Action exists.
+ * @retval false Action does not exist.
+ */
+ bool is_valid_action( const std::string &action ) const
+ {
+ return m_actions.find(action) != m_actions.end();
+ }
+
+ /**
              * Triggers an action.
              * @param action The name of the action.
              * @throw std::out_of_range The property requested does not exist.
@@ -694,7 +723,7 @@
          */
         void add_action( std::string name,
                          std::string description,
- boost::function<void ()> action )
+ std::tr1::function<void ()> action )
         {
             detail::action_info *action_info = new detail::action_info();
             
@@ -712,13 +741,7 @@
         void add_category( const std::string &category_name )
         {
             m_category_collection.insert( category_name );
-
- // notify the Property Manager of this new category if we are a root
- // element (and therefore managed by the manager directly.
- if ( m_manager && NULL == m_parent )
- {
- m_manager->add_category( category_name, this );
- }
+ m_manager->add_category( category_name );
         }
 
     protected:
@@ -739,8 +762,8 @@
         template<typename Value_Type>
         void internal_add_property( const std::string &name,
                                     const std::string &description,
- boost::function<void (const Value_Type&)> setter,
- boost::function<Value_Type ()> getter,
+ std::tr1::function<void (const Value_Type&)> setter,
+ std::tr1::function<Value_Type ()> getter,
                                     boost::any &metadata )
         {
             property_collection::iterator previousInstance = m_properties.find(name);
@@ -796,6 +819,7 @@
             else
             {
                 m_manager = property_manager::instance();
+ m_manager->add_property_group( this );
             }
 
             if ( m_manager != NULL )
@@ -803,7 +827,7 @@
                 // Register this group with this property manager...
                 m_manager->register_property_group( this );
             }
-
+
             add_category( "All" );
         }
 

Modified: sandbox/pinhole/boost/pinhole/property_manager.hpp
==============================================================================
--- sandbox/pinhole/boost/pinhole/property_manager.hpp (original)
+++ sandbox/pinhole/boost/pinhole/property_manager.hpp 2009-05-19 15:30:22 EDT (Tue, 19 May 2009)
@@ -10,6 +10,7 @@
 
 #include "exceptions.hpp"
 #include "map_key_value_iterators.hpp"
+#include "category_iterator.hpp"
 #include <set>
 #include <string>
 
@@ -37,7 +38,7 @@
         static event_source* instance()
         {
             static boost::shared_ptr<boost::pinhole::event_source> instance;
-
+
             if ( !instance ) // is it the first call?
             {
                 instance.reset( new event_source ); // create sole instance
@@ -46,16 +47,6 @@
             return instance.get(); // address of sole instance
         }
         
- void raise_on_add_event( property_group *group )
- {
- add_event( group );
- }
-
- void raise_on_remove_event( property_group *group )
- {
- remove_event( group );
- }
-
         #if defined(BOOST_MSVC)
             #pragma warning(push)
             #pragma warning( disable: 4251 )
@@ -65,6 +56,15 @@
         #if defined(BOOST_MSVC)
             #pragma warning(pop)
         #endif
+ void raise_on_add_event( property_group *group )
+ {
+ add_event( group );
+ }
+
+ void raise_on_remove_event( property_group *group )
+ {
+ remove_event( group );
+ }
         
     private :
         
@@ -76,9 +76,18 @@
     {
     public:
         typedef std::tr1::shared_ptr<property_manager> instance_type;
- typedef std::multimap<std::string, property_group*> category_to_property_group_map;
- typedef map_value_iterator<category_to_property_group_map::iterator> iterator;
- typedef map_value_iterator<category_to_property_group_map::const_iterator> const_iterator;
+
+ private:
+ static void deleter(property_manager* manager)
+ {
+ delete manager;
+ }
+
+ public:
+ typedef boost::pinhole::children_collection::iterator iterator;
+ typedef boost::pinhole::children_collection::const_iterator const_iterator;
+ typedef boost::pinhole::category_iterator<boost::pinhole::children_collection::iterator> filtered_iterator;
+ typedef boost::pinhole::category_iterator<boost::pinhole::children_collection::const_iterator> const_filtered_iterator;
         
         static instance_type instance()
         {
@@ -99,14 +108,31 @@
         {
             internal_instance().reset();
         }
-
+
+ protected:
+ property_manager(){;}
+
+ // TODO: This needs to be protected so no-one will deal with it, but
+ // checked_delete can't be made a friend in gcc, so I can't shared_ptr
+ // to work.
+ public:
+ virtual ~property_manager()
+ {
+ children_collection::iterator itr = m_property_group_collection.begin();
+ children_collection::iterator itr_end = m_property_group_collection.end();
+ for( ; itr != itr_end; ++itr )
+ {
+ event_source::instance()->raise_on_remove_event((*itr));
+ }
+ }
+
+ public:
         /**
          * Retrieves an iterator pointing to the first property group.
          */
         iterator begin()
         {
- return iterator( m_property_group_collection.lower_bound("All"),
- m_property_group_collection.upper_bound("All") );
+ return m_property_group_collection.begin();
         }
         
         /**
@@ -114,8 +140,7 @@
          */
         const_iterator begin() const
         {
- return const_iterator( m_property_group_collection.lower_bound("All"),
- m_property_group_collection.upper_bound("All") );
+ return m_property_group_collection.begin();
         }
         
         /**
@@ -123,7 +148,7 @@
          */
         iterator end()
         {
- return iterator( m_property_group_collection.upper_bound("All") );
+ return m_property_group_collection.end();
         }
         
         /**
@@ -131,7 +156,7 @@
          */
         const_iterator end() const
         {
- return const_iterator( m_property_group_collection.upper_bound("All") );
+ return m_property_group_collection.end();
         }
         
         /**
@@ -139,39 +164,39 @@
          */
         size_t count() const
         {
- return m_property_group_collection.count("All");
+ return m_property_group_collection.size();
         }
         
         /**
          * Retrieves an iterator pointing to the first property group for a specified category.
          */
- iterator begin(const std::string& strCategory)
+ filtered_iterator begin(const std::string& strCategory)
         {
- return iterator( m_property_group_collection.lower_bound(strCategory) );
+ return make_category_iterator( strCategory, m_property_group_collection.begin(), m_property_group_collection.end() );
         }
         
         /**
          * Retrieves an iterator pointing to the first property group for a specified category.
          */
- const_iterator begin(const std::string& strCategory) const
+ const_filtered_iterator begin(const std::string& strCategory) const
         {
- return const_iterator( m_property_group_collection.lower_bound(strCategory) );
+ return make_category_iterator( strCategory, m_property_group_collection.begin(), m_property_group_collection.end() );
         }
         
         /**
          * Retrieves an iterator pointing to the end of the root property list for a specified category.
          */
- iterator end(const std::string& strCategory)
+ filtered_iterator end(const std::string& strCategory)
         {
- return iterator( m_property_group_collection.upper_bound(strCategory) );
+ return make_category_iterator( strCategory, m_property_group_collection.end(), m_property_group_collection.end() );
         }
         
         /**
          * Retrieves an iterator pointing to the end of the root property list for a specified category.
          */
- const_iterator end(const std::string& strCategory) const
+ const_filtered_iterator end(const std::string& strCategory) const
         {
- return const_iterator( m_property_group_collection.upper_bound(strCategory) );
+ return make_category_iterator( strCategory, m_property_group_collection.end(), m_property_group_collection.end() );
         }
         
         /**
@@ -179,7 +204,7 @@
          */
         size_t count(const std::string& strCategory) const
         {
- return m_property_group_collection.count(strCategory);
+ return std::distance(begin(strCategory), end(strCategory));
         }
         
         /**
@@ -192,27 +217,16 @@
         }
 
     protected:
-
- property_manager(){;}
-
- virtual ~property_manager()
- {
- category_to_property_group_map::iterator itr = m_property_group_collection.begin();
- category_to_property_group_map::iterator itr_end = m_property_group_collection.end();
- for( ; itr != itr_end; ++itr )
- {
- event_source::instance()->raise_on_remove_event((*itr).second);
- }
- }
-
+
         /** Provides direct access to the shared_ptr that owns the property_manager singleton. */
         static boost::shared_ptr<boost::pinhole::property_manager>& internal_instance()
         {
- static boost::shared_ptr<boost::pinhole::property_manager> instance;
-
+ static boost::shared_ptr<boost::pinhole::property_manager>
+ instance(new boost::pinhole::property_manager);
+
             return instance;
         }
-
+
         /**
          * Register's group with the property_manager.
          */
@@ -224,65 +238,47 @@
         /**
          * Unregister's group from the property_manager.
          */
- virtual void unregister_property_group( property_group *group, category_collection &categories )
+ virtual void unregister_property_group( property_group *group )
         {
- category_collection::const_iterator categoryItr = categories.begin();
- category_collection::const_iterator categoryEnd = categories.end();
- for ( ; categoryItr != categoryEnd; ++categoryItr )
- {
- remove_category( *categoryItr, group );
- }
-
- event_source::instance()->raise_on_remove_event( group );
+ event_source::instance()->raise_on_remove_event( group );
         }
         
         /**
- * Adds a new category for the property group.
+ * Adds a root property group.
          */
- virtual void add_category( const std::string &category_name, property_group *group )
+ virtual void add_property_group( property_group *group )
         {
- m_category_collection.insert( category_name );
- m_property_group_collection.insert( make_pair( category_name, group ) );
+ m_property_group_collection.push_back( group );
+ }
+
+ /**
+ * Removes a root property group.
+ */
+ virtual void remove_property_group( property_group *group )
+ {
+ m_property_group_collection.remove( group );
         }
         
- virtual void remove_category( const std::string &category_name, property_group *group )
+ /**
+ * Adds a new category for the property group.
+ */
+ virtual void add_category( const std::string &category_name )
         {
- category_to_property_group_map::iterator pgItr;
- for ( pgItr = m_property_group_collection.find( category_name );
- pgItr != m_property_group_collection.end(); )
- {
- if ( pgItr->second == group )
- {
- m_property_group_collection.erase( pgItr++ );
- }
- else
- {
- pgItr++;
- }
- }
+ m_category_collection.insert( category_name );
         }
         
+ protected:
         #if defined(BOOST_MSVC)
             #pragma warning(push)
             #pragma warning( disable: 4251 )
         #endif
- category_to_property_group_map m_property_group_collection;
+ boost::pinhole::children_collection m_property_group_collection;
             category_collection m_category_collection;
         #if defined(BOOST_MSVC)
             #pragma warning(pop)
         #endif
-
- private:
-
- // This allows us make the destructor protected. I can't make checked_delete a friend
- // in gcc, so shared_ptr couldn't access the desctructor directly.
- static void deleter(property_manager* manager)
- {
- delete manager;
- }
-
             
- friend class boost::pinhole::property_group;
+ friend class property_group;
     };
 }}
 

Added: sandbox/pinhole/boost/pinhole/value.hpp
==============================================================================
--- (empty file)
+++ sandbox/pinhole/boost/pinhole/value.hpp 2009-05-19 15:30:22 EDT (Tue, 19 May 2009)
@@ -0,0 +1,134 @@
+// Pinhole Find.hpp file
+//
+// Copyright Jared McIntyre 2008-2009.
+// Distributed under 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 BOOST_PINHOLE_VALUE
+#define BOOST_PINHOLE_VALUE
+
+#include <vector>
+#include <boost/foreach.hpp>
+#include <boost\..\..\boost_sandbox\pinhole\boost\pinhole\find.hpp>
+
+namespace boost { namespace pinhole
+{
+ /**
+ * Finds specified property_group and returns the value of one of its properties as the
+ * type specified. Finds property_group based on a path that describes where that property_group
+ * exists within the property group hierarchy. This version does not allow for relative
+ * path accessing.
+ * @n
+ * Path format one: /A/X.Y=Z @n
+ * A represents a property group name. The assumption is that A is the only property
+ * group in the current level. The path search will start from root\
+ * @n
+ * Path format two: /A.B=C/X.Y=Z @n
+ * A and X represent property group names. B and Y represent property names. C and Z
+ * represent property values. The path search will start from root.
+ *
+ * @param current_property_group The property_group in which to search.
+ * @param path The path to search with.
+ * @param property The name of the property.
+ * @return The value of the property.
+ * @throw invalid_path The path does not meet the requirements for a valid path.
+ * @throw multiple_property_groups There were multiple property groups matching this path.
+ * @throw failed_to_find_group The path is not found.
+ * @throw boost::bad_function_call There isn't a get_as_string function associated with this property.
+ * @throw std::out_of_range The property requested does not exist.
+ * @throw std::bad_cast The requested return_type was not the same as the property's type.
+ */
+ template<typename T>
+ T get_single_value(boost::pinhole::property_group& current_property_group, const std::string& path, const std::string& property)
+ {
+ property_group* pGroup = select_single_node(current_property_group, path);
+ if( NULL == pGroup )
+ {
+ throw boost::pinhole::failed_to_find_group();
+ }
+ return pGroup->get<T>(property);
+ }
+
+ template<typename T>
+ T get_single_value(const std::string& path, const std::string& property)
+ {
+ property_group* pGroup = select_single_node(path);
+ if( NULL == pGroup )
+ {
+ throw boost::pinhole::failed_to_find_group();
+ }
+ return pGroup->get<T>(property);
+ }
+
+ /**
+ * Finds specified property_group and sets the value of one of its properties.
+ * Finds property_group based on a path that describes where that property_group
+ * exists within the property group hierarchy. This version does not allow for relative
+ * path accessing.
+ * @n
+ * Path format one: /A/X.Y=Z @n
+ * A represents a property group name. The assumption is that A is the only property
+ * group in the current level. The path search will start from root\
+ * @n
+ * Path format two: /A.B=C/X.Y=Z @n
+ * A and X represent property group names. B and Y represent property names. C and Z
+ * represent property values. The path search will start from root.
+ *
+ * @param current_property_group The property_group in which to search.
+ * @param path The path to search with.
+ * @param property The name of the property.
+ * @return The value to set on the property.
+ * @throw invalid_path The path does not meet the requirements for a valid path.
+ * @throw multiple_property_groups There were multiple property groups matching this path.
+ * @throw failed_to_find_group The path is not found.
+ * @throw boost::bad_function_call There isn't a set_as_string function associated with this property.
+ * @throw std::out_of_range The property requested does not exist.
+ * @throw std::bad_cast Type T is not the same as the property's type.
+ */
+ template<typename T>
+ void set_single_value(boost::pinhole::property_group& current_property_group, const std::string& path, const std::string& property, T value)
+ {
+ property_group* pGroup = select_single_node(current_property_group, path);
+ if( NULL == pGroup )
+ {
+ throw boost::pinhole::failed_to_find_group();
+ }
+ pGroup->set<T>(property, value);
+ }
+
+ template<typename T>
+ void set_single_value(const std::string& path, const std::string& property, T value)
+ {
+ property_group* pGroup = select_single_node(path);
+ if( NULL == pGroup )
+ {
+ throw boost::pinhole::failed_to_find_group();
+ }
+ pGroup->set<T>(property, value);
+ }
+
+ template<typename T>
+ void set_all_values(boost::pinhole::property_group& current_property_group, const std::string& path, const std::string& property, T value)
+ {
+ boost::pinhole::path_filtered_range range = get_path_filtered_range(path, current_property_group);
+
+ BOOST_FOREACH(property_group* group, range)
+ {
+ group->set<T>(property, value);
+ }
+ }
+
+ template<typename T>
+ void set_all_values(const std::string& path, const std::string& property, T value)
+ {
+ boost::pinhole::path_filtered_range range = get_path_filtered_range(path);
+
+ BOOST_FOREACH(property_group* group, range)
+ {
+ group->set<T>(property, value);
+ }
+ }
+}}
+
+#endif // include guard
\ No newline at end of file

Modified: sandbox/pinhole/libs/pinhole/test/Jamfile.v2
==============================================================================
--- sandbox/pinhole/libs/pinhole/test/Jamfile.v2 (original)
+++ sandbox/pinhole/libs/pinhole/test/Jamfile.v2 2009-05-19 15:30:22 EDT (Tue, 19 May 2009)
@@ -1,6 +1,6 @@
 # Boost.Pinhole Library
 
-# Copyright Jared McIntyre 2007-2008. Use, modification and
+# Copyright Jared McIntyre 2007-2009. 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)
@@ -30,6 +30,10 @@
   
   [ run test_actions.cpp ]
   
+ [ run test_tokenizer.cpp ]
+ [ run test_depth_first_iterator.cpp ]
+ [ run test_path_filtered_iterator.cpp ]
+ [ run test_category_iterator.cpp ]
   [ run test_find.cpp ]
  ;
 }

Added: sandbox/pinhole/libs/pinhole/test/test_category_iterator.cpp
==============================================================================
--- (empty file)
+++ sandbox/pinhole/libs/pinhole/test/test_category_iterator.cpp 2009-05-19 15:30:22 EDT (Tue, 19 May 2009)
@@ -0,0 +1,227 @@
+// Boost.Pinhole library
+
+// Copyright Jared McIntyre 2009. 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)
+
+// For more information, see http://www.boost.org
+
+#define BOOST_TEST_MODULE PinholeLib
+#include <boost/test/unit_test.hpp>
+#include <boost/pinhole.hpp>
+#include <boost/pinhole/category_iterator.hpp>
+
+using namespace std;
+using namespace boost;
+using namespace boost::pinhole;
+using namespace boost::pinhole::detail;
+
+class TestPropertyGroup : public property_group
+{
+public:
+ TestPropertyGroup( int level, int id, property_group *pParentGroup) :
+ property_group( lexical_cast<string>(level), pParentGroup ),
+ m_int(id)
+ {
+ add_property("ID", "ID", BOOST_SETTER_NONE, BOOST_GETTER_VAR(m_int));
+ }
+
+ int m_int;
+};
+
+BOOST_AUTO_TEST_CASE( TestCategoryIterator )
+{
+ std::list<property_group*> properties;
+
+ TestPropertyGroup group1(1, 1, NULL);
+ group1.add_category("a");
+ group1.add_category("e");
+ TestPropertyGroup group2(2, 2, NULL);
+ group2.add_category("b");
+ group2.add_category("e");
+ TestPropertyGroup group3(3, 3, NULL);
+ group3.add_category("c");
+ TestPropertyGroup group4(4, 4, NULL);
+ group4.add_category("d");
+ group4.add_category("e");
+
+ properties.push_back( &group1 );
+ properties.push_back( &group2 );
+ properties.push_back( &group3 );
+ properties.push_back( &group4 );
+
+ {
+ category_iterator< std::list<property_group*>::iterator > itr = make_category_iterator( "a", properties.begin(), properties.end() );
+ category_iterator< std::list<property_group*>::iterator > itrEnd = make_category_iterator( "a", properties.end(), properties.end() );
+
+ BOOST_CHECK_EQUAL( std::distance(itr, itrEnd), 1 );
+
+ int ct=0;
+ for( ; itr != itrEnd; ++itr, ++ct )
+ {
+ switch( ct )
+ {
+ case 0:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 1 );
+ break;
+ default:
+ BOOST_ERROR("found too many groups");
+ }
+ }
+ BOOST_CHECK_EQUAL( ct, 1 );
+ }
+
+ {
+ category_iterator< std::list<property_group*>::iterator > itr( "b", properties.begin(), properties.end() );
+ category_iterator< std::list<property_group*>::iterator > itrEnd( "b", properties.end(), properties.end() );
+
+ BOOST_CHECK_EQUAL( std::distance(itr, itrEnd), 1 );
+
+ int ct=0;
+ for( ; itr != itrEnd; ++itr, ++ct )
+ {
+ switch( ct )
+ {
+ case 0:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 2 );
+ break;
+ default:
+ BOOST_ERROR("found too many groups");
+ }
+ }
+ BOOST_CHECK_EQUAL( ct, 1 );
+ }
+
+ {
+ category_iterator< std::list<property_group*>::iterator > itr( "c", properties.begin(), properties.end() );
+ category_iterator< std::list<property_group*>::iterator > itrEnd( "c", properties.end(), properties.end() );
+
+ BOOST_CHECK_EQUAL( std::distance(itr, itrEnd), 1 );
+
+ int ct=0;
+ for( ; itr != itrEnd; ++itr, ++ct )
+ {
+ switch( ct )
+ {
+ case 0:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 3 );
+ break;
+ default:
+ BOOST_ERROR("found too many groups");
+ }
+ }
+ BOOST_CHECK_EQUAL( ct, 1 );
+ }
+
+ {
+ category_iterator< std::list<property_group*>::iterator > itr( "d", properties.begin(), properties.end() );
+ category_iterator< std::list<property_group*>::iterator > itrEnd( "d", properties.end(), properties.end() );
+
+ BOOST_CHECK_EQUAL( std::distance(itr, itrEnd), 1 );
+
+ int ct=0;
+ for( ; itr != itrEnd; ++itr, ++ct )
+ {
+ switch( ct )
+ {
+ case 0:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 4 );
+ break;
+ default:
+ BOOST_ERROR("found too many groups");
+ }
+ }
+ BOOST_CHECK_EQUAL( ct, 1 );
+ }
+
+ {
+ category_iterator< std::list<property_group*>::iterator > itr( "e", properties.begin(), properties.end() );
+ category_iterator< std::list<property_group*>::iterator > itrEnd( "e", properties.end(), properties.end() );
+
+ BOOST_CHECK_EQUAL( std::distance(itr, itrEnd), 3 );
+
+ int ct=0;
+ for( ; itr != itrEnd; ++itr, ++ct )
+ {
+ switch( ct )
+ {
+ case 0:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 1 );
+ break;
+ case 1:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 2 );
+ break;
+ case 2:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 4 );
+ break;
+ default:
+ BOOST_ERROR("found too many groups");
+ }
+ }
+ BOOST_CHECK_EQUAL( ct, 3 );
+ }
+
+ {
+ category_iterator< std::list<property_group*>::iterator > itr( "All", properties.begin(), properties.end() );
+ category_iterator< std::list<property_group*>::iterator > itrEnd( "All", properties.end(), properties.end() );
+
+ BOOST_CHECK_EQUAL( std::distance(itr, itrEnd), 4 );
+
+ int ct=0;
+ for( ; itr != itrEnd; ++itr, ++ct )
+ {
+ switch( ct )
+ {
+ case 0:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 1 );
+ break;
+ case 1:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 2 );
+ break;
+ case 2:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 3 );
+ break;
+ case 3:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 4 );
+ break;
+ default:
+ BOOST_ERROR("found too many groups");
+ }
+ }
+ BOOST_CHECK_EQUAL( ct, 4 );
+ }
+
+ {
+ category_iterator< std::list<property_group*>::iterator > itr( "none", properties.begin(), properties.end() );
+ category_iterator< std::list<property_group*>::iterator > itrEnd( "none", properties.end(), properties.end() );
+
+ BOOST_CHECK_EQUAL( std::distance(itr, itrEnd), 0 );
+
+ int ct=0;
+ for( ; itr != itrEnd; ++itr, ++ct )
+ {
+ BOOST_ERROR("found too many groups");
+ }
+ BOOST_CHECK_EQUAL( ct, 0 );
+ }
+}
+
+BOOST_AUTO_TEST_CASE( TestCategoryIterator_EmptyCollection )
+{
+ std::list<property_group*> properties;
+
+ {
+ category_iterator< std::list<property_group*>::iterator > itr = make_category_iterator( "a", properties.begin(), properties.end() );
+ category_iterator< std::list<property_group*>::iterator > itrEnd = make_category_iterator( "a", properties.end(), properties.end() );
+
+ BOOST_CHECK_EQUAL( std::distance(itr, itrEnd), 0 );
+
+ int ct=0;
+ for( ; itr != itrEnd; ++itr, ++ct )
+ {
+ BOOST_ERROR("found too many groups");
+ }
+ BOOST_CHECK_EQUAL( ct, 0 );
+ }
+}

Added: sandbox/pinhole/libs/pinhole/test/test_depth_first_iterator.cpp
==============================================================================
--- (empty file)
+++ sandbox/pinhole/libs/pinhole/test/test_depth_first_iterator.cpp 2009-05-19 15:30:22 EDT (Tue, 19 May 2009)
@@ -0,0 +1,265 @@
+// Boost.Pinhole library
+
+// Copyright Jared McIntyre 2009. 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)
+
+// For more information, see http://www.boost.org
+
+#define BOOST_TEST_MODULE PinholeLib
+#include <boost/test/unit_test.hpp>
+#include <boost/pinhole.hpp>
+#include <boost/pinhole/depth_first_iterator.hpp>
+
+using namespace std;
+using namespace boost;
+using namespace boost::pinhole;
+using namespace boost::pinhole::detail;
+
+class TestPropertyGroup : public property_group
+{
+public:
+ TestPropertyGroup( int level, int id, property_group *pParentGroup) :
+ property_group( lexical_cast<string>(level), pParentGroup ),
+ m_int(id)
+ {
+ add_property("ID", "ID", BOOST_SETTER_NONE, BOOST_GETTER_VAR(m_int));
+ }
+
+ int m_int;
+};
+
+BOOST_AUTO_TEST_CASE( TestSimplePath_RootSearch )
+{
+ TestPropertyGroup group1(1, 1, NULL);
+ TestPropertyGroup group2(2, 2, &group1);
+ TestPropertyGroup group3(3, 3, &group2);
+ TestPropertyGroup group4(4, 4, &group3);
+
+ depth_first_iterator itr( group1.get_children_collection().begin(), group1.get_children_collection().end() );
+ depth_first_iterator itrEnd( group1.get_children_collection().end(), group1.get_children_collection().end() );
+
+ BOOST_CHECK( itr != itrEnd );
+
+ BOOST_CHECK_EQUAL( std::distance(itr, itrEnd), 3 );
+
+ int ct=0;
+ for( ; itr != itrEnd; ++itr, ++ct )
+ {
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 4-ct );
+ }
+ BOOST_CHECK_EQUAL( ct, 3 );
+}
+
+BOOST_AUTO_TEST_CASE( TestComplexPath_RootSearch )
+{
+ TestPropertyGroup group1(1, 1, NULL);
+ TestPropertyGroup group2(2, 2, &group1);
+ TestPropertyGroup group3(3, 3, &group2);
+ TestPropertyGroup group4(2, 4, &group1);
+ TestPropertyGroup group5(2, 5, &group1);
+ TestPropertyGroup group6(3, 6, &group5);
+ TestPropertyGroup group7(3, 7, &group5);
+ TestPropertyGroup group8(4, 8, &group7);
+ TestPropertyGroup group9(3, 9, &group5);
+ {
+ depth_first_iterator itr( group1.get_children_collection().begin(), group1.get_children_collection().end() );
+ depth_first_iterator itrEnd( group1.get_children_collection().end() );
+
+ BOOST_CHECK( itr != itrEnd );
+
+ BOOST_CHECK_EQUAL( std::distance(itr, itrEnd), 8 );
+
+ int ct=0;
+ for( ; itr != itrEnd; ++itr, ++ct )
+ {
+ switch( ct )
+ {
+ case 0:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 3 );
+ break;
+ case 1:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 2 );
+ break;
+ case 2:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 4 );
+ break;
+ case 3:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 6 );
+ break;
+ case 4:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 8 );
+ break;
+ case 5:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 7 );
+ break;
+ case 6:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 9 );
+ break;
+ case 7:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 5 );
+ break;
+ case 8:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 1 );
+ break;
+ default:
+ BOOST_ERROR("found too many groups");
+ }
+ }
+ BOOST_CHECK_EQUAL( ct, 8 );
+ }
+
+ {
+ depth_first_iterator itr( group5.get_children_collection().begin(), group5.get_children_collection().end() );
+ depth_first_iterator itrEnd( group5.get_children_collection().end(), group5.get_children_collection().end() );
+
+ BOOST_CHECK( itr != itrEnd );
+
+ BOOST_CHECK_EQUAL( std::distance(itr, itrEnd), 4 );
+
+ int ct=0;
+ for( ; itr != itrEnd; ++itr, ++ct )
+ {
+ property_group* prop = (*itr);
+ switch( ct )
+ {
+ case 0:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 6 );
+ break;
+ case 1:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 8 );
+ break;
+ case 2:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 7 );
+ break;
+ case 3:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 9 );
+ break;
+ default:
+ BOOST_ERROR("found too many groups");
+ }
+ }
+ BOOST_CHECK_EQUAL( ct, 4 );
+ }
+}
+/*
+BOOST_AUTO_TEST_CASE( TestComplexPath_SubSearch )
+{
+ TestPropertyGroup group1(1, 1, NULL);
+ TestPropertyGroup group2(2, 2, &group1);
+ TestPropertyGroup group3(3, 3, &group2);
+ TestPropertyGroup group4(2, 4, &group1);
+ TestPropertyGroup group5(2, 5, &group1);
+ TestPropertyGroup group6(3, 6, &group5);
+ TestPropertyGroup group7(3, 7, &group5);
+ TestPropertyGroup group8(4, 8, &group7);
+ TestPropertyGroup group9(3, 9, &group5);
+ {
+ depth_first_iterator itr( group5.get_children_collection().begin(), group8.get_children_collection().begin() );
+ depth_first_iterator itrEnd( group8.get_children_collection().begin() );
+
+ BOOST_CHECK( itr != itrEnd );
+
+ BOOST_CHECK_EQUAL( std::distance(itr, itrEnd), 2 );
+
+ int ct=0;
+ for( ; itr != itrEnd; ++itr, ++ct )
+ {
+ switch( ct )
+ {
+ case 0:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 6 );
+ break;
+ case 1:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 7 );
+ break;
+ default:
+ BOOST_ERROR("found too many groups");
+ }
+ }
+ BOOST_CHECK_EQUAL( ct, 2 );
+ }
+}
+*/
+BOOST_AUTO_TEST_CASE( TestSimplePath_ManagerSearch )
+{
+ TestPropertyGroup group1(1, 1, NULL);
+ TestPropertyGroup group2(2, 2, &group1);
+ TestPropertyGroup group3(3, 3, &group2);
+ TestPropertyGroup group4(4, 4, &group3);
+
+ depth_first_iterator itr( property_manager::instance()->begin(), property_manager::instance()->end() );
+ depth_first_iterator itrEnd( property_manager::instance()->end(), property_manager::instance()->end() );
+
+ BOOST_CHECK( itr != itrEnd );
+
+ BOOST_CHECK_EQUAL( std::distance(itr, itrEnd), 4 );
+
+ int ct=0;
+ for( ; itr != itrEnd; ++itr, ++ct )
+ {
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 4-ct );
+ }
+ BOOST_CHECK_EQUAL( ct, 4 );
+}
+
+BOOST_AUTO_TEST_CASE( TestComplexPath_ManagerSearch )
+{
+ TestPropertyGroup group1(1, 1, NULL);
+ TestPropertyGroup group2(2, 2, &group1);
+ TestPropertyGroup group3(3, 3, &group2);
+ TestPropertyGroup group4(2, 4, &group1);
+ TestPropertyGroup group5(2, 5, &group1);
+ TestPropertyGroup group6(3, 6, &group5);
+ TestPropertyGroup group7(3, 7, &group5);
+ TestPropertyGroup group8(4, 8, &group7);
+ TestPropertyGroup group9(3, 9, &group5);
+
+ {
+ depth_first_iterator itr( property_manager::instance()->begin(), property_manager::instance()->end() );
+ depth_first_iterator itrEnd( property_manager::instance()->end() );
+
+ BOOST_CHECK( itr != itrEnd );
+
+ BOOST_CHECK_EQUAL( std::distance(itr, itrEnd), 9 );
+
+ int ct=0;
+ for( ; itr != itrEnd; ++itr, ++ct )
+ {
+ switch( ct )
+ {
+ case 0:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 3 );
+ break;
+ case 1:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 2 );
+ break;
+ case 2:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 4 );
+ break;
+ case 3:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 6 );
+ break;
+ case 4:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 8 );
+ break;
+ case 5:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 7 );
+ break;
+ case 6:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 9 );
+ break;
+ case 7:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 5 );
+ break;
+ case 8:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 1 );
+ break;
+ default:
+ BOOST_ERROR("found too many groups");
+ }
+ }
+ BOOST_CHECK_EQUAL( ct, 9 );
+ }
+}
\ No newline at end of file

Modified: sandbox/pinhole/libs/pinhole/test/test_find.cpp
==============================================================================
--- sandbox/pinhole/libs/pinhole/test/test_find.cpp (original)
+++ sandbox/pinhole/libs/pinhole/test/test_find.cpp 2009-05-19 15:30:22 EDT (Tue, 19 May 2009)
@@ -1,6 +1,6 @@
 // Boost.Pinhole library
 
-// Copyright Jared McIntyre 2008. Use, modification and
+// Copyright Jared McIntyre 2008-2009. 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)
@@ -10,6 +10,7 @@
 #define BOOST_TEST_MODULE PinholeLib
 #include <boost/test/unit_test.hpp>
 #include <boost/pinhole.hpp>
+#include <boost/foreach.hpp>
 
 using namespace std;
 using namespace boost;
@@ -28,20 +29,6 @@
     int m_int;
 };
 
-class TestPropertyManagerGuard
-{
-public:
- TestPropertyManagerGuard()
- {
- property_manager::delete_instance();
- }
-
- ~TestPropertyManagerGuard()
- {
- property_manager::delete_instance();
- }
-};
-
 BOOST_AUTO_TEST_CASE( TestSimplePath_RootSearch )
 {
     TestPropertyGroup group1(1, 1, NULL);
@@ -145,4 +132,381 @@
 
     BOOST_CHECK_THROW( select_single_node("/1"), boost::pinhole::multiple_property_groups );
     BOOST_CHECK_THROW( select_single_node("/1.ID=1/2"), boost::pinhole::multiple_property_groups );
+}
+
+BOOST_AUTO_TEST_CASE( TestFilterNodes_SimplePaths )
+{
+ TestPropertyGroup group1(1, 1, NULL);
+ TestPropertyGroup group2(2, 2, &group1);
+ TestPropertyGroup group3(3, 3, &group2);
+ TestPropertyGroup group4(4, 4, &group3);
+
+ BOOST_CHECK_THROW( get_path_filtered_range("1"), invalid_path );
+
+ {
+ boost::pinhole::path_filtered_range range = get_path_filtered_range("/5");
+
+ BOOST_CHECK( range.begin() == range.end() );
+ }
+
+ {
+ boost::pinhole::path_filtered_range range = get_path_filtered_range("/1/2");
+
+ BOOST_CHECK( range.begin() != range.end() );
+
+ BOOST_CHECK_EQUAL( std::distance(begin(range), end(range)), 1 );
+
+ int ct=0;
+ BOOST_FOREACH( property_group* prop, range )
+ {
+ switch(ct)
+ {
+ case 0:
+ BOOST_CHECK_EQUAL( prop->get<int>("ID"), 2 );
+ break;
+ default:
+ BOOST_ERROR("Too many items");
+ }
+
+ ++ct;
+ }
+ BOOST_CHECK_EQUAL( ct, 1 );
+ }
+
+ {
+ // test const
+
+ boost::pinhole::const_path_filtered_range range = get_const_path_filtered_range("/1/2");
+
+ BOOST_CHECK( range.begin() != range.end() );
+
+ BOOST_CHECK_EQUAL( std::distance(begin(range), end(range)), 1 );
+
+ int ct=0;
+ BOOST_FOREACH( property_group* prop, range )
+ {
+ switch(ct)
+ {
+ case 0:
+ BOOST_CHECK_EQUAL( prop->get<int>("ID"), 2 );
+ break;
+ default:
+ BOOST_ERROR("Too many items");
+ }
+
+ ++ct;
+ }
+ BOOST_CHECK_EQUAL( ct, 1 );
+ }
+
+ {
+ boost::pinhole::path_filtered_range range = get_path_filtered_range("/1/2/3/");
+
+ BOOST_CHECK( range.begin() != range.end() );
+
+ BOOST_CHECK_EQUAL( std::distance(begin(range), end(range)), 1 );
+
+ int ct=0;
+ BOOST_FOREACH( property_group* prop, range )
+ {
+ switch(ct)
+ {
+ case 0:
+ BOOST_CHECK_EQUAL( prop->get<int>("ID"), 3 );
+ break;
+ default:
+ BOOST_ERROR("Too many items");
+ }
+
+ ++ct;
+ }
+ BOOST_CHECK_EQUAL( ct, 1 );
+ }
+
+ {
+ boost::pinhole::path_filtered_range range = get_path_filtered_range("/1/2/3/4");
+
+ BOOST_CHECK( range.begin() != range.end() );
+
+ BOOST_CHECK_EQUAL( std::distance(begin(range), end(range)), 1 );
+
+ int ct=0;
+ BOOST_FOREACH( property_group* prop, range )
+ {
+ switch(ct)
+ {
+ case 0:
+ BOOST_CHECK_EQUAL( prop->get<int>("ID"), 4 );
+ break;
+ default:
+ BOOST_ERROR("Too many items");
+ }
+
+ ++ct;
+ }
+ BOOST_CHECK_EQUAL( ct, 1 );
+ }
+}
+
+BOOST_AUTO_TEST_CASE( TestPathFilteredIterator_ComplexPaths_NoValueCheck )
+{
+ TestPropertyGroup group1(1, 1, NULL);
+ TestPropertyGroup group2(2, 2, &group1);
+ TestPropertyGroup group3(3, 3, &group2);
+ TestPropertyGroup group4(2, 4, &group1);
+ TestPropertyGroup group5(2, 5, &group1);
+ TestPropertyGroup group6(3, 6, &group5);
+ TestPropertyGroup group7(3, 7, &group5);
+ TestPropertyGroup group8(4, 8, &group7);
+ TestPropertyGroup group9(3, 9, &group5);
+
+ {
+ boost::pinhole::path_filtered_range range = get_path_filtered_range("2/3", group1);
+
+ BOOST_CHECK( range.begin() != range.end() );
+
+ BOOST_CHECK_EQUAL( std::distance(begin(range), end(range)), 4 );
+
+ int ct = 0;
+ BOOST_FOREACH( property_group* prop, range )
+ {
+ switch( ct )
+ {
+ case 0:
+ BOOST_CHECK_EQUAL( prop->get<int>("ID"), 3 );
+ break;
+ case 1:
+ BOOST_CHECK_EQUAL( prop->get<int>("ID"), 6 );
+ break;
+ case 2:
+ BOOST_CHECK_EQUAL( prop->get<int>("ID"), 7 );
+ break;
+ case 3:
+ BOOST_CHECK_EQUAL( prop->get<int>("ID"), 9 );
+ break;
+ default:
+ BOOST_ERROR("found too many groups");
+ }
+
+ ++ct;
+ }
+ BOOST_CHECK_EQUAL( ct, 4 );
+ }
+
+ {
+ // test const
+
+ boost::pinhole::const_path_filtered_range range = get_const_path_filtered_range("2/3", group1);
+
+ BOOST_CHECK( range.begin() != range.end() );
+
+ BOOST_CHECK_EQUAL( std::distance(begin(range), end(range)), 4 );
+
+ int ct=0;
+ BOOST_FOREACH( property_group* prop, range )
+ {
+ switch( ct )
+ {
+ case 0:
+ BOOST_CHECK_EQUAL( prop->get<int>("ID"), 3 );
+ break;
+ case 1:
+ BOOST_CHECK_EQUAL( prop->get<int>("ID"), 6 );
+ break;
+ case 2:
+ BOOST_CHECK_EQUAL( prop->get<int>("ID"), 7 );
+ break;
+ case 3:
+ BOOST_CHECK_EQUAL( prop->get<int>("ID"), 9 );
+ break;
+ default:
+ BOOST_ERROR("found too many groups");
+ }
+
+ ++ct;
+ }
+ BOOST_CHECK_EQUAL( ct, 4 );
+ }
+
+ {
+ boost::pinhole::path_filtered_range range = get_path_filtered_range("/1/2/3", group1);
+
+ BOOST_CHECK( range.begin() != range.end() );
+
+ BOOST_CHECK_EQUAL( std::distance(begin(range), end(range)), 4 );
+
+ int ct=0;
+ BOOST_FOREACH( property_group* prop, range )
+ {
+ switch( ct )
+ {
+ case 0:
+ BOOST_CHECK_EQUAL( prop->get<int>("ID"), 3 );
+ break;
+ case 1:
+ BOOST_CHECK_EQUAL( prop->get<int>("ID"), 6 );
+ break;
+ case 2:
+ BOOST_CHECK_EQUAL( prop->get<int>("ID"), 7 );
+ break;
+ case 3:
+ BOOST_CHECK_EQUAL( prop->get<int>("ID"), 9 );
+ break;
+ default:
+ BOOST_ERROR("found too many groups");
+ }
+
+ ++ct;
+ }
+ BOOST_CHECK_EQUAL( ct, 4 );
+ }
+
+ {
+ // test const
+
+ boost::pinhole::const_path_filtered_range range = get_const_path_filtered_range("/1/2/3", group1);
+
+ BOOST_CHECK( range.begin() != range.end() );
+
+ BOOST_CHECK_EQUAL( std::distance(begin(range), end(range)), 4 );
+
+ int ct=0;
+ BOOST_FOREACH( property_group* prop, range )
+ {
+ switch( ct )
+ {
+ case 0:
+ BOOST_CHECK_EQUAL( prop->get<int>("ID"), 3 );
+ break;
+ case 1:
+ BOOST_CHECK_EQUAL( prop->get<int>("ID"), 6 );
+ break;
+ case 2:
+ BOOST_CHECK_EQUAL( prop->get<int>("ID"), 7 );
+ break;
+ case 3:
+ BOOST_CHECK_EQUAL( prop->get<int>("ID"), 9 );
+ break;
+ default:
+ BOOST_ERROR("found too many groups");
+ }
+
+ ++ct;
+ }
+ BOOST_CHECK_EQUAL( ct, 4 );
+ }
+
+ {
+ boost::pinhole::path_filtered_range range = get_path_filtered_range("2", group1);
+
+ BOOST_CHECK( range.begin() != range.end() );
+
+ BOOST_CHECK_EQUAL( std::distance(begin(range), end(range)), 3 );
+
+ int ct=0;
+ BOOST_FOREACH( property_group* prop, range )
+ {
+ switch( ct )
+ {
+ case 0:
+ BOOST_CHECK_EQUAL( prop->get<int>("ID"), 2 );
+ break;
+ case 1:
+ BOOST_CHECK_EQUAL( prop->get<int>("ID"), 4 );
+ break;
+ case 2:
+ BOOST_CHECK_EQUAL( prop->get<int>("ID"), 5 );
+ break;
+ default:
+ BOOST_ERROR("found too many groups");
+ }
+
+ ++ct;
+ }
+ BOOST_CHECK_EQUAL( ct, 3 );
+ }
+
+ {
+ boost::pinhole::path_filtered_range range = get_path_filtered_range("2/3/4/", group1);
+
+ BOOST_CHECK( range.begin() != range.end() );
+
+ BOOST_CHECK_EQUAL( std::distance(begin(range), end(range)), 1 );
+
+ int ct=0;
+ BOOST_FOREACH( property_group* prop, range )
+ {
+ switch( ct )
+ {
+ case 0:
+ BOOST_CHECK_EQUAL( prop->get<int>("ID"), 8 );
+ break;
+ default:
+ BOOST_ERROR("found too many groups");
+ }
+
+ ++ct;
+ }
+ BOOST_CHECK_EQUAL( ct, 1 );
+ }
+
+ {
+ boost::pinhole::path_filtered_range range = get_path_filtered_range("2", group5);
+
+ BOOST_CHECK( range.begin() == range.end() );
+ }
+
+ {
+ boost::pinhole::path_filtered_range range = get_path_filtered_range("3", group5);
+
+ BOOST_CHECK( range.begin() != range.end() );
+
+ BOOST_CHECK_EQUAL( std::distance(begin(range), end(range)), 3 );
+
+ int ct=0;
+ BOOST_FOREACH( property_group* prop, range )
+ {
+ switch( ct )
+ {
+ case 0:
+ BOOST_CHECK_EQUAL( prop->get<int>("ID"), 6 );
+ break;
+ case 1:
+ BOOST_CHECK_EQUAL( prop->get<int>("ID"), 7 );
+ break;
+ case 2:
+ BOOST_CHECK_EQUAL( prop->get<int>("ID"), 9 );
+ break;
+ default:
+ BOOST_ERROR("found too many groups");
+ }
+
+ ++ct;
+ }
+ BOOST_CHECK_EQUAL( ct, 3 );
+ }
+
+ {
+ boost::pinhole::path_filtered_range range = get_path_filtered_range("3/4", group5);
+
+ BOOST_CHECK( range.begin() != range.end() );
+
+ BOOST_CHECK_EQUAL( std::distance(begin(range), end(range)), 1 );
+
+ int ct=0;
+ BOOST_FOREACH( property_group* prop, range )
+ {
+ switch( ct )
+ {
+ case 0:
+ BOOST_CHECK_EQUAL( prop->get<int>("ID"), 8 );
+ break;
+ default:
+ BOOST_ERROR("found too many groups");
+ }
+
+ ++ct;
+ }
+ BOOST_CHECK_EQUAL( ct, 1 );
+ }
 }
\ No newline at end of file

Added: sandbox/pinhole/libs/pinhole/test/test_path_filtered_iterator.cpp
==============================================================================
--- (empty file)
+++ sandbox/pinhole/libs/pinhole/test/test_path_filtered_iterator.cpp 2009-05-19 15:30:22 EDT (Tue, 19 May 2009)
@@ -0,0 +1,418 @@
+// Boost.Pinhole library
+
+// Copyright Jared McIntyre 2009. 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)
+
+// For more information, see http://www.boost.org
+
+#define BOOST_TEST_MODULE PinholeLib
+#include <boost/test/unit_test.hpp>
+#include <boost/pinhole.hpp>
+#include <boost/pinhole/path_filtered_iterator.hpp>
+
+using namespace std;
+using namespace boost;
+using namespace boost::pinhole;
+using namespace boost::pinhole::detail;
+
+class TestPropertyGroup : public property_group
+{
+public:
+ TestPropertyGroup( int level, int id, property_group *pParentGroup) :
+ property_group( lexical_cast<string>(level), pParentGroup ),
+ m_int(id)
+ {
+ add_property("ID", "ID", BOOST_SETTER_NONE, BOOST_GETTER_VAR(m_int));
+ }
+
+ int m_int;
+};
+
+BOOST_AUTO_TEST_CASE( TestPathFilteredIterator_SimplePaths )
+{
+ TestPropertyGroup group1(1, 1, NULL);
+ TestPropertyGroup group2(2, 2, &group1);
+ TestPropertyGroup group3(3, 3, &group2);
+ TestPropertyGroup group4(4, 4, &group3);
+
+ {
+ path_filtered_iterator itr( "5", group1.get_children_collection().begin(), group1.get_children_collection().end() );
+ path_filtered_iterator itrEnd( "", group1.get_children_collection().end(), group1.get_children_collection().end() );
+
+ BOOST_CHECK( itr == itrEnd );
+ }
+
+ {
+ path_filtered_iterator itr( "2", group1.get_children_collection().begin(), group1.get_children_collection().end() );
+ path_filtered_iterator itrEnd( "", group1.get_children_collection().end(), group1.get_children_collection().end() );
+
+ BOOST_CHECK( itr != itrEnd );
+
+ BOOST_CHECK_EQUAL( std::distance(itr, itrEnd), 1 );
+
+ int ct=0;
+ for( ; itr != itrEnd; ++itr, ++ct )
+ {
+ switch(ct)
+ {
+ case 0:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 2 );
+ break;
+ default:
+ BOOST_ERROR("Too many items");
+ }
+ }
+ BOOST_CHECK_EQUAL( ct, 1 );
+ }
+
+ {
+ path_filtered_iterator itr( "2/3/", group1.get_children_collection().begin(), group1.get_children_collection().end() );
+ path_filtered_iterator itrEnd( "", group1.get_children_collection().end(), group1.get_children_collection().end() );
+
+ BOOST_CHECK( itr != itrEnd );
+
+ BOOST_CHECK_EQUAL( std::distance(itr, itrEnd), 1 );
+
+ int ct=0;
+ for( ; itr != itrEnd; ++itr, ++ct )
+ {
+ switch(ct)
+ {
+ case 0:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 3 );
+ break;
+ default:
+ BOOST_ERROR("Too many items");
+ }
+ }
+ BOOST_CHECK_EQUAL( ct, 1 );
+ }
+
+ {
+ path_filtered_iterator itr( "2/3/4", group1.get_children_collection().begin(), group1.get_children_collection().end() );
+ path_filtered_iterator itrEnd( "", group1.get_children_collection().end(), group1.get_children_collection().end() );
+
+ BOOST_CHECK( itr != itrEnd );
+
+ BOOST_CHECK_EQUAL( std::distance(itr, itrEnd), 1 );
+
+ int ct=0;
+ for( ; itr != itrEnd; ++itr, ++ct )
+ {
+ switch(ct)
+ {
+ case 0:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 4 );
+ break;
+ default:
+ BOOST_ERROR("Too many items");
+ }
+ }
+ BOOST_CHECK_EQUAL( ct, 1 );
+ }
+}
+
+BOOST_AUTO_TEST_CASE( TestPathFilteredIterator_ComplexPaths_NoValueCheck )
+{
+ TestPropertyGroup group1(1, 1, NULL);
+ TestPropertyGroup group2(2, 2, &group1);
+ TestPropertyGroup group3(3, 3, &group2);
+ TestPropertyGroup group4(2, 4, &group1);
+ TestPropertyGroup group5(2, 5, &group1);
+ TestPropertyGroup group6(3, 6, &group5);
+ TestPropertyGroup group7(3, 7, &group5);
+ TestPropertyGroup group8(4, 8, &group7);
+ TestPropertyGroup group9(3, 9, &group5);
+
+ {
+ path_filtered_iterator itr( "2/3", group1.get_children_collection().begin(), group1.get_children_collection().end() );
+ path_filtered_iterator itrEnd( "", group1.get_children_collection().end(), group1.get_children_collection().end() );
+
+ BOOST_CHECK( itr != itrEnd );
+
+ BOOST_CHECK_EQUAL( std::distance(itr, itrEnd), 4 );
+
+ int ct=0;
+ for( ; itr != itrEnd; ++itr, ++ct )
+ {
+ switch( ct )
+ {
+ case 0:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 3 );
+ break;
+ case 1:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 6 );
+ break;
+ case 2:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 7 );
+ break;
+ case 3:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 9 );
+ break;
+ default:
+ BOOST_ERROR("found too many groups");
+ }
+ }
+ BOOST_CHECK_EQUAL( ct, 4 );
+ }
+
+ {
+ path_filtered_iterator itr( "2", group1.get_children_collection().begin(), group1.get_children_collection().end() );
+ path_filtered_iterator itrEnd( "", group1.get_children_collection().end(), group1.get_children_collection().end() );
+
+ BOOST_CHECK( itr != itrEnd );
+
+ BOOST_CHECK_EQUAL( std::distance(itr, itrEnd), 3 );
+
+ int ct=0;
+ for( ; itr != itrEnd; ++itr, ++ct )
+ {
+ switch( ct )
+ {
+ case 0:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 2 );
+ break;
+ case 1:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 4 );
+ break;
+ case 2:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 5 );
+ break;
+ default:
+ BOOST_ERROR("found too many groups");
+ }
+ }
+ BOOST_CHECK_EQUAL( ct, 3 );
+ }
+
+ {
+ path_filtered_iterator itr( "2/3/4/", group1.get_children_collection().begin(), group1.get_children_collection().end() );
+ path_filtered_iterator itrEnd( "", group1.get_children_collection().end(), group1.get_children_collection().end() );
+
+ BOOST_CHECK( itr != itrEnd );
+
+ BOOST_CHECK_EQUAL( std::distance(itr, itrEnd), 1 );
+
+ int ct=0;
+ for( ; itr != itrEnd; ++itr, ++ct )
+ {
+ switch( ct )
+ {
+ case 0:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 8 );
+ break;
+ default:
+ BOOST_ERROR("found too many groups");
+ }
+ }
+ BOOST_CHECK_EQUAL( ct, 1 );
+ }
+
+ {
+ path_filtered_iterator itr( "2", group5.get_children_collection().begin(), group5.get_children_collection().end() );
+ path_filtered_iterator itrEnd( "", group5.get_children_collection().end(), group5.get_children_collection().end() );
+
+ BOOST_CHECK( itr == itrEnd );
+ }
+
+ {
+ path_filtered_iterator itr( "3", group5.get_children_collection().begin(), group5.get_children_collection().end() );
+ path_filtered_iterator itrEnd( "", group5.get_children_collection().end(), group5.get_children_collection().end() );
+
+ BOOST_CHECK( itr != itrEnd );
+
+ BOOST_CHECK_EQUAL( std::distance(itr, itrEnd), 3 );
+
+ int ct=0;
+ for( ; itr != itrEnd; ++itr, ++ct )
+ {
+ property_group* prop = (*itr);
+ switch( ct )
+ {
+ case 0:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 6 );
+ break;
+ case 1:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 7 );
+ break;
+ case 2:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 9 );
+ break;
+ default:
+ BOOST_ERROR("found too many groups");
+ }
+ }
+ BOOST_CHECK_EQUAL( ct, 3 );
+ }
+
+ {
+ path_filtered_iterator itr( "3/4", group5.get_children_collection().begin(), group5.get_children_collection().end() );
+ path_filtered_iterator itrEnd( "", group5.get_children_collection().end(), group5.get_children_collection().end() );
+
+ BOOST_CHECK( itr != itrEnd );
+
+ BOOST_CHECK_EQUAL( std::distance(itr, itrEnd), 1 );
+
+ int ct=0;
+ for( ; itr != itrEnd; ++itr, ++ct )
+ {
+ property_group* prop = (*itr);
+ switch( ct )
+ {
+ case 0:
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 8 );
+ break;
+ default:
+ BOOST_ERROR("found too many groups");
+ }
+ }
+ BOOST_CHECK_EQUAL( ct, 1 );
+ }
+}
+
+BOOST_AUTO_TEST_CASE( TestPathFilteredIterator_ComplexPaths_WithValueCheck )
+{
+ TestPropertyGroup group1(1, 1, NULL);
+ TestPropertyGroup group2(2, 2, &group1);
+ TestPropertyGroup group3(3, 3, &group2);
+ TestPropertyGroup group4(2, 4, &group1);
+ TestPropertyGroup group5(2, 5, &group1);
+ TestPropertyGroup group6(3, 6, &group5);
+ TestPropertyGroup group7(3, 7, &group5);
+ TestPropertyGroup group8(4, 8, &group7);
+ TestPropertyGroup groupB(4, 9, &group7);
+ TestPropertyGroup group9(3, 6, &group5);
+ TestPropertyGroup groupA(3, 7, &group5);
+
+ {
+ path_filtered_iterator itr( "2/3.ID=6", group1.get_children_collection().begin(), group1.get_children_collection().end() );
+ path_filtered_iterator itrEnd( "", group1.get_children_collection().end(), group1.get_children_collection().end() );
+
+ BOOST_CHECK( itr != itrEnd );
+
+ BOOST_CHECK_EQUAL( std::distance(itr, itrEnd), 2 );
+
+ int ct=0;
+ for( ; itr != itrEnd; ++itr, ++ct )
+ {
+ BOOST_CHECK_EQUAL( (*itr)->get<int>("ID"), 6 );
+ switch( ct )
+ {
+ case 0:
+ BOOST_CHECK_EQUAL((*itr), &group6);
+ break;
+ case 1:
+ BOOST_CHECK_EQUAL((*itr), &group9);
+ break;
+ default:
+ BOOST_ERROR("found too many groups");
+ }
+ }
+ BOOST_CHECK_EQUAL( ct, 2 );
+ }
+
+ {
+ path_filtered_iterator itr( "2/3.ID=7", group1.get_children_collection().begin(), group1.get_children_collection().end() );
+ path_filtered_iterator itrEnd( "", group1.get_children_collection().end(), group1.get_children_collection().end() );
+
+ BOOST_CHECK( itr != itrEnd );
+
+ BOOST_CHECK_EQUAL( std::distance(itr, itrEnd), 2 );
+
+ int ct=0;
+ for( ; itr != itrEnd; ++itr, ++ct )
+ {
+ switch( ct )
+ {
+ case 0:
+ BOOST_CHECK_EQUAL((*itr), &group7);
+ break;
+ case 1:
+ BOOST_CHECK_EQUAL((*itr), &groupA);
+ break;
+ default:
+ BOOST_ERROR("found too many groups");
+ }
+ }
+ BOOST_CHECK_EQUAL( ct, 2 );
+ }
+
+ {
+ path_filtered_iterator itr( "2/3.ID=7/4.ID=8", group1.get_children_collection().begin(), group1.get_children_collection().end() );
+ path_filtered_iterator itrEnd( "", group1.get_children_collection().end(), group1.get_children_collection().end() );
+
+ BOOST_CHECK( itr != itrEnd );
+
+ BOOST_CHECK_EQUAL( std::distance(itr, itrEnd), 1 );
+
+ int ct=0;
+ for( ; itr != itrEnd; ++itr, ++ct )
+ {
+ switch( ct )
+ {
+ case 0:
+ BOOST_CHECK_EQUAL((*itr), &group8);
+ break;
+ default:
+ BOOST_ERROR("found too many groups");
+ }
+ }
+ BOOST_CHECK_EQUAL( ct, 1 );
+ }
+
+ {
+ path_filtered_iterator itr( "2/3.ID=7/4", group1.get_children_collection().begin(), group1.get_children_collection().end() );
+ path_filtered_iterator itrEnd( "", group1.get_children_collection().end(), group1.get_children_collection().end() );
+
+ BOOST_CHECK( itr != itrEnd );
+
+ BOOST_CHECK_EQUAL( std::distance(itr, itrEnd), 2 );
+
+ int ct=0;
+ for( ; itr != itrEnd; ++itr, ++ct )
+ {
+ switch( ct )
+ {
+ case 0:
+ BOOST_CHECK_EQUAL((*itr), &group8);
+ break;
+ case 1:
+ BOOST_CHECK_EQUAL((*itr), &groupB);
+ break;
+ default:
+ BOOST_ERROR("found too many groups");
+ }
+ }
+ BOOST_CHECK_EQUAL( ct, 2 );
+ }
+
+ {
+ path_filtered_iterator itr( "2/3.ID=99/4.ID=8", group1.get_children_collection().begin(), group1.get_children_collection().end() );
+ path_filtered_iterator itrEnd( "", group1.get_children_collection().end(), group1.get_children_collection().end() );
+
+ BOOST_CHECK( itr == itrEnd );
+ }
+
+ {
+ path_filtered_iterator itr( "2/3.ID=7/4.ID=99", group1.get_children_collection().begin(), group1.get_children_collection().end() );
+ path_filtered_iterator itrEnd( group1.get_children_collection().end() );
+
+ BOOST_CHECK( itr == itrEnd );
+ }
+
+ {
+ path_filtered_iterator itr( "2.ID=99", group1.get_children_collection().begin(), group1.get_children_collection().end() );
+ path_filtered_iterator itrEnd( "", group1.get_children_collection().end(), group1.get_children_collection().end() );
+
+ BOOST_CHECK( itr == itrEnd );
+ }
+
+ {
+ path_filtered_iterator itr( "2.missing=99", group1.get_children_collection().begin(), group1.get_children_collection().end() );
+ path_filtered_iterator itrEnd( group1.get_children_collection().end() );
+
+ BOOST_CHECK( itr == itrEnd );
+ }
+}
\ No newline at end of file

Modified: sandbox/pinhole/libs/pinhole/test/test_property_groups.cpp
==============================================================================
--- sandbox/pinhole/libs/pinhole/test/test_property_groups.cpp (original)
+++ sandbox/pinhole/libs/pinhole/test/test_property_groups.cpp 2009-05-19 15:30:22 EDT (Tue, 19 May 2009)
@@ -1,6 +1,6 @@
 // Boost.Pinhole library
 
-// Copyright Jared McIntyre 2007-2008. Use, modification and
+// Copyright Jared McIntyre 2007-2009. 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)
@@ -118,35 +118,40 @@
         uiChildCount = 0;
         uiRegisterPropertyGroupCallCount = 0;
         uiUnRegisterPropertyGroupCallCount = 0;
- uiAddCategoryCallCount = 0;
     }
     virtual void register_property_group( property_group *pPropertyGroup )
     {
         ++uiRegisterPropertyGroupCallCount;
 
- if( NULL == pPropertyGroup->get_parent() )
- {
- ++uiChildCount;
- }
-
         property_manager::register_property_group( pPropertyGroup );
     }
- virtual void unregister_property_group( property_group *pPropertyGroup, category_collection &categories )
+ virtual void unregister_property_group( property_group *pPropertyGroup )
     {
         ++uiUnRegisterPropertyGroupCallCount;
 
- if( NULL == pPropertyGroup->get_parent() )
- {
- --uiChildCount;
- }
+ property_manager::unregister_property_group( pPropertyGroup );
+ }
+
+ /**
+ * Adds a root property group.
+ */
+ virtual void add_property_group( property_group *group )
+ {
+ ++uiChildCount;
+
+ property_manager::add_property_group( group );
+ }
+ virtual void remove_property_group( property_group *group )
+ {
+ --uiChildCount;
 
- property_manager::unregister_property_group( pPropertyGroup, categories );
+ m_property_group_collection.remove( group );
     }
- virtual void add_category( const string &sCategoryName, property_group *pPropertyGroup )
+ virtual void add_category( const string &sCategoryName )
     {
         ++uiAddCategoryCallCount;
 
- property_manager::add_category( sCategoryName, pPropertyGroup );
+ property_manager::add_category( sCategoryName );
     }
 
     unsigned int uiChildCount;

Modified: sandbox/pinhole/libs/pinhole/test/test_string_properties.cpp
==============================================================================
--- sandbox/pinhole/libs/pinhole/test/test_string_properties.cpp (original)
+++ sandbox/pinhole/libs/pinhole/test/test_string_properties.cpp 2009-05-19 15:30:22 EDT (Tue, 19 May 2009)
@@ -1,6 +1,6 @@
 // Boost.Pinhole library
 
-// Copyright Jared McIntyre 2007. Use, modification and
+// Copyright Jared McIntyre 2007-2009. 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)

Added: sandbox/pinhole/libs/pinhole/test/test_tokenizer.cpp
==============================================================================
--- (empty file)
+++ sandbox/pinhole/libs/pinhole/test/test_tokenizer.cpp 2009-05-19 15:30:22 EDT (Tue, 19 May 2009)
@@ -0,0 +1,192 @@
+// Boost.Pinhole library
+
+// Copyright Jared McIntyre 2009. 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)
+
+// For more information, see http://www.boost.org
+
+#define BOOST_TEST_MODULE PinholeLib
+
+#include <boost/pinhole.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/foreach.hpp>
+
+using namespace std;
+using namespace boost;
+using namespace boost::pinhole;
+using namespace boost::pinhole::detail;
+
+BOOST_AUTO_TEST_CASE( TestTokenizer_ValidPaths )
+{
+ boost::pinhole::detail::token_path path;
+
+ // empty path
+
+ BOOST_CHECK_EQUAL( process_path("", path), 0);
+ BOOST_CHECK_EQUAL( path.relative_path, false );
+ BOOST_CHECK_EQUAL( path.tokens.size(), 0 );
+
+ // Simple relative path
+
+ BOOST_CHECK_EQUAL( process_path("relative/", path), 1);
+ BOOST_CHECK_EQUAL( path.relative_path, true );
+ BOOST_CHECK_EQUAL( path.tokens.size(), 1 );
+ BOOST_CHECK_EQUAL( (*path.tokens.begin()).name, "relative" );
+ BOOST_CHECK( (*path.tokens.begin()).property.empty() );
+ BOOST_CHECK( (*path.tokens.begin()).value.empty() );
+
+ BOOST_CHECK_EQUAL( process_path("relative", path), 1);
+ BOOST_CHECK_EQUAL( path.relative_path, true );
+ BOOST_CHECK_EQUAL( path.tokens.size(), 1 );
+ BOOST_CHECK_EQUAL( (*path.tokens.begin()).name, "relative" );
+ BOOST_CHECK( (*path.tokens.begin()).property.empty() );
+ BOOST_CHECK( (*path.tokens.begin()).value.empty() );
+
+ // Simple fixed path
+
+ BOOST_CHECK_EQUAL( process_path("/non-relative", path), 1);
+ BOOST_CHECK_EQUAL( path.tokens.size(), 1 );
+ BOOST_CHECK_EQUAL( (*path.tokens.begin()).name, "non-relative" );
+ BOOST_CHECK( (*path.tokens.begin()).property.empty() );
+ BOOST_CHECK( (*path.tokens.begin()).value.empty() );
+
+ BOOST_CHECK_EQUAL( process_path("/non-relative/", path), 1);
+ BOOST_CHECK_EQUAL( path.tokens.size(), 1 );
+ BOOST_CHECK_EQUAL( (*path.tokens.begin()).name, "non-relative" );
+ BOOST_CHECK( (*path.tokens.begin()).property.empty() );
+ BOOST_CHECK( (*path.tokens.begin()).value.empty() );
+
+ // multiple tokens
+
+ BOOST_CHECK_EQUAL( process_path("first/second/third/fourth/fifth/", path), 5);
+ BOOST_CHECK_EQUAL( path.relative_path, true );
+ BOOST_CHECK_EQUAL( path.tokens.size(), 5 );
+ int ct=0;
+ BOOST_FOREACH( const boost::pinhole::detail::token_path::token& token, path.tokens )
+ {
+ if( ct == 0 ) BOOST_CHECK_EQUAL( token.name, "first" );
+ if( ct == 1 ) BOOST_CHECK_EQUAL( token.name, "second" );
+ if( ct == 2 ) BOOST_CHECK_EQUAL( token.name, "third" );
+ if( ct == 3 ) BOOST_CHECK_EQUAL( token.name, "fourth" );
+ if( ct == 4 ) BOOST_CHECK_EQUAL( token.name, "fifth" );
+
+ BOOST_CHECK( token.property.empty() );
+ BOOST_CHECK( token.value.empty() );
+
+ ++ct;
+ }
+
+ // simple property values
+
+ BOOST_CHECK_EQUAL( process_path("name.property=value", path), 1);
+ BOOST_CHECK_EQUAL( path.relative_path, true );
+ BOOST_CHECK_EQUAL( path.tokens.size(), 1 );
+ BOOST_CHECK_EQUAL( (*path.tokens.begin()).name, "name" );
+ BOOST_CHECK_EQUAL( (*path.tokens.begin()).property, "property" );
+ BOOST_CHECK_EQUAL( (*path.tokens.begin()).value, "value" );
+
+ // multiple property values
+
+ BOOST_CHECK_EQUAL( process_path("/first.a1=b2/second.c=d/third.f3=g4/fourth.h=/fifth.5=6", path), 5);
+ BOOST_CHECK_EQUAL( path.relative_path, false );
+ BOOST_CHECK_EQUAL( path.tokens.size(), 5 );
+ ct=0;
+ BOOST_FOREACH( const boost::pinhole::detail::token_path::token& token, path.tokens )
+ {
+ if( ct == 0 )
+ {
+ BOOST_CHECK_EQUAL( token.name, "first" );
+ BOOST_CHECK_EQUAL( token.property, "a1" );
+ BOOST_CHECK_EQUAL( token.value, "b2" );
+ }
+ if( ct == 1 )
+ {
+ BOOST_CHECK_EQUAL( token.name, "second" );
+ BOOST_CHECK_EQUAL( token.property, "c" );
+ BOOST_CHECK_EQUAL( token.value, "d" );
+ }
+ if( ct == 2 )
+ {
+ BOOST_CHECK_EQUAL( token.name, "third" );
+ BOOST_CHECK_EQUAL( token.property, "f3" );
+ BOOST_CHECK_EQUAL( token.value, "g4" );
+ }
+ if( ct == 3 )
+ {
+ BOOST_CHECK_EQUAL( token.name, "fourth" );
+ BOOST_CHECK_EQUAL( token.property, "h" );
+ BOOST_CHECK_EQUAL( token.value, "" );
+ }
+ if( ct == 4 )
+ {
+ BOOST_CHECK_EQUAL( token.name, "fifth" );
+ BOOST_CHECK_EQUAL( token.property, "5" );
+ BOOST_CHECK_EQUAL( token.value, "6" );
+ }
+
+ ++ct;
+ }
+
+ // spaces
+
+ BOOST_CHECK_EQUAL( process_path(" relat ive ", path), 1);
+ BOOST_CHECK_EQUAL( (*path.tokens.begin()).name, " relat ive " );
+ BOOST_CHECK( (*path.tokens.begin()).property.empty() );
+ BOOST_CHECK( (*path.tokens.begin()).value.empty() );
+
+ BOOST_CHECK_EQUAL( process_path(" relat ive / more spaces ", path), 2);
+ ct=0;
+ BOOST_FOREACH( const boost::pinhole::detail::token_path::token& token, path.tokens )
+ {
+ if( ct == 0 )
+ {
+ BOOST_CHECK_EQUAL( token.name, " relat ive " );
+ }
+ if( ct == 1 )
+ {
+ BOOST_CHECK_EQUAL( token.name, " more spaces " );
+ }
+
+ BOOST_CHECK( token.property.empty() );
+ BOOST_CHECK( token.value.empty() );
+
+ ++ct;
+ }
+
+ BOOST_CHECK_EQUAL( process_path(" relat ive . som eSpaces = a value / more spaces . mor eSpaces = another value ", path), 2);
+ ct=0;
+ BOOST_FOREACH( const boost::pinhole::detail::token_path::token& token, path.tokens )
+ {
+ if( ct == 0 )
+ {
+ BOOST_CHECK_EQUAL( token.name, " relat ive " );
+ BOOST_CHECK_EQUAL( token.property, " som eSpaces " );
+ BOOST_CHECK_EQUAL( token.value, " a value " );
+ }
+ if( ct == 1 )
+ {
+ BOOST_CHECK_EQUAL( token.name, " more spaces " );
+ BOOST_CHECK_EQUAL( token.property, " mor eSpaces " );
+ BOOST_CHECK_EQUAL( token.value, " another value " );
+ }
+
+ ++ct;
+ }
+}
+
+BOOST_AUTO_TEST_CASE( TestTokenizer_InvalidPaths )
+{
+ boost::pinhole::detail::token_path path;
+
+ // Simple relative path
+
+ BOOST_CHECK_THROW( process_path("first/second//fourth/fifth", path), invalid_path);
+ BOOST_CHECK_THROW( process_path("first.=value", path), invalid_path);
+ BOOST_CHECK_THROW( process_path("first=value", path), invalid_path);
+ BOOST_CHECK_THROW( process_path("first.value", path), invalid_path);
+ BOOST_CHECK_THROW( process_path("first/second.=value", path), invalid_path);
+ BOOST_CHECK_THROW( process_path("first/second=value", path), invalid_path);
+ BOOST_CHECK_THROW( process_path("first/second.value", path), invalid_path);
+}
\ No newline at end of file


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