Changeset 74025 in vbox
- Timestamp:
- Sep 2, 2018 2:14:43 PM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 124772
- Location:
- trunk
- Files:
-
- 6 edited
- 3 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/cpp/restarray.h
r74024 r74025 1 1 /** @file 2 * IPRT - C++ Representational State Transfer (REST) Base Classes.2 * IPRT - C++ Representational State Transfer (REST) Array Template Class. 3 3 */ 4 4 … … 24 24 */ 25 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. 26 #ifndef ___iprt_cpp_restarray_h 27 #define ___iprt_cpp_restarray_h 28 29 #include <iprt/cpp/restbase.h> 30 31 32 /** @defgroup grp_rt_cpp_restarray C++ Representational State Transfer (REST) Array Template Class. 42 33 * @ingroup grp_rt_cpp 43 34 * @{ 44 35 */ 45 46 47 48 /**49 * Abstract base class for serializing data objects.50 */51 class RT_DECL_CLASS RTCRestOutputBase52 {53 public: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 110 protected:111 /** The current indentation level. */112 unsigned m_uIndent;113 };114 115 116 /**117 * Serialize to a string object.118 */119 class RT_DECL_CLASS RTCRestOutputToString : public RTCRestOutputBase120 {121 public: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, or127 * 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 if138 * called already.139 *140 * @remark This sets m_pDst to NULL and the object cannot be use for any141 * more output afterwards.142 */143 virtual RTCString *finalize();144 145 146 protected: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: */162 class RTCRestJsonPrimaryCursor;163 164 /**165 * JSON cursor structure.166 *167 * This reduces the number of parameters passed around when deserializing JSON168 * input and also helps constructing full object name for logging and error reporting.169 */170 struct RT_DECL_CLASS RTCRestJsonCursor171 {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 */207 class RT_DECL_CLASS RTCRestJsonPrimaryCursor208 {209 public: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_rc230 * @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 pszDst249 * @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 */262 class RT_DECL_CLASS RTCRestObjectBase263 {264 public: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_rDst297 * @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 arrays313 * are formatted. They are ignored by everyone else.314 *315 * @note When adding collection format types, make sure to also316 * update RTCRestArrayBase::toString().317 * @note Bit 24 is reserved (for kHdrField_MapCollection).318 */319 enum320 {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 kTypeClass366 {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 398 protected: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 would402 * 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 */413 class RT_DECL_CLASS RTCRestBool : public RTCRestObjectBase414 {415 public: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 444 public:445 /** The value. */446 bool m_fValue;447 };448 449 450 /**451 * Class wrapping 'int64_t'.452 */453 class RT_DECL_CLASS RTCRestInt64 : public RTCRestObjectBase454 {455 public: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 484 public:485 /** The value. */486 int64_t m_iValue;487 };488 489 490 /**491 * Class wrapping 'int32_t'.492 */493 class RT_DECL_CLASS RTCRestInt32 : public RTCRestObjectBase494 {495 public: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 524 public:525 /** The value. */526 int32_t m_iValue;527 };528 529 530 /**531 * Class wrapping 'int16_t'.532 */533 class RT_DECL_CLASS RTCRestInt16 : public RTCRestObjectBase534 {535 public: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 564 public:565 /** The value. */566 int16_t m_iValue;567 };568 569 570 /**571 * Class wrapping 'double'.572 */573 class RT_DECL_CLASS RTCRestDouble : public RTCRestObjectBase574 {575 public: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 604 public:605 /** The value. */606 double m_rdValue;607 };608 609 610 /**611 * Class wrapping 'RTCString'.612 */613 class RT_DECL_CLASS RTCRestString : public RTCString, public RTCRestObjectBase614 {615 public: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 36 650 37 /** … … 1036 423 1037 424 1038 /**1039 * Abstract base class for the RTCRestStringMap template.1040 */1041 class RT_DECL_CLASS RTCRestStringMapBase : public RTCRestObjectBase1042 {1043 public: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 1125 protected:1126 /** Map entry. */1127 typedef struct MapEntry1128 {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 1146 public:1147 /** @name Map Iteration1148 * @{ */1149 /** Const iterator. */1150 class ConstIterator1151 {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 1197 protected: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 has1220 * 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 1265 private:1266 static DECLCALLBACK(int) stringSpaceDestructorCallback(PRTSTRSPACECORE pStr, void *pvUser);1267 };1268 1269 1270 /**1271 * Limited map class.1272 */1273 template<class ValueType> class RTCRestStringMap : public RTCRestStringMapBase1274 {1275 public: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) const1404 {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) const1415 {1416 return (ValueType const *)getWorker(a_rStrKey.c_str());1417 }1418 1419 /** @todo enumerator*/1420 1421 protected:1422 virtual RTCRestObjectBase *createValue(void) RT_OVERRIDE1423 {1424 return new (std::nothrow) ValueType();1425 }1426 1427 virtual RTCRestObjectBase *createValueCopy(RTCRestObjectBase const *a_pSrc) RT_OVERRIDE1428 {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 and1446 * could be a specialized map implementation.1447 */1448 class /*RT_DECL_CLASS*/ RTCRestObject : public RTCRestObjectBase1449 {1450 public: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 1477 protected: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. In1497 * swagger 3 they can also be nullable, which means the null-indicator cannot1498 * be used for tracking optional parameters.1499 */1500 class RT_DECL_CLASS RTCRestClientRequestBase1501 {1502 public: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 1538 protected: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 struct1546 {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 struct1555 {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 code1564 * @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 struct1576 {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 code1587 * @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 struct1597 {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 code1609 * @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 */1622 class RT_DECL_CLASS RTCRestClientResponseBase1623 {1624 public: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, in1657 * 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 1713 protected: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_rc1731 * @param a_rc The status code to report and return. The first1732 * error status is assigned to m_rcStatus, subsequent1733 * ones as well as informational statuses are not1734 * 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 enum1742 {1743 /** Collection map, name is a prefix followed by '*'. */1744 kHdrField_MapCollection = RT_BIT_32(24),1745 };1746 1747 /** Header field descriptor. */1748 typedef struct1749 {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_SUCCESS1776 * @retval VERR_NOT_FOUND if not found.1777 * @retval VERR_NO_STR_MEMORY1778 * @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 RTCRestJsonPrimaryCursor1800 {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 */1813 class RT_DECL_CLASS RTCRestClientApiBase1814 {1815 public: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) const1829 {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 a1837 * different server from the one specified in the API specification, like1838 * 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 a1851 * different server from the one specified in the API specification, like1852 * 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 1867 protected: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 425 /** @} */ 1899 426 -
trunk/include/iprt/cpp/restbase.h
r74024 r74025 27 27 #define ___iprt_cpp_restbase_h 28 28 29 #include <iprt/cdefs.h> 29 30 #include <iprt/types.h> 30 #include <iprt/assert.h>31 #include <iprt/err.h>32 #include <iprt/http.h>33 31 #include <iprt/json.h> 34 #include <iprt/list.h>35 #include <iprt/string.h>36 32 #include <iprt/stdarg.h> 37 33 #include <iprt/cpp/ministring.h> 38 #include <iprt/cpp/utils.h>39 34 40 35 … … 649 644 650 645 /** 651 * Abstract base class for the RTCRestArray template.652 */653 class RT_DECL_CLASS RTCRestArrayBase : public RTCRestObjectBase654 {655 public: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() const682 {683 return m_cElements == 0;684 }685 686 /**687 * Gets the number of entries in the map.688 */689 size_t size() const690 {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) const714 {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 737 protected: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 has768 * 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 795 private: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 */807 template<class ElementType> class RTCRestArray : public RTCRestArrayBase808 {809 public: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) const974 {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() const994 {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() const1012 {1013 return at(m_cElements - 1);1014 }1015 1016 1017 protected:1018 virtual RTCRestObjectBase *createValue(void) RT_OVERRIDE1019 {1020 return new (std::nothrow) ElementType();1021 }1022 1023 virtual RTCRestObjectBase *createValueCopy(RTCRestObjectBase const *a_pSrc) RT_OVERRIDE1024 {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 */1041 class RT_DECL_CLASS RTCRestStringMapBase : public RTCRestObjectBase1042 {1043 public: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 1125 protected:1126 /** Map entry. */1127 typedef struct MapEntry1128 {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 1146 public:1147 /** @name Map Iteration1148 * @{ */1149 /** Const iterator. */1150 class ConstIterator1151 {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 1197 protected: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 has1220 * 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 1265 private:1266 static DECLCALLBACK(int) stringSpaceDestructorCallback(PRTSTRSPACECORE pStr, void *pvUser);1267 };1268 1269 1270 /**1271 * Limited map class.1272 */1273 template<class ValueType> class RTCRestStringMap : public RTCRestStringMapBase1274 {1275 public: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) const1404 {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) const1415 {1416 return (ValueType const *)getWorker(a_rStrKey.c_str());1417 }1418 1419 /** @todo enumerator*/1420 1421 protected:1422 virtual RTCRestObjectBase *createValue(void) RT_OVERRIDE1423 {1424 return new (std::nothrow) ValueType();1425 }1426 1427 virtual RTCRestObjectBase *createValueCopy(RTCRestObjectBase const *a_pSrc) RT_OVERRIDE1428 {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 646 * Dynamic REST object. 1444 647 * … … 1480 683 1481 684 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. In1497 * swagger 3 they can also be nullable, which means the null-indicator cannot1498 * be used for tracking optional parameters.1499 */1500 class RT_DECL_CLASS RTCRestClientRequestBase1501 {1502 public: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 1538 protected: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 struct1546 {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 struct1555 {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 code1564 * @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 struct1576 {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 code1587 * @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 struct1597 {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 code1609 * @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 */1622 class RT_DECL_CLASS RTCRestClientResponseBase1623 {1624 public: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, in1657 * 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 1713 protected: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_rc1731 * @param a_rc The status code to report and return. The first1732 * error status is assigned to m_rcStatus, subsequent1733 * ones as well as informational statuses are not1734 * 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 enum1742 {1743 /** Collection map, name is a prefix followed by '*'. */1744 kHdrField_MapCollection = RT_BIT_32(24),1745 };1746 1747 /** Header field descriptor. */1748 typedef struct1749 {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_SUCCESS1776 * @retval VERR_NOT_FOUND if not found.1777 * @retval VERR_NO_STR_MEMORY1778 * @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 RTCRestJsonPrimaryCursor1800 {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 */1813 class RT_DECL_CLASS RTCRestClientApiBase1814 {1815 public: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) const1829 {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 a1837 * different server from the one specified in the API specification, like1838 * 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 a1851 * different server from the one specified in the API specification, like1852 * 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 1867 protected: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 685 /** @} */ 1899 686 -
trunk/include/iprt/cpp/restclient.h
r74024 r74025 1 1 /** @file 2 * IPRT - C++ Representational State Transfer (REST) BaseClasses.2 * IPRT - C++ Representational State Transfer (REST) Client Classes. 3 3 */ 4 4 … … 24 24 */ 25 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> 26 #ifndef ___iprt_cpp_restclient_h 27 #define ___iprt_cpp_restclient_h 28 32 29 #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. 30 #include <iprt/cpp/restbase.h> 31 32 33 /** @defgroup grp_rt_cpp_restclient C++ Representational State Transfer (REST) Client Classes. 42 34 * @ingroup grp_rt_cpp 43 35 * @{ 44 36 */ 45 46 47 48 /**49 * Abstract base class for serializing data objects.50 */51 class RT_DECL_CLASS RTCRestOutputBase52 {53 public: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 110 protected:111 /** The current indentation level. */112 unsigned m_uIndent;113 };114 115 116 /**117 * Serialize to a string object.118 */119 class RT_DECL_CLASS RTCRestOutputToString : public RTCRestOutputBase120 {121 public: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, or127 * 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 if138 * called already.139 *140 * @remark This sets m_pDst to NULL and the object cannot be use for any141 * more output afterwards.142 */143 virtual RTCString *finalize();144 145 146 protected: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: */162 class RTCRestJsonPrimaryCursor;163 164 /**165 * JSON cursor structure.166 *167 * This reduces the number of parameters passed around when deserializing JSON168 * input and also helps constructing full object name for logging and error reporting.169 */170 struct RT_DECL_CLASS RTCRestJsonCursor171 {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 */207 class RT_DECL_CLASS RTCRestJsonPrimaryCursor208 {209 public: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_rc230 * @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 pszDst249 * @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 */262 class RT_DECL_CLASS RTCRestObjectBase263 {264 public: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_rDst297 * @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 arrays313 * are formatted. They are ignored by everyone else.314 *315 * @note When adding collection format types, make sure to also316 * update RTCRestArrayBase::toString().317 * @note Bit 24 is reserved (for kHdrField_MapCollection).318 */319 enum320 {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 kTypeClass366 {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 398 protected: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 would402 * 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 */413 class RT_DECL_CLASS RTCRestBool : public RTCRestObjectBase414 {415 public: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 444 public:445 /** The value. */446 bool m_fValue;447 };448 449 450 /**451 * Class wrapping 'int64_t'.452 */453 class RT_DECL_CLASS RTCRestInt64 : public RTCRestObjectBase454 {455 public: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 484 public:485 /** The value. */486 int64_t m_iValue;487 };488 489 490 /**491 * Class wrapping 'int32_t'.492 */493 class RT_DECL_CLASS RTCRestInt32 : public RTCRestObjectBase494 {495 public: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 524 public:525 /** The value. */526 int32_t m_iValue;527 };528 529 530 /**531 * Class wrapping 'int16_t'.532 */533 class RT_DECL_CLASS RTCRestInt16 : public RTCRestObjectBase534 {535 public: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 564 public:565 /** The value. */566 int16_t m_iValue;567 };568 569 570 /**571 * Class wrapping 'double'.572 */573 class RT_DECL_CLASS RTCRestDouble : public RTCRestObjectBase574 {575 public: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 604 public:605 /** The value. */606 double m_rdValue;607 };608 609 610 /**611 * Class wrapping 'RTCString'.612 */613 class RT_DECL_CLASS RTCRestString : public RTCString, public RTCRestObjectBase614 {615 public: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 */653 class RT_DECL_CLASS RTCRestArrayBase : public RTCRestObjectBase654 {655 public: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() const682 {683 return m_cElements == 0;684 }685 686 /**687 * Gets the number of entries in the map.688 */689 size_t size() const690 {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) const714 {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 737 protected: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 has768 * 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 795 private: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 */807 template<class ElementType> class RTCRestArray : public RTCRestArrayBase808 {809 public: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) const974 {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() const994 {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() const1012 {1013 return at(m_cElements - 1);1014 }1015 1016 1017 protected:1018 virtual RTCRestObjectBase *createValue(void) RT_OVERRIDE1019 {1020 return new (std::nothrow) ElementType();1021 }1022 1023 virtual RTCRestObjectBase *createValueCopy(RTCRestObjectBase const *a_pSrc) RT_OVERRIDE1024 {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 */1041 class RT_DECL_CLASS RTCRestStringMapBase : public RTCRestObjectBase1042 {1043 public: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 1125 protected:1126 /** Map entry. */1127 typedef struct MapEntry1128 {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 1146 public:1147 /** @name Map Iteration1148 * @{ */1149 /** Const iterator. */1150 class ConstIterator1151 {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 1197 protected: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 has1220 * 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 1265 private:1266 static DECLCALLBACK(int) stringSpaceDestructorCallback(PRTSTRSPACECORE pStr, void *pvUser);1267 };1268 1269 1270 /**1271 * Limited map class.1272 */1273 template<class ValueType> class RTCRestStringMap : public RTCRestStringMapBase1274 {1275 public: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) const1404 {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) const1415 {1416 return (ValueType const *)getWorker(a_rStrKey.c_str());1417 }1418 1419 /** @todo enumerator*/1420 1421 protected:1422 virtual RTCRestObjectBase *createValue(void) RT_OVERRIDE1423 {1424 return new (std::nothrow) ValueType();1425 }1426 1427 virtual RTCRestObjectBase *createValueCopy(RTCRestObjectBase const *a_pSrc) RT_OVERRIDE1428 {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 and1446 * could be a specialized map implementation.1447 */1448 class /*RT_DECL_CLASS*/ RTCRestObject : public RTCRestObjectBase1449 {1450 public: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 1477 protected:1478 /** @todo figure out the value stuff here later... */1479 };1480 1481 37 1482 38 /** -
trunk/include/iprt/cpp/reststringmap.h
r74024 r74025 1 1 /** @file 2 * IPRT - C++ Representational State Transfer (REST) Base Classes.2 * IPRT - C++ Representational State Transfer (REST) String Map Template. 3 3 */ 4 4 … … 24 24 */ 25 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> 26 #ifndef ___iprt_cpp_reststringmap_h 27 #define ___iprt_cpp_reststringmap_h 28 34 29 #include <iprt/list.h> 35 30 #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. 31 #include <iprt/cpp/restbase.h> 32 33 34 /** @defgroup grp_rt_cpp_reststingmap C++ Representational State Transfer (REST) String Map Template 42 35 * @ingroup grp_rt_cpp 43 36 * @{ 44 37 */ 45 46 47 48 /**49 * Abstract base class for serializing data objects.50 */51 class RT_DECL_CLASS RTCRestOutputBase52 {53 public: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 110 protected:111 /** The current indentation level. */112 unsigned m_uIndent;113 };114 115 116 /**117 * Serialize to a string object.118 */119 class RT_DECL_CLASS RTCRestOutputToString : public RTCRestOutputBase120 {121 public: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, or127 * 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 if138 * called already.139 *140 * @remark This sets m_pDst to NULL and the object cannot be use for any141 * more output afterwards.142 */143 virtual RTCString *finalize();144 145 146 protected: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: */162 class RTCRestJsonPrimaryCursor;163 164 /**165 * JSON cursor structure.166 *167 * This reduces the number of parameters passed around when deserializing JSON168 * input and also helps constructing full object name for logging and error reporting.169 */170 struct RT_DECL_CLASS RTCRestJsonCursor171 {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 */207 class RT_DECL_CLASS RTCRestJsonPrimaryCursor208 {209 public: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_rc230 * @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 pszDst249 * @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 */262 class RT_DECL_CLASS RTCRestObjectBase263 {264 public: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_rDst297 * @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 arrays313 * are formatted. They are ignored by everyone else.314 *315 * @note When adding collection format types, make sure to also316 * update RTCRestArrayBase::toString().317 * @note Bit 24 is reserved (for kHdrField_MapCollection).318 */319 enum320 {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 kTypeClass366 {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 398 protected: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 would402 * 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 */413 class RT_DECL_CLASS RTCRestBool : public RTCRestObjectBase414 {415 public: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 444 public:445 /** The value. */446 bool m_fValue;447 };448 449 450 /**451 * Class wrapping 'int64_t'.452 */453 class RT_DECL_CLASS RTCRestInt64 : public RTCRestObjectBase454 {455 public: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 484 public:485 /** The value. */486 int64_t m_iValue;487 };488 489 490 /**491 * Class wrapping 'int32_t'.492 */493 class RT_DECL_CLASS RTCRestInt32 : public RTCRestObjectBase494 {495 public: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 524 public:525 /** The value. */526 int32_t m_iValue;527 };528 529 530 /**531 * Class wrapping 'int16_t'.532 */533 class RT_DECL_CLASS RTCRestInt16 : public RTCRestObjectBase534 {535 public: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 564 public:565 /** The value. */566 int16_t m_iValue;567 };568 569 570 /**571 * Class wrapping 'double'.572 */573 class RT_DECL_CLASS RTCRestDouble : public RTCRestObjectBase574 {575 public: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 604 public:605 /** The value. */606 double m_rdValue;607 };608 609 610 /**611 * Class wrapping 'RTCString'.612 */613 class RT_DECL_CLASS RTCRestString : public RTCString, public RTCRestObjectBase614 {615 public: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 */653 class RT_DECL_CLASS RTCRestArrayBase : public RTCRestObjectBase654 {655 public: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() const682 {683 return m_cElements == 0;684 }685 686 /**687 * Gets the number of entries in the map.688 */689 size_t size() const690 {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) const714 {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 737 protected: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 has768 * 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 795 private: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 */807 template<class ElementType> class RTCRestArray : public RTCRestArrayBase808 {809 public: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) const974 {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() const994 {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() const1012 {1013 return at(m_cElements - 1);1014 }1015 1016 1017 protected:1018 virtual RTCRestObjectBase *createValue(void) RT_OVERRIDE1019 {1020 return new (std::nothrow) ElementType();1021 }1022 1023 virtual RTCRestObjectBase *createValueCopy(RTCRestObjectBase const *a_pSrc) RT_OVERRIDE1024 {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 38 1038 39 /** … … 1440 441 1441 442 1442 /**1443 * Dynamic REST object.1444 *1445 * @todo figure this one out. it's possible this is only used in maps and1446 * could be a specialized map implementation.1447 */1448 class /*RT_DECL_CLASS*/ RTCRestObject : public RTCRestObjectBase1449 {1450 public: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 1477 protected: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. In1497 * swagger 3 they can also be nullable, which means the null-indicator cannot1498 * be used for tracking optional parameters.1499 */1500 class RT_DECL_CLASS RTCRestClientRequestBase1501 {1502 public: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 1538 protected: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 struct1546 {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 struct1555 {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 code1564 * @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 struct1576 {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 code1587 * @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 struct1597 {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 code1609 * @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 */1622 class RT_DECL_CLASS RTCRestClientResponseBase1623 {1624 public: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, in1657 * 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 1713 protected: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_rc1731 * @param a_rc The status code to report and return. The first1732 * error status is assigned to m_rcStatus, subsequent1733 * ones as well as informational statuses are not1734 * 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 enum1742 {1743 /** Collection map, name is a prefix followed by '*'. */1744 kHdrField_MapCollection = RT_BIT_32(24),1745 };1746 1747 /** Header field descriptor. */1748 typedef struct1749 {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_SUCCESS1776 * @retval VERR_NOT_FOUND if not found.1777 * @retval VERR_NO_STR_MEMORY1778 * @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 RTCRestJsonPrimaryCursor1800 {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 */1813 class RT_DECL_CLASS RTCRestClientApiBase1814 {1815 public: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) const1829 {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 a1837 * different server from the one specified in the API specification, like1838 * 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 a1851 * different server from the one specified in the API specification, like1852 * 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 1867 protected: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 443 /** @} */ 1899 444 -
trunk/src/VBox/Runtime/common/rest/RTCRestArrayBase.cpp
r74023 r74025 30 30 *********************************************************************************************************************************/ 31 31 #define LOG_GROUP RTLOGGROUP_REST 32 #include <iprt/cpp/rest base.h>32 #include <iprt/cpp/restarray.h> 33 33 34 34 #include <iprt/err.h> -
trunk/src/VBox/Runtime/common/rest/RTCRestClientApiBase.cpp
r74013 r74025 30 30 *********************************************************************************************************************************/ 31 31 #define LOG_GROUP RTLOGGROUP_REST 32 #include <iprt/cpp/rest base.h>32 #include <iprt/cpp/restclient.h> 33 33 34 34 #include <iprt/err.h> -
trunk/src/VBox/Runtime/common/rest/RTCRestClientRequestBase.cpp
r74024 r74025 30 30 *********************************************************************************************************************************/ 31 31 #define LOG_GROUP RTLOGGROUP_REST 32 #include <iprt/cpp/rest base.h>32 #include <iprt/cpp/restclient.h> 33 33 34 34 #include <iprt/assert.h> 35 35 #include <iprt/err.h> 36 #include <iprt/cpp/restarray.h> 37 #include <iprt/cpp/reststringmap.h> 36 38 37 39 -
trunk/src/VBox/Runtime/common/rest/RTCRestClientResponseBase.cpp
r74023 r74025 30 30 *********************************************************************************************************************************/ 31 31 #define LOG_GROUP RTLOGGROUP_REST 32 #include <iprt/cpp/rest base.h>32 #include <iprt/cpp/restclient.h> 33 33 34 34 #include <iprt/ctype.h> 35 35 #include <iprt/err.h> 36 #include <iprt/cpp/reststringmap.h> 36 37 37 38 -
trunk/src/VBox/Runtime/common/rest/RTCRestStringMapBase.cpp
r74023 r74025 30 30 *********************************************************************************************************************************/ 31 31 #define LOG_GROUP RTLOGGROUP_REST 32 #include <iprt/cpp/rest base.h>32 #include <iprt/cpp/reststringmap.h> 33 33 34 34 #include <iprt/err.h>
Note:
See TracChangeset
for help on using the changeset viewer.