Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/core/StarMap.hpp
diff options
context:
space:
mode:
authorKae <80987908+Novaenia@users.noreply.github.com>2023-06-20 14:33:09 +1000
committerKae <80987908+Novaenia@users.noreply.github.com>2023-06-20 14:33:09 +1000
commit6352e8e3196f78388b6c771073f9e03eaa612673 (patch)
treee23772f79a7fbc41bc9108951e9e136857484bf4 /source/core/StarMap.hpp
parent6741a057e5639280d85d0f88ba26f000baa58f61 (diff)
everything everywhere
all at once
Diffstat (limited to 'source/core/StarMap.hpp')
-rw-r--r--source/core/StarMap.hpp318
1 files changed, 318 insertions, 0 deletions
diff --git a/source/core/StarMap.hpp b/source/core/StarMap.hpp
new file mode 100644
index 0000000..45dd219
--- /dev/null
+++ b/source/core/StarMap.hpp
@@ -0,0 +1,318 @@
+#ifndef STAR_MAP_HPP
+#define STAR_MAP_HPP
+
+#include <map>
+#include <unordered_map>
+
+#include "StarFlatHashMap.hpp"
+#include "StarList.hpp"
+
+namespace Star {
+
+STAR_EXCEPTION(MapException, StarException);
+
+template <typename BaseMap>
+class MapMixin : public BaseMap {
+public:
+ typedef BaseMap Base;
+
+ typedef typename Base::iterator iterator;
+ typedef typename Base::const_iterator const_iterator;
+
+ typedef typename Base::key_type key_type;
+ typedef typename Base::mapped_type mapped_type;
+ typedef typename Base::value_type value_type;
+
+ typedef typename std::decay<mapped_type>::type* mapped_ptr;
+ typedef typename std::decay<mapped_type>::type const* mapped_const_ptr;
+
+ template <typename MapType>
+ static MapMixin from(MapType const& m);
+
+ using Base::Base;
+
+ List<key_type> keys() const;
+ List<mapped_type> values() const;
+ List<pair<key_type, mapped_type>> pairs() const;
+
+ bool contains(key_type const& k) const;
+
+ // Removes the item with key k and returns true if contains(k) is true,
+ // false otherwise.
+ bool remove(key_type const& k);
+
+ // Removes *all* items that have a value matching the given one. Returns
+ // true if any elements were removed.
+ bool removeValues(mapped_type const& v);
+
+ // Throws exception if key not found
+ mapped_type take(key_type const& k);
+
+ Maybe<mapped_type> maybeTake(key_type const& k);
+
+ // Throws exception if key not found
+ mapped_type& get(key_type const& k);
+ mapped_type const& get(key_type const& k) const;
+
+ // Return d if key not found
+ mapped_type value(key_type const& k, mapped_type d = mapped_type()) const;
+
+ Maybe<mapped_type> maybe(key_type const& k) const;
+
+ mapped_const_ptr ptr(key_type const& k) const;
+ mapped_ptr ptr(key_type const& k);
+
+ // Finds first value matching the given value and returns its key.
+ key_type keyOf(mapped_type const& v) const;
+
+ // Finds all of the values matching the given value and returns their keys.
+ List<key_type> keysOf(mapped_type const& v) const;
+
+ bool hasValue(mapped_type const& v) const;
+
+ using Base::insert;
+
+ // Same as insert(value_type), returns the iterator to either the newly
+ // inserted value or the existing value, and then a bool that is true if the
+ // new element was inserted.
+ pair<iterator, bool> insert(key_type k, mapped_type v);
+
+ // Add a key / value pair, throw if the key already exists
+ mapped_type& add(key_type k, mapped_type v);
+
+ // Set a key to a value, always override if it already exists
+ mapped_type& set(key_type k, mapped_type v);
+
+ // Appends all values of given map into this map. If overwite is false, then
+ // skips values that already exist in this map. Returns false if any keys
+ // previously existed.
+ template <typename MapType>
+ bool merge(MapType const& m, bool overwrite = false);
+
+ bool operator==(MapMixin const& m) const;
+};
+
+template <typename BaseMap>
+std::ostream& operator<<(std::ostream& os, MapMixin<BaseMap> const& m);
+
+template <typename Key, typename Value, typename Compare = std::less<Key>, typename Allocator = std::allocator<pair<Key const, Value>>>
+using Map = MapMixin<std::map<Key, Value, Compare, Allocator>>;
+
+template <typename Key, typename Value, typename Hash = hash<Key>, typename Equals = std::equal_to<Key>, typename Allocator = std::allocator<pair<Key const, Value>>>
+using HashMap = MapMixin<FlatHashMap<Key, Value, Hash, Equals, Allocator>>;
+
+template <typename Key, typename Value, typename Hash = hash<Key>, typename Equals = std::equal_to<Key>, typename Allocator = std::allocator<pair<Key const, Value>>>
+using StableHashMap = MapMixin<std::unordered_map<Key, Value, Hash, Equals, Allocator>>;
+
+template <typename BaseMap>
+template <typename MapType>
+auto MapMixin<BaseMap>::from(MapType const& m) -> MapMixin {
+ return MapMixin(m.begin(), m.end());
+}
+
+template <typename BaseMap>
+auto MapMixin<BaseMap>::keys() const -> List<key_type> {
+ List<key_type> klist;
+ for (const_iterator i = Base::begin(); i != Base::end(); ++i)
+ klist.push_back(i->first);
+ return klist;
+}
+
+template <typename BaseMap>
+auto MapMixin<BaseMap>::values() const -> List<mapped_type> {
+ List<mapped_type> vlist;
+ for (const_iterator i = Base::begin(); i != Base::end(); ++i)
+ vlist.push_back(i->second);
+ return vlist;
+}
+
+template <typename BaseMap>
+auto MapMixin<BaseMap>::pairs() const -> List<pair<key_type, mapped_type>> {
+ List<pair<key_type, mapped_type>> plist;
+ for (const_iterator i = Base::begin(); i != Base::end(); ++i)
+ plist.push_back(*i);
+ return plist;
+}
+
+template <typename BaseMap>
+bool MapMixin<BaseMap>::contains(key_type const& k) const {
+ return Base::find(k) != Base::end();
+}
+
+template <typename BaseMap>
+bool MapMixin<BaseMap>::remove(key_type const& k) {
+ return Base::erase(k) != 0;
+}
+
+template <typename BaseMap>
+bool MapMixin<BaseMap>::removeValues(mapped_type const& v) {
+ bool removed = false;
+ const_iterator i = Base::begin();
+ while (i != Base::end()) {
+ if (i->second == v) {
+ Base::erase(i++);
+ removed = true;
+ } else {
+ ++i;
+ }
+ }
+ return removed;
+}
+
+template <typename BaseMap>
+auto MapMixin<BaseMap>::take(key_type const& k) -> mapped_type {
+ if (auto v = maybeTake(k))
+ return v.take();
+ throw MapException(strf("Key '%s' not found in Map::take()", outputAny(k)));
+}
+
+template <typename BaseMap>
+auto MapMixin<BaseMap>::maybeTake(key_type const& k) -> Maybe<mapped_type> {
+ const_iterator i = Base::find(k);
+ if (i != Base::end()) {
+ mapped_type v = std::move(i->second);
+ Base::erase(i);
+ return move(v);
+ }
+
+ return {};
+}
+
+template <typename BaseMap>
+auto MapMixin<BaseMap>::get(key_type const& k) -> mapped_type& {
+ iterator i = Base::find(k);
+ if (i == Base::end())
+ throw MapException(strf("Key '%s' not found in Map::get()", outputAny(k)));
+ return i->second;
+}
+
+template <typename BaseMap>
+auto MapMixin<BaseMap>::get(key_type const& k) const -> mapped_type const& {
+ const_iterator i = Base::find(k);
+ if (i == Base::end())
+ throw MapException(strf("Key '%s' not found in Map::get()", outputAny(k)));
+ return i->second;
+}
+
+template <typename BaseMap>
+auto MapMixin<BaseMap>::value(key_type const& k, mapped_type d) const -> mapped_type {
+ const_iterator i = Base::find(k);
+ if (i == Base::end())
+ return std::move(d);
+ else
+ return i->second;
+}
+
+template <typename BaseMap>
+auto MapMixin<BaseMap>::maybe(key_type const& k) const -> Maybe<mapped_type> {
+ auto i = Base::find(k);
+ if (i == Base::end())
+ return {};
+ else
+ return i->second;
+}
+
+template <typename BaseMap>
+auto MapMixin<BaseMap>::ptr(key_type const& k) const -> mapped_const_ptr {
+ auto i = Base::find(k);
+ if (i == Base::end())
+ return nullptr;
+ else
+ return &i->second;
+}
+
+template <typename BaseMap>
+auto MapMixin<BaseMap>::ptr(key_type const& k) -> mapped_ptr {
+ auto i = Base::find(k);
+ if (i == Base::end())
+ return nullptr;
+ else
+ return &i->second;
+}
+
+template <typename BaseMap>
+auto MapMixin<BaseMap>::keyOf(mapped_type const& v) const -> key_type {
+ for (const_iterator i = Base::begin(); i != Base::end(); ++i) {
+ if (i->second == v)
+ return i->first;
+ }
+ throw MapException(strf("Value '%s' not found in Map::keyOf()", outputAny(v)));
+}
+
+template <typename BaseMap>
+auto MapMixin<BaseMap>::keysOf(mapped_type const& v) const -> List<key_type> {
+ List<key_type> keys;
+ for (const_iterator i = Base::begin(); i != Base::end(); ++i) {
+ if (i->second == v)
+ keys.append(i->first);
+ }
+ return keys;
+}
+
+template <typename BaseMap>
+auto MapMixin<BaseMap>::hasValue(mapped_type const& v) const -> bool {
+ for (const_iterator i = Base::begin(); i != Base::end(); ++i) {
+ if (i->second == v)
+ return true;
+ }
+ return false;
+}
+
+template <typename BaseMap>
+auto MapMixin<BaseMap>::insert(key_type k, mapped_type v) -> pair<iterator, bool> {
+ return Base::insert(value_type(move(k), move(v)));
+}
+
+template <typename BaseMap>
+auto MapMixin<BaseMap>::add(key_type k, mapped_type v) -> mapped_type& {
+ auto pair = Base::insert(value_type(move(k), move(v)));
+ if (!pair.second)
+ throw MapException(strf("Entry with key '%s' already present.", outputAny(k)));
+ else
+ return pair.first->second;
+}
+
+template <typename BaseMap>
+auto MapMixin<BaseMap>::set(key_type k, mapped_type v) -> mapped_type& {
+ auto i = Base::find(k);
+ if (i != Base::end()) {
+ i->second = move(v);
+ return i->second;
+ } else {
+ return Base::insert(value_type(move(k), move(v))).first->second;
+ }
+}
+
+template <typename BaseMap>
+template <typename OtherMapType>
+bool MapMixin<BaseMap>::merge(OtherMapType const& m, bool overwrite) {
+ return mapMerge(*this, m, overwrite);
+}
+
+template <typename BaseMap>
+bool MapMixin<BaseMap>::operator==(MapMixin const& m) const {
+ return this == &m || mapsEqual(*this, m);
+}
+
+template <typename MapType>
+void printMap(std::ostream& os, MapType const& m) {
+ os << "{ ";
+ for (auto i = m.begin(); i != m.end(); ++i) {
+ if (m.begin() == i)
+ os << "\"";
+ else
+ os << ", \"";
+ os << i->first << "\" : \"" << i->second << "\"";
+ }
+ os << " }";
+}
+
+template <typename BaseMap>
+std::ostream& operator<<(std::ostream& os, MapMixin<BaseMap> const& m) {
+ printMap(os, m);
+ return os;
+}
+
+}
+
+#endif