$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r55215 - in sandbox/pinhole: boost/pinhole libs/pinhole/test
From: jmcintyre_at_[hidden]
Date: 2009-07-30 14:43:38
Author: jared
Date: 2009-07-27 17:43:08 EDT (Mon, 27 Jul 2009)
New Revision: 55215
URL: http://svn.boost.org/trac/boost/changeset/55215
Log:
Pinhole: Properties could cause memory corruption if an old property was replaced with a new one.
Exceptions now use boost::exception
select helper functions now use parser from depth-first search
Text files modified: 
   sandbox/pinhole/boost/pinhole/exceptions.hpp         |    23 +++++--                                 
   sandbox/pinhole/boost/pinhole/find.hpp               |   116 +++++++++++++++++---------------------- 
   sandbox/pinhole/boost/pinhole/property_group.hpp     |    88 +++++++++++++----------------           
   sandbox/pinhole/boost/pinhole/property_info.hpp      |     6 +                                       
   sandbox/pinhole/boost/pinhole/property_manager.hpp   |    22 ++++++-                                 
   sandbox/pinhole/boost/pinhole/value.hpp              |    38 +++++++-----                            
   sandbox/pinhole/libs/pinhole/test/Jamfile.v2         |     3                                         
   sandbox/pinhole/libs/pinhole/test/test_tokenizer.cpp |    23 +++++++                                 
   8 files changed, 179 insertions(+), 140 deletions(-)
Modified: sandbox/pinhole/boost/pinhole/exceptions.hpp
==============================================================================
--- sandbox/pinhole/boost/pinhole/exceptions.hpp	(original)
+++ sandbox/pinhole/boost/pinhole/exceptions.hpp	2009-07-27 17:43:08 EDT (Mon, 27 Jul 2009)
@@ -11,26 +11,37 @@
 #include <exception>
 #include <stdexcept>
 #include <string>
+#include <boost/exception.hpp>
 
 namespace boost { namespace pinhole
 {
-    class multiple_property_groups : public std::runtime_error
+    class multiple_property_groups : public std::runtime_error, public ::boost::exception
     {
         public: multiple_property_groups(const std::string& strErrMsg) : std::runtime_error(strErrMsg) {;}
     };
 
-    class invalid_path : public std::runtime_error
+    class invalid_path : public std::runtime_error, public ::boost::exception
     {
         public: invalid_path(const std::string& strErrMsg) : std::runtime_error(strErrMsg) {;}
     };
 
-    class failed_to_find_group : public std::exception{};
+    class failed_to_find_group : public std::runtime_error, public ::boost::exception
+    {
+        public: failed_to_find_group(const std::string& strErrMsg) : std::runtime_error(strErrMsg) {;}
+    };
     
-    class no_metadata_defined_error : public std::runtime_error
+    class no_metadata_defined : public std::runtime_error, public ::boost::exception
     {
-        public:
-        no_metadata_defined_error() : runtime_error( "No Property Editor Defined" ) {;}
+        public: no_metadata_defined() : runtime_error( "No metadata defined for property" ) {;}
     };
+
+    typedef boost::error_info< struct tag_requested_type, const std::string > exception_requested_type;
+    typedef boost::error_info< struct tag_property_name,  const std::string > exception_property_name;
+    typedef boost::error_info< struct tag_property_type,  const std::string > exception_property_type;
+    typedef boost::error_info< struct tag_actual_type,    const std::string > exception_actual_type;
+    typedef boost::error_info< struct tag_action_name,    const std::string > exception_action_name;
+    typedef boost::error_info< struct tag_path,           const std::string > exception_path;
+    typedef boost::error_info< struct tag_path_section,   const std::string > exception_path_section;
 }}
 
 #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-07-27 17:43:08 EDT (Mon, 27 Jul 2009)
@@ -10,11 +10,24 @@
 
 #include <vector>
 
