VirtualBox

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

Last change on this file since 74197 was 74197, checked in by vboxsync, 6 years ago

IPRT/rest: String map tests. A couple of bugfixes (removal, enumeration). bugref:9167

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