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 : : typename std::vector<TValue>::iterator begin() { return m_array.begin(); }
60 : : typename std::vector<TValue>::const_iterator begin() const { return m_array.begin(); }
61 : : typename std::vector<TValue>::iterator end() { return m_array.end(); }
62 : : typename std::vector<TValue>::const_iterator end() const { return m_array.end(); }
63 : 4 : bool exist(const TKey& vKey) const { return (m_dico.find(vKey) != m_dico.end()); }
64 : : TValue& value(const TKey& vKey) { return at(m_dico.at(vKey)); }
65 : : const TValue& value(const TKey& vKey) const { return at(m_dico.at(vKey)); }
66 : : void resize(const size_t vNewSize) { m_array.resize(vNewSize); }
67 : : void resize(const size_t vNewSize, const TValue& vVal) { m_array.resize(vNewSize, vVal); }
68 : : void reserve(const size_t vNewCapacity) { m_array.reserve(vNewCapacity); }
69 : : bool erase(const TKey& vKey) {
70 : : if (exist(vKey)) {
71 : : // when we erase an entry, there is as issue
72 : : // in the vector because the indexs are not more corresponding
73 : : auto idx = m_dico.at(vKey);
74 : : for (auto& it : m_dico) {
75 : : // we must modify all index greater than the index to delete
76 : : if (it.second > idx) {
77 : : --it.second;
78 : : }
79 : : }
80 : : // now we can safely erase the item from both dico and vector
81 : : m_array.erase(m_array.begin() + idx);
82 : : m_dico.erase(vKey);
83 : : return true;
84 : : }
85 : : return false;
86 : : }
87 : 3 : bool tryAdd(const TKey& vKey, const TValue& vValue) {
88 [ + + ][ + - ]: 3 : if (!exist(vKey)) {
89 : 2 : m_dico[vKey] = m_array.size();
90 : 2 : m_array.push_back(vValue);
91 : 2 : return true;
92 : 2 : }
93 : 1 : return false;
94 : 3 : }
95 : : template <typename = std::enable_if<std::is_same<TKey, TValue>::value>>
96 : 1 : bool tryAdd(const TKey& vKeyValue) { return tryAdd(vKeyValue, vKeyValue); }
97 : 1 : bool trySetExisting(const TKey& vKey, const TValue& vValue) {
98 [ + - ]: 1 : if (exist(vKey)) {
99 : 1 : auto row = m_dico.at(vKey);
100 : 1 : m_array[row] = vValue;
101 : 1 : return true;
102 : 1 : }
103 : 0 : return false;
104 : 1 : }
105 : : template <typename = std::enable_if<std::is_same<TKey, TValue>::value>>
106 : : bool trySetExisting(const TKey& vKeyValue) { return trySetExisting(vKeyValue, vKeyValue); }
107 : : // the merge can be partialy done, if already key was existing
108 : : bool tryMerge(const DicoVector<TKey, TValue>& vDico) {
109 : : bool ret = false;
110 : : for (const auto& it : vDico.m_dico) {
111 : : ret |= tryAdd(it.first, vDico.at(it.second));
112 : : }
113 : : return ret;
114 : : }
115 : : };
116 : :
117 : : } // namespace cnt
118 : : } // namespace ez
|