#include <boost/signals/detail/config.hpp>
#include <boost/signals/detail/signals_common.hpp>
#include <boost/signals/connection.hpp>
-#include <boost/smart_ptr.hpp>
-#include <boost/any.hpp>
#include <boost/utility.hpp>
+#include <boost/shared_ptr.hpp>
#include <boost/function/function2.hpp>
#include <boost/iterator/iterator_facade.hpp>
+#include <map>
#include <memory>
#include <utility>
namespace detail {
-typedef function2<bool, any, any> compare_type;
+class stored_group
+{
+ public:
+ enum storage_kind { sk_empty, sk_front, sk_back, sk_group };
+
+ stored_group(storage_kind kind = sk_empty) : kind(kind), group() { }
+
+ template<typename T>
+ stored_group(const T& group) : kind(sk_group), group(new T(group)) { }
+
+ bool is_front() const { return kind == sk_front; }
+ bool is_back() const { return kind == sk_back; }
+ bool empty() const { return kind == sk_empty; }
+
+ void* get() const { return group.get(); }
+
+ private:
+ storage_kind kind;
+ shared_ptr<void> group;
+};
-// Used to delimit the front and back of the list for O(1) insertion.
-struct front_type {};
-struct back_type {};
+typedef function2<bool, stored_group, stored_group> compare_type;
// This function object bridges from a pair of any objects that hold
// values of type Key to the underlying function object that compares
// values of type Key.
template<typename Compare, typename Key>
-class any_bridge_compare {
+class group_bridge_compare {
public:
typedef bool result_type;
- typedef const any& first_argument_type;
- typedef const any& second_argument_type;
+ typedef const stored_group& first_argument_type;
+ typedef const stored_group& second_argument_type;
- any_bridge_compare(const Compare& c) : comp(c) {}
+ group_bridge_compare(const Compare& c) : comp(c)
+ { }
- bool operator()(const any& k1, const any& k2) const
+ bool operator()(const stored_group& k1, const stored_group& k2) const
{
- if (k1.type() == typeid(front_type))
- return !(k2.type() == typeid(front_type));
- if (k1.type() == typeid(back_type))
- return false;
- if (k2.type() == typeid(front_type))
- return false;
- if (k2.type() == typeid(back_type))
- return true;
+ if (k1.is_front()) return !k2.is_front();
+ if (k1.is_back()) return false;
+ if (k2.is_front()) return false;
+ if (k2.is_back()) return true;
// Neither is empty, so compare their values to order them
- // The strange */& is so that we will get a reference to the
- // value stored in the any object instead of a copy
- return comp(*any_cast<Key>(&k1), *any_cast<Key>(&k2));
+ return comp(*static_cast<Key*>(k1.get()), *static_cast<Key*>(k2.get()));
}
private:
connection_slot_pair,
forward_traversal_tag>
{
- class impl;
+ typedef std::list<connection_slot_pair> group_list;
+ typedef group_list::iterator slot_pair_iterator;
+ typedef std::map<stored_group, group_list, compare_type> slot_container_type;
+ typedef slot_container_type::iterator group_iterator;
+ typedef slot_container_type::const_iterator const_group_iterator;
typedef iterator_facade<named_slot_map_iterator,
connection_slot_pair,
forward_traversal_tag> inherited;
public:
- named_slot_map_iterator();
- named_slot_map_iterator(const named_slot_map_iterator& other);
- ~named_slot_map_iterator();
- named_slot_map_iterator& operator=(const named_slot_map_iterator& other);
-
- connection_slot_pair& dereference() const;
- void increment();
- bool equal(const named_slot_map_iterator& other) const;
+ named_slot_map_iterator() : slot_assigned(false)
+ { }
+ named_slot_map_iterator(const named_slot_map_iterator& other)
+ : group(other.group), last_group(other.last_group),
+ slot_assigned(other.slot_assigned)
+ {
+ if (slot_assigned) slot_ = other.slot_;
+ }
+ named_slot_map_iterator& operator=(const named_slot_map_iterator& other)
+ {
+ slot_assigned = other.slot_assigned;
+ group = other.group;
+ last_group = other.last_group;
+ if (slot_assigned) slot_ = other.slot_;
+ return *this;
+ }
+ connection_slot_pair& dereference() const
+ {
+ return *slot_;
+ }
+ void increment()
+ {
+ ++slot_;
+ if (slot_ == group->second.end()) {
+ ++group;
+ init_next_group();
+ }
+ }
+ bool equal(const named_slot_map_iterator& other) const {
+ return (group == other.group
+ && (group == last_group
+ || slot_ == other.slot_));
+ }
-#if BOOST_WORKAROUND(BOOST_MSVC, <= 0x1701)
+#if BOOST_WORKAROUND(_MSC_VER, <= 1400)
void decrement();
void advance(difference_type);
#endif
private:
- named_slot_map_iterator(std::auto_ptr<impl>);
+ named_slot_map_iterator(group_iterator group, group_iterator last) :
+ group(group), last_group(last), slot_assigned(false)
+ { init_next_group(); }
+ named_slot_map_iterator(group_iterator group, group_iterator last,
+ slot_pair_iterator slot) :
+ group(group), last_group(last), slot_(slot), slot_assigned(true)
+ { }
+
+ void init_next_group()
+ {
+ while (group != last_group && group->second.empty()) ++group;
+ if (group != last_group) {
+ slot_ = group->second.begin();
+ slot_assigned = true;
+ }
+ }
-#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
- shared_ptr<impl> impl_;
-#else
- scoped_ptr<impl> impl_;
-#endif
+ group_iterator group;
+ group_iterator last_group;
+ slot_pair_iterator slot_;
+ bool slot_assigned;
friend class named_slot_map;
};
typedef named_slot_map_iterator iterator;
named_slot_map(const compare_type& compare);
- ~named_slot_map();
void clear();
iterator begin();
iterator end();
- iterator insert(const any& name, const connection& con, const any& slot,
- connect_position at);
- void disconnect(const any& name);
+ iterator insert(const stored_group& name, const connection& con,
+ const any& slot, connect_position at);
+ void disconnect(const stored_group& name);
void erase(iterator pos);
void remove_disconnected_slots();
private:
- class impl;
+ typedef std::list<connection_slot_pair> group_list;
+ typedef std::map<stored_group, group_list, compare_type> slot_container_type;
+ typedef slot_container_type::iterator group_iterator;
+ typedef slot_container_type::const_iterator const_group_iterator;
-#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
- shared_ptr<impl> impl_;
-#else
- scoped_ptr<impl> impl_;
-#endif
+ bool empty(const_group_iterator group) const
+ {
+ return (group->second.empty() && group != groups.begin() && group != back);
+ }
+ slot_container_type groups;
+ group_iterator back;
};
} } }