VirtualBox

source: vbox/trunk/include/iprt/cpp/restbase.h@ 74024

Last change on this file since 74024 was 74024, checked in by vboxsync, 7 years ago

IPRT/rest: Implemented header collection (x-obmcs-header-collection) and multi-query array mapping. Renamed RTCRestObjectBase::getType() to typeName() to avoid clashing with generated code. bugref:9167 [build fix]

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 63.7 KB
Line 
1/** @file
2 * IPRT - C++ Representational State Transfer (REST) Base Classes.
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_restbase_h
27#define ___iprt_cpp_restbase_h
28
29#include <iprt/types.h>
30#include <iprt/assert.h>
31#include <iprt/err.h>
32#include <iprt/http.h>
33#include <iprt/json.h>
34#include <iprt/list.h>
35#include <iprt/string.h>
36#include <iprt/stdarg.h>
37#include <iprt/cpp/ministring.h>
38#include <iprt/cpp/utils.h>
39
40
41/** @defgroup grp_rt_cpp_restbase C++ Representational State Transfer (REST) Base Classes.
42 * @ingroup grp_rt_cpp
43 * @{
44 */
45
46
47
48/**
49 * Abstract base class for serializing data objects.
50 */
51class RT_DECL_CLASS RTCRestOutputBase
52{
53public:
54 RTCRestOutputBase()
55 : m_uIndent(0)
56 { }
57 virtual ~RTCRestOutputBase()
58 { }
59
60 /**
61 * RTStrPrintf like function (see @ref pg_rt_str_format).
62 *
63 * @returns Number of bytes outputted.
64 * @param pszFormat The format string.
65 * @param ... Argument specfied in @a pszFormat.
66 */
67 size_t printf(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(2, 3)
68 {
69 va_list va;
70 va_start(va, pszFormat);
71 size_t cchWritten = this->vprintf(pszFormat, va);
72 va_end(va);
73 return cchWritten;
74 }
75
76 /**
77 * RTStrPrintfV like function (see @ref pg_rt_str_format).
78 *
79 * @returns Number of bytes outputted.
80 * @param pszFormat The format string.
81 * @param va Argument specfied in @a pszFormat.
82 */
83 virtual size_t vprintf(const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(2, 0) = 0;
84
85 /**
86 * Sets the indentation level for use when pretty priting things.
87 *
88 * @returns Previous indentation level.
89 * @param uIndent The indentation level.
90 */
91 unsigned setIndent(unsigned uIndent)
92 {
93 unsigned const uRet = m_uIndent;
94 m_uIndent = uIndent;
95 return uRet;
96 }
97
98 /**
99 * Increases the indentation level.
100 *
101 * @returns Previous indentation level.
102 */
103 unsigned incrementIndent()
104 {
105 unsigned const uRet = m_uIndent;
106 m_uIndent = uRet + 1;
107 return uRet;
108 }
109
110protected:
111 /** The current indentation level. */
112 unsigned m_uIndent;
113};
114
115
116/**
117 * Serialize to a string object.
118 */
119class RT_DECL_CLASS RTCRestOutputToString : public RTCRestOutputBase
120{
121public:
122 /**
123 * Creates an instance that appends to @a a_pDst.
124 * @param a_pDst Pointer to the destination string object.
125 * NULL is not accepted and will assert.
126 * @param a_fAppend Whether to append to the current string value, or
127 * nuke the string content before starting the output.
128 */
129 RTCRestOutputToString(RTCString *a_pDst, bool a_fAppend = false);
130 virtual ~RTCRestOutputToString();
131
132 virtual size_t vprintf(const char *pszFormat, va_list va) RT_OVERRIDE;
133
134 /**
135 * Finalizes the output and releases the string object to the caller.
136 *
137 * @returns The released string object. NULL if we ran out of memory or if
138 * called already.
139 *
140 * @remark This sets m_pDst to NULL and the object cannot be use for any
141 * more output afterwards.
142 */
143 virtual RTCString *finalize();
144
145
146protected:
147 /** Pointer to the destination string. NULL after finalize(). */
148 RTCString *m_pDst;
149 /** Set if we ran out of memory and should ignore subsequent calls. */
150 bool m_fOutOfMemory;
151
152 /** @callback_method_impl{FNRTSTROUTPUT} */
153 static DECLCALLBACK(size_t) strOutput(void *pvArg, const char *pachChars, size_t cbChars);
154
155 /* Make non-copyable (RTCNonCopyable causes warnings): */
156 RTCRestOutputToString(RTCRestOutputToString const &);
157 RTCRestOutputToString *operator=(RTCRestOutputToString const &);
158};
159
160
161/* forward decl: */
162class RTCRestJsonPrimaryCursor;
163
164/**
165 * JSON cursor structure.
166 *
167 * This reduces the number of parameters passed around when deserializing JSON
168 * input and also helps constructing full object name for logging and error reporting.
169 */
170struct RT_DECL_CLASS RTCRestJsonCursor
171{
172 /** Handle to the value being parsed. */
173 RTJSONVAL m_hValue;
174 /** Name of the value. */
175 const char *m_pszName;
176 /** Pointer to the parent, NULL if primary. */
177 struct RTCRestJsonCursor const *m_pParent;
178 /** Pointer to the primary cursor structure. */
179 RTCRestJsonPrimaryCursor *m_pPrimary;
180
181 RTCRestJsonCursor(struct RTCRestJsonCursor const &a_rParent)
182 : m_hValue(NIL_RTJSONVAL), m_pszName(NULL), m_pParent(&a_rParent), m_pPrimary(a_rParent.m_pPrimary)
183 { }
184
185 RTCRestJsonCursor(RTJSONVAL hValue, const char *pszName, struct RTCRestJsonCursor *pParent)
186 : m_hValue(hValue), m_pszName(pszName), m_pParent(pParent), m_pPrimary(pParent->m_pPrimary)
187 { }
188
189 RTCRestJsonCursor(RTJSONVAL hValue, const char *pszName)
190 : m_hValue(hValue), m_pszName(pszName), m_pParent(NULL), m_pPrimary(NULL)
191 { }
192
193 ~RTCRestJsonCursor()
194 {
195 if (m_hValue != NIL_RTJSONVAL)
196 {
197 RTJsonValueRelease(m_hValue);
198 m_hValue = NIL_RTJSONVAL;
199 }
200 }
201};
202
203
204/**
205 * The primary JSON cursor class.
206 */
207class RT_DECL_CLASS RTCRestJsonPrimaryCursor
208{
209public:
210 /** The cursor for the first level. */
211 RTCRestJsonCursor m_Cursor;
212 /** Error info keeper. */
213 PRTERRINFO m_pErrInfo;
214
215 /** Creates a primary json cursor with optiona error info. */
216 RTCRestJsonPrimaryCursor(RTJSONVAL hValue, const char *pszName, PRTERRINFO pErrInfo = NULL)
217 : m_Cursor(hValue, pszName)
218 , m_pErrInfo(pErrInfo)
219 {
220 m_Cursor.m_pPrimary = this;
221 }
222
223 virtual ~RTCRestJsonPrimaryCursor()
224 { }
225
226 /**
227 * Add an error message.
228 *
229 * @returns a_rc
230 * @param a_rCursor The cursor reporting the error.
231 * @param a_rc The status code.
232 * @param a_pszFormat Format string.
233 * @param ... Format string arguments.
234 */
235 virtual int addError(RTCRestJsonCursor const &a_rCursor, int a_rc, const char *a_pszFormat, ...);
236
237 /**
238 * Reports that the current field is not known.
239 *
240 * @returns Status to propagate.
241 * @param a_rCursor The cursor for the field.
242 */
243 virtual int unknownField(RTCRestJsonCursor const &a_rCursor);
244
245 /**
246 * Copies the full path into pszDst.
247 *
248 * @returns pszDst
249 * @param a_rCursor The cursor to start walking at.
250 * @param a_pszDst Where to put the path.
251 * @param a_cbDst Size of the destination buffer.
252 */
253 virtual char *getPath(RTCRestJsonCursor const &a_rCursor, char *a_pszDst, size_t a_cbDst) const;
254};
255
256
257/**
258 * Abstract base class for REST data objects.
259 *
260 * The only information this keeps is the null indicator.
261 */
262class RT_DECL_CLASS RTCRestObjectBase
263{
264public:
265 RTCRestObjectBase();
266 RTCRestObjectBase(RTCRestObjectBase const &a_rThat);
267 virtual ~RTCRestObjectBase();
268
269 /**
270 * Tests if the object is @a null.
271 * @returns true if null, false if not.
272 */
273 bool isNull(void) const { return m_fNullIndicator; };
274
275 /**
276 * Sets the object to @a null and fills it with defaults.
277 * @returns IPRT status code (from resetToDefault).
278 */
279 virtual int setNull(void);
280
281 /**
282 * Sets the object to not-null state (i.e. undoes setNull()).
283 * @remarks Only really important for strings.
284 */
285 virtual void setNotNull(void);
286
287 /**
288 * Resets the object to all default values.
289 * @returns IPRT status code.
290 */
291 virtual int resetToDefault() = 0;
292
293 /**
294 * Serialize the object as JSON.
295 *
296 * @returns a_rDst
297 * @param a_rDst The destination for the serialization.
298 */
299 virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const = 0;
300
301 /**
302 * Deserialize object from the given JSON iterator.
303 *
304 * @returns IPRT status code.
305 * @param a_rCursor The JSON cursor.
306 */
307 virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) = 0;
308
309 /**
310 * Flags for toString().
311 *
312 * The kCollectionFormat_xxx bunch controls multiple values in arrays
313 * are formatted. They are ignored by everyone else.
314 *
315 * @note When adding collection format types, make sure to also
316 * update RTCRestArrayBase::toString().
317 * @note Bit 24 is reserved (for kHdrField_MapCollection).
318 */
319 enum
320 {
321 kCollectionFormat_Unspecified = 0, /**< Not specified. */
322 kCollectionFormat_csv, /**< Comma-separated list. */
323 kCollectionFormat_ssv, /**< Space-separated list. */
324 kCollectionFormat_tsv, /**< Tab-separated list. */
325 kCollectionFormat_pipes, /**< Pipe-separated list. */
326 kCollectionFormat_multi, /**< Special collection type that must be handled by caller of toString. */
327 kCollectionFormat_Mask = 7, /**< Collection type mask. */
328
329 kToString_Append = 8 /**< Append to the string (rather than assigning). */
330 };
331
332 /**
333 * String conversion.
334 *
335 * The default implementation of is a wrapper around serializeAsJson().
336 *
337 * @returns IPRT status code.
338 * @param a_pDst Pointer to the destionation string.
339 * @param a_fFlags kCollectionFormat_xxx.
340 */
341 virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = kCollectionFormat_Unspecified) const;
342
343 /**
344 * String convertsion, naive variant.
345 *
346 * @returns String represenation.
347 */
348 RTCString toString() const;
349
350 /**
351 * Convert from (header) string value.
352 *
353 * The default implementation of is a wrapper around deserializeFromJson().
354 *
355 * @returns IPRT status code.
356 * @param a_rValue The string value string to parse.
357 * @param a_pszName Field name or similar.
358 * @param a_pErrInfo Where to return additional error info. Optional.
359 * @param a_fFlags kCollectionFormat_xxx.
360 */
361 virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
362 uint32_t a_fFlags = kCollectionFormat_Unspecified);
363
364 /** Type classification */
365 typedef enum kTypeClass
366 {
367 kTypeClass_Invalid = 0,
368 kTypeClass_Bool, /**< Primitive: bool. */
369 kTypeClass_Int64, /**< Primitive: bool. */
370 kTypeClass_Int32, /**< Primitive: bool. */
371 kTypeClass_Int16, /**< Primitive: bool. */
372 kTypeClass_Double, /**< Primitive: bool. */
373 kTypeClass_String, /**< Primitive: bool. */
374 kTypeClass_Object, /**< Object (any kind of data model object). */
375 kTypeClass_Array, /**< Array (containing any kind of object). */
376 kTypeClass_StringMap /**< String map (containing any kind of object). */
377 } kTypeClass;
378
379 /**
380 * Returns the object type class.
381 */
382 virtual kTypeClass typeClass(void) const;
383
384 /**
385 * Returns the object type name.
386 */
387 virtual const char *typeName(void) const = 0;
388
389 /**
390 * Factory method.
391 * @returns Pointer to new object on success, NULL if out of memory.
392 */
393 typedef DECLCALLBACK(RTCRestObjectBase *) FNCREATEINSTANCE(void);
394 /** Pointer to factory method. */
395 typedef FNCREATEINSTANCE *PFNCREATEINSTANCE;
396
397
398protected:
399 /** Null indicator.
400 * @remarks The null values could be mapped onto C/C++ NULL pointer values,
401 * with the consequence that all data members in objects and such would
402 * have had to been allocated individually, even simple @a bool members.
403 * Given that we're overly paranoid about heap allocations (std::bad_alloc),
404 * it's more fitting to use a null indicator for us.
405 */
406 bool m_fNullIndicator;
407};
408
409
410/**
411 * Class wrapping 'bool'.
412 */
413class RT_DECL_CLASS RTCRestBool : public RTCRestObjectBase
414{
415public:
416 /** Default destructor. */
417 RTCRestBool();
418 /** Copy constructor. */
419 RTCRestBool(RTCRestBool const &a_rThat);
420 /** From value constructor. */
421 RTCRestBool(bool fValue);
422 /** Destructor. */
423 virtual ~RTCRestBool();
424 /** Copy assignment operator. */
425 RTCRestBool &operator=(RTCRestBool const &a_rThat);
426 /** Safe copy assignment method. */
427 int assignCopy(RTCRestBool const &a_rThat);
428 /** Assign value and clear null indicator. */
429 void assignValue(bool a_fValue);
430
431 /* Overridden methods: */
432 virtual int resetToDefault() RT_OVERRIDE;
433 virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_OVERRIDE;
434 virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_OVERRIDE;
435 virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = 0) const RT_OVERRIDE;
436 virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
437 uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_OVERRIDE;
438 virtual kTypeClass typeClass(void) const RT_OVERRIDE;
439 virtual const char *typeName(void) const RT_OVERRIDE;
440
441 /** Factory method. */
442 static DECLCALLBACK(RTCRestObjectBase *) createInstance(void);
443
444public:
445 /** The value. */
446 bool m_fValue;
447};
448
449
450/**
451 * Class wrapping 'int64_t'.
452 */
453class RT_DECL_CLASS RTCRestInt64 : public RTCRestObjectBase
454{
455public:
456 /** Default destructor. */
457 RTCRestInt64();
458 /** Copy constructor. */
459 RTCRestInt64(RTCRestInt64 const &a_rThat);
460 /** From value constructor. */
461 RTCRestInt64(int64_t a_iValue);
462 /** Destructor. */
463 virtual ~RTCRestInt64();
464 /** Copy assignment operator. */
465 RTCRestInt64 &operator=(RTCRestInt64 const &a_rThat);
466 /** Safe copy assignment method. */
467 int assignCopy(RTCRestInt64 const &a_rThat);
468 /** Assign value and clear null indicator. */
469 void assignValue(int64_t a_iValue);
470
471 /* Overridden methods: */
472 virtual int resetToDefault() RT_OVERRIDE;
473 virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_OVERRIDE;
474 virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_OVERRIDE;
475 virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = 0) const RT_OVERRIDE;
476 virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
477 uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_OVERRIDE;
478 virtual kTypeClass typeClass(void) const RT_OVERRIDE;
479 virtual const char *typeName(void) const RT_OVERRIDE;
480
481 /** Factory method. */
482 static DECLCALLBACK(RTCRestObjectBase *) createInstance(void);
483
484public:
485 /** The value. */
486 int64_t m_iValue;
487};
488
489
490/**
491 * Class wrapping 'int32_t'.
492 */
493class RT_DECL_CLASS RTCRestInt32 : public RTCRestObjectBase
494{
495public:
496 /** Default destructor. */
497 RTCRestInt32();
498 /** Copy constructor. */
499 RTCRestInt32(RTCRestInt32 const &a_rThat);
500 /** From value constructor. */
501 RTCRestInt32(int32_t iValue);
502 /** Destructor. */
503 virtual ~RTCRestInt32();
504 /** Copy assignment operator. */
505 RTCRestInt32 &operator=(RTCRestInt32 const &a_rThat);
506 /** Safe copy assignment method. */
507 int assignCopy(RTCRestInt32 const &a_rThat);
508 /** Assign value and clear null indicator. */
509 void assignValue(int32_t a_iValue);
510
511 /* Overridden methods: */
512 virtual int resetToDefault() RT_OVERRIDE;
513 virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_OVERRIDE;
514 virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_OVERRIDE;
515 virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = 0) const RT_OVERRIDE;
516 virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
517 uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_OVERRIDE;
518 virtual kTypeClass typeClass(void) const RT_OVERRIDE;
519 virtual const char *typeName(void) const RT_OVERRIDE;
520
521 /** Factory method. */
522 static DECLCALLBACK(RTCRestObjectBase *) createInstance(void);
523
524public:
525 /** The value. */
526 int32_t m_iValue;
527};
528
529
530/**
531 * Class wrapping 'int16_t'.
532 */
533class RT_DECL_CLASS RTCRestInt16 : public RTCRestObjectBase
534{
535public:
536 /** Default destructor. */
537 RTCRestInt16();
538 /** Copy constructor. */
539 RTCRestInt16(RTCRestInt16 const &a_rThat);
540 /** From value constructor. */
541 RTCRestInt16(int16_t iValue);
542 /** Destructor. */
543 virtual ~RTCRestInt16();
544 /** Copy assignment operator. */
545 RTCRestInt16 &operator=(RTCRestInt16 const &a_rThat);
546 /** Safe copy assignment method. */
547 int assignCopy(RTCRestInt16 const &a_rThat);
548 /** Assign value and clear null indicator. */
549 void assignValue(int16_t a_iValue);
550
551 /* Overridden methods: */
552 virtual int resetToDefault() RT_OVERRIDE;
553 virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_OVERRIDE;
554 virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_OVERRIDE;
555 virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = 0) const RT_OVERRIDE;
556 virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
557 uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_OVERRIDE;
558 virtual kTypeClass typeClass(void) const RT_OVERRIDE;
559 virtual const char *typeName(void) const RT_OVERRIDE;
560
561 /** Factory method. */
562 static DECLCALLBACK(RTCRestObjectBase *) createInstance(void);
563
564public:
565 /** The value. */
566 int16_t m_iValue;
567};
568
569
570/**
571 * Class wrapping 'double'.
572 */
573class RT_DECL_CLASS RTCRestDouble : public RTCRestObjectBase
574{
575public:
576 /** Default destructor. */
577 RTCRestDouble();
578 /** Copy constructor. */
579 RTCRestDouble(RTCRestDouble const &a_rThat);
580 /** From value constructor. */
581 RTCRestDouble(double rdValue);
582 /** Destructor. */
583 virtual ~RTCRestDouble();
584 /** Copy assignment operator. */
585 RTCRestDouble &operator=(RTCRestDouble const &a_rThat);
586 /** Safe copy assignment method. */
587 int assignCopy(RTCRestDouble const &a_rThat);
588 /** Assign value and clear null indicator. */
589 void assignValue(double a_rdValue);
590
591 /* Overridden methods: */
592 virtual int resetToDefault() RT_OVERRIDE;
593 virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_OVERRIDE;
594 virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_OVERRIDE;
595 virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = 0) const RT_OVERRIDE;
596 virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
597 uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_OVERRIDE;
598 virtual kTypeClass typeClass(void) const RT_OVERRIDE;
599 virtual const char *typeName(void) const RT_OVERRIDE;
600
601 /** Factory method. */
602 static DECLCALLBACK(RTCRestObjectBase *) createInstance(void);
603
604public:
605 /** The value. */
606 double m_rdValue;
607};
608
609
610/**
611 * Class wrapping 'RTCString'.
612 */
613class RT_DECL_CLASS RTCRestString : public RTCString, public RTCRestObjectBase
614{
615public:
616 /** Default destructor. */
617 RTCRestString();
618 /** Destructor. */
619 virtual ~RTCRestString();
620
621 /** Copy constructor. */
622 RTCRestString(RTCRestString const &a_rThat);
623 /** From value constructor. */
624 RTCRestString(RTCString const &a_rThat);
625 /** From value constructor. */
626 RTCRestString(const char *a_pszSrc);
627 /** Safe copy assignment method. */
628 int assignCopy(RTCRestString const &a_rThat);
629 /** Safe copy assignment method. */
630 int assignCopy(RTCString const &a_rThat);
631 /** Safe copy assignment method. */
632 int assignCopy(const char *a_pszThat);
633
634 /* Overridden methods: */
635 virtual int setNull(void) RT_OVERRIDE; /* (ambigious, so overrider it to make sure.) */
636 virtual int resetToDefault() RT_OVERRIDE;
637 virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_OVERRIDE;
638 virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_OVERRIDE;
639 virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = kCollectionFormat_Unspecified) const RT_OVERRIDE;
640 virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
641 uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_OVERRIDE;
642 virtual kTypeClass typeClass(void) const RT_OVERRIDE;
643 virtual const char *typeName(void) const RT_OVERRIDE;
644
645 /** Factory method. */
646 static DECLCALLBACK(RTCRestObjectBase *) createInstance(void);
647};
648
649
650/**
651 * Abstract base class for the RTCRestArray template.
652 */
653class RT_DECL_CLASS RTCRestArrayBase : public RTCRestObjectBase
654{
655public:
656 /** Default destructor. */
657 RTCRestArrayBase();
658 /** Destructor. */
659 virtual ~RTCRestArrayBase();
660
661 /* Overridden methods: */
662 virtual int resetToDefault() RT_OVERRIDE;
663 virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_OVERRIDE;
664 virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_OVERRIDE;
665 virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = kCollectionFormat_Unspecified) const RT_OVERRIDE;
666 virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
667 uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_OVERRIDE;
668 virtual kTypeClass typeClass(void) const RT_OVERRIDE;
669 virtual const char *typeName(void) const RT_OVERRIDE;
670
671 /**
672 * Clear the content of the map.
673 */
674 void clear();
675
676 /**
677 * Check if an list contains any items.
678 *
679 * @return True if there is more than zero items, false otherwise.
680 */
681 bool isEmpty() const
682 {
683 return m_cElements == 0;
684 }
685
686 /**
687 * Gets the number of entries in the map.
688 */
689 size_t size() const
690 {
691 return m_cElements;
692 }
693
694 /**
695 * Returns the base object pointer at a given index.
696 *
697 * @returns The base object at @a a_idx, NULL if out of range.
698 * @param a_idx The array index.
699 */
700 RTCRestObjectBase *atBase(size_t a_idx)
701 {
702 if (a_idx < m_cElements)
703 return m_papElements[a_idx];
704 return NULL;
705 }
706
707 /**
708 * Returns the const base object pointer at a given index.
709 *
710 * @returns The base object at @a a_idx, NULL if out of range.
711 * @param a_idx The array index.
712 */
713 RTCRestObjectBase const *atBase(size_t a_idx) const
714 {
715 if (a_idx < m_cElements)
716 return m_papElements[a_idx];
717 return NULL;
718 }
719
720 /**
721 * Removes the element at @a a_idx.
722 * @returns true if @a a_idx is valid, false if out of range.
723 * @param a_idx The index of the element to remove.
724 * The value ~(size_t)0 is an alias for the final element.
725 */
726 bool removeAt(size_t a_idx);
727
728 /**
729 * Makes sure the array can hold at the given number of entries.
730 *
731 * @returns VINF_SUCCESS or VERR_NO_MEMORY.
732 * @param a_cEnsureCapacity The number of elements to ensure capacity to hold.
733 */
734 int ensureCapacity(size_t a_cEnsureCapacity);
735
736
737protected:
738 /** The array. */
739 RTCRestObjectBase **m_papElements;
740 /** Number of elements in the array. */
741 size_t m_cElements;
742 /** The number of elements m_papElements can hold.
743 * The difference between m_cCapacity and m_cElements are all NULLs. */
744 size_t m_cCapacity;
745
746 /**
747 * Wrapper around the value constructor.
748 *
749 * @returns Pointer to new value object on success, NULL if out of memory.
750 */
751 virtual RTCRestObjectBase *createValue(void) = 0;
752
753 /**
754 * Wrapper around the value copy constructor.
755 *
756 * @returns Pointer to copy on success, NULL if out of memory.
757 * @param a_pSrc The value to copy.
758 */
759 virtual RTCRestObjectBase *createValueCopy(RTCRestObjectBase const *a_pSrc) = 0;
760
761 /**
762 * Worker for the copy constructor and the assignment operator.
763 *
764 * This will use createEntryCopy to do the copying.
765 *
766 * @returns VINF_SUCCESS on success, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
767 * @param a_rThat The array to copy. Caller makes 100% sure the it has
768 * the same type as the destination.
769 * @param a_fThrow Whether to throw error.
770 */
771 int copyArrayWorker(RTCRestArrayBase const &a_rThat, bool a_fThrow);
772
773 /**
774 * Worker for performing inserts.
775 *
776 * @returns VINF_SUCCESS or VWRN_ALREADY_EXISTS on success.
777 * VERR_ALREADY_EXISTS, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
778 * @param a_idx Where to insert it. The value ~(size_t)0 is an alias for m_cElements.
779 * @param a_pValue The value to insert. Ownership is transferred to the map on success.
780 * @param a_fReplace Whether to replace existing entry rather than insert.
781 */
782 int insertWorker(size_t a_idx, RTCRestObjectBase *a_pValue, bool a_fReplace);
783
784 /**
785 * Worker for performing inserts.
786 *
787 * @returns VINF_SUCCESS or VWRN_ALREADY_EXISTS on success.
788 * VERR_ALREADY_EXISTS, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
789 * @param a_idx Where to insert it. The value ~(size_t)0 is an alias for m_cElements.
790 * @param a_rValue The value to copy into the map.
791 * @param a_fReplace Whether to replace existing key-value pair with matching key.
792 */
793 int insertCopyWorker(size_t a_idx, RTCRestObjectBase const &a_rValue, bool a_fReplace);
794
795private:
796 /** Copy constructor on this class should never be used. */
797 RTCRestArrayBase(RTCRestArrayBase const &a_rThat);
798 /** Copy assignment operator on this class should never be used. */
799 RTCRestArrayBase &operator=(RTCRestArrayBase const &a_rThat);
800};
801
802
803
804/**
805 * Limited array class.
806 */
807template<class ElementType> class RTCRestArray : public RTCRestArrayBase
808{
809public:
810 /** Default constructor - empty array. */
811 RTCRestArray()
812 : RTCRestArrayBase()
813 {
814 }
815
816 /** Destructor. */
817 ~RTCRestArray()
818 {
819 }
820
821 /** Copy constructor. */
822 RTCRestArray(RTCRestArray const &a_rThat)
823 : RTCRestArrayBase()
824 {
825 copyArrayWorker(a_rThat, true /*fThrow*/);
826 }
827
828 /** Copy assignment operator. */
829 RTCRestArray &operator=(RTCRestArray const &a_rThat)
830 {
831 copyArrayWorker(a_rThat, true /*fThrow*/);
832 return *this;
833 }
834
835 /** Safe copy assignment method. */
836 int assignCopy(RTCRestArray const &a_rThat)
837 {
838 return copyArrayWorker(a_rThat, false /*fThrow*/);
839 }
840
841 /** Factory method. */
842 static DECLCALLBACK(RTCRestObjectBase *) createInstance(void)
843 {
844 return new (std::nothrow) RTCRestArray<ElementType>();
845 }
846
847 /** Factory method for elements. */
848 static DECLCALLBACK(RTCRestObjectBase *) createElementInstance(void)
849 {
850 return new (std::nothrow) ElementType();
851 }
852
853
854 /**
855 * Insert the given object at the specified index.
856 *
857 * @returns VINF_SUCCESS on success.
858 * VERR_INVALID_POINTER, VERR_NO_MEMORY, VERR_NO_STR_MEMORY or VERR_OUT_OF_RANGE on failure.
859 * @param a_idx The insertion index. ~(size_t)0 is an alias for the end.
860 * @param a_pThat The object to insert. The array takes ownership of the object on success.
861 */
862 int insert(size_t a_idx, ElementType *a_pThat)
863 {
864 return insertWorker(a_idx, a_pThat, false /*a_fReplace*/);
865 }
866
867 /**
868 * Insert a copy of the object at the specified index.
869 *
870 * @returns VINF_SUCCESS on success.
871 * VERR_NO_MEMORY, VERR_NO_STR_MEMORY or VERR_OUT_OF_RANGE on failure.
872 * @param a_idx The insertion index. ~(size_t)0 is an alias for the end.
873 * @param a_rThat The object to insert a copy of.
874 */
875 int insertCopy(size_t a_idx, ElementType const &a_rThat)
876 {
877 return insertCopyWorker(a_idx, a_rThat, false /*a_fReplace*/);
878 }
879
880 /**
881 * Appends the given object to the array.
882 *
883 * @returns VINF_SUCCESS on success.
884 * VERR_INVALID_POINTER, VERR_NO_MEMORY, VERR_NO_STR_MEMORY or VERR_OUT_OF_RANGE on failure.
885 * @param a_pThat The object to insert. The array takes ownership of the object on success.
886 */
887 int append(ElementType *a_pThat)
888 {
889 return insertWorker(~(size_t)0, a_pThat, false /*a_fReplace*/);
890 }
891
892 /**
893 * Appends a copy of the object at the specified index.
894 *
895 * @returns VINF_SUCCESS on success.
896 * VERR_NO_MEMORY, VERR_NO_STR_MEMORY or VERR_OUT_OF_RANGE on failure.
897 * @param a_rThat The object to insert a copy of.
898 */
899 int appendCopy(ElementType const &a_rThat)
900 {
901 return insertCopyWorker(~(size_t)0, a_rThat, false /*a_fReplace*/);
902 }
903
904 /**
905 * Prepends the given object to the array.
906 *
907 * @returns VINF_SUCCESS on success.
908 * VERR_INVALID_POINTER, VERR_NO_MEMORY, VERR_NO_STR_MEMORY or VERR_OUT_OF_RANGE on failure.
909 * @param a_pThat The object to insert. The array takes ownership of the object on success.
910 */
911 int prepend(ElementType *a_pThat)
912 {
913 return insertWorker(0, a_pThat, false /*a_fReplace*/);
914 }
915
916 /**
917 * Prepends a copy of the object at the specified index.
918 *
919 * @returns VINF_SUCCESS on success.
920 * VERR_NO_MEMORY, VERR_NO_STR_MEMORY or VERR_OUT_OF_RANGE on failure.
921 * @param a_rThat The object to insert a copy of.
922 */
923 int prependCopy(ElementType const &a_rThat)
924 {
925 return insertCopyWorker(0, a_rThat, false /*a_fReplace*/);
926 }
927
928 /**
929 * Insert the given object at the specified index.
930 *
931 * @returns VINF_SUCCESS on success.
932 * VERR_INVALID_POINTER, VERR_NO_MEMORY, VERR_NO_STR_MEMORY or VERR_OUT_OF_RANGE on failure.
933 * @param a_idx The index of the existing object to replace.
934 * @param a_pThat The replacement object. The array takes ownership of the object on success.
935 */
936 int replace(size_t a_idx, ElementType *a_pThat)
937 {
938 return insertWorker(a_idx, a_pThat, true /*a_fReplace*/);
939 }
940
941 /**
942 * Insert a copy of the object at the specified index.
943 *
944 * @returns VINF_SUCCESS on success.
945 * VERR_NO_MEMORY, VERR_NO_STR_MEMORY or VERR_OUT_OF_RANGE on failure.
946 * @param a_idx The index of the existing object to replace.
947 * @param a_rThat The object to insert a copy of.
948 */
949 int replaceCopy(size_t a_idx, ElementType const &a_rThat)
950 {
951 return insertCopyWorker(a_idx, a_rThat, true /*a_fReplace*/);
952 }
953
954 /**
955 * Returns the object at a given index.
956 *
957 * @returns The object at @a a_idx, NULL if out of range.
958 * @param a_idx The array index.
959 */
960 ElementType *at(size_t a_idx)
961 {
962 if (a_idx < m_cElements)
963 return (ElementType *)m_papElements[a_idx];
964 return NULL;
965 }
966
967 /**
968 * Returns the object at a given index, const variant.
969 *
970 * @returns The object at @a a_idx, NULL if out of range.
971 * @param a_idx The array index.
972 */
973 ElementType const *at(size_t a_idx) const
974 {
975 if (a_idx < m_cElements)
976 return (ElementType const *)m_papElements[a_idx];
977 return NULL;
978 }
979
980 /**
981 * Returns the first object in the array.
982 * @returns The first object, NULL if empty.
983 */
984 ElementType *first()
985 {
986 return at(0);
987 }
988
989 /**
990 * Returns the first object in the array, const variant.
991 * @returns The first object, NULL if empty.
992 */
993 ElementType const *first() const
994 {
995 return at(0);
996 }
997
998 /**
999 * Returns the last object in the array.
1000 * @returns The last object, NULL if empty.
1001 */
1002 ElementType *last()
1003 {
1004 return at(m_cElements - 1);
1005 }
1006
1007 /**
1008 * Returns the last object in the array, const variant.
1009 * @returns The last object, NULL if empty.
1010 */
1011 ElementType const *last() const
1012 {
1013 return at(m_cElements - 1);
1014 }
1015
1016
1017protected:
1018 virtual RTCRestObjectBase *createValue(void) RT_OVERRIDE
1019 {
1020 return new (std::nothrow) ElementType();
1021 }
1022
1023 virtual RTCRestObjectBase *createValueCopy(RTCRestObjectBase const *a_pSrc) RT_OVERRIDE
1024 {
1025 ElementType *pCopy = new (std::nothrow) ElementType();
1026 if (pCopy)
1027 {
1028 int rc = pCopy->assignCopy(*(ElementType const *)a_pSrc);
1029 if (RT_SUCCESS(rc))
1030 return pCopy;
1031 delete pCopy;
1032 }
1033 return NULL;
1034 }
1035};
1036
1037
1038/**
1039 * Abstract base class for the RTCRestStringMap template.
1040 */
1041class RT_DECL_CLASS RTCRestStringMapBase : public RTCRestObjectBase
1042{
1043public:
1044 /** Default destructor. */
1045 RTCRestStringMapBase();
1046 /** Copy constructor. */
1047 RTCRestStringMapBase(RTCRestStringMapBase const &a_rThat);
1048 /** Destructor. */
1049 virtual ~RTCRestStringMapBase();
1050 /** Copy assignment operator. */
1051 RTCRestStringMapBase &operator=(RTCRestStringMapBase const &a_rThat);
1052
1053 /* Overridden methods: */
1054 virtual int resetToDefault() RT_OVERRIDE;
1055 virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_OVERRIDE;
1056 virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_OVERRIDE;
1057 // later?
1058 //virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = kCollectionFormat_Unspecified) const RT_OVERRIDE;
1059 //virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
1060 // uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_OVERRIDE;
1061 virtual kTypeClass typeClass(void) const RT_OVERRIDE;
1062 virtual const char *typeName(void) const RT_OVERRIDE;
1063
1064 /**
1065 * Clear the content of the map.
1066 */
1067 void clear();
1068
1069 /**
1070 * Gets the number of entries in the map.
1071 */
1072 size_t size() const;
1073
1074 /**
1075 * Checks if the map contains the given key.
1076 * @returns true if key found, false if not.
1077 * @param a_pszKey The key to check fo.
1078 */
1079 bool constainsKey(const char *a_pszKey) const;
1080
1081 /**
1082 * Checks if the map contains the given key.
1083 * @returns true if key found, false if not.
1084 * @param a_rStrKey The key to check fo.
1085 */
1086 bool constainsKey(RTCString const &a_rStrKey) const;
1087
1088 /**
1089 * Remove any key-value pair with the given key.
1090 * @returns true if anything was removed, false if not found.
1091 * @param a_pszKey The key to remove.
1092 */
1093 bool remove(const char *a_pszKey);
1094
1095 /**
1096 * Remove any key-value pair with the given key.
1097 * @returns true if anything was removed, false if not found.
1098 * @param a_rStrKey The key to remove.
1099 */
1100 bool remove(RTCString const &a_rStrKey);
1101
1102 /**
1103 * Creates a new value and inserts it under the given key, returning the new value.
1104 *
1105 * @returns VINF_SUCCESS or VWRN_ALREADY_EXISTS on success.
1106 * VERR_ALREADY_EXISTS, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
1107 * @param a_ppValue Where to return the pointer to the value.
1108 * @param a_pszKey The key to put it under.
1109 * @param a_cchKey The length of the key. Default is the entire string.
1110 * @param a_fReplace Whether to replace or fail on key collision.
1111 */
1112 int putNewValue(RTCRestObjectBase **a_ppValue, const char *a_pszKey, size_t a_cchKey = RTSTR_MAX, bool a_fReplace = false);
1113
1114 /**
1115 * Creates a new value and inserts it under the given key, returning the new value.
1116 *
1117 * @returns VINF_SUCCESS or VWRN_ALREADY_EXISTS on success.
1118 * VERR_ALREADY_EXISTS, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
1119 * @param a_ppValue Where to return the pointer to the value.
1120 * @param a_pszKey The key to put it under.
1121 * @param a_fReplace Whether to replace or fail on key collision.
1122 */
1123 int putNewValue(RTCRestObjectBase **a_ppValue, RTCString const &a_rStrKey, bool a_fReplace = false);
1124
1125protected:
1126 /** Map entry. */
1127 typedef struct MapEntry
1128 {
1129 /** String space core. */
1130 RTSTRSPACECORE Core;
1131 /** List node for enumeration. */
1132 RTLISTNODE ListEntry;
1133 /** The key.
1134 * @remarks Core.pszString points to the value of this object. So, consider it const. */
1135 RTCString strKey;
1136 /** The value. */
1137 RTCRestObjectBase *pValue;
1138 } MapEntry;
1139 /** The map tree. */
1140 RTSTRSPACE m_Map;
1141 /** The enumeration list head (MapEntry). */
1142 RTLISTANCHOR m_ListHead;
1143 /** Number of map entries. */
1144 size_t m_cEntries;
1145
1146public:
1147 /** @name Map Iteration
1148 * @{ */
1149 /** Const iterator. */
1150 class ConstIterator
1151 {
1152 private:
1153 MapEntry *m_pCur;
1154 ConstIterator();
1155 protected:
1156 ConstIterator(MapEntry *a_pEntry) : m_pCur(a_pEntry) { }
1157 public:
1158 ConstIterator(ConstIterator const &a_rThat) : m_pCur(a_rThat.m_pCur) { }
1159
1160 /** Gets the key string. */
1161 RTCString const &getKey() { return m_pCur->strKey; }
1162 /** Gets poitner to the value object. */
1163 RTCRestObjectBase const *getValue() { return m_pCur->pValue; }
1164
1165 /** Advance to the next map entry. */
1166 ConstIterator &operator++()
1167 {
1168 m_pCur = RTListNodeGetNextCpp(&m_pCur->ListEntry, MapEntry, ListEntry);
1169 return *this;
1170 }
1171
1172 /** Advance to the previous map entry. */
1173 ConstIterator &operator--()
1174 {
1175 m_pCur = RTListNodeGetPrevCpp(&m_pCur->ListEntry, MapEntry, ListEntry);
1176 return *this;
1177 }
1178
1179 /** Compare equal. */
1180 bool operator==(ConstIterator const &a_rThat) { return m_pCur == a_rThat.m_pCur; }
1181 /** Compare not equal. */
1182 bool operator!=(ConstIterator const &a_rThat) { return m_pCur != a_rThat.m_pCur; }
1183
1184 /* Map class must be friend so it can use the MapEntry constructor. */
1185 friend class RTCRestStringMapBase;
1186 };
1187
1188 /** Returns iterator for the first map entry (unless it's empty and it's also the end). */
1189 ConstIterator begin() const { return ConstIterator(RTListGetFirstCpp(&m_ListHead, MapEntry, ListEntry)); }
1190 /** Returns iterator for the last map entry (unless it's empty and it's also the end). */
1191 ConstIterator last() const { return ConstIterator(RTListGetLastCpp(&m_ListHead, MapEntry, ListEntry)); }
1192 /** Returns the end iterator. This does not ever refer to an actual map entry. */
1193 ConstIterator end() const { return ConstIterator(RT_FROM_CPP_MEMBER(&m_ListHead, MapEntry, ListEntry)); }
1194 /** @} */
1195
1196
1197protected:
1198 /**
1199 * Wrapper around the value constructor.
1200 *
1201 * @returns Pointer to new value object on success, NULL if out of memory.
1202 */
1203 virtual RTCRestObjectBase *createValue(void) = 0;
1204
1205 /**
1206 * Wrapper around the value copy constructor.
1207 *
1208 * @returns Pointer to copy on success, NULL if out of memory.
1209 * @param a_pSrc The value to copy.
1210 */
1211 virtual RTCRestObjectBase *createValueCopy(RTCRestObjectBase const *a_pSrc) = 0;
1212
1213 /**
1214 * Worker for the copy constructor and the assignment operator.
1215 *
1216 * This will use createEntryCopy to do the copying.
1217 *
1218 * @returns VINF_SUCCESS on success, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
1219 * @param a_rThat The map to copy. Caller makes 100% sure the it has
1220 * the same type as the destination.
1221 * @param a_fThrow Whether to throw error.
1222 */
1223 int copyMapWorker(RTCRestStringMapBase const &a_rThat, bool a_fThrow);
1224
1225 /**
1226 * Worker for performing inserts.
1227 *
1228 * @returns VINF_SUCCESS or VWRN_ALREADY_EXISTS on success.
1229 * VERR_ALREADY_EXISTS, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
1230 * @param a_pszKey The key.
1231 * @param a_pValue The value to insert. Ownership is transferred to the map on success.
1232 * @param a_fReplace Whether to replace existing key-value pair with matching key.
1233 * @param a_cchKey The key length, the whole string by default.
1234 */
1235 int putWorker(const char *a_pszKey, RTCRestObjectBase *a_pValue, bool a_fReplace, size_t a_cchKey = RTSTR_MAX);
1236
1237 /**
1238 * Worker for performing inserts.
1239 *
1240 * @returns VINF_SUCCESS or VWRN_ALREADY_EXISTS on success.
1241 * VERR_ALREADY_EXISTS, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
1242 * @param a_pszKey The key.
1243 * @param a_rValue The value to copy into the map.
1244 * @param a_fReplace Whether to replace existing key-value pair with matching key.
1245 * @param a_cchKey The key length, the whole string by default.
1246 */
1247 int putCopyWorker(const char *a_pszKey, RTCRestObjectBase const &a_rValue, bool a_fReplace, size_t a_cchKey = RTSTR_MAX);
1248
1249 /**
1250 * Worker for getting the value corresponding to the given key.
1251 *
1252 * @returns Pointer to the value object if found, NULL if key not in the map.
1253 * @param a_pszKey The key which value to look up.
1254 */
1255 RTCRestObjectBase *getWorker(const char *a_pszKey);
1256
1257 /**
1258 * Worker for getting the value corresponding to the given key, const variant.
1259 *
1260 * @returns Pointer to the value object if found, NULL if key not in the map.
1261 * @param a_pszKey The key which value to look up.
1262 */
1263 RTCRestObjectBase const *getWorker(const char *a_pszKey) const;
1264
1265private:
1266 static DECLCALLBACK(int) stringSpaceDestructorCallback(PRTSTRSPACECORE pStr, void *pvUser);
1267};
1268
1269
1270/**
1271 * Limited map class.
1272 */
1273template<class ValueType> class RTCRestStringMap : public RTCRestStringMapBase
1274{
1275public:
1276 /** Default constructor, creates emtpy map. */
1277 RTCRestStringMap()
1278 : RTCRestStringMapBase()
1279 {}
1280
1281 /** Copy constructor. */
1282 RTCRestStringMap(RTCRestStringMap const &a_rThat)
1283 : RTCRestStringMapBase()
1284 {
1285 copyMapWorker(a_rThat, true /*a_fThrow*/);
1286 }
1287
1288 /** Destructor. */
1289 virtual ~RTCRestStringMap()
1290 {
1291 /* nothing to do here. */
1292 }
1293
1294 /** Copy assignment operator. */
1295 RTCRestStringMap &operator=(RTCRestStringMap const &a_rThat)
1296 {
1297 copyMapWorker(a_rThat, true /*a_fThrow*/);
1298 return *this;
1299 }
1300
1301 /** Safe copy assignment method. */
1302 int assignCopy(RTCRestStringMap const &a_rThat)
1303 {
1304 return copyMapWorker(a_rThat, false /*a_fThrow*/);
1305 }
1306
1307 /** Factory method. */
1308 static DECLCALLBACK(RTCRestObjectBase *) createInstance(void)
1309 {
1310 return new (std::nothrow) RTCRestStringMap<ValueType>();
1311 }
1312
1313 /** Factory method for values. */
1314 static DECLCALLBACK(RTCRestObjectBase *) createValueInstance(void)
1315 {
1316 return new (std::nothrow) ValueType();
1317 }
1318
1319 /**
1320 * Inserts the given object into the map.
1321 *
1322 * @returns VINF_SUCCESS or VWRN_ALREADY_EXISTS on success.
1323 * VERR_ALREADY_EXISTS, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
1324 * @param a_pszKey The key.
1325 * @param a_pValue The value to insert. Ownership is transferred to the map on success.
1326 * @param a_fReplace Whether to replace existing key-value pair with matching key.
1327 */
1328 int put(const char *a_pszKey, ValueType *a_pValue, bool a_fReplace = false)
1329 {
1330 return putWorker(a_pszKey, a_pValue, a_fReplace);
1331 }
1332
1333 /**
1334 * Inserts the given object into the map.
1335 *
1336 * @returns VINF_SUCCESS or VWRN_ALREADY_EXISTS on success.
1337 * VERR_ALREADY_EXISTS, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
1338 * @param a_rStrKey The key.
1339 * @param a_pValue The value to insert. Ownership is transferred to the map on success.
1340 * @param a_fReplace Whether to replace existing key-value pair with matching key.
1341 */
1342 int put(RTCString const &a_rStrKey, ValueType *a_pValue, bool a_fReplace = false)
1343 {
1344 return putWorker(a_rStrKey.c_str(), a_pValue, a_fReplace, a_rStrKey.length());
1345 }
1346
1347 /**
1348 * Inserts a copy of the given object into the map.
1349 *
1350 * @returns VINF_SUCCESS or VWRN_ALREADY_EXISTS on success.
1351 * VERR_ALREADY_EXISTS, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
1352 * @param a_pszKey The key.
1353 * @param a_rValue The value to insert a copy of.
1354 * @param a_fReplace Whether to replace existing key-value pair with matching key.
1355 */
1356 int putCopy(const char *a_pszKey, const ValueType &a_rValue, bool a_fReplace = false)
1357 {
1358 return putCopyWorker(a_pszKey, a_rValue, a_fReplace);
1359 }
1360
1361 /**
1362 * Inserts a copy of the given object into the map.
1363 *
1364 * @returns VINF_SUCCESS or VWRN_ALREADY_EXISTS on success.
1365 * VERR_ALREADY_EXISTS, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
1366 * @param a_rStrKey The key.
1367 * @param a_rValue The value to insert a copy of.
1368 * @param a_fReplace Whether to replace existing key-value pair with matching key.
1369 */
1370 int putCopy(RTCString const &a_rStrKey, const ValueType &a_rValue, bool a_fReplace = false)
1371 {
1372 return putCopyWorker(a_rStrKey.c_str(), a_rValue, a_fReplace, a_rStrKey.length());
1373 }
1374
1375 /**
1376 * Gets the value corresponding to the given key.
1377 *
1378 * @returns Pointer to the value object if found, NULL if key not in the map.
1379 * @param a_pszKey The key which value to look up.
1380 */
1381 ValueType *get(const char *a_pszKey)
1382 {
1383 return (ValueType *)getWorker(a_pszKey);
1384 }
1385
1386 /**
1387 * Gets the value corresponding to the given key.
1388 *
1389 * @returns Pointer to the value object if found, NULL if key not in the map.
1390 * @param a_rStrKey The key which value to look up.
1391 */
1392 ValueType *get(RTCString const &a_rStrKey)
1393 {
1394 return (ValueType *)getWorker(a_rStrKey.c_str());
1395 }
1396
1397 /**
1398 * Gets the const value corresponding to the given key.
1399 *
1400 * @returns Pointer to the value object if found, NULL if key not in the map.
1401 * @param a_pszKey The key which value to look up.
1402 */
1403 ValueType const *get(const char *a_pszKey) const
1404 {
1405 return (ValueType const *)getWorker(a_pszKey);
1406 }
1407
1408 /**
1409 * Gets the const value corresponding to the given key.
1410 *
1411 * @returns Pointer to the value object if found, NULL if key not in the map.
1412 * @param a_rStrKey The key which value to look up.
1413 */
1414 ValueType const *get(RTCString const &a_rStrKey) const
1415 {
1416 return (ValueType const *)getWorker(a_rStrKey.c_str());
1417 }
1418
1419 /** @todo enumerator*/
1420
1421protected:
1422 virtual RTCRestObjectBase *createValue(void) RT_OVERRIDE
1423 {
1424 return new (std::nothrow) ValueType();
1425 }
1426
1427 virtual RTCRestObjectBase *createValueCopy(RTCRestObjectBase const *a_pSrc) RT_OVERRIDE
1428 {
1429 ValueType *pCopy = new (std::nothrow) ValueType();
1430 if (pCopy)
1431 {
1432 int rc = pCopy->assignCopy(*(ValueType const *)a_pSrc);
1433 if (RT_SUCCESS(rc))
1434 return pCopy;
1435 delete pCopy;
1436 }
1437 return NULL;
1438 }
1439};
1440
1441
1442/**
1443 * Dynamic REST object.
1444 *
1445 * @todo figure this one out. it's possible this is only used in maps and
1446 * could be a specialized map implementation.
1447 */
1448class /*RT_DECL_CLASS*/ RTCRestObject : public RTCRestObjectBase
1449{
1450public:
1451 /** Default destructor. */
1452 RTCRestObject();
1453 /** Destructor. */
1454 virtual ~RTCRestObject();
1455
1456 /** Copy constructor. */
1457 RTCRestObject(RTCRestObject const &a_rThat);
1458 /** Copy assignment operator. */
1459 RTCRestObject &operator=(RTCRestObject const &a_rThat);
1460 /** Safe Safe copy assignment method. */
1461 int assignCopy(RTCRestObject const &a_rThat);
1462
1463 /* Overridden methods: */
1464 virtual int setNull(void) RT_OVERRIDE;
1465 virtual int resetToDefault() RT_OVERRIDE;
1466 virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_OVERRIDE;
1467 virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_OVERRIDE;
1468 virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = kCollectionFormat_Unspecified) const RT_OVERRIDE;
1469 virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
1470 uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_OVERRIDE;
1471 virtual kTypeClass typeClass(void) const RT_OVERRIDE;
1472 virtual const char *typeName(void) const RT_OVERRIDE;
1473
1474 /** Factory method. */
1475 static DECLCALLBACK(RTCRestObjectBase *) createInstance(void);
1476
1477protected:
1478 /** @todo figure out the value stuff here later... */
1479};
1480
1481
1482/**
1483 * Base class for REST client requests.
1484 *
1485 * This encapsulates parameters and helps transform them into a HTTP request.
1486 *
1487 * Parameters can be transfered in a number of places:
1488 * - Path part of the URL.
1489 * - Query part of the URL.
1490 * - HTTP header fields.
1491 * - FORM body.
1492 * - JSON body.
1493 * - XML body.
1494 * - ...
1495 *
1496 * They can be require or optional. The latter may have default values. In
1497 * swagger 3 they can also be nullable, which means the null-indicator cannot
1498 * be used for tracking optional parameters.
1499 */
1500class RT_DECL_CLASS RTCRestClientRequestBase
1501{
1502public:
1503 RTCRestClientRequestBase();
1504 virtual ~RTCRestClientRequestBase();
1505 RTCRestClientRequestBase(RTCRestClientRequestBase const &a_rThat);
1506 RTCRestClientRequestBase &operator=(RTCRestClientRequestBase const &a_rThat);
1507
1508 /**
1509 * Reset all members to default values.
1510 * @returns IPRT status code.
1511 */
1512 virtual int resetToDefault() = 0;
1513
1514 /**
1515 * Prepares the HTTP handle for transmitting this request.
1516 *
1517 * @returns IPRT status code.
1518 * @param a_pStrPath Where to set path parameters. Will be appended to the base path.
1519 * @param a_pStrQuery Where to set query parameters.
1520 * @param a_hHttp Where to set header parameters and such.
1521 * @param a_pStrBody Where to set body parameters.
1522 */
1523 virtual int xmitPrepare(RTCString *a_pStrPath, RTCString *a_pStrQuery, RTHTTP a_hHttp, RTCString *a_pStrBody) const = 0;
1524
1525 /**
1526 * Always called after the request has been transmitted.
1527 *
1528 * @param a_rcStatus Negative numbers are IPRT errors, positive are HTTP status codes.
1529 * @param a_hHttp The HTTP handle the request was performed on.
1530 */
1531 virtual void xmitComplete(int a_rcStatus, RTHTTP a_hHttp) const = 0;
1532
1533 /**
1534 * Checks if there are were any assignment errors.
1535 */
1536 bool hasAssignmentErrors() const { return m_fErrorSet != 0; }
1537
1538protected:
1539 /** Set of fields that have been explicitly assigned a value. */
1540 uint64_t m_fIsSet;
1541 /** Set of fields where value assigning failed. */
1542 uint64_t m_fErrorSet;
1543
1544 /** Path parameter descriptor. */
1545 typedef struct
1546 {
1547 const char *pszName; /**< The name string to replace (including {}). */
1548 size_t cchName; /**< Length of pszName. */
1549 uint32_t fFlags; /**< The toString flags. */
1550 uint8_t iBitNo; /**< The parameter bit number. */
1551 } PATHPARAMDESC;
1552
1553 /** Path parameter state. */
1554 typedef struct
1555 {
1556 RTCRestObjectBase const *pObj; /**< Pointer to the parameter object. */
1557 size_t offName; /**< Maintained by worker. */
1558 } PATHPARAMSTATE;
1559
1560 /**
1561 * Do path parameters.
1562 *
1563 * @returns IPRT status code
1564 * @param a_pStrPath The destination path.
1565 * @param a_pszPathTemplate The path template string.
1566 * @param a_cchPathTemplate The length of the path template string.
1567 * @param a_paPathParams The path parameter descriptors (static).
1568 * @param a_paPathParamStates The path parameter objects and states.
1569 * @param a_cPathParams Number of path parameters.
1570 */
1571 int doPathParameters(RTCString *a_pStrPath, const char *a_pszPathTemplate, size_t a_cchPathTemplate,
1572 PATHPARAMDESC const *a_paPathParams, PATHPARAMSTATE *a_paPathParamStates, size_t a_cPathParams) const;
1573
1574 /** Query parameter descriptor. */
1575 typedef struct
1576 {
1577 const char *pszName; /**< The parameter name. */
1578 uint32_t fFlags; /**< The toString flags. */
1579 bool fRequired; /**< Required or not. */
1580 uint8_t iBitNo; /**< The parameter bit number. */
1581 } QUERYPARAMDESC;
1582
1583 /**
1584 * Do query parameters.
1585 *
1586 * @returns IPRT status code
1587 * @param a_pStrQuery The destination string.
1588 * @param a_paQueryParams The query parameter descriptors.
1589 * @param a_papQueryParamObjs The query parameter objects, parallel to @a a_paQueryParams.
1590 * @param a_cQueryParams Number of query parameters.
1591 */
1592 int doQueryParameters(RTCString *a_pStrQuery, QUERYPARAMDESC const *a_paQueryParams,
1593 RTCRestObjectBase const **a_papQueryParamObjs, size_t a_cQueryParams) const;
1594
1595 /** Header parameter descriptor. */
1596 typedef struct
1597 {
1598 const char *pszName; /**< The parameter name. */
1599 uint32_t fFlags; /**< The toString flags. */
1600 bool fRequired; /**< Required or not. */
1601 uint8_t iBitNo; /**< The parameter bit number. */
1602 bool fMapCollection; /**< Collect headers starting with pszName into a map. */
1603 } HEADERPARAMDESC;
1604
1605 /**
1606 * Do header parameters.
1607 *
1608 * @returns IPRT status code
1609 * @param a_hHttp Where to set header parameters.
1610 * @param a_paHeaderParams The header parameter descriptors.
1611 * @param a_papHeaderParamObjs The header parameter objects, parallel to @a a_paHeaderParams.
1612 * @param a_cHeaderParams Number of header parameters.
1613 */
1614 int doHeaderParameters(RTHTTP a_hHttp, HEADERPARAMDESC const *a_paHeaderParams,
1615 RTCRestObjectBase const **a_papHeaderParamObjs, size_t a_cHeaderParams) const;
1616};
1617
1618
1619/**
1620 * Base class for REST client responses.
1621 */
1622class RT_DECL_CLASS RTCRestClientResponseBase
1623{
1624public:
1625 /** Default constructor. */
1626 RTCRestClientResponseBase();
1627 /** Destructor. */
1628 virtual ~RTCRestClientResponseBase();
1629 /** Copy constructor. */
1630 RTCRestClientResponseBase(RTCRestClientResponseBase const &a_rThat);
1631 /** Copy assignment operator. */
1632 RTCRestClientResponseBase &operator=(RTCRestClientResponseBase const &a_rThat);
1633
1634 /**
1635 * Resets the object state.
1636 */
1637 virtual void reset(void);
1638
1639 /**
1640 * Prepares the HTTP handle for receiving the response.
1641 *
1642 * This may install callbacks and such like.
1643 *
1644 * @returns IPRT status code.
1645 * @param a_hHttp The HTTP handle to prepare for receiving.
1646 * @param a_pppvHdr If a header callback handler is installed, set the value pointed to to NULL.
1647 * @param a_pppvBody If a body callback handler is installed, set the value pointed to to NULL.
1648 */
1649 virtual int receivePrepare(RTHTTP a_hHttp, void ***a_pppvHdr, void ***a_pppvBody);
1650
1651 /**
1652 * Called when the HTTP request has been completely received.
1653 *
1654 * @param a_rcStatus Negative numbers are IPRT errors, positive are HTTP status codes.
1655 * @param a_hHttp The HTTP handle the request was performed on.
1656 * This can be NIL_RTHTTP should something fail early, in
1657 * which case it is possible receivePrepare() wasn't called.
1658 *
1659 * @note Called before consumeHeaders() and consumeBody().
1660 */
1661 virtual void receiveComplete(int a_rcStatus, RTHTTP a_hHttp);
1662
1663 /**
1664 * Callback that consumes HTTP header data from the server.
1665 *
1666 * @param a_pchData Body data.
1667 * @param a_cbData Amount of body data.
1668 *
1669 * @note Called after receiveComplete()..
1670 */
1671 virtual void consumeHeaders(const char *a_pchData, size_t a_cbData);
1672
1673 /**
1674 * Callback that consumes HTTP body data from the server.
1675 *
1676 * @param a_pchData Body data.
1677 * @param a_cbData Amount of body data.
1678 *
1679 * @note Called after consumeHeaders().
1680 */
1681 virtual void consumeBody(const char *a_pchData, size_t a_cbData);
1682
1683 /**
1684 * Called after status, headers and body all have been presented.
1685 *
1686 * @returns IPRT status code.
1687 */
1688 virtual void receiveFinal();
1689
1690 /**
1691 * Getter for m_rcStatus.
1692 * @returns Negative numbers are IPRT errors, positive are HTTP status codes.
1693 */
1694 int getStatus() { return m_rcStatus; }
1695
1696 /**
1697 * Getter for m_rcHttp.
1698 * @returns HTTP status code or VERR_NOT_AVAILABLE.
1699 */
1700 int getHttpStatus() { return m_rcHttp; }
1701
1702 /**
1703 * Getter for m_pErrInfo.
1704 */
1705 PCRTERRINFO getErrInfo(void) const { return m_pErrInfo; }
1706
1707 /**
1708 * Getter for m_strContentType.
1709 */
1710 RTCString const &getContentType(void) const { return m_strContentType; }
1711
1712
1713protected:
1714 /** Negative numbers are IPRT errors, positive are HTTP status codes. */
1715 int m_rcStatus;
1716 /** The HTTP status code, VERR_NOT_AVAILABLE if not set. */
1717 int m_rcHttp;
1718 /** Error information. */
1719 PRTERRINFO m_pErrInfo;
1720 /** The value of the Content-Type header field. */
1721 RTCString m_strContentType;
1722
1723 PRTERRINFO getErrInfoInternal(void);
1724 void deleteErrInfo(void);
1725 void copyErrInfo(PCRTERRINFO pErrInfo);
1726
1727 /**
1728 * Reports an error (or warning if a_rc non-negative).
1729 *
1730 * @returns a_rc
1731 * @param a_rc The status code to report and return. The first
1732 * error status is assigned to m_rcStatus, subsequent
1733 * ones as well as informational statuses are not
1734 * recorded by m_rcStatus.
1735 * @param a_pszFormat The message format string.
1736 * @param ... Message arguments.
1737 */
1738 int addError(int a_rc, const char *a_pszFormat, ...);
1739
1740 /** Field flags. */
1741 enum
1742 {
1743 /** Collection map, name is a prefix followed by '*'. */
1744 kHdrField_MapCollection = RT_BIT_32(24),
1745 };
1746
1747 /** Header field descriptor. */
1748 typedef struct
1749 {
1750 /** The header field name. */
1751 const char *pszName;
1752 /** The length of the field name.*/
1753 uint32_t cchName;
1754 /** Flags, TBD. */
1755 uint32_t fFlags;
1756 /** Object factory. */
1757 RTCRestObjectBase::PFNCREATEINSTANCE pfnCreateInstance;
1758 } HEADERFIELDDESC;
1759
1760 /**
1761 * Helper that extracts fields from the HTTP headers.
1762 *
1763 * @param a_paFieldDescs Pointer to an array of field descriptors.
1764 * @param a_pappFieldValues Pointer to a parallel array of value pointer pointers.
1765 * @param a_cFields Number of field descriptors..
1766 * @param a_pchData The header blob to search.
1767 * @param a_cbData The size of the header blob to search.
1768 */
1769 void extracHeaderFieldsFromBlob(HEADERFIELDDESC const *a_paFieldDescs, RTCRestObjectBase ***a_pappFieldValues,
1770 size_t a_cFields, const char *a_pchData, size_t a_cbData);
1771
1772 /**
1773 * Helper that extracts a header field.
1774 *
1775 * @retval VINF_SUCCESS
1776 * @retval VERR_NOT_FOUND if not found.
1777 * @retval VERR_NO_STR_MEMORY
1778 * @param a_pszField The header field header name.
1779 * @param a_cchField The length of the header field name.
1780 * @param a_pchData The header blob to search.
1781 * @param a_cbData The size of the header blob to search.
1782 * @param a_pStrDst Where to store the header value on successs.
1783 */
1784 int extractHeaderFromBlob(const char *a_pszField, size_t a_cchField, const char *a_pchData, size_t a_cbData,
1785 RTCString *a_pStrDst);
1786
1787 /**
1788 * Helper that does the deserializing of the response body.
1789 *
1790 * @param a_pDst The destination object for the body content.
1791 * @param a_pchData The body blob.
1792 * @param a_cbData The size of the body blob.
1793 */
1794 void deserializeBody(RTCRestObjectBase *a_pDst, const char *a_pchData, size_t a_cbData);
1795
1796 /**
1797 * Primary json cursor for parsing bodies.
1798 */
1799 class PrimaryJsonCursorForBody : public RTCRestJsonPrimaryCursor
1800 {
1801 public:
1802 RTCRestClientResponseBase *m_pThat; /**< Pointer to response object. */
1803 PrimaryJsonCursorForBody(RTJSONVAL hValue, const char *pszName, RTCRestClientResponseBase *a_pThat);
1804 virtual int addError(RTCRestJsonCursor const &a_rCursor, int a_rc, const char *a_pszFormat, ...) RT_OVERRIDE;
1805 virtual int unknownField(RTCRestJsonCursor const &a_rCursor) RT_OVERRIDE;
1806 };
1807};
1808
1809
1810/**
1811 * Base class for REST client responses.
1812 */
1813class RT_DECL_CLASS RTCRestClientApiBase
1814{
1815public:
1816 RTCRestClientApiBase()
1817 : m_hHttp(NIL_RTHTTP)
1818 {}
1819 virtual ~RTCRestClientApiBase();
1820
1821 /** @name Base path (URL) handling.
1822 * @{ */
1823 /**
1824 * Gets the base path we're using.
1825 *
1826 * @returns Base URL string. If empty, we'll be using the default one.
1827 */
1828 RTCString const &getBasePath(void) const
1829 {
1830 return m_strBasePath;
1831 }
1832
1833 /**
1834 * Sets the base path (URL) to use when talking to the server.
1835 *
1836 * Setting the base path is only required if there is a desire to use a
1837 * different server from the one specified in the API specification, like
1838 * for instance regional one.
1839 *
1840 * @param a_pszPath The base path to use.
1841 */
1842 virtual void setBasePath(const char *a_pszPath)
1843 {
1844 m_strBasePath = a_pszPath;
1845 }
1846
1847 /**
1848 * Sets the base path (URL) to use when talking to the server.
1849 *
1850 * Setting the base path is only required if there is a desire to use a
1851 * different server from the one specified in the API specification, like
1852 * for instance regional one.
1853 *
1854 * @param a_strPath The base path to use.
1855 * @note Defers to the C-string variant.
1856 */
1857 void setBasePath(RTCString const &a_strPath) { setBasePath(a_strPath.c_str()); }
1858
1859 /**
1860 * Gets the default base path (URL) as specified in the specs.
1861 *
1862 * @returns Base path (URL) string.
1863 */
1864 virtual const char *getDefaultBasePath() = 0;
1865 /** @} */
1866
1867protected:
1868 /** Handle to the HTTP connection object. */
1869 RTHTTP m_hHttp;
1870 /** The base path to use. */
1871 RTCString m_strBasePath;
1872
1873 /* Make non-copyable (RTCNonCopyable causes warnings): */
1874 RTCRestClientApiBase(RTCRestOutputToString const &);
1875 RTCRestClientApiBase *operator=(RTCRestOutputToString const &);
1876
1877 /**
1878 * Re-initializes the HTTP instance.
1879 *
1880 * @returns IPRT status code.
1881 */
1882 virtual int reinitHttpInstance();
1883
1884 /**
1885 * Implements stuff for making an API call.
1886 *
1887 * @returns a_pResponse->getStatus()
1888 * @param a_rRequest Reference to the request object.
1889 * @param a_enmHttpMethod The HTTP request method.
1890 * @param a_pResponse Pointer to the response object.
1891 * @param a_pszMethod The method name, for logging purposes.
1892 */
1893 virtual int doCall(RTCRestClientRequestBase const &a_rRequest, RTHTTPMETHOD a_enmHttpMethod,
1894 RTCRestClientResponseBase *a_pResponse, const char *a_pszMethod);
1895
1896};
1897
1898/** @} */
1899
1900#endif
1901
Note: See TracBrowser for help on using the repository browser.

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