-#include "./detail/path.hpp"
+#include "./detail/tokenizer.hpp"
 #include "path_filtered_iterator.hpp"
 
 namespace boost { namespace pinhole
 {
+    namespace detail
+    {
+        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.")
+                    << ::boost::pinhole::exception_path(path);
+            }
+        }
+    }
+
     /** 
      * 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
@@ -45,87 +58,62 @@
      */
     inline boost::pinhole::property_group* select_single_node(boost::pinhole::property_group* current_property_group, const std::string& path)
     {
-        std::pair<boost::pinhole::children_collection::iterator,boost::pinhole::children_collection::iterator> range;
+        typedef boost::iterator_range< boost::pinhole::children_collection::iterator > child_range;
+        
+        child_range range;
 
         if( NULL != current_property_group )
         {
-            range.first  = current_property_group->get_children_collection().begin();
-            range.second = current_property_group->get_children_collection().end();
+            range = child_range( current_property_group->get_children_collection().begin(),
+                                 current_property_group->get_children_collection().end() );
         }
         else
         {
             detail::ThrowIfPathIsRelative(path);
         }
-        boost::pinhole::children_collection* root_property_group_collection = 0; //The root collection might not be needed if it is not referred.
-        
-        typedef std::vector< std::string > split_vector_type;
-        split_vector_type vecproperty_groups; 
-        boost::split( vecproperty_groups, path, boost::is_any_of("/") ); //Note: "/" is the separator for a property group
-        try
+
+        detail::token_path token_path;
+        process_path( path, token_path );
+
+        if( false == token_path.relative_path )
         {
-            for(split_vector_type::const_iterator iter_property_group = vecproperty_groups.begin(); iter_property_group != vecproperty_groups.end(); iter_property_group++)
+            boost::pinhole::property_manager::instance_type manager = boost::pinhole::property_manager::instance();
+            range = child_range(manager->begin(), manager->end() );
+        }
+
+        boost::pinhole::property_group* property_group_found = NULL;
+
+        BOOST_FOREACH( const boost::pinhole::detail::token_path::token& token, token_path.tokens )
+        {
+            property_group_found = NULL;
+            
+            BOOST_FOREACH( property_group* group, range )
             {
-                std::string strproperty_group = *iter_property_group;
-                split_vector_type properties;
-                boost::split( properties, strproperty_group, boost::is_any_of(".=") ); 
-                //Note: "." is the separator between Property group name and Property name.
-                //"=" is the separator between property name and property value. If there's no "." or "=",
-                //we will just use this property group.
-                size_t nNumOfItems = properties.size();
-                switch(nNumOfItems)
+                if( token.name == group->get_name() &&
+                    (true == token.property.empty() || 
+                    (group->is_valid_property(token.property) && token.value == group->get_as_string(token.property)) ))
                 {
-                    case 1:
-                    {
-                        std::string strItem = properties[0]; //It either is "/" or the property group name.
-                        boost::trim(strItem);
-                        if(strItem.empty()) //It is "/"
-                        {
-                            boost::pinhole::property_manager::instance_type manager = boost::pinhole::property_manager::instance();
-                            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(range.first, range.second, strItem);
-                            
-                            range.first  = current_property_group->get_children_collection().begin();
-                            range.second = current_property_group->get_children_collection().end();
-                        }
-                    }
-                        break;
-                    case 3:
+                    if( NULL == property_group_found )
                     {
-                        std::string property_group_name = properties[0];
-                        boost::trim(property_group_name);
-                        
-                        std::string property_name = properties[1];
-                        boost::trim(property_name);
-                        
-                        std::string property_value = properties[2];
-                        boost::trim(property_value);
-                        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();
+                        property_group_found = group;
                     }
-                        break;
-                    default:
+                    else
                     {
-                        std::string strError = path + " is not a valid path. Details: " + strproperty_group + " should be either A.B=C or A format";
-                        throw invalid_path(strError.c_str());
+                        throw ::boost::pinhole::multiple_property_groups("Requested path does not lead to a unique property group."); 
                     }
                 }
             }
+
+            if( NULL == property_group_found )
+            {
+                break;
+            }
+
+            range = child_range( property_group_found->get_children_collection().begin(),
+                                 property_group_found->get_children_collection().end() );
         }
-        catch(no_metadata_defined_error&)
-        {
-            current_property_group = NULL;
-        }
-        
-        delete root_property_group_collection;
-        return current_property_group;
+
+        return property_group_found;
     }
 
     inline property_group* select_single_node(boost::pinhole::property_group& current_property_group, const std::string& path)
