diff options
author | George L. Albany <Megacake1234@gmail.com> | 2024-01-01 04:32:01 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-01-01 04:32:01 +0100 |
commit | 9988b21278dc1c8df044631bd2935a7e450a7bff (patch) | |
tree | ba081f9f4d74865ab5851a2efd560745900ca81a /src/openvic-simulation/utility | |
parent | 0a425fbe05d6138b753c0e4a7c06f06695bde8af (diff) | |
parent | e1496a87178d925277aceed0ebcbab06920e15ee (diff) |
Merge pull request #105 from OpenVicProject/add/ordered-map
Diffstat (limited to 'src/openvic-simulation/utility')
-rw-r--r-- | src/openvic-simulation/utility/BMP.cpp | 3 | ||||
-rw-r--r-- | src/openvic-simulation/utility/TslHelper.hpp | 129 | ||||
-rw-r--r-- | src/openvic-simulation/utility/Utility.hpp | 48 |
3 files changed, 179 insertions, 1 deletions
diff --git a/src/openvic-simulation/utility/BMP.cpp b/src/openvic-simulation/utility/BMP.cpp index 4c220da..c615aea 100644 --- a/src/openvic-simulation/utility/BMP.cpp +++ b/src/openvic-simulation/utility/BMP.cpp @@ -3,6 +3,7 @@ #include <cstring> #include <set> +#include "openvic-simulation/types/OrderedContainers.hpp" #include "openvic-simulation/utility/Logger.hpp" using namespace OpenVic; @@ -91,7 +92,7 @@ bool BMP::read_header() { // Validate colours #define VALID_BITS_PER_PIXEL 1, 2, 4, 8, 16, 24, 32 #define STR(x) #x - static const std::set<uint16_t> BITS_PER_PIXEL { VALID_BITS_PER_PIXEL }; + static const ordered_set<uint16_t> BITS_PER_PIXEL { VALID_BITS_PER_PIXEL }; if (!BITS_PER_PIXEL.contains(header.bits_per_pixel)) { Logger::error("Invalid BMP bits per pixel: ", header.bits_per_pixel, " (must be one of " STR(VALID_BITS_PER_PIXEL) ")"); header_validated = false; diff --git a/src/openvic-simulation/utility/TslHelper.hpp b/src/openvic-simulation/utility/TslHelper.hpp new file mode 100644 index 0000000..9d1ae77 --- /dev/null +++ b/src/openvic-simulation/utility/TslHelper.hpp @@ -0,0 +1,129 @@ +#pragma once + +#include <type_traits> + +#include <tsl/ordered_map.h> +#include <tsl/ordered_set.h> + +#include "openvic-simulation/types/OrderedContainers.hpp" +#include "openvic-simulation/utility/Utility.hpp" + +namespace OpenVic { + template<IsOrderedMap Map, typename Key = typename Map::key_type, typename Mapped = typename Map::mapped_type> + struct _OrderedMapMutable { + using map_type = Map; + struct ordered_iterator { + using key_type = Key; + using mapped_type = Mapped; + using pair_type = std::pair<key_type const&, mapped_type&>; + using value_type = pair_type; + using iterator = typename map_type::iterator; + + using iterator_category = std::random_access_iterator_tag; + using difference_type = typename map_type::values_container_type::iterator::difference_type; + + pair_type operator*() { + return { m_iterator.key(), m_iterator.value() }; + } + + ordered_iterator& operator++() { + ++m_iterator; + return *this; + } + ordered_iterator& operator--() { + --m_iterator; + return *this; + } + + ordered_iterator operator++(int) { + ordered_iterator tmp(*this); + ++(*this); + return tmp; + } + ordered_iterator operator--(int) { + ordered_iterator tmp(*this); + --(*this); + return tmp; + } + + pair_type operator[](difference_type n) { + return *(*this + n); + } + + ordered_iterator& operator+=(difference_type n) { + m_iterator += n; + return *this; + } + ordered_iterator& operator-=(difference_type n) { + m_iterator -= n; + return *this; + } + + ordered_iterator operator+(difference_type n) { + ordered_iterator tmp(*this); + tmp += n; + return tmp; + } + ordered_iterator operator-(difference_type n) { + ordered_iterator tmp(*this); + tmp -= n; + return tmp; + } + + bool operator==(const ordered_iterator& rhs) const { + return m_iterator == rhs.m_iterator; + } + + bool operator!=(const ordered_iterator& rhs) const { + return m_iterator != rhs.m_iterator; + } + + bool operator<(const ordered_iterator& rhs) const { + return m_iterator < rhs.m_iterator; + } + + bool operator>(const ordered_iterator& rhs) const { + return m_iterator > rhs.m_iterator; + } + + bool operator<=(const ordered_iterator& rhs) const { + return m_iterator <= rhs.m_iterator; + } + + bool operator>=(const ordered_iterator& rhs) const { + return m_iterator >= rhs.m_iterator; + } + + friend ordered_iterator operator+(difference_type n, const ordered_iterator& it) { + return n + it.m_iterator; + } + + ordered_iterator operator+(const ordered_iterator& rhs) const { + return m_iterator + rhs.m_iterator; + } + + difference_type operator-(const ordered_iterator& rhs) const { + return m_iterator - rhs.m_iterator; + } + + iterator m_iterator; + }; + + _OrderedMapMutable(map_type& map) : _map(map) {} + + ordered_iterator begin() { + return ordered_iterator { _map.begin() }; + } + ordered_iterator end() { + return ordered_iterator { _map.end() }; + } + + private: + map_type& _map; + }; + + template<IsOrderedMap Map, typename Key = typename Map::key_type, typename Mapped = typename Map::mapped_type> + _OrderedMapMutable<Map, Key, Mapped> mutable_iterator(Map& map) { + return _OrderedMapMutable<Map, Key, Mapped> { map }; + } +} diff --git a/src/openvic-simulation/utility/Utility.hpp b/src/openvic-simulation/utility/Utility.hpp index e8d7205..0387e7f 100644 --- a/src/openvic-simulation/utility/Utility.hpp +++ b/src/openvic-simulation/utility/Utility.hpp @@ -1,5 +1,9 @@ #pragma once +#include <climits> +#include <functional> +#include <type_traits> + namespace OpenVic::utility { [[noreturn]] inline void unreachable() { // Uses compiler specific extensions if possible. @@ -11,4 +15,48 @@ namespace OpenVic::utility { __assume(false); #endif } + + template<class T> + constexpr inline void hash_combine(std::size_t& s, const T& v) { + std::hash<T> h; + s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2); + } + + template<size_t Shift, class T> + constexpr inline void hash_combine_index(std::size_t& s, const T& v) { + std::hash<T> h; + if constexpr(Shift == 0) { + s = h(v); + } else { + s ^= h(v) << Shift; + } + } + + template<class T, typename ...Args> + constexpr void perfect_hash(std::size_t& s, T&& v, Args&&... args) { + static_assert(sizeof(T) + (sizeof(Args) + ...) <= sizeof(std::size_t), "Perfect hashes must be able to fit into size_t"); + std::hash<T> h; + if constexpr(sizeof...(args) == 0) { + s = h(v); + } else { + const std::tuple arg_tuple { args... }; + s = h(v) << (sizeof(T) * CHAR_BIT); + ([&]{ + // If args is not last pointer of args + if (static_cast<const void*>(&(std::get<sizeof...(args) - 1>(arg_tuple))) != static_cast<const void*>(&args)) { + s <<= sizeof(Args) * CHAR_BIT; + } + s |= std::hash<Args>{}(args); + }(), ...); + } + } + + template<typename T, template<typename...> class Z> + struct is_specialization_of : std::false_type {}; + + template<typename... Args, template<typename...> class Z> + struct is_specialization_of<Z<Args...>, Z> : std::true_type {}; + + template<typename T, template<typename...> class Z> + inline constexpr bool is_specialization_of_v = is_specialization_of<T, Z>::value; } |