291 lines
7.3 KiB
C++
291 lines
7.3 KiB
C++
/*
|
|
* Copyright 2015 - 2025 gary@drinkingtea.net
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "def.hpp"
|
|
#include "hash.hpp"
|
|
#include "ignore.hpp"
|
|
#include "stringview.hpp"
|
|
#include "strops.hpp"
|
|
#include "vector.hpp"
|
|
|
|
namespace ox {
|
|
|
|
template<typename K, typename T, size_t SmallSz = 0>
|
|
class SmallMap {
|
|
|
|
public:
|
|
using key_t = K;
|
|
using value_t = T;
|
|
struct Pair {
|
|
K key = {};
|
|
T value{};
|
|
};
|
|
|
|
protected:
|
|
using PairVector = Vector<Pair, SmallSz>;
|
|
PairVector m_pairs;
|
|
|
|
public:
|
|
constexpr SmallMap() = default;
|
|
|
|
constexpr SmallMap(SmallMap const&other);
|
|
|
|
constexpr SmallMap(SmallMap &&other) noexcept;
|
|
|
|
constexpr bool operator==(SmallMap const&other) const;
|
|
|
|
constexpr SmallMap &operator=(SmallMap const&other);
|
|
|
|
constexpr SmallMap &operator=(SmallMap &&other) noexcept;
|
|
|
|
constexpr T &operator[](MaybeView_t<K> const&key);
|
|
|
|
constexpr Result<T*> at(MaybeView_t<K> const&key) noexcept;
|
|
|
|
constexpr Result<const T*> at(MaybeView_t<K> const&key) const noexcept;
|
|
|
|
constexpr void erase(MaybeView_t<K> const&key);
|
|
|
|
[[nodiscard]]
|
|
constexpr bool contains(MaybeView_t<K> const&key) const noexcept;
|
|
|
|
[[nodiscard]]
|
|
constexpr std::size_t size() const noexcept;
|
|
|
|
[[nodiscard]]
|
|
constexpr Vector<K> keys() const noexcept;
|
|
|
|
[[nodiscard]]
|
|
constexpr Vector<T> values() const noexcept;
|
|
|
|
[[nodiscard]]
|
|
constexpr K const&key(size_t i) const noexcept;
|
|
|
|
[[nodiscard]]
|
|
constexpr T const&value(size_t i) const noexcept;
|
|
|
|
[[nodiscard]]
|
|
constexpr T &value(size_t i) noexcept;
|
|
|
|
[[nodiscard]]
|
|
constexpr Pair const&get(size_t i) const noexcept;
|
|
|
|
[[nodiscard]]
|
|
constexpr Pair &get(size_t i) noexcept;
|
|
|
|
[[nodiscard]]
|
|
constexpr ox::SpanView<Pair> pairs() const noexcept {
|
|
return m_pairs;
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr ox::Span<Pair> pairs() noexcept {
|
|
return m_pairs;
|
|
}
|
|
|
|
constexpr void clear();
|
|
|
|
private:
|
|
template<typename KK>
|
|
constexpr Pair const*access(PairVector const&pairs, KK const&key, bool &isNew) const;
|
|
|
|
template<typename KK>
|
|
constexpr Pair *access(PairVector &pairs, KK const&key, bool &isNew);
|
|
|
|
template<typename KK>
|
|
constexpr Pair *accessNoCreate(PairVector &pairs, KK const&key);
|
|
|
|
};
|
|
|
|
template<typename K, typename T, size_t SmallSz>
|
|
constexpr SmallMap<K, T, SmallSz>::SmallMap(SmallMap<K, T, SmallSz> const&other) {
|
|
m_pairs = other.m_pairs;
|
|
}
|
|
|
|
template<typename K, typename T, size_t SmallSz>
|
|
constexpr SmallMap<K, T, SmallSz>::SmallMap(SmallMap<K, T, SmallSz> &&other) noexcept {
|
|
m_pairs = std::move(other.m_pairs);
|
|
}
|
|
|
|
template<typename K, typename T, size_t SmallSz>
|
|
constexpr bool SmallMap<K, T, SmallSz>::operator==(SmallMap const&other) const {
|
|
return m_pairs == other.m_pairs;
|
|
}
|
|
|
|
template<typename K, typename T, size_t SmallSz>
|
|
constexpr SmallMap<K, T, SmallSz> &SmallMap<K, T, SmallSz>::operator=(SmallMap<K, T, SmallSz> const&other) {
|
|
if (this != &other) {
|
|
clear();
|
|
m_pairs = other.m_pairs;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
template<typename K, typename T, size_t SmallSz>
|
|
constexpr SmallMap<K, T, SmallSz> &SmallMap<K, T, SmallSz>::operator=(SmallMap<K, T, SmallSz> &&other) noexcept {
|
|
if (this != &other) {
|
|
clear();
|
|
m_pairs = std::move(other.m_pairs);
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
template<typename K, typename T, size_t SmallSz>
|
|
constexpr T &SmallMap<K, T, SmallSz>::operator[](MaybeView_t<K> const&k) {
|
|
bool isNew{};
|
|
auto p = access(m_pairs, k, isNew);
|
|
if (isNew) {
|
|
p->key = k;
|
|
}
|
|
return p->value;
|
|
}
|
|
|
|
template<typename K, typename T, size_t SmallSz>
|
|
constexpr Result<T*> SmallMap<K, T, SmallSz>::at(MaybeView_t<K> const&k) noexcept {
|
|
auto const p = accessNoCreate(m_pairs, k);
|
|
if (!p) {
|
|
return {nullptr, ox::Error(1, "value not found for given key")};
|
|
}
|
|
return &p->value;
|
|
}
|
|
|
|
template<typename K, typename T, size_t SmallSz>
|
|
constexpr Result<const T*> SmallMap<K, T, SmallSz>::at(MaybeView_t<K> const&k) const noexcept {
|
|
bool isNew{};
|
|
auto p = access(m_pairs, k, isNew);
|
|
if (!p) {
|
|
return {nullptr, ox::Error(1, "value not found for given key")};
|
|
}
|
|
return &p->value;
|
|
}
|
|
|
|
template<typename K, typename T, size_t SmallSz>
|
|
constexpr void SmallMap<K, T, SmallSz>::erase(MaybeView_t<K> const&k) {
|
|
size_t i{};
|
|
for (auto const&p : m_pairs) {
|
|
if (k == p.key) {
|
|
break;
|
|
}
|
|
++i;
|
|
}
|
|
std::ignore = m_pairs.erase(i);
|
|
}
|
|
|
|
template<typename K, typename T, size_t SmallSz>
|
|
constexpr bool SmallMap<K, T, SmallSz>::contains(MaybeView_t<K> const&k) const noexcept {
|
|
bool isNew{};
|
|
return access(m_pairs, k, isNew) != nullptr;
|
|
}
|
|
|
|
template<typename K, typename T, size_t SmallSz>
|
|
constexpr std::size_t SmallMap<K, T, SmallSz>::size() const noexcept {
|
|
return m_pairs.size();
|
|
}
|
|
|
|
template<typename K, typename T, size_t SmallSz>
|
|
constexpr Vector<K> SmallMap<K, T, SmallSz>::keys() const noexcept {
|
|
ox::Vector<K> keys;
|
|
keys.reserve(m_pairs.size());
|
|
for (auto const&p : m_pairs) {
|
|
keys.emplace_back(p.key);
|
|
}
|
|
return keys;
|
|
}
|
|
|
|
template<typename K, typename T, size_t SmallSz>
|
|
constexpr Vector<T> SmallMap<K, T, SmallSz>::values() const noexcept {
|
|
ox::Vector<T> keys;
|
|
keys.reserve(m_pairs.size());
|
|
for (auto const&p : m_pairs) {
|
|
keys.emplace_back(p.key);
|
|
}
|
|
return keys;
|
|
}
|
|
|
|
template<typename K, typename T, size_t SmallSz>
|
|
constexpr K const&SmallMap<K, T, SmallSz>::key(size_t i) const noexcept {
|
|
return m_pairs[i].key;
|
|
}
|
|
|
|
template<typename K, typename T, size_t SmallSz>
|
|
constexpr T const&SmallMap<K, T, SmallSz>::value(size_t i) const noexcept {
|
|
return m_pairs[i].value;
|
|
}
|
|
|
|
template<typename K, typename T, size_t SmallSz>
|
|
constexpr T &SmallMap<K, T, SmallSz>::value(size_t i) noexcept {
|
|
return m_pairs[i].value;
|
|
}
|
|
|
|
template<typename K, typename T, size_t SmallSz>
|
|
constexpr typename SmallMap<K, T, SmallSz>::Pair const&SmallMap<K, T, SmallSz>::get(size_t i) const noexcept {
|
|
return m_pairs[i];
|
|
}
|
|
|
|
template<typename K, typename T, size_t SmallSz>
|
|
constexpr typename SmallMap<K, T, SmallSz>::Pair &SmallMap<K, T, SmallSz>::get(size_t i) noexcept {
|
|
return m_pairs[i];
|
|
}
|
|
|
|
template<typename K, typename T, size_t SmallSz>
|
|
constexpr void SmallMap<K, T, SmallSz>::clear() {
|
|
m_pairs.clear();
|
|
}
|
|
|
|
template<typename K, typename T, size_t SmallSz>
|
|
template<typename KK>
|
|
constexpr typename SmallMap<K, T, SmallSz>::Pair const*SmallMap<K, T, SmallSz>::access(
|
|
PairVector const&pairs, KK const&k, bool &isNew) const {
|
|
for (auto const&p : pairs) {
|
|
if (p.key == k) {
|
|
isNew = false;
|
|
return &p;
|
|
}
|
|
}
|
|
isNew = true;
|
|
return nullptr;
|
|
}
|
|
|
|
template<typename K, typename T, size_t SmallSz>
|
|
template<typename KK>
|
|
constexpr typename SmallMap<K, T, SmallSz>::Pair *SmallMap<K, T, SmallSz>::access(
|
|
PairVector &pairs, KK const&k, bool &isNew) {
|
|
for (auto &p : pairs) {
|
|
if (p.key == k) {
|
|
isNew = false;
|
|
return &p;
|
|
}
|
|
}
|
|
isNew = true;
|
|
return &pairs.emplace_back();
|
|
}
|
|
|
|
template<typename K, typename T, size_t SmallSz>
|
|
template<typename KK>
|
|
constexpr typename SmallMap<K, T, SmallSz>::Pair *SmallMap<K, T, SmallSz>::accessNoCreate(
|
|
PairVector &pairs, KK const&k) {
|
|
for (auto &p : pairs) {
|
|
if (p.key == k) {
|
|
return &p;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
template<typename T, typename K, typename V, size_t SmallSz>
|
|
constexpr Error model(T *io, ox::CommonPtrWith<SmallMap<K, V, SmallSz>> auto *obj) noexcept {
|
|
using Map = SmallMap<K, V, SmallSz>;
|
|
OX_RETURN_ERROR(io->template setTypeInfo<Map>());
|
|
OX_RETURN_ERROR(io->field("pairs", &obj->m_pairs));
|
|
return {};
|
|
}
|
|
|
|
}
|