Modified: sandbox/pinhole/boost/pinhole/property_group.hpp
==============================================================================
--- sandbox/pinhole/boost/pinhole/property_group.hpp	(original)
+++ sandbox/pinhole/boost/pinhole/property_group.hpp	2009-07-27 17:43:08 EDT (Mon, 27 Jul 2009)
@@ -15,18 +15,12 @@
 #include "property_manager.hpp"
 #include <sstream>
 
-#if defined(BOOST_MSVC)
-    #pragma warning(push)
-    #pragma warning( disable: 4561)
-#endif
 #include <boost/bind.hpp>
 #include <boost/type_traits.hpp>
 #include <boost/function.hpp>
 #include <boost/static_assert.hpp>
 #include <boost/any.hpp>
-#if defined(BOOST_MSVC)
-    #pragma warning(pop)
-#endif
+#include <boost/throw_exception.hpp>
 
 #define BOOST_SETTER(c) boost::bind(c, this, _1)
 #if defined(BOOST_MSVC) && (_MSC_VER > 1310) && (_MSC_VER <= 1400)
@@ -95,6 +89,7 @@
      */
     class property_group
     {
+
     public:
         /**
          * Constructor.
@@ -334,19 +329,20 @@
                 {
                     detail::property_info_base* propInfo = (*itemItr).second;
                     
-                    // throws boost::bad_function_call if there isn't a get_as_string
-                    // function associated with this property.
-                    if( NULL != propInfo && typeid(Return_Type) == propInfo->m_type )
+                    if( typeid(Return_Type) == propInfo->m_type )
                     {
+                        // throws boost::bad_function_call if there isn't a get_as_string
+                        // function associated with this property.
                         return static_cast<detail::property_info<Return_Type>*>(propInfo)->getter();
                     }
                     
-                    throw std::bad_cast();
+                    throw ::boost::enable_error_info(std::bad_cast("Attempted to get a property using a type different from the properties type."))
+                                << ::boost::pinhole::exception_property_name(property)
+                                << ::boost::pinhole::exception_requested_type(typeid(Return_Type).name())
+                                << ::boost::pinhole::exception_property_type(propInfo->m_type.name());
                 }
                 
-                std::stringstream err;
-                err << "The requested property \"" << property << "\" does not exist.";
-                throw std::out_of_range(err.str().c_str());                
+                throw ::boost::enable_error_info(std::out_of_range("The requested property does not exist.")) << ::boost::pinhole::exception_property_name(property);
             }
             
             /**
@@ -377,12 +373,13 @@
                         return static_cast<detail::property_info<Set_Type>*>(propInfo)->setter(value);
                     }
                     
-                    throw std::bad_cast();
+                    throw ::boost::enable_error_info(std::bad_cast("Attempted to set a property using a type different from the properties type."))
+                            << ::boost::pinhole::exception_property_name(property)
+                            << ::boost::pinhole::exception_requested_type(typeid(Set_Type).name())
+                            << ::boost::pinhole::exception_property_type(propInfo->m_type.name());
                 }
                 
-                std::stringstream err;
-                err << "The requested property \"" << property << "\" does not exist.";
-                throw std::out_of_range(err.str().c_str());                
+                throw ::boost::enable_error_info(std::out_of_range("The requested property does not exist.")) << ::boost::pinhole::exception_property_name(property);
             }
 
             /**
@@ -406,9 +403,7 @@
                 }
                 else
                 {
-                    std::stringstream err;
-                    err << "The requested property \"" << property << "\" does not exist.";
-                    throw std::out_of_range(err.str().c_str());
+                    throw ::boost::enable_error_info(std::out_of_range("The requested property does not exist.")) << ::boost::pinhole::exception_property_name(property);
                 }
             }
 
@@ -433,9 +428,7 @@
                 }
                 else
                 {
-                    std::stringstream err;
-                    err << "The requested property \"" << property << "\" does not exist.";
-                    throw std::out_of_range(err.str().c_str());
+                    throw ::boost::enable_error_info(std::out_of_range("The requested property does not exist.")) << ::boost::pinhole::exception_property_name(property);
                 }
             }
 
@@ -457,9 +450,7 @@
                     return (*itemItr).second->get_as_string();
                 }
                 
-                std::stringstream err;
-                err << "The requested property \"" << property << "\" does not exist.";
-                throw std::out_of_range(err.str().c_str());    
+                throw ::boost::enable_error_info(std::out_of_range("The requested property does not exist.")) << ::boost::pinhole::exception_property_name(property);    
             }
 
             /**
@@ -480,9 +471,7 @@
                     return (*itemItr).second->get_as_wstring();
                 }
 
-                std::stringstream err;
-                err << "The requested property \"" << property << "\" does not exist.";
-                throw std::out_of_range(err.str().c_str());    
+                throw ::boost::enable_error_info(std::out_of_range("The requested property does not exist.")) << ::boost::pinhole::exception_property_name(property);    
             }
 
             /**
@@ -502,9 +491,7 @@
                 }
                 else
                 {
-                    std::stringstream err;
-                    err << "The requested property \"" << property << "\" does not exist.";
-                    throw std::out_of_range(err.str().c_str());
+                    throw ::boost::enable_error_info(std::out_of_range("The requested property does not exist.")) << ::boost::pinhole::exception_property_name(property);
                 }
             }
 
@@ -524,9 +511,7 @@
                 }
                 else
                 {
-                    std::stringstream err;
-                    err << "The requested property \"" << property << "\" does not exist.";
-                    throw std::out_of_range(err.str().c_str());
+                    throw ::boost::enable_error_info(std::out_of_range("The requested property does not exist.")) << ::boost::pinhole::exception_property_name(property);
                 }
             }
 
@@ -547,9 +532,7 @@
                 }
                 else
                 {
-                    std::stringstream err;
-                    err << "The requested property \"" << property << "\" does not exist.";
-                    throw std::out_of_range(err.str().c_str());
+                    throw ::boost::enable_error_info(std::out_of_range("The requested property does not exist.")) << ::boost::pinhole::exception_property_name(property);
                 }
             }
         //@}
@@ -627,9 +610,8 @@
                 }
                 else
                 {
-                    std::stringstream err;
-                    err << "The requested action \"" << action << "\" does not exist.";
-                    throw std::out_of_range(err.str().c_str());
+                    throw ::boost::enable_error_info(std::out_of_range("The requested action does not exist."))
+                        << ::boost::pinhole::exception_action_name(action);
                 }
             }
 
@@ -758,15 +740,11 @@
                                     boost::function<Value_Type ()> getter,
                                     boost::any &metadata )
         {
-            property_collection::iterator previousInstance = m_properties.find(name);
-            if( m_properties.end() != previousInstance )
-            {
-                delete (*previousInstance).second;
-            }
-
             // If you get an error here, then the type you are using for the property likely doesn't have a proper operator<< for it
             detail::property_info<Value_Type> *prop = new detail::property_info<Value_Type>();
 
+            // Fill out property information
+
             prop->m_name        = name;
             prop->m_description = description;
             if( NULL != setter )
@@ -779,7 +757,19 @@
             }
             prop->m_metadata = metadata;
 
-            m_properties.insert( std::make_pair(name, prop) );
+            // Store property information
+
+            property_collection::iterator previousInstance = m_properties.find(name);
+            if( m_properties.end() != previousInstance )
+            {
+                // Object already exists. Destroy existing instance and replace it.
+                delete (*previousInstance).second;
+                (*previousInstance).second = prop;
+            }
+            else
+            {
+                m_properties.insert( std::make_pair(name, prop) );
+            }
         }
 
     private:
Modified: sandbox/pinhole/boost/pinhole/property_info.hpp
==============================================================================
--- sandbox/pinhole/boost/pinhole/property_info.hpp	(original)
+++ sandbox/pinhole/boost/pinhole/property_info.hpp	2009-07-27 17:43:08 EDT (Mon, 27 Jul 2009)
@@ -46,13 +46,17 @@
         template<typename Set_Type>
         inline void operator()( Set_Type setter, String_Type value )
         {
+            typedef boost::error_info< struct tag_requested_value, const String_Type > exception_requested_value;
+
             try
             {
                 setter( boost::lexical_cast<Value_Type>(value) );
             }
             catch(boost::bad_lexical_cast &)
             {
-                throw std::invalid_argument( "An invalid property value was used to set." );
+                throw ::boost::enable_error_info(std::invalid_argument("Could not convert string to the property's type."))
+                            << exception_requested_value(value)
+                            << ::boost::pinhole::exception_property_type(typeid(Value_Type).name());
             }
         }
     };
Modified: sandbox/pinhole/boost/pinhole/property_manager.hpp
==============================================================================
--- sandbox/pinhole/boost/pinhole/property_manager.hpp	(original)
+++ sandbox/pinhole/boost/pinhole/property_manager.hpp	2009-07-27 17:43:08 EDT (Mon, 27 Jul 2009)
@@ -24,6 +24,19 @@
     #pragma warning(pop)
 #endif
 
+#if defined(BOOST_HAS_DECLSPEC) && (defined(BOOST_PINHOLE_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)) && !defined(BOOST_PINHOLE_STATIC_LINK)
+#  if defined(BOOST_PINHOLE_SOURCE)
+#     define BOOST_PINHOLE_DECL __declspec(dllexport)
+#     define BOOST_PINHOLE_BUILD_DLL
+#  else
+#     define BOOST_PINHOLE_DECL __declspec(dllimport)
+#  endif
+#endif
+
+#ifndef BOOST_PINHOLE_DECL
+#  define BOOST_PINHOLE_DECL
+#endif
+
 namespace boost { namespace pinhole
 {
     class property_group;
@@ -31,10 +44,10 @@
     typedef std::set<std::string> category_collection;
     typedef std::list<property_group*> children_collection;
     
-    class event_source
+    class BOOST_PINHOLE_DECL event_source
     {
     public :
-        static event_source* instance()
+        inline static event_source* instance()
         {
             static boost::shared_ptr<boost::pinhole::event_source> instance;
 
@@ -55,6 +68,7 @@
         #if defined(BOOST_MSVC)
             #pragma warning(pop)
         #endif
+
         void raise_on_add_event( property_group *group )
         {
             add_event( group );
@@ -71,7 +85,7 @@
         
     };
 
-    class property_manager
+    class BOOST_PINHOLE_DECL property_manager
     {
     public:
         typedef boost::shared_ptr<property_manager> instance_type;
@@ -88,7 +102,7 @@
         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()
+        inline static instance_type instance()
         {
             if ( !exists() )  // is it the first call?
             {  
Modified: sandbox/pinhole/boost/pinhole/value.hpp
==============================================================================
--- sandbox/pinhole/boost/pinhole/value.hpp	(original)
+++ sandbox/pinhole/boost/pinhole/value.hpp	2009-07-27 17:43:08 EDT (Mon, 27 Jul 2009)
@@ -17,19 +17,18 @@
     /**
      * 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
+     * exists within the property group hierarchy.
+     * @n_at_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
+     * @n_at_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 path The path to search with. See format above.
      * @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.
@@ -45,18 +44,23 @@
         property_group* pGroup = select_single_node(current_property_group, path);
         if( NULL == pGroup )
         {
-            throw boost::pinhole::failed_to_find_group();
+            throw ::boost::pinhole::failed_to_find_group("Property Group doesn't exist at requested path.")
+                        << ::boost::pinhole::exception_path(path);
         }
         return pGroup->get<T>(property);
     }
 
+    /**
+     * @overload
+     */
     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();
+            throw ::boost::pinhole::failed_to_find_group("Property Group doesn't exist at requested path.")
+                        << ::boost::pinhole::exception_path(path);
         }
         return pGroup->get<T>(property);
     }
