Branch data Line data Source code
1 : : #pragma once
2 : :
3 : : /*
4 : : MIT License
5 : :
6 : : Copyright (c) 2014-2024 Stephane Cuillerdier (aka aiekick)
7 : :
8 : : Permission is hereby granted, free of charge, to any person obtaining a copy
9 : : of this software and associated documentation files (the "Software"), to deal
10 : : in the Software without restriction, including without limitation the rights
11 : : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 : : copies of the Software, and to permit persons to whom the Software is
13 : : furnished to do so, subject to the following conditions:
14 : :
15 : : The above copyright notice and this permission notice shall be included in all
16 : : copies or substantial portions of the Software.
17 : :
18 : : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 : : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 : : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 : : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 : : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 : : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 : : SOFTWARE.
25 : : */
26 : :
27 : : // ezBmp is part of the ezLibs project : https://github.com/aiekick/ezLibs.git
28 : :
29 : : #include <string>
30 : : #include <vector>
31 : : #include <unordered_map>
32 : :
33 : : namespace ez {
34 : : namespace cnt {
35 : :
36 : : // this class can be indexed like a vector
37 : : // and searched in like a dico
38 : : template <typename TKey, typename TValue = TKey>
39 : : class DicoVector {
40 : : protected:
41 : : std::unordered_map<TKey, size_t> m_dico;
42 : : std::vector<TValue> m_array;
43 : :
44 : : public:
45 : : void clear() {
46 : : m_dico.clear();
47 : : m_array.clear();
48 : : }
49 : : bool empty() const { return m_array.empty(); }
50 : : size_t size() const { return m_array.size(); }
51 : : TValue& operator[](const size_t& vIdx) { return m_array[vIdx]; }
52 : : TValue& at(const size_t& vIdx) { return m_array.at(vIdx); }
53 : : const TValue& operator[](const size_t& vIdx) const { return m_array[vIdx]; }
54 : : const TValue& at(const size_t& vIdx) const { return m_array.at(vIdx); }
55 : : std::unordered_map<TKey, size_t>& getDico() { return m_dico; }
56 : : const std::unordered_map<TKey, size_t>& getDico() const { return m_dico; }
57 : : std::vector<TValue>& getArray() { return m_array; }
58 : : const std::vector<TValue>& getArray() const { return m_array; }
59 : : TValue& front() { return m_array.front(); }
60 : : const TValue& front() const { return m_array.front(); }
61 : : TValue& back() { return m_array.front(); }
62 : : const TValue& back() const { return m_array.back(); }
63 : : typename std::vector<TValue>::iterator begin() { return m_array.begin(); }
64 : : typename std::vector<TValue>::const_iterator begin() const { return m_array.begin(); }
65 : : typename std::vector<TValue>::iterator end() { return m_array.end(); }
66 : : typename std::vector<TValue>::const_iterator end() const { return m_array.end(); }
67 : 4 : bool exist(const TKey& vKey) const { return (m_dico.find(vKey) != m_dico.end()); }
68 : : TValue& value(const TKey& vKey) { return at(m_dico.at(vKey)); }
69 : : const TValue& value(const TKey& vKey) const { return at(m_dico.at(vKey)); }
70 : : void resize(const size_t vNewSize) { m_array.resize(vNewSize); }
71 : : void resize(const size_t vNewSize, const TValue& vVal) { m_array.resize(vNewSize, vVal); }
72 : : void reserve(const size_t vNewCapacity) { m_array.reserve(vNewCapacity); }
73 : : bool erase(const TKey& vKey) {
74 : : if (exist(vKey)) {
75 : : // when we erase an entry, there is as issue
76 : : // in the vector because the indexs are not more corresponding
77 : : auto idx = m_dico.at(vKey);
78 : : for (auto& it : m_dico) {
79 : : // we must modify all index greater than the index to delete
80 : : if (it.second > idx) {
81 : : --it.second;
82 : : }
83 : : }
84 : : // now we can safely erase the item from both dico and vector
85 : : m_array.erase(m_array.begin() + idx);
86 : : m_dico.erase(vKey);
87 : : return true;
88 : : }
89 : : return false;
90 : : }
91 : 3 : bool tryAdd(const TKey& vKey, const TValue& vValue) {
92 [ + + ][ + - ]: 3 : if (!exist(vKey)) {
93 : 2 : m_dico[vKey] = m_array.size();
94 : 2 : m_array.push_back(vValue);
95 : 2 : return true;
96 : 2 : }
97 : 1 : return false;
98 : 3 : }
99 : : template <typename = std::enable_if<std::is_same<TKey, TValue>::value>>
100 : 1 : bool tryAdd(const TKey& vKeyValue) { return tryAdd(vKeyValue, vKeyValue); }
101 : 1 : bool trySetExisting(const TKey& vKey, const TValue& vValue) {
102 [ + - ]: 1 : if (exist(vKey)) {
103 : 1 : auto row = m_dico.at(vKey);
104 : 1 : m_array[row] = vValue;
105 : 1 : return true;
106 : 1 : }
107 : 0 : return false;
108 : 1 : }
109 : : template <typename = std::enable_if<std::is_same<TKey, TValue>::value>>
110 : : bool trySetExisting(const TKey& vKeyValue) { return trySetExisting(vKeyValue, vKeyValue); }
111 : : // the merge can be partialy done, if already key was existing
112 : : bool tryMerge(const DicoVector<TKey, TValue>& vDico) {
113 : : bool ret = false;
114 : : for (const auto& it : vDico.m_dico) {
115 : : ret |= tryAdd(it.first, vDico.at(it.second));
116 : : }
117 : : return ret;
118 : : }
119 : : };
120 : :
121 : : } // namespace cnt
122 : : } // namespace ez
|