summaryrefslogtreecommitdiffstats
path: root/xbmc/utils/Map.h
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/utils/Map.h')
-rw-r--r--xbmc/utils/Map.h102
1 files changed, 102 insertions, 0 deletions
diff --git a/xbmc/utils/Map.h b/xbmc/utils/Map.h
new file mode 100644
index 0000000..17af545
--- /dev/null
+++ b/xbmc/utils/Map.h
@@ -0,0 +1,102 @@
+
+/*
+ * Copyright (C) 2005-2022 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include <algorithm>
+#include <array>
+#include <stdexcept>
+
+/*!
+ * \brief This class is designed to implement a constexpr version of std::map.
+ * The standard library std::map doesn't allow constexpr (and it
+ * doesn't look like it will be implemented in the future). This class
+ * utilizes std::array and std::pair as they allow constexpr.
+ *
+ * When using this class you should use the helper make_map instead of
+ * constructing this class directly. For example:
+ * constexpr auto myMap = make_map<int, std::string_view>({{1, "one"}});
+ *
+ * This class is useful for mapping enum values to strings that can be
+ * compile time checked. This also helps with heap usage.
+ *
+ * Lookups have linear complexity, so should not be used for "big" maps.
+ */
+template<typename Key, typename Value, size_t Size>
+class CMap
+{
+public:
+ template<typename Iterable>
+ constexpr CMap(Iterable begin, Iterable end)
+ {
+ size_t index = 0;
+ while (begin != end)
+ {
+ // c++17 doesn't have constexpr assignment operator for std::pair
+ auto& first = m_map[index].first;
+ auto& second = m_map[index].second;
+ ++index;
+
+ first = std::move(begin->first);
+ second = std::move(begin->second);
+ ++begin;
+
+ //! @todo: c++20 can use constexpr assignment operator instead
+ // auto& p = data[index];
+ // ++index;
+
+ // p = std::move(*begin);
+ // ++begin;
+ //
+ }
+ }
+
+ ~CMap() = default;
+
+ constexpr const Value& at(const Key& key) const
+ {
+ const auto it = find(key);
+ if (it != m_map.cend())
+ {
+ return it->second;
+ }
+ else
+ {
+ throw std::range_error("Not Found");
+ }
+ }
+
+ constexpr auto find(const Key& key) const
+ {
+ return std::find_if(m_map.cbegin(), m_map.cend(),
+ [&key](const auto& pair) { return pair.first == key; });
+ }
+
+ constexpr size_t size() const { return Size; }
+
+ constexpr auto cbegin() const { return m_map.cbegin(); }
+ constexpr auto cend() const { return m_map.cend(); }
+
+private:
+ CMap() = delete;
+
+ std::array<std::pair<Key, Value>, Size> m_map;
+};
+
+/*!
+ * \brief Use this helper when wanting to use CMap. This is needed to allow
+ * deducing the size of the map from the initializer list without
+ * needing to explicitly give the size of the map (similar to std::map).
+ *
+ */
+template<typename Key, typename Value, std::size_t Size>
+constexpr auto make_map(std::pair<Key, Value>(&&m)[Size]) -> CMap<Key, Value, Size>
+{
+ return CMap<Key, Value, Size>(std::begin(m), std::end(m));
+}