VirtualBox

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

Last change on this file since 90062 was 82968, checked in by vboxsync, 5 years ago

Copyright year updates by scm.

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