@@ -64,21 +68,20 @@
     /**
      * 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
+     * exists within the property group hierarchy.
+     * @n_at_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
+     * @n_at_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 path The path to search with. See format above.
      * @param property The name of the property.
-     * @return The value to set on the property.
+     * @param value 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.
@@ -92,18 +95,23 @@
         property_group* pGroup = select_single_node(current_property_group, path);
         if( NULL == pGroup )
         {
-            throw boost::pinhole::failed_to_find_group();
+            throw ::boost::pinhole::failed_to_find_group("Property Group doesn't exist at requested path.")
+                        << ::boost::pinhole::exception_path(path);
         }
         pGroup->set<T>(property, value);
     }
 
+    /**
+     * @overload
+     */
     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();
+            throw ::boost::pinhole::failed_to_find_group("Property Group doesn't exist at requested path.")
+                        << ::boost::pinhole::exception_path(path);
         }
         pGroup->set<T>(property, value);
     }
Modified: sandbox/pinhole/libs/pinhole/test/Jamfile.v2
==============================================================================
--- sandbox/pinhole/libs/pinhole/test/Jamfile.v2	(original)
+++ sandbox/pinhole/libs/pinhole/test/Jamfile.v2	2009-07-27 17:43:08 EDT (Mon, 27 Jul 2009)
@@ -29,11 +29,12 @@
   [ run test_string_properties.cpp  ]
   
   [ 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  ]
