VirtualBox

source: vbox/trunk/include/iprt/cpp/reststringmap.h@ 100442

Last change on this file since 100442 was 98103, checked in by vboxsync, 21 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.1 KB
Line 
1/** @file
2 * IPRT - C++ Representational State Transfer (REST) String Map Template.
3 */
4
5/*
6 * Copyright (C) 2008-2023 Oracle and/or its affiliates.
7 *
8 * This file is part of VirtualBox base platform packages, as
9 * available from https://www.virtualbox.org.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation, in version 3 of the
14 * License.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, see <https://www.gnu.org/licenses>.
23 *
24 * The contents of this file may alternatively be used under the terms
25 * of the Common Development and Distribution License Version 1.0
26 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
27 * in the VirtualBox distribution, in which case the provisions of the
28 * CDDL are applicable instead of those of the GPL.
29 *
30 * You may elect to license modified versions of this file under the
31 * terms and conditions of either the GPL or the CDDL or both.
32 *
33 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
34 */
35
36#ifndef IPRT_INCLUDED_cpp_reststringmap_h
37#define IPRT_INCLUDED_cpp_reststringmap_h
38#ifndef RT_WITHOUT_PRAGMA_ONCE
39# pragma once
40#endif
41
42#include <iprt/list.h>
43#include <iprt/string.h>
44#include <iprt/cpp/restbase.h>
45
46
47/** @defgroup grp_rt_cpp_reststingmap C++ Representational State Transfer (REST) String Map Template
48 * @ingroup grp_rt_cpp
49 * @{
50 */
51
52/**
53 * Abstract base class for the RTCRestStringMap template.
54 */
55class RT_DECL_CLASS RTCRestStringMapBase : public RTCRestObjectBase
56{
57public:
58 /** Default destructor. */
59 RTCRestStringMapBase() RT_NOEXCEPT;
60 /** Copy constructor. */
61 RTCRestStringMapBase(RTCRestStringMapBase const &a_rThat);
62 /** Destructor. */
63 virtual ~RTCRestStringMapBase();
64 /** Copy assignment operator. */
65 RTCRestStringMapBase &operator=(RTCRestStringMapBase const &a_rThat);
66
67 /* Overridden methods: */
68 virtual RTCRestObjectBase *baseClone() const RT_NOEXCEPT RT_OVERRIDE;
69 virtual int resetToDefault() RT_NOEXCEPT RT_OVERRIDE;
70 virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT RT_OVERRIDE;
71 virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT RT_OVERRIDE;
72 // later?
73 //virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = kCollectionFormat_Unspecified) const RT_NOEXCEPT RT_OVERRIDE;
74 //virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
75 // uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_NOEXCEPT RT_OVERRIDE;
76 virtual kTypeClass typeClass(void) const RT_NOEXCEPT RT_OVERRIDE;
77 virtual const char *typeName(void) const RT_NOEXCEPT RT_OVERRIDE;
78
79 /**
80 * Clear the content of the map.
81 */
82 void clear() RT_NOEXCEPT;
83
84 /**
85 * Checks if the map is empty.
86 */
87 inline bool isEmpty() const RT_NOEXCEPT { return m_cEntries == 0; }
88
89 /**
90 * Gets the number of entries in the map.
91 */
92 size_t size() const RT_NOEXCEPT;
93
94 /**
95 * Checks if the map contains the given key.
96 * @returns true if key found, false if not.
97 * @param a_pszKey The key to check fo.
98 */
99 bool containsKey(const char *a_pszKey) const RT_NOEXCEPT;
100
101 /**
102 * Checks if the map contains the given key.
103 * @returns true if key found, false if not.
104 * @param a_rStrKey The key to check fo.
105 */
106 bool containsKey(RTCString const &a_rStrKey) const RT_NOEXCEPT;
107
108 /**
109 * Remove any key-value pair with the given key.
110 * @returns true if anything was removed, false if not found.
111 * @param a_pszKey The key to remove.
112 */
113 bool remove(const char *a_pszKey) RT_NOEXCEPT;
114
115 /**
116 * Remove any key-value pair with the given key.
117 * @returns true if anything was removed, false if not found.
118 * @param a_rStrKey The key to remove.
119 */
120 bool remove(RTCString const &a_rStrKey) RT_NOEXCEPT;
121
122 /**
123 * Creates a new value and inserts it under the given key, returning the new value.
124 *
125 * @returns VINF_SUCCESS or VWRN_ALREADY_EXISTS on success.
126 * VERR_ALREADY_EXISTS, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
127 * @param a_ppValue Where to return the pointer to the value.
128 * @param a_pszKey The key to put it under.
129 * @param a_cchKey The length of the key. Default is the entire string.
130 * @param a_fReplace Whether to replace or fail on key collision.
131 */
132 int putNewValue(RTCRestObjectBase **a_ppValue, const char *a_pszKey, size_t a_cchKey = RTSTR_MAX, bool a_fReplace = false) RT_NOEXCEPT;
133
134 /**
135 * Creates a new value and inserts it under the given key, returning the new value.
136 *
137 * @returns VINF_SUCCESS or VWRN_ALREADY_EXISTS on success.
138 * VERR_ALREADY_EXISTS, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
139 * @param a_ppValue Where to return the pointer to the value.
140 * @param a_rStrKey The key to put it under.
141 * @param a_fReplace Whether to replace or fail on key collision.
142 */
143 int putNewValue(RTCRestObjectBase **a_ppValue, RTCString const &a_rStrKey, bool a_fReplace = false) RT_NOEXCEPT;
144
145protected:
146 /** Map entry. */
147 typedef struct MapEntry
148 {
149 /** String space core. */
150 RTSTRSPACECORE Core;
151 /** List node for enumeration. */
152 RTLISTNODE ListEntry;
153 /** The key.
154 * @remarks Core.pszString points to the value of this object. So, consider it const. */
155 RTCString strKey;
156 /** The value. */
157 RTCRestObjectBase *pValue;
158 } MapEntry;
159 /** The map tree. */
160 RTSTRSPACE m_Map;
161 /** The enumeration list head (MapEntry). */
162 RTLISTANCHOR m_ListHead;
163 /** Number of map entries. */
164 size_t m_cEntries;
165
166public:
167 /** @name Map Iteration
168 * @{ */
169 /** Const iterator. */
170 class ConstIterator
171 {
172 private:
173 MapEntry *m_pCur;
174 ConstIterator() RT_NOEXCEPT;
175 protected:
176 ConstIterator(MapEntry *a_pEntry) RT_NOEXCEPT : m_pCur(a_pEntry) { }
177 public:
178 ConstIterator(ConstIterator const &a_rThat) RT_NOEXCEPT : m_pCur(a_rThat.m_pCur) { }
179
180 /** Gets the key string. */
181 inline RTCString const &getKey() RT_NOEXCEPT { return m_pCur->strKey; }
182 /** Gets poitner to the value object. */
183 inline RTCRestObjectBase const *getValue() RT_NOEXCEPT { return m_pCur->pValue; }
184
185 /** Advance to the next map entry. */
186 inline ConstIterator &operator++() RT_NOEXCEPT
187 {
188 m_pCur = RTListNodeGetNextCpp(&m_pCur->ListEntry, MapEntry, ListEntry);
189 return *this;
190 }
191
192 /** Advance to the previous map entry. */
193 inline ConstIterator &operator--() RT_NOEXCEPT
194 {
195 m_pCur = RTListNodeGetPrevCpp(&m_pCur->ListEntry, MapEntry, ListEntry);
196 return *this;
197 }
198
199 /** Compare equal. */
200 inline bool operator==(ConstIterator const &a_rThat) RT_NOEXCEPT { return m_pCur == a_rThat.m_pCur; }
201 /** Compare not equal. */
202 inline bool operator!=(ConstIterator const &a_rThat) RT_NOEXCEPT { return m_pCur != a_rThat.m_pCur; }
203
204 /* Map class must be friend so it can use the MapEntry constructor. */
205 friend class RTCRestStringMapBase;
206 };
207
208 /** Returns iterator for the first map entry (unless it's empty and it's also the end). */
209 inline ConstIterator begin() const RT_NOEXCEPT
210 {
211 if (!RTListIsEmpty(&m_ListHead))
212 return ConstIterator(RTListNodeGetNextCpp(&m_ListHead, MapEntry, ListEntry));
213 return end();
214 }
215 /** Returns iterator for the last map entry (unless it's empty and it's also the end). */
216 inline ConstIterator last() const RT_NOEXCEPT
217 {
218 if (!RTListIsEmpty(&m_ListHead))
219 return ConstIterator(RTListNodeGetPrevCpp(&m_ListHead, MapEntry, ListEntry));
220 return end();
221 }
222 /** Returns the end iterator. This does not ever refer to an actual map entry. */
223 inline ConstIterator end() const RT_NOEXCEPT
224 {
225 return ConstIterator(RT_FROM_CPP_MEMBER(&m_ListHead, MapEntry, ListEntry));
226 }
227 /** @} */
228
229
230protected:
231 /**
232 * Helper for creating a clone.
233 *
234 * @returns Pointer to new map object on success, NULL if out of memory.
235 */
236 virtual RTCRestStringMapBase *createClone(void) const RT_NOEXCEPT = 0;
237
238 /**
239 * Wrapper around the value constructor.
240 *
241 * @returns Pointer to new value object on success, NULL if out of memory.
242 */
243 virtual RTCRestObjectBase *createValue(void) RT_NOEXCEPT = 0;
244
245 /**
246 * For accessing the static deserializeInstanceFromJson() method of the value.
247 */
248 virtual int deserializeValueInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT = 0;
249
250 /**
251 * Worker for the copy assignment method and copyMapWorkerMayThrow.
252 *
253 * This will use createEntryCopy to do the copying.
254 *
255 * @returns VINF_SUCCESS on success, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
256 * @param a_rThat The map to copy. Caller makes 100% sure the it has
257 * the same type as the destination.
258 */
259 int copyMapWorkerNoThrow(RTCRestStringMapBase const &a_rThat) RT_NOEXCEPT;
260
261 /**
262 * Wrapper around copyMapWorkerNoThrow() that throws allocation errors, making
263 * it suitable for copy constructors and assignment operators.
264 */
265 void copyMapWorkerMayThrow(RTCRestStringMapBase const &a_rThat);
266
267 /**
268 * Worker for performing inserts.
269 *
270 * @returns VINF_SUCCESS or VWRN_ALREADY_EXISTS on success.
271 * VERR_ALREADY_EXISTS, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
272 * @param a_pszKey The key.
273 * @param a_pValue The value to insert. Ownership is transferred to the map on success.
274 * @param a_fReplace Whether to replace existing key-value pair with matching key.
275 * @param a_cchKey The key length, the whole string by default.
276 */
277 int putWorker(const char *a_pszKey, RTCRestObjectBase *a_pValue, bool a_fReplace, size_t a_cchKey = RTSTR_MAX) RT_NOEXCEPT;
278
279 /**
280 * Worker for performing inserts.
281 *
282 * @returns VINF_SUCCESS or VWRN_ALREADY_EXISTS on success.
283 * VERR_ALREADY_EXISTS, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
284 * @param a_pszKey The key.
285 * @param a_rValue The value to copy into the map.
286 * @param a_fReplace Whether to replace existing key-value pair with matching key.
287 * @param a_cchKey The key length, the whole string by default.
288 */
289 int putCopyWorker(const char *a_pszKey, RTCRestObjectBase const &a_rValue, bool a_fReplace, size_t a_cchKey = RTSTR_MAX) RT_NOEXCEPT;
290
291 /**
292 * Worker for getting the value corresponding to the given key.
293 *
294 * @returns Pointer to the value object if found, NULL if key not in the map.
295 * @param a_pszKey The key which value to look up.
296 */
297 RTCRestObjectBase *getWorker(const char *a_pszKey) RT_NOEXCEPT;
298
299 /**
300 * Worker for getting the value corresponding to the given key, const variant.
301 *
302 * @returns Pointer to the value object if found, NULL if key not in the map.
303 * @param a_pszKey The key which value to look up.
304 */
305 RTCRestObjectBase const *getWorker(const char *a_pszKey) const RT_NOEXCEPT;
306
307private:
308 static DECLCALLBACK(int) stringSpaceDestructorCallback(PRTSTRSPACECORE pStr, void *pvUser) RT_NOEXCEPT;
309};
310
311
312/**
313 * Limited map class.
314 */
315template<class ValueType> class RTCRestStringMap : public RTCRestStringMapBase
316{
317public:
318 /** Default constructor, creates emtpy map. */
319 RTCRestStringMap() RT_NOEXCEPT
320 : RTCRestStringMapBase()
321 {}
322
323 /** Copy constructor. */
324 RTCRestStringMap(RTCRestStringMap const &a_rThat)
325 : RTCRestStringMapBase()
326 {
327 copyMapWorkerMayThrow(a_rThat);
328 }
329
330 /** Destructor. */
331 virtual ~RTCRestStringMap()
332 {
333 /* nothing to do here. */
334 }
335
336 /** Copy assignment operator. */
337 RTCRestStringMap &operator=(RTCRestStringMap const &a_rThat)
338 {
339 copyMapWorkerMayThrow(a_rThat);
340 return *this;
341 }
342
343 /** Safe copy assignment method. */
344 int assignCopy(RTCRestStringMap const &a_rThat) RT_NOEXCEPT
345 {
346 return copyMapWorkerNoThrow(a_rThat);
347 }
348
349 /** Make a clone of this object. */
350 inline RTCRestStringMap *clone() const RT_NOEXCEPT
351 {
352 return (RTCRestStringMap *)baseClone();
353 }
354
355 /** Factory method. */
356 static DECLCALLBACK(RTCRestObjectBase *) createInstance(void) RT_NOEXCEPT
357 {
358 return new (std::nothrow) RTCRestStringMap<ValueType>();
359 }
360
361 /** Factory method for values. */
362 static DECLCALLBACK(RTCRestObjectBase *) createValueInstance(void) RT_NOEXCEPT
363 {
364 return new (std::nothrow) ValueType();
365 }
366
367 /** @copydoc RTCRestObjectBase::FNDESERIALIZEINSTANCEFROMJSON */
368 static DECLCALLBACK(int) deserializeInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT
369 {
370 *a_ppInstance = new (std::nothrow) RTCRestStringMap<ValueType>();
371 if (*a_ppInstance)
372 return (*a_ppInstance)->deserializeFromJson(a_rCursor);
373 return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_NO_MEMORY, "Out of memory");
374 }
375
376 /**
377 * Inserts the given object into the map.
378 *
379 * @returns VINF_SUCCESS or VWRN_ALREADY_EXISTS on success.
380 * VERR_ALREADY_EXISTS, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
381 * @param a_pszKey The key.
382 * @param a_pValue The value to insert. Ownership is transferred to the map on success.
383 * @param a_fReplace Whether to replace existing key-value pair with matching key.
384 */
385 inline int put(const char *a_pszKey, ValueType *a_pValue, bool a_fReplace = false) RT_NOEXCEPT
386 {
387 return putWorker(a_pszKey, a_pValue, a_fReplace);
388 }
389
390 /**
391 * Inserts the given object into the map.
392 *
393 * @returns VINF_SUCCESS or VWRN_ALREADY_EXISTS on success.
394 * VERR_ALREADY_EXISTS, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
395 * @param a_rStrKey The key.
396 * @param a_pValue The value to insert. Ownership is transferred to the map on success.
397 * @param a_fReplace Whether to replace existing key-value pair with matching key.
398 */
399 inline int put(RTCString const &a_rStrKey, ValueType *a_pValue, bool a_fReplace = false) RT_NOEXCEPT
400 {
401 return putWorker(a_rStrKey.c_str(), a_pValue, a_fReplace, a_rStrKey.length());
402 }
403
404 /**
405 * Inserts a copy of the given object into the map.
406 *
407 * @returns VINF_SUCCESS or VWRN_ALREADY_EXISTS on success.
408 * VERR_ALREADY_EXISTS, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
409 * @param a_pszKey The key.
410 * @param a_rValue The value to insert a copy of.
411 * @param a_fReplace Whether to replace existing key-value pair with matching key.
412 */
413 inline int putCopy(const char *a_pszKey, const ValueType &a_rValue, bool a_fReplace = false) RT_NOEXCEPT
414 {
415 return putCopyWorker(a_pszKey, a_rValue, a_fReplace);
416 }
417
418 /**
419 * Inserts a copy of the given object into the map.
420 *
421 * @returns VINF_SUCCESS or VWRN_ALREADY_EXISTS on success.
422 * VERR_ALREADY_EXISTS, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
423 * @param a_rStrKey The key.
424 * @param a_rValue The value to insert a copy of.
425 * @param a_fReplace Whether to replace existing key-value pair with matching key.
426 */
427 inline int putCopy(RTCString const &a_rStrKey, const ValueType &a_rValue, bool a_fReplace = false) RT_NOEXCEPT
428 {
429 return putCopyWorker(a_rStrKey.c_str(), a_rValue, a_fReplace, a_rStrKey.length());
430 }
431
432 /**
433 * Gets the value corresponding to the given key.
434 *
435 * @returns Pointer to the value object if found, NULL if key not in the map.
436 * @param a_pszKey The key which value to look up.
437 */
438 inline ValueType *get(const char *a_pszKey) RT_NOEXCEPT
439 {
440 return (ValueType *)getWorker(a_pszKey);
441 }
442
443 /**
444 * Gets the value corresponding to the given key.
445 *
446 * @returns Pointer to the value object if found, NULL if key not in the map.
447 * @param a_rStrKey The key which value to look up.
448 */
449 inline ValueType *get(RTCString const &a_rStrKey) RT_NOEXCEPT
450 {
451 return (ValueType *)getWorker(a_rStrKey.c_str());
452 }
453
454 /**
455 * Gets the const value corresponding to the given key.
456 *
457 * @returns Pointer to the value object if found, NULL if key not in the map.
458 * @param a_pszKey The key which value to look up.
459 */
460 inline ValueType const *get(const char *a_pszKey) const RT_NOEXCEPT
461 {
462 return (ValueType const *)getWorker(a_pszKey);
463 }
464
465 /**
466 * Gets the const value corresponding to the given key.
467 *
468 * @returns Pointer to the value object if found, NULL if key not in the map.
469 * @param a_rStrKey The key which value to look up.
470 */
471 inline ValueType const *get(RTCString const &a_rStrKey) const RT_NOEXCEPT
472 {
473 return (ValueType const *)getWorker(a_rStrKey.c_str());
474 }
475
476 /** @todo enumerator*/
477
478protected:
479 virtual RTCRestStringMapBase *createClone(void) const RT_NOEXCEPT RT_OVERRIDE
480 {
481 return new (std::nothrow) RTCRestStringMap();
482 }
483
484 virtual RTCRestObjectBase *createValue(void) RT_NOEXCEPT RT_OVERRIDE
485 {
486 return new (std::nothrow) ValueType();
487 }
488
489 virtual int deserializeValueInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT RT_OVERRIDE
490 {
491 return ValueType::deserializeInstanceFromJson(a_rCursor, a_ppInstance);
492 }
493};
494
495
496/** @} */
497
498#endif /* !IPRT_INCLUDED_cpp_reststringmap_h */
499
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette