diff options
author | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-20 14:33:09 +1000 |
---|---|---|
committer | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-20 14:33:09 +1000 |
commit | 6352e8e3196f78388b6c771073f9e03eaa612673 (patch) | |
tree | e23772f79a7fbc41bc9108951e9e136857484bf4 /source/core/StarIdMap.hpp | |
parent | 6741a057e5639280d85d0f88ba26f000baa58f61 (diff) |
everything everywhere
all at once
Diffstat (limited to 'source/core/StarIdMap.hpp')
-rw-r--r-- | source/core/StarIdMap.hpp | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/source/core/StarIdMap.hpp b/source/core/StarIdMap.hpp new file mode 100644 index 0000000..15946da --- /dev/null +++ b/source/core/StarIdMap.hpp @@ -0,0 +1,151 @@ +#ifndef STAR_ID_MAP_HPP +#define STAR_ID_MAP_HPP + +#include "StarMap.hpp" +#include "StarMathCommon.hpp" +#include "StarDataStream.hpp" + +namespace Star { + +STAR_EXCEPTION(IdMapException, StarException); + +// Maps key ids to values with auto generated ids in a given id range. Tries +// to cycle through ids as new values are added and avoid re-using ids until +// the id space wraps around. +template <typename BaseMap> +class IdMapWrapper : private BaseMap { +public: + typedef typename BaseMap::iterator iterator; + typedef typename BaseMap::const_iterator const_iterator; + typedef typename BaseMap::key_type key_type; + typedef typename BaseMap::value_type value_type; + typedef typename BaseMap::mapped_type mapped_type; + + typedef key_type IdType; + typedef value_type ValueType; + typedef mapped_type MappedType; + + IdMapWrapper(); + IdMapWrapper(IdType min, IdType max); + + // New valid id that does not exist in this map. Tries not to immediately + // recycle ids, to avoid temporally close id repeats. + IdType nextId(); + + // Throws exception if key already exists + void add(IdType id, MappedType mappedType); + + // Add with automatically allocated id + IdType add(MappedType mappedType); + + void clear(); + + bool operator==(IdMapWrapper const& rhs) const; + bool operator!=(IdMapWrapper const& rhs) const; + + using BaseMap::keys; + using BaseMap::values; + using BaseMap::pairs; + using BaseMap::contains; + using BaseMap::size; + using BaseMap::empty; + using BaseMap::get; + using BaseMap::ptr; + using BaseMap::maybe; + using BaseMap::take; + using BaseMap::maybeTake; + using BaseMap::remove; + using BaseMap::value; + using BaseMap::begin; + using BaseMap::end; + using BaseMap::erase; + + template <typename Base> + friend DataStream& operator>>(DataStream& ds, IdMapWrapper<Base>& map); + template <typename Base> + friend DataStream& operator<<(DataStream& ds, IdMapWrapper<Base> const& map); + +private: + IdType m_min; + IdType m_max; + IdType m_nextId; +}; + +template <class Key, class Value> +using IdMap = IdMapWrapper<Map<Key, Value>>; + +template <class Key, class Value> +using IdHashMap = IdMapWrapper<HashMap<Key, Value>>; + +template <typename BaseMap> +IdMapWrapper<BaseMap>::IdMapWrapper() + : m_min(lowest<IdType>()), m_max(highest<IdType>()), m_nextId(m_min) {} + +template <typename BaseMap> +IdMapWrapper<BaseMap>::IdMapWrapper(IdType min, IdType max) + : m_min(min), m_max(max), m_nextId(m_min) { + starAssert(m_max > m_min); +} + +template <typename BaseMap> +auto IdMapWrapper<BaseMap>::nextId() -> IdType { + if ((IdType)BaseMap::size() > m_max - m_min) + throw IdMapException("No id space left in IdMapWrapper"); + + IdType nextId = m_nextId; + while (BaseMap::contains(nextId)) + nextId = cycleIncrement(nextId, m_min, m_max); + m_nextId = cycleIncrement(nextId, m_min, m_max); + return nextId; +} + +template <typename BaseMap> +void IdMapWrapper<BaseMap>::add(IdType id, MappedType mappedType) { + if (!BaseMap::insert(make_pair(move(id), move(mappedType))).second) + throw IdMapException::format("IdMapWrapper::add(id, value) called with pre-existing id '%s'", outputAny(id)); +} + +template <typename BaseMap> +auto IdMapWrapper<BaseMap>::add(MappedType mappedType) -> IdType { + auto id = nextId(); + BaseMap::insert(id, mappedType); + return id; +} + +template <typename BaseMap> +void IdMapWrapper<BaseMap>::clear() { + BaseMap::clear(); + m_nextId = m_min; +} + +template <typename BaseMap> +bool IdMapWrapper<BaseMap>::operator==(IdMapWrapper const& rhs) const { + return tie(m_min, m_max) == tie(rhs.m_min, rhs.m_max) && BaseMap::operator==(rhs); +} + +template <typename BaseMap> +bool IdMapWrapper<BaseMap>::operator!=(IdMapWrapper const& rhs) const { + return !operator==(rhs); +} + +template <typename BaseMap> +DataStream& operator>>(DataStream& ds, IdMapWrapper<BaseMap>& map) { + ds.readMapContainer((BaseMap&)map); + ds.read(map.m_min); + ds.read(map.m_max); + ds.read(map.m_nextId); + return ds; +} + +template <typename BaseMap> +DataStream& operator<<(DataStream& ds, IdMapWrapper<BaseMap> const& map) { + ds.writeMapContainer((BaseMap const&)map); + ds.write(map.m_min); + ds.write(map.m_max); + ds.write(map.m_nextId); + return ds; +} + +} + +#endif |