Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r55980 - in sandbox/pinhole: boost/pinhole libs/pinhole/test
From: jmcintyre_at_[hidden]
Date: 2009-09-02 15:45:30


Author: jared
Date: 2009-09-02 15:45:29 EDT (Wed, 02 Sep 2009)
New Revision: 55980
URL: http://svn.boost.org/trac/boost/changeset/55980

Log:
Pinhole - Add initial pass at signals support. The interface needs improvement, but it is functional.
Added:
   sandbox/pinhole/boost/pinhole/signal_info.hpp (contents, props changed)
   sandbox/pinhole/libs/pinhole/test/test_signals.cpp (contents, props changed)
Text files modified:
   sandbox/pinhole/boost/pinhole/exceptions.hpp | 2
   sandbox/pinhole/boost/pinhole/property_group.hpp | 160 ++++++++++++++++++++++++++++++++++++++-
   sandbox/pinhole/boost/pinhole/property_info.hpp | 2
   sandbox/pinhole/boost/pinhole/types.hpp | 2
   sandbox/pinhole/libs/pinhole/test/Jamfile.v2 | 1
   5 files changed, 159 insertions(+), 8 deletions(-)

Modified: sandbox/pinhole/boost/pinhole/exceptions.hpp
==============================================================================
--- sandbox/pinhole/boost/pinhole/exceptions.hpp (original)
+++ sandbox/pinhole/boost/pinhole/exceptions.hpp 2009-09-02 15:45:29 EDT (Wed, 02 Sep 2009)
@@ -41,6 +41,8 @@
     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_signal_name, const std::string > exception_signal_name;
+ typedef ::boost::error_info< struct tag_signal_type, const std::string > exception_signal_type;
     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;
 }}

Modified: sandbox/pinhole/boost/pinhole/property_group.hpp
==============================================================================
--- sandbox/pinhole/boost/pinhole/property_group.hpp (original)
+++ sandbox/pinhole/boost/pinhole/property_group.hpp 2009-09-02 15:45:29 EDT (Wed, 02 Sep 2009)
@@ -11,12 +11,13 @@
 #include "types.hpp"
 #include "map_key_value_iterators.hpp"
 #include "property_info.hpp"
+#include "signal_info.hpp"
 #include "action_info.hpp"
 #include "property_manager.hpp"
 #include <sstream>
 
 #include <boost/bind.hpp>
-#include <boost/type_traits.hpp>
+#include <boost/type_traits/add_reference.hpp>
 #include <boost/function.hpp>
 #include <boost/static_assert.hpp>
 #include <boost/any.hpp>
@@ -545,7 +546,7 @@
             typedef map_key_iterator<action_collection::const_iterator> const_action_iterator;
 
             /**
- * Retrieves an iterator pointing to the name of the first property.
+ * Retrieves an iterator pointing to the name of the first action.
              */
             action_iterator action_begin()
             {
@@ -553,7 +554,7 @@
             }
 
             /**
- * Retrieves an iterator pointing to the name of the first property.
+ * Retrieves an iterator pointing to the name of the first action.
              */
             const_action_iterator action_begin() const
             {
@@ -561,7 +562,7 @@
             }
 
             /**
- * Retrieves an iterator pointing to the end of the property list.
+ * Retrieves an iterator pointing to the end of the action list.
              */
             action_iterator action_end()
             {
@@ -569,7 +570,7 @@
             }
 
             /**
- * Retrieves an iterator pointing to the end of the property list.
+ * Retrieves an iterator pointing to the end of the action list.
              */
             const_action_iterator action_end() const
             {
@@ -577,7 +578,7 @@
             }
 
             /**
- * Retrieves the number of properties.
+ * Retrieves the number of actions.
              */
             action_size_type action_count() const
             {
@@ -637,6 +638,114 @@
             }
         //@}
         
