diff --git a/src/linearmap.hpp b/src/linearmap.hpp
new file mode 100644
index 0000000..0c8e5e8
--- /dev/null
+++ b/src/linearmap.hpp
@@ -0,0 +1,195 @@
+/*
+ Copyright 2014 Michele "King_DuckZ" Santullo
+
+ This file is part of CloonelJump.
+
+ CloonelJump is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ CloonelJump is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with CloonelJump. If not, see .
+*/
+
+#ifndef idEA67296D7EC847B58BB3D52DBC9E51BA
+#define idEA67296D7EC847B58BB3D52DBC9E51BA
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace cloonel {
+ namespace implem {
+ template
+ class LinearMapIterator : public boost::iterator_facade, typename std::iterator_traits::value_type, typename std::iterator_traits::iterator_category, typename std::iterator_traits::reference, typename std::iterator_traits::difference_type> {
+
+ typedef boost::iterator_facade, typename std::iterator_traits::value_type, typename std::iterator_traits::iterator_category, typename std::iterator_traits::reference, typename std::iterator_traits::difference_type> parent_type;
+
+ typedef typename parent_type::reference reference;
+ typedef typename parent_type::value_type value_type;
+ typedef S size_type;
+ public:
+ LinearMapIterator ( I parItemsStart, I parItemsEnd, std::vector::const_iterator parOccupiedStart ) :
+ m_itStart(parItemsStart),
+ m_itEnd(parItemsEnd),
+ m_itOccupied(parOccupiedStart)
+ {
+ }
+ ~LinearMapIterator ( void ) noexcept = default;
+
+ private:
+ friend class boost::iterator_core_access;
+
+ void increment ( void ) {
+ do {
+ ++m_itStart;
+ ++m_itOccupied;
+ } while (m_itEnd != m_itStart and not *m_itOccupied);
+ }
+ bool equal ( const LinearMapIterator& parOther ) const {
+ return m_itStart == parOther.m_itStart;
+ }
+ reference dereference ( void ) const {
+ return *m_itStart;
+ }
+ void advance ( size_type parAdv ) {
+ while (parAdv and m_itEnd != m_itStart) {
+ increment();
+ --parAdv;
+ }
+ }
+
+ I m_itStart;
+ const I m_itEnd;
+ std::vector::const_iterator m_itOccupied;
+ };
+ } //namespace implem
+
+ template >
+ class LinearMap {
+ public:
+ typedef size_t size_type;
+ typedef T value_type;
+ typedef typename implem::LinearMapIterator iterator;
+ typedef typename implem::LinearMapIterator const_iterator;
+
+ LinearMap ( void ) = default;
+ LinearMap ( LinearMap&& parOther );
+ ~LinearMap ( void ) noexcept = default;
+
+ size_type size ( void ) const { return m_usedCount; }
+ size_type max_size ( void ) const noexcept { return m_list.max_size(); }
+ size_type capacity ( void ) const noexcept { return m_list.capacity(); }
+ void shrink_to_fit ( void );
+ bool empty ( void ) const noexcept { return m_list.empty(); }
+ void push_back ( const value_type& parNew );
+ void push_back ( value_type&& parNew );
+ void swap ( LinearMap& parOther );
+ void clear ( void );
+ iterator erase_absolute ( size_type parIndex );
+ iterator at_absolute ( size_type parIndex );
+
+ iterator begin ( void ) { return iterator(m_list.begin(), m_list.end(), m_occupied.cbegin()); }
+ iterator end ( void ) { return iterator(m_list.end(), m_list.end(), m_occupied.cend()); }
+ const_iterator begin ( void ) const { return const_iterator(m_list.begin(), m_list.end(), m_occupied.cbegin()); }
+ const_iterator end ( void ) const { return const_iterator(m_list.end(), m_list.end(), m_occupied.cend()); }
+ const_iterator cbegin ( void ) const { return const_iterator(m_list.begin(), m_list.end(), m_occupied.cbegin()); }
+ const_iterator cend ( void ) const { return const_iterator(m_list.end(), m_list.end(), m_occupied.cend()); }
+
+ private:
+ Container m_list;
+ std::vector m_occupied;
+ size_type m_usedCount;
+ };
+
+ ///--------------------------------------------------------------------------
+ ///--------------------------------------------------------------------------
+ template
+ void LinearMap::shrink_to_fit() {
+ m_list.shrink_to_fit();
+ m_occupied.shrink_to_fit();
+ }
+
+ ///--------------------------------------------------------------------------
+ ///--------------------------------------------------------------------------
+ template
+ void LinearMap::push_back (const value_type& parNew) {
+ m_list.push_back(parNew);
+ m_occupied.push_back(true);
+ ++m_usedCount;
+ }
+
+ ///--------------------------------------------------------------------------
+ ///--------------------------------------------------------------------------
+ template
+ void LinearMap::push_back (value_type&& parNew) {
+ m_list.push_back(std::move(parNew));
+ m_occupied.push_back(true);
+ ++m_usedCount;
+ }
+
+ ///--------------------------------------------------------------------------
+ ///--------------------------------------------------------------------------
+ template
+ void LinearMap::swap (LinearMap& parOther) {
+ m_list.swap(parOther.m_list);
+ m_occupied.swap(parOther.m_occupied);
+ std::swap(m_usedCount, parOther.m_usedCount);
+ }
+
+ ///--------------------------------------------------------------------------
+ ///--------------------------------------------------------------------------
+ template
+ void LinearMap::clear() {
+ m_list.clear();
+ m_occupied.clear();
+ m_usedCount = 0;
+ }
+
+ ///--------------------------------------------------------------------------
+ ///--------------------------------------------------------------------------
+ template
+ typename LinearMap::iterator LinearMap::erase_absolute (size_type parIndex) {
+ auto ret = at_absolute(parIndex);
+ ++ret;
+
+ m_occupied[parIndex] = false;
+ --m_usedCount;
+
+ size_type deleCount = 0;
+ for (auto itOcc = m_occupied.rbegin(), itOccEND = m_occupied.rend(); itOcc != itOccEND and not *itOcc; ++itOcc) {
+ ++deleCount;
+ }
+
+ if (deleCount) {
+ assert(deleCount <= m_occupied.size());
+ const auto newSize = m_occupied.size() - deleCount;
+ m_occupied.resize(newSize);
+ m_list.resize(newSize);
+ }
+ return ret;
+ }
+
+ ///--------------------------------------------------------------------------
+ ///--------------------------------------------------------------------------
+ template
+ typename LinearMap::iterator LinearMap::at_absolute (size_type parIndex) {
+ assert(m_usedCount > 0);
+ assert(m_list.size() == m_occupied.size());
+ assert(parIndex < m_list.size());
+ assert(m_occupied[parIndex]);
+
+ return begin() + std::count_if(m_occupied.begin(), m_occupied.begin() + parIndex, [] (bool a) { return a; });
+ }
+} //namespace cloonel
+
+#endif
diff --git a/src/observersmanager.hpp b/src/observersmanager.hpp
index 6a9d657..40d08f3 100644
--- a/src/observersmanager.hpp
+++ b/src/observersmanager.hpp
@@ -20,6 +20,7 @@
#ifndef idF5E41734950640CDA3C949E0D3A9A30D
#define idF5E41734950640CDA3C949E0D3A9A30D
+#include "linearmap.hpp"
#include
#include
#include
@@ -27,101 +28,31 @@
#include
namespace cloonel {
- namespace implem {
- template
- class Iterator {
- public:
- Iterator ( const std::vector& parOccupied, std::vector& parItems, bool parEnd ) :
- m_occupied(parOccupied),
- m_items(parItems),
- m_pos(parEnd ? m_occupied.size() : 0)
- {
- assert(m_occupied.size() == m_items.size());
- }
- Iterator ( const Iterator& parOther ) :
- m_occupied(parOther.m_occupied),
- m_items(parOther.m_items),
- m_pos(parOther.m_pos)
- {
- }
- ~Iterator ( void ) noexcept = default;
-
- T operator-> ( void ) {
- assert(m_pos < m_occupied.size());
- assert(m_occupied[m_pos]);
- return m_items[m_pos];
- }
- T operator* ( void ) {
- assert(m_pos < m_occupied.size());
- assert(m_occupied[m_pos]);
- return m_items[m_pos];
- }
-
- Iterator& operator++ ( void ) {
- if (m_occupied.size() == m_pos)
- return *this;
- auto itNext = std::find(m_occupied.begin() + static_cast::difference_type>(m_pos + 1), m_occupied.end(), true);
- if (m_occupied.end() != itNext)
- m_pos = static_cast(itNext - m_occupied.begin());
- else
- m_pos = m_occupied.size();
- return *this;
- }
- Iterator operator++ ( int ) {
- Iterator prevState(*this);
- ++(*this);
- return prevState;
- }
-
- bool operator== ( const Iterator& parOther ) const {
- return m_pos == parOther.m_pos and &m_items == &parOther.m_items;
- }
- bool operator!= ( const Iterator& parOther ) const { return not this->operator==(parOther); }
-
- private:
- const std::vector& m_occupied;
- std::vector& m_items;
- std::size_t m_pos;
- };
- } //namespace implem
-
template
class ObserversManager {
public:
typedef size_t TicketType;
- typedef implem::Iterator iterator;
+ typedef typename LinearMap::iterator iterator;
- ObserversManager ( void );
+ ObserversManager ( void ) = default;
~ObserversManager ( void ) noexcept = default;
TicketType Add ( T parObserver );
void Remove ( TicketType parTicket ) noexcept;
void Update ( TicketType parTicket, T parObserver );
- std::size_t size ( void ) const { return m_usedCount; }
- iterator begin ( void ) { return iterator(m_occupied, m_list, false); }
- iterator end ( void ) { return iterator(m_occupied, m_list, true); }
+ std::size_t size ( void ) const { return m_list.size(); }
+ iterator begin ( void ) { return m_list.begin(); }
+ iterator end ( void ) { return m_list.end(); }
private:
- std::vector m_list;
- std::vector m_occupied;
- std::size_t m_usedCount;
+ LinearMap m_list;
};
- ///--------------------------------------------------------------------------
- ///--------------------------------------------------------------------------
- template
- ObserversManager::ObserversManager() :
- m_usedCount(0)
- {
- }
-
///--------------------------------------------------------------------------
///--------------------------------------------------------------------------
template
typename ObserversManager::TicketType ObserversManager::Add (T parObserver) {
m_list.push_back(parObserver);
- m_occupied.push_back(true);
- ++m_usedCount;
return static_cast(m_list.size());
}
@@ -129,37 +60,14 @@ namespace cloonel {
///--------------------------------------------------------------------------
template
void ObserversManager::Remove (TicketType parTicket) noexcept {
- assert(static_cast(parTicket) <= m_list.size());
- assert(m_occupied[parTicket - 1]);
- assert(m_usedCount > 0);
- assert(m_list.size() == m_occupied.size());
-
- m_occupied[parTicket - 1] = false;
- --m_usedCount;
-
- std::size_t deleCount = 0;
- for (auto itOcc = m_occupied.rbegin(), itOccEND = m_occupied.rend(); itOcc != itOccEND and not *itOcc; ++itOcc) {
- ++deleCount;
- }
-
- if (deleCount) {
- assert(deleCount <= m_occupied.size());
- const std::size_t newSize = m_occupied.size() - deleCount;
- m_occupied.resize(newSize);
- m_list.resize(newSize);
- }
+ m_list.erase_absolute(parTicket - 1);
}
///--------------------------------------------------------------------------
///--------------------------------------------------------------------------
template
void ObserversManager::Update (TicketType parTicket, T parObserver) {
- assert(static_cast(parTicket) <= m_list.size());
- assert(m_occupied[parTicket - 1]);
- assert(m_usedCount > 0);
- assert(m_list.size() == m_occupied.size());
-
- std::swap(m_list[parTicket - 1], parObserver);
+ std::swap(*m_list.at_absolute(parTicket - 1), parObserver);
}
} //namespace cloonel