+  [ run test_value.cpp  ]
  ;
 }
Modified: sandbox/pinhole/libs/pinhole/test/test_tokenizer.cpp
==============================================================================
--- sandbox/pinhole/libs/pinhole/test/test_tokenizer.cpp	(original)
+++ sandbox/pinhole/libs/pinhole/test/test_tokenizer.cpp	2009-07-27 17:43:08 EDT (Mon, 27 Jul 2009)
@@ -176,6 +176,29 @@
 
         ++ct;
     }
+
+    // obscure values
+
+    BOOST_CHECK_EQUAL( process_path("name.pro.perty=value", path), 1u);
+    BOOST_CHECK_EQUAL( path.relative_path, true );
+    BOOST_CHECK_EQUAL( path.tokens.size(), 1u );
+    BOOST_CHECK_EQUAL( (*path.tokens.begin()).name,     "name" );
+    BOOST_CHECK_EQUAL( (*path.tokens.begin()).property, "pro.perty" );
+    BOOST_CHECK_EQUAL( (*path.tokens.begin()).value,    "value" );
+
+    BOOST_CHECK_EQUAL( process_path("name.property=va.lue", path), 1u);
+    BOOST_CHECK_EQUAL( path.relative_path, true );
+    BOOST_CHECK_EQUAL( path.tokens.size(), 1u );
+    BOOST_CHECK_EQUAL( (*path.tokens.begin()).name,     "name" );
+    BOOST_CHECK_EQUAL( (*path.tokens.begin()).property, "property" );
+    BOOST_CHECK_EQUAL( (*path.tokens.begin()).value,    "va.lue" );
+
+    BOOST_CHECK_EQUAL( process_path("name.property=va=lue", path), 1u);
+    BOOST_CHECK_EQUAL( path.relative_path, true );
+    BOOST_CHECK_EQUAL( path.tokens.size(), 1u );
+    BOOST_CHECK_EQUAL( (*path.tokens.begin()).name,     "name" );
+    BOOST_CHECK_EQUAL( (*path.tokens.begin()).property, "property" );
+    BOOST_CHECK_EQUAL( (*path.tokens.begin()).value,    "va=lue" );
 }
 
 BOOST_AUTO_TEST_CASE( TestTokenizer_InvalidPaths )