+ /** @name Signals */
+ //@{
+ typedef signal_collection::size_type signal_size_type;
+ typedef map_key_iterator<signal_collection::iterator> signal_iterator;
+ typedef map_key_iterator<signal_collection::const_iterator> const_signal_iterator;
+
+ /**
+ * Retrieves an iterator pointing to the name of the first signal.
+ */
+ signal_iterator signal_begin()
+ {
+ return signal_iterator( m_signals.begin() );
+ }
+
+ /**
+ * Retrieves an iterator pointing to the name of the first signal.
+ */
+ const_signal_iterator signal_begin() const
+ {
+ return const_signal_iterator( m_signals.begin() );
+ }
+
+ /**
+ * Retrieves an iterator pointing to the end of the signal list.
+ */
+ signal_iterator signal_end()
+ {
+ return signal_iterator( m_signals.end() );
+ }
+
+ /**
+ * Retrieves an iterator pointing to the end of the signal list.
+ */
+ const_signal_iterator signal_end() const
+ {
+ return const_signal_iterator( m_signals.end() );
+ }
+
+ /**
+ * Retrieves the number of properties.
+ */
+ signal_size_type signal_count() const
+ {
+ return m_signals.size();
+ }
+
+ /**
+ * Returns whether the signal exists.
+ * @retval true Signal exists.
+ * @retval false Signal does not exist.
+ */
+ bool is_valid_signal( const std::string &signal ) const
+ {
+ return m_signals.find(signal) != m_signals.end();
+ }
+
+ /**
+ * Returns a signal.
+ * @param signal The name of the signal.
+ * @throw std::out_of_range The signal requested does not exist.
+ */
+ template<typename SignalType>
+ typename boost::add_reference<SignalType>::type get_signal(const std::string &signal) const
+ {
+ typedef typename boost::add_reference<SignalType>::type SignalTypeRef;
+
+ signal_collection::const_iterator itemItr = m_signals.find(signal);
+
+ if( m_signals.end() != itemItr )
+ {
+ detail::signal_info_base* signalInfo = (*itemItr).second;
+
+ if( typeid(SignalTypeRef) == signalInfo->m_type )
+ {
+ return static_cast<detail::signal_info<SignalTypeRef>*>(signalInfo)->m_signal;
+ }
+
+ throw ::boost::enable_error_info(std::bad_cast())
+ << ::boost::pinhole::exception_additional_info("Attempted to get a signal using a type different from the signal's type.")
+ << ::boost::pinhole::exception_property_name(signal)
+ << ::boost::pinhole::exception_requested_type(typeid(SignalType).name())
+ << ::boost::pinhole::exception_signal_type(signalInfo->m_type.name());
+ }
+
+ throw ::boost::enable_error_info(std::out_of_range("The requested signal does not exist.")) << ::boost::pinhole::exception_signal_name(signal);
+ }
+
+ /**
+ * Gets an anction's metadata object.
+ * @param property The name of the property.
+ * @return The metadata object of the property.
+ * @throw std::out_of_range The property requested does not exist.
+ */
+ const boost::any& get_signal_metadata(const std::string &signal) const
+ {
+ signal_collection::const_iterator itemItr = m_signals.find(signal);
+
+ if( itemItr != m_signals.end() )
+ {
+ return( (*itemItr).second->m_metadata );
+ }
+ else
+ {
+ throw ::boost::enable_error_info(std::out_of_range("The requested signal does not exist.")) << ::boost::pinhole::exception_signal_name(signal);
+ }
+ }
+ //@}
+
         /**
          * Adds a property to the property list.
          * @param name The name of the property.
@@ -728,6 +837,42 @@
                 m_actions.insert( std::make_pair(name, action_info) );
             }
         }
+
+ /**
+ * Adds a signal to the signal list.
+ * @param name The name of the property.
+ * @param signal The signal to add.
+ * @param metadata A pointer to the editor to be used with this signal, or null
+ * if there isn't one.
+ */
+ template< typename SignalType>
+ void add_signal( std::string name,
+ SignalType& signal,
+ boost::any metadata = boost::any() )
+ {
+ typedef typename boost::add_reference<SignalType>::type SignalTypeRef;
+
+ detail::signal_info<SignalTypeRef> *sig = new detail::signal_info<SignalTypeRef>(signal);
+
+ // Fill out property information
+
+ sig->m_name = name;
+ sig->m_metadata = metadata;
+
+ // Store property information
+
+ signal_collection::iterator previousInstance = m_signals.find(name);
+ if( m_signals.end() != previousInstance )
+ {
+ // Object already exists. Destroy existing instance and replace it.
+ delete (*previousInstance).second;
+ (*previousInstance).second = sig;
+ }
+ else
+ {
+ m_signals.insert( std::make_pair(name, sig) );
+ }
+ }
 
         /**
         * Adds this property to the specified category.
@@ -748,7 +893,8 @@
             category_collection m_category_collection;
             children_collection m_children_collection;
             property_collection m_properties;
- action_collection m_actions;
+ signal_collection m_signals;
+ action_collection m_actions;
         #if defined(BOOST_MSVC)
             #pragma warning(pop)
         #endif

Modified: sandbox/pinhole/boost/pinhole/property_info.hpp
==============================================================================
--- sandbox/pinhole/boost/pinhole/property_info.hpp (original)
+++ sandbox/pinhole/boost/pinhole/property_info.hpp 2009-09-02 15:45:29 EDT (Wed, 02 Sep 2009)
@@ -1,4 +1,4 @@
-// Pinhole property_manager.hpp file
+// Pinhole prooperty_info.hpp file
 //
 // Copyright Jared McIntyre 2007.
 // Distributed under the Boost Software License, Version 1.0.

Added: sandbox/pinhole/boost/pinhole/signal_info.hpp
==============================================================================
--- (empty file)
+++ sandbox/pinhole/boost/pinhole/signal_info.hpp 2009-09-02 15:45:29 EDT (Wed, 02 Sep 2009)
@@ -0,0 +1,65 @@
+// Pinhole signal_info.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_SIGNAL_INFO
+#define BOOST_PINHOLE_SIGNAL_INFO
+
+#if defined(BOOST_MSVC)
+#pragma warning(push)
+#pragma warning( disable: 4561 4793 )
+#endif
+#include "exceptions.hpp"
+#include <boost/type_traits.hpp>
+#include <boost/function.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/algorithm/string/predicate.hpp>
+#include <boost/format.hpp>
+#include <boost/any.hpp>
+#include <boost/archive/iterators/mb_from_wchar.hpp>
+#include <boost/archive/iterators/wchar_from_mb.hpp>
+#if defined(BOOST_MSVC)
+#pragma warning(pop)
+#endif
+
+namespace boost { namespace pinhole { namespace detail
+{
+ struct signal_info_base
+ {
+ public:
+ signal_info_base(const std::type_info &type) :
+ m_type(type)
+ {;}
+
+ virtual ~signal_info_base(){;}
+
+ std::string m_name;
+ boost::any m_metadata;
+ const std::type_info &m_type;
+
+ private:
+ signal_info_base(const property_info_base&):m_type(typeid(void)){;} // this would be bad
+ };
+
+ template<typename SignalType>
+ struct signal_info : signal_info_base
+ {
+
+ public:
+ // Signals must be references
+ BOOST_STATIC_ASSERT(true == boost::is_reference<SignalType>::value);
+
+ SignalType m_signal;
+
+ signal_info(SignalType signal) : signal_info_base(typeid(SignalType)), m_signal(signal) {;}
+
+ private:
+ signal_info() : signal_info_base(typeid(void)){;} // this would be bad
+ signal_info(const signal_info<SignalType>&) : signal_info_base(typeid(void)){;} // this would be bad
+ };
+}}}
+
+#endif // include guard
\ No newline at end of file

Modified: sandbox/pinhole/boost/pinhole/types.hpp
==============================================================================
--- sandbox/pinhole/boost/pinhole/types.hpp (original)
+++ sandbox/pinhole/boost/pinhole/types.hpp 2009-09-02 15:45:29 EDT (Wed, 02 Sep 2009)
@@ -20,12 +20,14 @@
     namespace detail
     {
         struct property_info_base;
+ struct signal_info_base;
         struct action_info;
     }
 
     typedef std::set<std::string> category_collection;
     typedef std::list<property_group*> children_collection;
     typedef std::map<std::string, detail::property_info_base*> property_collection;
+ typedef std::map<std::string, detail::signal_info_base*> signal_collection;
     typedef std::map<std::string, detail::action_info*> action_collection;
 }}
 

Modified: sandbox/pinhole/libs/pinhole/test/Jamfile.v2
==============================================================================
--- sandbox/pinhole/libs/pinhole/test/Jamfile.v2 (original)
+++ sandbox/pinhole/libs/pinhole/test/Jamfile.v2 2009-09-02 15:45:29 EDT (Wed, 02 Sep 2009)
@@ -29,6 +29,7 @@
   [ run test_string_properties.cpp ]
   
   [ run test_actions.cpp ]
+ [ run test_signals.cpp ]
  
   [ run test_tokenizer.cpp ]
   [ run test_depth_first_iterator.cpp ]

Added: sandbox/pinhole/libs/pinhole/test/test_signals.cpp
==============================================================================
--- (empty file)
+++ sandbox/pinhole/libs/pinhole/test/test_signals.cpp 2009-09-02 15:45:29 EDT (Wed, 02 Sep 2009)
@@ -0,0 +1,120 @@
+// 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/config.hpp>
+#include <boost/pinhole.hpp>
+#include <boost/signals.hpp>
+#include <boost/test/unit_test.hpp>
+
+using namespace std;
+using namespace boost;
+using namespace boost::pinhole;
+
+#define SIGNAL_1 ("BOOST_SIGNAL 1")
+#define SIGNAL_2 ("BOOST_SIGNAL 2")
+
+typedef boost::signal<void(int)> OneIntSignal;
+typedef boost::signal<void(int,int)> TwoIntSignal;
+
+class TestSignalsFixture : public property_group
+{
+public:
+ #if defined(BOOST_MSVC)
+ #pragma warning(push)
+ #pragma warning( disable: 4355 )
+ #endif
+ TestSignalsFixture()
+ : property_group( "PropertyGroupName", NULL )
+ , m_val1(-1)
+ , m_val2(-1)
+ {
+
+ add_signal(SIGNAL_1, int1Signal);
+ add_signal(SIGNAL_2, int2Signal, string("some info"));
+ }
+ #if defined(BOOST_MSVC)
+ #pragma warning(pop)
+ #endif
+
+ void clear_actions()
+ {
+ m_actions.clear();
+ }
+
+ OneIntSignal int1Signal;
+ TwoIntSignal int2Signal;
+
+ void Signal1Triggered(int val) {m_val1 = val; m_val2 = -1;}
+ void Signal2Triggered(int val1, int val2) {m_val1 = val1; m_val2 = val2;}
+
+ int m_val1;
+ int m_val2;
+};
+
+void someFunc(int)
+{
+}
+
+BOOST_AUTO_TEST_CASE( TestSignal )
+{
+ TestSignalsFixture testFixture;
+
+ boost::signals::connection c1 =
+ testFixture.get_signal<OneIntSignal>(SIGNAL_1).connect( boost::bind(&TestSignalsFixture::Signal1Triggered, &testFixture, _1) );
+
+ boost::signals::connection c2 =
+ testFixture.get_signal<TwoIntSignal>(SIGNAL_2).connect( bind(&TestSignalsFixture::Signal2Triggered, &testFixture, _1, _2) );
+
+ BOOST_CHECK_EQUAL(testFixture.m_val1, -1);
+ BOOST_CHECK_EQUAL(testFixture.m_val2, -1);
+
+ testFixture.int2Signal(2,3);
+
+ BOOST_CHECK_EQUAL(testFixture.m_val1, 2);
+ BOOST_CHECK_EQUAL(testFixture.m_val2, 3);
+
+ testFixture.int1Signal(1);
+
+ BOOST_CHECK_EQUAL(testFixture.m_val1, 1);
+ BOOST_CHECK_EQUAL(testFixture.m_val2, -1);
+
+ c1.disconnect();
+ c2.disconnect();
+
+ testFixture.m_val1 = 999999;
+ testFixture.m_val2 = 999999;
+
+ testFixture.int2Signal(2,3);
+
+ BOOST_CHECK_EQUAL(testFixture.m_val1, 999999);
+ BOOST_CHECK_EQUAL(testFixture.m_val2, 999999);
+
+
+ testFixture.int1Signal(1);
+
+ BOOST_CHECK_EQUAL(testFixture.m_val1, 999999);
+ BOOST_CHECK_EQUAL(testFixture.m_val2, 999999);
+}
+
+BOOST_AUTO_TEST_CASE( TestNonExistentSignal )
+{
+ TestSignalsFixture testFixture;
+
+ BOOST_CHECK_THROW( testFixture.get_signal< boost::signal<void(int)> >("NonExistent Signal"), std::out_of_range );
+ BOOST_CHECK_THROW( testFixture.get_signal_metadata("NonExistent Signal"), std::out_of_range );
+}
+
+BOOST_AUTO_TEST_CASE( TestSignalMetadata )
+{
+ TestSignalsFixture testFixture;
+
+ BOOST_CHECK_EQUAL( any_cast<string>(testFixture.get_signal_metadata(SIGNAL_2)), string("some info") );
+}
\ 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