VirtualBox

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

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

IPRT/rest: Early support for polymorphic data objects in the data model. bugref:9167

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 39.4 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.215389.xyz. 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/cdefs.h>
30#include <iprt/types.h>
31#include <iprt/json.h>
32#include <iprt/stdarg.h>
33#include <iprt/time.h>
34#include <iprt/cpp/ministring.h>
35
36
37/** @defgroup grp_rt_cpp_restbase C++ Representational State Transfer (REST) Base Classes.
38 * @ingroup grp_rt_cpp
39 * @{
40 */
41
42
43
44/**
45 * Abstract base class for serializing data objects.
46 */
47class RT_DECL_CLASS RTCRestOutputBase
48{
49public:
50 RTCRestOutputBase()
51 : m_uIndent(0)
52 { }
53 virtual ~RTCRestOutputBase()
54 { }
55
56 /**
57 * RTStrPrintf like function (see @ref pg_rt_str_format).
58 *
59 * @returns Number of bytes outputted.
60 * @param pszFormat The format string.
61 * @param ... Argument specfied in @a pszFormat.
62 */
63 size_t printf(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(2, 3)
64 {
65 va_list va;
66 va_start(va, pszFormat);
67 size_t cchWritten = this->vprintf(pszFormat, va);
68 va_end(va);
69 return cchWritten;
70 }
71
72 /**
73 * RTStrPrintfV like function (see @ref pg_rt_str_format).
74 *
75 * @returns Number of bytes outputted.
76 * @param pszFormat The format string.
77 * @param va Argument specfied in @a pszFormat.
78 */
79 virtual size_t vprintf(const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(2, 0) = 0;
80
81 /**
82 * Sets the indentation level for use when pretty priting things.
83 *
84 * @returns Previous indentation level.
85 * @param uIndent The indentation level.
86 */
87 inline unsigned setIndent(unsigned uIndent)
88 {
89 unsigned const uRet = m_uIndent;
90 m_uIndent = uIndent;
91 return uRet;
92 }
93
94 /**
95 * Increases the indentation level.
96 *
97 * @returns Previous indentation level.
98 */
99 inline unsigned incrementIndent()
100 {
101 unsigned const uRet = m_uIndent;
102 m_uIndent = uRet + 1;
103 return uRet;
104 }
105
106protected:
107 /** The current indentation level. */
108 unsigned m_uIndent;
109};
110
111
112/**
113 * Serialize to a string object.
114 */
115class RT_DECL_CLASS RTCRestOutputToString : public RTCRestOutputBase
116{
117public:
118 /**
119 * Creates an instance that appends to @a a_pDst.
120 * @param a_pDst Pointer to the destination string object.
121 * NULL is not accepted and will assert.
122 * @param a_fAppend Whether to append to the current string value, or
123 * nuke the string content before starting the output.
124 */
125 RTCRestOutputToString(RTCString *a_pDst, bool a_fAppend = false);
126 virtual ~RTCRestOutputToString();
127
128 virtual size_t vprintf(const char *pszFormat, va_list va) RT_OVERRIDE;
129
130 /**
131 * Finalizes the output and releases the string object to the caller.
132 *
133 * @returns The released string object. NULL if we ran out of memory or if
134 * called already.
135 *
136 * @remark This sets m_pDst to NULL and the object cannot be use for any
137 * more output afterwards.
138 */
139 virtual RTCString *finalize();
140
141
142protected:
143 /** Pointer to the destination string. NULL after finalize(). */
144 RTCString *m_pDst;
145 /** Set if we ran out of memory and should ignore subsequent calls. */
146 bool m_fOutOfMemory;
147
148 /** @callback_method_impl{FNRTSTROUTPUT} */
149 static DECLCALLBACK(size_t) strOutput(void *pvArg, const char *pachChars, size_t cbChars);
150
151 /* Make non-copyable (RTCNonCopyable causes warnings): */
152 RTCRestOutputToString(RTCRestOutputToString const &);
153 RTCRestOutputToString *operator=(RTCRestOutputToString const &);
154};
155
156
157/* forward decl: */
158class RTCRestJsonPrimaryCursor;
159
160/**
161 * JSON cursor structure.
162 *
163 * This reduces the number of parameters passed around when deserializing JSON
164 * input and also helps constructing full object name for logging and error reporting.
165 */
166struct RT_DECL_CLASS RTCRestJsonCursor
167{
168 /** Handle to the value being parsed. */
169 RTJSONVAL m_hValue;
170 /** Name of the value. */
171 const char *m_pszName;
172 /** Pointer to the parent, NULL if primary. */
173 struct RTCRestJsonCursor const *m_pParent;
174 /** Pointer to the primary cursor structure. */
175 RTCRestJsonPrimaryCursor *m_pPrimary;
176
177 RTCRestJsonCursor(struct RTCRestJsonCursor const &a_rParent)
178 : m_hValue(NIL_RTJSONVAL), m_pszName(NULL), m_pParent(&a_rParent), m_pPrimary(a_rParent.m_pPrimary)
179 { }
180
181 RTCRestJsonCursor(RTJSONVAL hValue, const char *pszName, struct RTCRestJsonCursor *pParent)
182 : m_hValue(hValue), m_pszName(pszName), m_pParent(pParent), m_pPrimary(pParent->m_pPrimary)
183 { }
184
185 RTCRestJsonCursor(RTJSONVAL hValue, const char *pszName)
186 : m_hValue(hValue), m_pszName(pszName), m_pParent(NULL), m_pPrimary(NULL)
187 { }
188
189 ~RTCRestJsonCursor()
190 {
191 if (m_hValue != NIL_RTJSONVAL)
192 {
193 RTJsonValueRelease(m_hValue);
194 m_hValue = NIL_RTJSONVAL;
195 }
196 }
197};
198
199
200/**
201 * The primary JSON cursor class.
202 */
203class RT_DECL_CLASS RTCRestJsonPrimaryCursor
204{
205public:
206 /** The cursor for the first level. */
207 RTCRestJsonCursor m_Cursor;
208 /** Error info keeper. */
209 PRTERRINFO m_pErrInfo;
210
211 /** Creates a primary json cursor with optiona error info. */
212 RTCRestJsonPrimaryCursor(RTJSONVAL hValue, const char *pszName, PRTERRINFO pErrInfo = NULL)
213 : m_Cursor(hValue, pszName)
214 , m_pErrInfo(pErrInfo)
215 {
216 m_Cursor.m_pPrimary = this;
217 }
218
219 virtual ~RTCRestJsonPrimaryCursor()
220 { }
221
222 /**
223 * Add an error message.
224 *
225 * @returns a_rc
226 * @param a_rCursor The cursor reporting the error.
227 * @param a_rc The status code.
228 * @param a_pszFormat Format string.
229 * @param ... Format string arguments.
230 */
231 virtual int addError(RTCRestJsonCursor const &a_rCursor, int a_rc, const char *a_pszFormat, ...);
232
233 /**
234 * Reports that the current field is not known.
235 *
236 * @returns Status to propagate.
237 * @param a_rCursor The cursor for the field.
238 */
239 virtual int unknownField(RTCRestJsonCursor const &a_rCursor);
240
241 /**
242 * Copies the full path into pszDst.
243 *
244 * @returns pszDst
245 * @param a_rCursor The cursor to start walking at.
246 * @param a_pszDst Where to put the path.
247 * @param a_cbDst Size of the destination buffer.
248 */
249 virtual char *getPath(RTCRestJsonCursor const &a_rCursor, char *a_pszDst, size_t a_cbDst) const;
250};
251
252
253/**
254 * Abstract base class for REST primitive types and data objects (via
255 * RTCRestDataObject).
256 *
257 * The only information this keeps is the null indicator.
258 */
259class RT_DECL_CLASS RTCRestObjectBase
260{
261public:
262 RTCRestObjectBase();
263 RTCRestObjectBase(RTCRestObjectBase const &a_rThat);
264 virtual ~RTCRestObjectBase();
265
266 /**
267 * Create a copy of this object.
268 *
269 * @returns Pointer to copy.
270 */
271 virtual RTCRestObjectBase *baseClone() const = 0;
272
273 /**
274 * Tests if the object is @a null.
275 * @returns true if null, false if not.
276 */
277 inline bool isNull(void) const { return m_fNullIndicator; };
278
279 /**
280 * Sets the object to @a null and fills it with defaults.
281 * @returns IPRT status code (from resetToDefault).
282 */
283 virtual int setNull(void);
284
285 /**
286 * Sets the object to not-null state (i.e. undoes setNull()).
287 * @remarks Only really important for strings.
288 */
289 virtual void setNotNull(void);
290
291 /**
292 * Resets the object to all default values.
293 * @returns IPRT status code.
294 */
295 virtual int resetToDefault() = 0;
296
297 /**
298 * Serialize the object as JSON.
299 *
300 * @returns a_rDst
301 * @param a_rDst The destination for the serialization.
302 */
303 virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const = 0;
304
305 /**
306 * Deserialize object from the given JSON iterator.
307 *
308 * @returns IPRT status code.
309 * @param a_rCursor The JSON cursor.
310 */
311 virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) = 0;
312
313 /**
314 * Flags for toString().
315 *
316 * The kCollectionFormat_xxx bunch controls multiple values in arrays
317 * are formatted. They are ignored by everyone else.
318 *
319 * @note When adding collection format types, make sure to also
320 * update RTCRestArrayBase::toString().
321 * @note Bit 24 is reserved (for kHdrField_MapCollection).
322 */
323 enum
324 {
325 kCollectionFormat_Unspecified = 0, /**< Not specified. */
326 kCollectionFormat_csv, /**< Comma-separated list. */
327 kCollectionFormat_ssv, /**< Space-separated list. */
328 kCollectionFormat_tsv, /**< Tab-separated list. */
329 kCollectionFormat_pipes, /**< Pipe-separated list. */
330 kCollectionFormat_multi, /**< Special collection type that must be handled by caller of toString. */
331 kCollectionFormat_Mask = 7, /**< Collection type mask. */
332
333 kToString_Append = 8 /**< Append to the string/object (rather than assigning). */
334 };
335
336 /**
337 * String conversion.
338 *
339 * The default implementation of is a wrapper around serializeAsJson().
340 *
341 * @returns IPRT status code.
342 * @param a_pDst Pointer to the destionation string.
343 * @param a_fFlags kCollectionFormat_xxx.
344 */
345 virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = kCollectionFormat_Unspecified) const;
346
347 /**
348 * String convertsion, naive variant.
349 *
350 * @returns String represenation.
351 */
352 RTCString toString() const;
353
354 /**
355 * Convert from (header) string value.
356 *
357 * The default implementation of is a wrapper around deserializeFromJson().
358 *
359 * @returns IPRT status code.
360 * @param a_rValue The string value string to parse.
361 * @param a_pszName Field name or similar.
362 * @param a_pErrInfo Where to return additional error info. Optional.
363 * @param a_fFlags kCollectionFormat_xxx.
364 */
365 virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
366 uint32_t a_fFlags = kCollectionFormat_Unspecified);
367
368 /** Type classification */
369 typedef enum kTypeClass
370 {
371 kTypeClass_Invalid = 0,
372 kTypeClass_Bool, /**< Primitive: bool. */
373 kTypeClass_Int64, /**< Primitive: int64_t. */
374 kTypeClass_Int32, /**< Primitive: int32_t. */
375 kTypeClass_Int16, /**< Primitive: int16_t. */
376 kTypeClass_Double, /**< Primitive: double. */
377 kTypeClass_String, /**< Primitive: string. */
378 kTypeClass_Date, /**< Date. */
379 kTypeClass_Uuid, /**< UUID. */
380 kTypeClass_Binary, /**< Binary blob. */
381 kTypeClass_DataObject, /**< Data object child (RTCRestDataObject). */
382 kTypeClass_AnyObject, /**< Any kind of object (RTCRestAnyObject). */
383 kTypeClass_Array, /**< Array (containing any kind of object). */
384 kTypeClass_StringMap, /**< String map (containing any kind of object). */
385 kTypeClass_StringEnum /**< String enum. */
386 } kTypeClass;
387
388 /**
389 * Returns the object type class.
390 */
391 virtual kTypeClass typeClass(void) const = 0;
392
393 /**
394 * Returns the object type name.
395 */
396 virtual const char *typeName(void) const = 0;
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 constructor. */
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 /** Make a clone of this object. */
431 inline RTCRestBool *clone() const { return (RTCRestBool *)baseClone(); }
432
433 /* Overridden methods: */
434 virtual RTCRestObjectBase *baseClone() const RT_OVERRIDE;
435 virtual int resetToDefault() RT_OVERRIDE;
436 virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_OVERRIDE;
437 virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_OVERRIDE;
438 virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = 0) const RT_OVERRIDE;
439 virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
440 uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_OVERRIDE;
441 virtual kTypeClass typeClass(void) const RT_OVERRIDE;
442 virtual const char *typeName(void) const RT_OVERRIDE;
443
444 /** Factory method. */
445 static DECLCALLBACK(RTCRestObjectBase *) createInstance(void);
446
447public:
448 /** The value. */
449 bool m_fValue;
450};
451
452
453/**
454 * Class wrapping 'int64_t'.
455 */
456class RT_DECL_CLASS RTCRestInt64 : public RTCRestObjectBase
457{
458public:
459 /** Default constructor. */
460 RTCRestInt64();
461 /** Copy constructor. */
462 RTCRestInt64(RTCRestInt64 const &a_rThat);
463 /** From value constructor. */
464 RTCRestInt64(int64_t a_iValue);
465 /** Destructor. */
466 virtual ~RTCRestInt64();
467 /** Copy assignment operator. */
468 RTCRestInt64 &operator=(RTCRestInt64 const &a_rThat);
469 /** Safe copy assignment method. */
470 int assignCopy(RTCRestInt64 const &a_rThat);
471 /** Assign value and clear null indicator. */
472 void assignValue(int64_t a_iValue);
473 /** Make a clone of this object. */
474 inline RTCRestInt64 *clone() const { return (RTCRestInt64 *)baseClone(); }
475
476 /* Overridden methods: */
477 virtual RTCRestObjectBase *baseClone() const RT_OVERRIDE;
478 virtual int resetToDefault() RT_OVERRIDE;
479 virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_OVERRIDE;
480 virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_OVERRIDE;
481 virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = 0) const RT_OVERRIDE;
482 virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
483 uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_OVERRIDE;
484 virtual kTypeClass typeClass(void) const RT_OVERRIDE;
485 virtual const char *typeName(void) const RT_OVERRIDE;
486
487 /** Factory method. */
488 static DECLCALLBACK(RTCRestObjectBase *) createInstance(void);
489
490public:
491 /** The value. */
492 int64_t m_iValue;
493};
494
495
496/**
497 * Class wrapping 'int32_t'.
498 */
499class RT_DECL_CLASS RTCRestInt32 : public RTCRestObjectBase
500{
501public:
502 /** Default constructor. */
503 RTCRestInt32();
504 /** Copy constructor. */
505 RTCRestInt32(RTCRestInt32 const &a_rThat);
506 /** From value constructor. */
507 RTCRestInt32(int32_t iValue);
508 /** Destructor. */
509 virtual ~RTCRestInt32();
510 /** Copy assignment operator. */
511 RTCRestInt32 &operator=(RTCRestInt32 const &a_rThat);
512 /** Safe copy assignment method. */
513 int assignCopy(RTCRestInt32 const &a_rThat);
514 /** Assign value and clear null indicator. */
515 void assignValue(int32_t a_iValue);
516 /** Make a clone of this object. */
517 inline RTCRestInt32 *clone() const { return (RTCRestInt32 *)baseClone(); }
518
519 /* Overridden methods: */
520 virtual RTCRestObjectBase *baseClone() const RT_OVERRIDE;
521 virtual int resetToDefault() RT_OVERRIDE;
522 virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_OVERRIDE;
523 virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_OVERRIDE;
524 virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = 0) const RT_OVERRIDE;
525 virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
526 uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_OVERRIDE;
527 virtual kTypeClass typeClass(void) const RT_OVERRIDE;
528 virtual const char *typeName(void) const RT_OVERRIDE;
529
530 /** Factory method. */
531 static DECLCALLBACK(RTCRestObjectBase *) createInstance(void);
532
533public:
534 /** The value. */
535 int32_t m_iValue;
536};
537
538
539/**
540 * Class wrapping 'int16_t'.
541 */
542class RT_DECL_CLASS RTCRestInt16 : public RTCRestObjectBase
543{
544public:
545 /** Default constructor. */
546 RTCRestInt16();
547 /** Copy constructor. */
548 RTCRestInt16(RTCRestInt16 const &a_rThat);
549 /** From value constructor. */
550 RTCRestInt16(int16_t iValue);
551 /** Destructor. */
552 virtual ~RTCRestInt16();
553 /** Copy assignment operator. */
554 RTCRestInt16 &operator=(RTCRestInt16 const &a_rThat);
555 /** Safe copy assignment method. */
556 int assignCopy(RTCRestInt16 const &a_rThat);
557 /** Assign value and clear null indicator. */
558 void assignValue(int16_t a_iValue);
559 /** Make a clone of this object. */
560 inline RTCRestInt16 *clone() const { return (RTCRestInt16 *)baseClone(); }
561
562 /* Overridden methods: */
563 virtual RTCRestObjectBase *baseClone() const RT_OVERRIDE;
564 virtual int resetToDefault() RT_OVERRIDE;
565 virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_OVERRIDE;
566 virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_OVERRIDE;
567 virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = 0) const RT_OVERRIDE;
568 virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
569 uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_OVERRIDE;
570 virtual kTypeClass typeClass(void) const RT_OVERRIDE;
571 virtual const char *typeName(void) const RT_OVERRIDE;
572
573 /** Factory method. */
574 static DECLCALLBACK(RTCRestObjectBase *) createInstance(void);
575
576public:
577 /** The value. */
578 int16_t m_iValue;
579};
580
581
582/**
583 * Class wrapping 'double'.
584 */
585class RT_DECL_CLASS RTCRestDouble : public RTCRestObjectBase
586{
587public:
588 /** Default constructor. */
589 RTCRestDouble();
590 /** Copy constructor. */
591 RTCRestDouble(RTCRestDouble const &a_rThat);
592 /** From value constructor. */
593 RTCRestDouble(double rdValue);
594 /** Destructor. */
595 virtual ~RTCRestDouble();
596 /** Copy assignment operator. */
597 RTCRestDouble &operator=(RTCRestDouble const &a_rThat);
598 /** Safe copy assignment method. */
599 int assignCopy(RTCRestDouble const &a_rThat);
600 /** Assign value and clear null indicator. */
601 void assignValue(double a_rdValue);
602 /** Make a clone of this object. */
603 inline RTCRestDouble *clone() const { return (RTCRestDouble *)baseClone(); }
604
605 /* Overridden methods: */
606 virtual RTCRestObjectBase *baseClone() const RT_OVERRIDE;
607 virtual int resetToDefault() RT_OVERRIDE;
608 virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_OVERRIDE;
609 virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_OVERRIDE;
610 virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = 0) const RT_OVERRIDE;
611 virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
612 uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_OVERRIDE;
613 virtual kTypeClass typeClass(void) const RT_OVERRIDE;
614 virtual const char *typeName(void) const RT_OVERRIDE;
615
616 /** Factory method. */
617 static DECLCALLBACK(RTCRestObjectBase *) createInstance(void);
618
619public:
620 /** The value. */
621 double m_rdValue;
622};
623
624
625/**
626 * Class wrapping 'RTCString'.
627 */
628class RT_DECL_CLASS RTCRestString : public RTCRestObjectBase, public RTCString
629{
630public:
631 /** Default constructor. */
632 RTCRestString();
633 /** Destructor. */
634 virtual ~RTCRestString();
635
636 /** Copy constructor. */
637 RTCRestString(RTCRestString const &a_rThat);
638 /** From value constructor. */
639 RTCRestString(RTCString const &a_rThat);
640 /** From value constructor. */
641 RTCRestString(const char *a_pszSrc);
642 /** Safe copy assignment method. */
643 int assignCopy(RTCRestString const &a_rThat);
644 /** Safe copy assignment method. */
645 int assignCopy(RTCString const &a_rThat);
646 /** Safe copy assignment method. */
647 int assignCopy(const char *a_pszThat);
648 /** Make a clone of this object. */
649 inline RTCRestString *clone() const { return (RTCRestString *)baseClone(); }
650
651 /* Overridden methods: */
652 virtual RTCRestObjectBase *baseClone() const RT_OVERRIDE;
653 virtual int setNull(void) RT_OVERRIDE; /* (ambigious, so overrider it to make sure.) */
654 virtual int resetToDefault() RT_OVERRIDE;
655 virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_OVERRIDE;
656 virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_OVERRIDE;
657 virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = kCollectionFormat_Unspecified) const RT_OVERRIDE;
658 virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
659 uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_OVERRIDE;
660 virtual kTypeClass typeClass(void) const RT_OVERRIDE;
661 virtual const char *typeName(void) const RT_OVERRIDE;
662
663 /** Factory method. */
664 static DECLCALLBACK(RTCRestObjectBase *) createInstance(void);
665
666 /** @name RTCString assignment methods we need to replace to manage the null indicator
667 * @{ */
668 int assignNoThrow(const RTCString &a_rSrc) RT_NOEXCEPT;
669 int assignNoThrow(const char *a_pszSrc) RT_NOEXCEPT;
670 int assignNoThrow(const RTCString &a_rSrc, size_t a_offSrc, size_t a_cchSrc = npos) RT_NOEXCEPT;
671 int assignNoThrow(const char *a_pszSrc, size_t a_cchSrc) RT_NOEXCEPT;
672 int assignNoThrow(size_t a_cTimes, char a_ch) RT_NOEXCEPT;
673 int printfNoThrow(const char *pszFormat, ...) RT_NOEXCEPT RT_IPRT_FORMAT_ATTR(1, 2);
674 int printfVNoThrow(const char *pszFormat, va_list va) RT_NOEXCEPT RT_IPRT_FORMAT_ATTR(1, 0);
675 RTCRestString &operator=(const char *a_pcsz);
676 RTCRestString &operator=(const RTCString &a_rThat);
677 RTCRestString &operator=(const RTCRestString &a_rThat);
678 RTCRestString &assign(const RTCString &a_rSrc);
679 RTCRestString &assign(const char *a_pszSrc);
680 RTCRestString &assign(const RTCString &a_rSrc, size_t a_offSrc, size_t a_cchSrc = npos);
681 RTCRestString &assign(const char *a_pszSrc, size_t a_cchSrc);
682 RTCRestString &assign(size_t a_cTimes, char a_ch);
683 RTCRestString &printf(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
684 RTCRestString &printfV(const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(1, 0);
685 /** @} */
686};
687
688
689/**
690 * Date class.
691 *
692 * There are numerous ways of formatting a timestamp and the specifications
693 * we're currently working with doesn't have a way of telling it seems.
694 * Thus, decoding need to have fail safes built in so the user can give hints.
695 * The formatting likewise needs to be told which format to use by the user.
696 *
697 * Two side-effects of the format stuff is that the default constructor creates
698 * an object that is null, and resetToDefault will do the same bug leave the
699 * format as a hint.
700 */
701class RT_DECL_CLASS RTCRestDate : public RTCRestObjectBase
702{
703public:
704 /** Default constructor.
705 * @note The result is a null-object. */
706 RTCRestDate();
707 /** Copy constructor. */
708 RTCRestDate(RTCRestDate const &a_rThat);
709 /** Destructor. */
710 virtual ~RTCRestDate();
711 /** Copy assignment operator. */
712 RTCRestDate &operator=(RTCRestDate const &a_rThat);
713 /** Safe copy assignment method. */
714 int assignCopy(RTCRestDate const &a_rThat);
715 /** Make a clone of this object. */
716 inline RTCRestDate *clone() const { return (RTCRestDate *)baseClone(); }
717
718 /* Overridden methods: */
719 virtual RTCRestObjectBase *baseClone() const RT_OVERRIDE;
720 virtual int resetToDefault() RT_OVERRIDE;
721 virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_OVERRIDE;
722 virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_OVERRIDE;
723 virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = 0) const RT_OVERRIDE;
724 virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
725 uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_OVERRIDE;
726 virtual kTypeClass typeClass(void) const RT_OVERRIDE;
727 virtual const char *typeName(void) const RT_OVERRIDE;
728
729 /** Factory method. */
730 static DECLCALLBACK(RTCRestObjectBase *) createInstance(void);
731
732 /** Date formats. */
733 typedef enum
734 {
735 kFormat_Invalid = 0,
736 kFormat_Rfc2822, /**< Format it according to RFC-2822. */
737 kFormat_Rfc7131, /**< Format it according to RFC-7131 (HTTP). */
738 kFormat_Rfc3339, /**< Format it according to RFC-3339 (ISO-8601) (no fraction). */
739 kFormat_Rfc3339_Fraction_2, /**< Format it according to RFC-3339 (ISO-8601) with two digit fraction (hundreths). */
740 kFormat_Rfc3339_Fraction_3, /**< Format it according to RFC-3339 (ISO-8601) with three digit fraction (milliseconds). */
741 kFormat_Rfc3339_Fraction_6, /**< Format it according to RFC-3339 (ISO-8601) with six digit fraction (microseconds). */
742 kFormat_Rfc3339_Fraction_9, /**< Format it according to RFC-3339 (ISO-8601) with nine digit fraction (nanoseconds). */
743 kFormat_End
744 } kFormat;
745
746 /**
747 * Assigns the value, formats it as a string and clears the null indicator.
748 *
749 * @returns VINF_SUCCESS, VERR_NO_STR_MEMORY or VERR_INVALID_PARAMETER.
750 * @param a_pTimeSpec The time spec to set.
751 * @param a_enmFormat The date format to use when formatting it.
752 */
753 int assignValue(PCRTTIMESPEC a_pTimeSpec, kFormat a_enmFormat);
754 int assignValueRfc2822(PCRTTIMESPEC a_pTimeSpec); /**< Convenience method for email/whatnot. */
755 int assignValueRfc7131(PCRTTIMESPEC a_pTimeSpec); /**< Convenience method for HTTP date. */
756 int assignValueRfc3339(PCRTTIMESPEC a_pTimeSpec); /**< Convenience method for ISO-8601 timstamp. */
757
758 /**
759 * Assigns the current UTC time and clears the null indicator .
760 *
761 * @returns VINF_SUCCESS, VERR_NO_STR_MEMORY or VERR_INVALID_PARAMETER.
762 * @returns VINF_SUCCESS or VERR_NO_STR_MEMORY.
763 * @param a_enmFormat The date format to use when formatting it.
764 */
765 int assignNow(kFormat a_enmFormat);
766 int assignNowRfc2822(); /**< Convenience method for email/whatnot. */
767 int assignNowRfc7131(); /**< Convenience method for HTTP date. */
768 int assignNowRfc3339(); /**< Convenience method for ISO-8601 timstamp. */
769
770 /**
771 * Sets the format to help deal with decoding issues.
772 *
773 * This can also be used to change the date format for an okay timespec.
774 * @returns IPRT status code.
775 * @param a_enmFormat The date format to try/set.
776 */
777 int setFormat(kFormat a_enmFormat);
778
779 /** Check if the value is okay (m_TimeSpec & m_Exploded). */
780 inline bool isOkay() const { return m_fTimeSpecOkay; }
781 /** Get the timespec value. */
782 inline RTTIMESPEC const &getTimeSpec() const { return m_TimeSpec; }
783 /** Get the exploded time. */
784 inline RTTIME const &getExploded() const { return m_Exploded; }
785 /** Gets the format. */
786 inline kFormat getFormat() const { return m_enmFormat; }
787 /** Get the formatted/raw string value. */
788 inline RTCString const &getString() const { return m_strFormatted; }
789
790 /** Get nanoseconds since unix epoch. */
791 inline int64_t getEpochNano() const { return RTTimeSpecGetNano(&m_TimeSpec); }
792 /** Get seconds since unix epoch. */
793 inline int64_t getEpochSeconds() const { return RTTimeSpecGetSeconds(&m_TimeSpec); }
794 /** Checks if UTC time. */
795 inline bool isUtc() const { return (m_Exploded.fFlags & RTTIME_FLAGS_TYPE_MASK) != RTTIME_FLAGS_TYPE_LOCAL; }
796 /** Checks if local time. */
797 inline bool isLocal() const { return (m_Exploded.fFlags & RTTIME_FLAGS_TYPE_MASK) == RTTIME_FLAGS_TYPE_LOCAL; }
798
799protected:
800 /** The value. */
801 RTTIMESPEC m_TimeSpec;
802 /** The exploded time value. */
803 RTTIME m_Exploded;
804 /** Set if m_TimeSpec is okay, consult m_strFormatted if not. */
805 bool m_fTimeSpecOkay;
806 /** The format / format hint. */
807 kFormat m_enmFormat;
808 /** The formatted date string.
809 * This will be the raw input string for a deserialized value, where as for
810 * a value set by the user it will be the formatted value. */
811 RTCString m_strFormatted;
812
813 /**
814 * Explodes and formats the m_TimeSpec value.
815 *
816 * Sets m_Exploded, m_strFormatted, m_fTimeSpecOkay, and m_enmFormat, clears m_fNullIndicator.
817 *
818 * @returns VINF_SUCCESS or VERR_NO_STR_MEMORY.
819 * @param a_enmFormat The format to use.
820 */
821 int explodeAndFormat(kFormat a_enmFormat);
822
823 /**
824 * Formats the m_Exploded value.
825 *
826 * Sets m_strFormatted, m_fTimeSpecOkay, and m_enmFormat, clears m_fNullIndicator.
827 *
828 * @returns VINF_SUCCESS or VERR_NO_STR_MEMORY.
829 * @param a_enmFormat The format to use.
830 */
831 int format(kFormat a_enmFormat);
832
833 /**
834 * Internal worker that attempts to decode m_strFormatted.
835 *
836 * Sets m_fTimeSpecOkay.
837 *
838 * @returns IPRT status code.
839 * @param enmFormat Specific format to try, kFormat_Invalid (default) to try guess it.
840 */
841 int decodeFormattedString(kFormat enmFormat = kFormat_Invalid);
842};
843
844
845/** We should provide a proper UUID class eventually. Currently it is not used. */
846typedef RTCRestString RTCRestUuid;
847
848
849/**
850 * String enum base class.
851 */
852class RT_DECL_CLASS RTCRestStringEnumBase : public RTCRestObjectBase
853{
854public:
855 /** Enum map entry. */
856 typedef struct ENUMMAPENTRY
857 {
858 const char *pszName;
859 uint32_t cchName;
860 int32_t iValue;
861 } ENUMMAPENTRY;
862
863 /** Default constructor. */
864 RTCRestStringEnumBase();
865 /** Destructor. */
866 virtual ~RTCRestStringEnumBase();
867
868 /** Copy constructor. */
869 RTCRestStringEnumBase(RTCRestStringEnumBase const &a_rThat);
870 /** Copy assignment operator. */
871 RTCRestStringEnumBase &operator=(RTCRestStringEnumBase const &a_rThat);
872
873 /** Safe copy assignment method. */
874 int assignCopy(RTCRestStringEnumBase const &a_rThat);
875 /** Safe copy assignment method. */
876 inline int assignCopy(RTCString const &a_rThat) { return setByString(a_rThat); }
877 /** Safe copy assignment method. */
878 inline int assignCopy(const char *a_pszThat) { return setByString(a_pszThat); }
879
880 /* Overridden methods: */
881 virtual int resetToDefault() RT_OVERRIDE;
882 virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_OVERRIDE;
883 virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_OVERRIDE;
884 virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = kCollectionFormat_Unspecified) const RT_OVERRIDE;
885 virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
886 uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_OVERRIDE;
887 virtual kTypeClass typeClass(void) const RT_OVERRIDE;
888
889 /**
890 * Sets the value given a C-string value.
891 *
892 * @retval VINF_SUCCESS on success.
893 * @retval VWRN_NOT_FOUND if not mappable to enum value.
894 * @retval VERR_NO_STR_MEMORY if not mappable and we're out of memory.
895 * @param a_pszValue The string value.
896 * @param a_cchValue The string value length. Optional.
897 */
898 int setByString(const char *a_pszValue, size_t a_cchValue = RTSTR_MAX);
899
900 /**
901 * Sets the value given a string value.
902 *
903 * @retval VINF_SUCCESS on success.
904 * @retval VWRN_NOT_FOUND if not mappable to enum value.
905 * @retval VERR_NO_STR_MEMORY if not mappable and we're out of memory.
906 * @param a_rValue The string value.
907 */
908 int setByString(RTCString const &a_rValue);
909
910 /**
911 * Gets the string value.
912 */
913 const char *getString() const;
914
915 /** Maps the given string value to an enum. */
916 int stringToEnum(const char *a_pszValue, size_t a_cchValue = RTSTR_MAX);
917 /** Maps the given string value to an enum. */
918 int stringToEnum(RTCString const &a_rStrValue);
919 /** Maps the given string value to an enum. */
920 const char *enumToString(int a_iEnumValue, size_t *a_pcchString);
921
922
923protected:
924 /** The enum value. */
925 int m_iEnumValue;
926 /** The string value if not a match. */
927 RTCString m_strValue;
928
929 /**
930 * Worker for setting the object to the given enum value.
931 *
932 * @retval true on success.
933 * @retval false if a_iEnumValue can't be translated.
934 * @param a_iEnumValue The enum value to set.
935 */
936 bool setWorker(int a_iEnumValue);
937
938 /** Helper for implementing RTCRestObjectBase::clone(). */
939 RTCRestObjectBase *cloneWorker(RTCRestStringEnumBase *a_pDst) const;
940
941 /**
942 * Gets the mapping table.
943 *
944 * @returns Pointer to the translation table.
945 * @param pcEntries Where to return the translation table size.
946 */
947 virtual ENUMMAPENTRY const *getMappingTable(size_t *pcEntries) const = 0;
948};
949
950
951/**
952 * Class for handling binary blobs (strings).
953 *
954 * There are specializations of this class for body parameters and responses,
955 * see RTCRestBinaryParameter and RTCRestBinaryResponse.
956 */
957class RT_DECL_CLASS RTCRestBinary : public RTCRestObjectBase
958{
959public:
960 /** Default constructor. */
961 RTCRestBinary();
962 /** Destructor. */
963 virtual ~RTCRestBinary();
964
965 /** Safe copy assignment method. */
966 virtual int assignCopy(RTCRestBinary const &a_rThat);
967 /** Safe buffer copy method. */
968 virtual int assignCopy(void const *a_pvData, size_t a_cbData);
969
970 /** Use the specified data buffer directly. */
971 virtual int assignReadOnly(void const *a_pvData, size_t a_cbData);
972 /** Use the specified data buffer directly. */
973 virtual int assignWriteable(void *a_pvBuf, size_t a_cbBuf);
974 /** Frees the data held by the object and resets it default state. */
975 virtual void freeData();
976
977 /** Returns a pointer to the data blob. */
978 inline const uint8_t *getPtr() const { return m_pbData; }
979 /** Gets the size of the data. */
980 inline size_t getSize() const { return m_cbData; }
981
982 /** Make a clone of this object. */
983 inline RTCRestBinary *clone() const { return (RTCRestBinary *)baseClone(); }
984
985 /* Overridden methods: */
986 virtual RTCRestObjectBase *baseClone() const RT_OVERRIDE;
987 virtual int setNull(void) RT_OVERRIDE;
988 virtual int resetToDefault(void) RT_OVERRIDE;
989 virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_OVERRIDE;
990 virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_OVERRIDE;
991 virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = kCollectionFormat_Unspecified) const RT_OVERRIDE;
992 virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
993 uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_OVERRIDE;
994 virtual kTypeClass typeClass(void) const RT_OVERRIDE;
995 virtual const char *typeName(void) const RT_OVERRIDE;
996
997 /** Factory method. */
998 static DECLCALLBACK(RTCRestObjectBase *) createInstance(void);
999
1000protected:
1001 /** Pointer to data blob. */
1002 uint8_t *m_pbData;
1003 /** Amount of valid data in the blob. */
1004 size_t m_cbData;
1005 /** Number of bytes allocated for the m_pbData buffer. */
1006 size_t m_cbAllocated;
1007 /** Set if the data is freeable, only ever clear if user data. */
1008 bool m_fFreeable;
1009 /** Set if the data blob is readonly user provided data. */
1010 bool m_fReadOnly;
1011
1012private:
1013 /* No copy constructor or copy assignment: */
1014 RTCRestBinary(RTCRestBinary const &a_rThat);
1015 RTCRestBinary &operator=(RTCRestBinary const &a_rThat);
1016};
1017
1018
1019/**
1020 * Abstract base class for REST data model classes.
1021 */
1022class RT_DECL_CLASS RTCRestDataObject : public RTCRestObjectBase
1023{
1024public:
1025 RTCRestDataObject();
1026 RTCRestDataObject(RTCRestDataObject const &a_rThat);
1027 virtual ~RTCRestDataObject();
1028
1029 /* Overridden methods:*/
1030 virtual int resetToDefault() RT_OVERRIDE;
1031 virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_OVERRIDE;
1032 virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_OVERRIDE;
1033 virtual kTypeClass typeClass(void) const RT_OVERRIDE;
1034
1035 /**
1036 * Serialize the members as JSON.
1037 *
1038 * @returns Leading separator prefix (empty string or comma string).
1039 * @param a_rDst The destination for the serialization.
1040 * @param a_pszSep Leading separator prefix (empty or comma).
1041 */
1042 virtual const char *serializeMembersAsJson(RTCRestOutputBase &a_rDst, const char *a_pszSep) const;
1043
1044 /**
1045 * Deserialize object from the given JSON iterator.
1046 *
1047 * @returns IPRT status code.
1048 * @retval VERR_NOT_FOUND if field is unknown. Top level caller will do
1049 * invoke unknownField() on it.
1050 *
1051 * @param a_rCursor The JSON cursor with the current member.
1052 * @param a_cchName The length of a_rCursor.m_pszName.
1053 */
1054 virtual int deserializeMemberFromJson(RTCRestJsonCursor const &a_rCursor, size_t a_cchName);
1055
1056protected:
1057 /** The is-set bits for all the fields. */
1058 uint64_t m_fIsSet;
1059
1060 /** Copy assignment operator. */
1061 RTCRestDataObject &operator=(RTCRestDataObject const &a_rThat);
1062
1063 /** Safe copy assignment method. */
1064 virtual int assignCopy(RTCRestDataObject const &a_rThat);
1065};
1066
1067
1068/**
1069 * Abstract base class for polymorphic REST data model classes.
1070 */
1071class RT_DECL_CLASS RTCRestPolyDataObject : public RTCRestDataObject
1072{
1073public:
1074 RTCRestPolyDataObject();
1075 RTCRestPolyDataObject(RTCRestPolyDataObject const &a_rThat);
1076 virtual ~RTCRestPolyDataObject();
1077
1078 /* Overridden methods:*/
1079 virtual int resetToDefault() RT_OVERRIDE;
1080
1081 /** Checks if the instance is of a child class (@c true) or of the parent (@c false). */
1082 virtual bool isChild() const;
1083
1084protected:
1085
1086 /** Copy assignment operator. */
1087 RTCRestPolyDataObject &operator=(RTCRestPolyDataObject const &a_rThat);
1088};
1089
1090
1091/** @} */
1092
1093#endif
1094
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