container_maps.h
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * @author phesch ( ulila at student dot kit dot edu )
17 * @date 2022
18 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
19 * GNU General Public License
20 */
21
22#pragma once
23
24#include <map>
25#include <optional>
26#include <tuple>
27
29
30namespace armarx::armem
31{
32
33 namespace detail
34 {
35
36 /**
37 * @brief Get the entry in the map for which the returned key is the longest prefix
38 * of the given key among the keys in the map.
39 *
40 * `prefixFunc` is used to successively calculate the prefixes of the given key.
41 * It must be pure and return an empty optional when there is no shorter
42 * prefix of the given key (for strings, this would be the case when passed the empty string).
43 *
44 * @param keyValMap the map that contains the key-value-pairs to search
45 * @param prefixFunc the function that returns the longest non-identical prefix of the key
46 * @param key the key to calculate the prefixes of
47 *
48 * @return The iterator pointing to the found entry, or `keyValMap.end()`.
49 */
50 template <typename KeyT, typename ValueT>
51 typename std::map<KeyT, ValueT>::const_iterator
52 findEntryWithLongestPrefix(const std::map<KeyT, ValueT>& keyValMap,
53 const std::function<std::optional<KeyT>(KeyT&)>& prefixFunc,
54 const KeyT& key)
55 {
56 std::optional<KeyT> curKey = key;
57
58 typename std::map<KeyT, ValueT>::const_iterator result = keyValMap.end();
59 do
60 {
61 auto iterator = keyValMap.find(curKey.value());
62 if (iterator != keyValMap.end())
63 {
64 result = iterator;
65 }
66 else
67 {
68 curKey = prefixFunc(curKey.value());
69 }
70 } while (result == keyValMap.end() and curKey.has_value());
71
72 return result;
73 }
74
75 /**
76 * @brief Get the entry in the map for which the returned key is the longest prefix
77 * of the given key among the keys in the map that satisfy the predicate.
78 *
79 * `prefixFunc` is used to successively calculate the prefixes of the given key.
80 * It must be pure and return an empty optional when there is no shorter
81 * prefix of the given key (for strings, this would be the case when passed the empty string).
82 * `predicate` is used to filter for entries that satisfy the desired condition.
83 * It must be pure.
84 *
85 * @param keyValMap the map that contains the key-value-pairs to search
86 * @param prefixFunc the function that returns the longest non-identical prefix of the key
87 * @param predicate the predicate to filter entries on
88 * @param key the key to calculate the prefixes of
89 *
90 * @return The iterator pointing to the found entry, or `keyValMap.end()`.
91 */
92 template <typename KeyT, typename ValueT>
93 typename std::map<KeyT, ValueT>::const_iterator
95 const std::map<KeyT, ValueT>& keyValMap,
96 const std::function<std::optional<KeyT>(KeyT&)>& prefixFunc,
97 const KeyT& key,
98 const std::function<bool(const KeyT&, const ValueT&)>& predicate)
99 {
100 std::optional<KeyT> curKey = key;
101
102 typename std::map<KeyT, ValueT>::const_iterator result = keyValMap.end();
103 do
104 {
105 auto iterator = keyValMap.find(curKey.value());
106 if (iterator != keyValMap.end() and predicate(iterator->first, iterator->second))
107 {
108 result = iterator;
109 }
110 else
111 {
112 curKey = prefixFunc(curKey.value());
113 }
114 } while (result == keyValMap.end() and curKey.has_value());
115
116 return result;
117 }
118
119 /**
120 * @brief Accumulate all the values in a map for which the keys are prefixes of the given key.
121 *
122 * `AccumulateT` is a type that the values will be accumulated into using `accumulateFunc`.
123 * `accumulateFunc` is a function that modifies the given accumulator
124 * (by, e.g., adding the given value to it).
125 *
126 * The values are accumulated in order from the longest key to the shortest.
127 *
128 * @see `getWithLongestPrefix` for a description of `prefixFunc`
129 * @param keyValMap the map that contains the key-value-pairs to search
130 * @param prefixFunc the function that returns the longest non-identical prefix of the key
131 * @param accumulateFunc the function that accumulates the values in the accumulator
132 * @param key the key to calculate the prefixes of
133 */
134 template <typename KeyT, typename ValueT, typename AccumulateT>
135 AccumulateT
137 const std::map<KeyT, ValueT>& keyValMap,
138 const std::function<std::optional<KeyT>(const KeyT&)>& prefixFunc,
139 const std::function<void(AccumulateT&, const ValueT&)> accumulateFunc,
140 const KeyT& key)
141 {
142 std::optional<KeyT> curKey = key;
143 AccumulateT values;
144 do
145 {
146 const auto nextEntry =
147 findEntryWithLongestPrefix<KeyT, ValueT>(keyValMap, prefixFunc, curKey.value());
148 if (nextEntry != keyValMap.end())
149 {
150 curKey = prefixFunc(nextEntry->first);
151 accumulateFunc(values, nextEntry->second);
152 }
153 else
154 {
155 curKey.reset();
156 }
157 } while (curKey.has_value());
158
159 return values;
160 }
161
162 /**
163 * @brief Collect all the values in a map for which the keys are prefixes of the given key.
164 *
165 * This is a specialization of the general `accumulateFromPrefixes`
166 * for collecting single values into a vector.
167 *
168 * @see `accumulateFromPrefixes` for a detailed description
169 * @param keyValMap the map that contains the key-value-pairs to search
170 * @param prefixFunc the function that returns the longest non-identical prefix of the key
171 * @param key the key to calculate the prefixes of
172 */
173 template <typename KeyT, typename ValueT>
174 std::vector<ValueT>
175 accumulateFromPrefixes(const std::map<KeyT, ValueT>& keyValMap,
176 const std::function<std::optional<KeyT>(const KeyT&)>& prefixFunc,
177 const KeyT& key)
178 {
180 keyValMap,
181 prefixFunc,
182 [](std::vector<ValueT>& values, const ValueT& val) { values.push_back(val); },
183 key);
184 }
185
186 /**
187 * @brief Collect all the values in a map for which the keys are prefixes of the given key.
188 *
189 * This is a specialization of the general `accumulateFromPrefixes`
190 * for appending vector values into a single vector.
191 *
192 * @see `accumulateFromPrefixes` for a detailed description
193 * @param keyValMap the map that contains the key-value-pairs to search
194 * @param prefixFunc the function that returns the longest non-identical prefix of the key
195 * @param key the key to calculate the prefixes of
196 */
197 template <typename KeyT, typename ValueT>
198 std::vector<ValueT>
199 accumulateFromPrefixes(const std::map<KeyT, std::vector<ValueT>>& keyValMap,
200 const std::function<std::optional<KeyT>(const KeyT&)>& prefixFunc,
201 const KeyT& key)
202 {
203 return accumulateFromPrefixes<KeyT, std::vector<ValueT>, std::vector<ValueT>>(
204 keyValMap,
205 prefixFunc,
206 [](std::vector<ValueT>& values, const std::vector<ValueT>& val)
207 { values.insert(values.end(), val.begin(), val.end()); },
208 key);
209 }
210
211 } // namespace detail
212
213 std::optional<MemoryID> inline getMemoryIDParent(const MemoryID& memID)
214 {
215 if (!memID.hasMemoryName())
216 {
217 return std::nullopt;
218 }
219 MemoryID parent = memID.removeLeafItem();
220 return {parent};
221 }
222
223 /**
224 * @brief Find the entry with the most specific key that contains the given ID,
225 * or `idMap.end()` if no key contains the ID.
226 *
227 * @see `detail::findEntryWithLongestPrefix()`
228 */
229 template <typename ValueT>
230 typename std::map<MemoryID, ValueT>::const_iterator
231 findMostSpecificEntryContainingID(const std::map<MemoryID, ValueT>& idMap, const MemoryID& id)
232 {
234 }
235
236 /**
237 * @brief Find the entry with the most specific key that contains the given ID
238 * and satisfies the predicate, or `idMap.end()` if no key contains the ID and satisfies
239 * the predicate.
240 *
241 * @see `detail::findEntryWithLongestPrefixAnd()`
242 */
243 template <typename ValueT>
244 typename std::map<MemoryID, ValueT>::const_iterator
246 const std::map<MemoryID, ValueT>& idMap,
247 const MemoryID& id,
248 const std::function<bool(const MemoryID&, const ValueT&)>& predicate)
249 {
251 idMap, &getMemoryIDParent, id, predicate);
252 }
253
254 /**
255 * @brief Return all values of keys containing the given ID.
256 *
257 * @see `detail::accumulateFromPrefixes()`
258 */
259 template <typename ValueT>
260 std::vector<ValueT>
261 accumulateEntriesContainingID(const std::map<MemoryID, ValueT>& idMap, const MemoryID& id)
262 {
264 }
265
266 /**
267 * @brief Return all values of keys containing the given ID in a flattened vector.
268 *
269 * @see `detail::accumulateFromPrefixes()`
270 */
271 template <typename ValueT>
272 std::vector<ValueT>
273 accumulateEntriesContainingID(const std::map<MemoryID, std::vector<ValueT>>& idMap,
274 const MemoryID& key)
275 {
277 }
278
279
280} // namespace armarx::armem
bool hasMemoryName() const
Definition MemoryID.h:103
MemoryID removeLeafItem() const
Definition MemoryID.cpp:334
AccumulateT accumulateFromPrefixes(const std::map< KeyT, ValueT > &keyValMap, const std::function< std::optional< KeyT >(const KeyT &)> &prefixFunc, const std::function< void(AccumulateT &, const ValueT &)> accumulateFunc, const KeyT &key)
Accumulate all the values in a map for which the keys are prefixes of the given key.
std::map< KeyT, ValueT >::const_iterator findEntryWithLongestPrefix(const std::map< KeyT, ValueT > &keyValMap, const std::function< std::optional< KeyT >(KeyT &)> &prefixFunc, const KeyT &key)
Get the entry in the map for which the returned key is the longest prefix of the given key among the ...
std::map< KeyT, ValueT >::const_iterator findEntryWithLongestPrefixAnd(const std::map< KeyT, ValueT > &keyValMap, const std::function< std::optional< KeyT >(KeyT &)> &prefixFunc, const KeyT &key, const std::function< bool(const KeyT &, const ValueT &)> &predicate)
Get the entry in the map for which the returned key is the longest prefix of the given key among the ...
std::vector< ValueT > accumulateEntriesContainingID(const std::map< MemoryID, ValueT > &idMap, const MemoryID &id)
Return all values of keys containing the given ID.
std::optional< MemoryID > getMemoryIDParent(const MemoryID &memID)
std::map< MemoryID, ValueT >::const_iterator findMostSpecificEntryContainingID(const std::map< MemoryID, ValueT > &idMap, const MemoryID &id)
Find the entry with the most specific key that contains the given ID, or idMap.end() if no key contai...
std::map< MemoryID, ValueT >::const_iterator findMostSpecificEntryContainingIDAnd(const std::map< MemoryID, ValueT > &idMap, const MemoryID &id, const std::function< bool(const MemoryID &, const ValueT &)> &predicate)
Find the entry with the most specific key that contains the given ID and satisfies the predicate,...