VirtualBox

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

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

IPRT/swagger: Hacking api source. bugref:9167

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.1 KB
Line 
1/** @file
2 * IPRT - C++ Representational State Transfer (REST) Base Classes.
3 */
4
5/*
6 * Copyright (C) 2008-2018 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 *
16 * The contents of this file may alternatively be used under the terms
17 * of the Common Development and Distribution License Version 1.0
18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
19 * VirtualBox OSE distribution, in which case the provisions of the
20 * CDDL are applicable instead of those of the GPL.
21 *
22 * You may elect to license modified versions of this file under the
23 * terms and conditions of either the GPL or the CDDL or both.
24 */
25
26#ifndef ___iprt_cpp_restbase_h
27#define ___iprt_cpp_restbase_h
28
29#include <iprt/types.h>
30#include <iprt/assert.h>
31#include <iprt/err.h>
32#include <iprt/http.h>
33#include <iprt/json.h>
34#include <iprt/stdarg.h>
35#include <iprt/cpp/ministring.h>
36#include <iprt/cpp/utils.h>
37
38
39/** @defgroup grp_rt_cpp_restbase C++ Representational State Transfer (REST) Base Classes.
40 * @ingroup grp_rt_cpp
41 * @{
42 */
43
44
45
46/**
47 * Abstract base class for serializing data objects.
48 */
49class RTCRestOutputBase
50{
51public:
52 RTCRestOutputBase()
53 : m_uIndent(0)
54 { }
55 virtual ~RTCRestOutputBase()
56 { }
57
58 /**
59 * RTStrPrintf like function (see @ref pg_rt_str_format).
60 *
61 * @returns Number of bytes outputted.
62 * @param pszFormat The format string.
63 * @param ... Argument specfied in @a pszFormat.
64 */
65 size_t printf(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(2, 3)
66 {
67 va_list va;
68 va_start(va, pszFormat);
69 size_t cchWritten = this->vprintf(pszFormat, va);
70 va_end(va);
71 return cchWritten;
72 }
73
74 /**
75 * RTStrPrintfV like function (see @ref pg_rt_str_format).
76 *
77 * @returns Number of bytes outputted.
78 * @param pszFormat The format string.
79 * @param va Argument specfied in @a pszFormat.
80 */
81 virtual size_t vprintf(const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(2, 0) = 0;
82
83 /**
84 * Sets the indentation level for use when pretty priting things.
85 *
86 * @returns Previous indentation level.
87 * @param uIndent The indentation level.
88 */
89 unsigned setIndent(unsigned uIndent)
90 {
91 unsigned const uRet = m_uIndent;
92 m_uIndent = uIndent;
93 return uRet;
94 }
95
96 /**
97 * Increases the indentation level.
98 *
99 * @returns Previous indentation level.
100 */
101 unsigned incrementIndent()
102 {
103 unsigned const uRet = m_uIndent;
104 m_uIndent = uRet + 1;
105 return uRet;
106 }
107
108protected:
109 /** The current indentation level. */
110 unsigned m_uIndent;
111};
112
113
114/**
115 * Serialize to a string object.
116 */
117class RTCRestOutputToString : public RTCRestOutputBase
118{
119public:
120 /**
121 * Creates an instance that appends to @a a_pDst.
122 * @param a_pDst Pointer to the destination string object.
123 * NULL is not accepted and will assert.
124 */
125 RTCRestOutputToString(RTCString *a_pDst);
126 virtual ~RTCRestOutputToString();
127
128 size_t vprintf(const char *pszFormat, va_list va);
129
130 /**
131 * Finalizes the output and releases the string object to the caller.
132 *
133 * @returns The released string object. NULL if we ran out of memory or if
134 * called already.
135 *
136 * @remark This sets m_pDst to NULL and the object cannot be use for any
137 * more output afterwards.
138 */
139 virtual RTCString *finalize();
140
141
142protected:
143 /** Pointer to the destination string. NULL after finalize(). */
144 RTCString *m_pDst;
145 /** Set if we ran out of memory and should ignore subsequent calls. */
146 bool m_fOutOfMemory;
147
148 /** @callback_method_impl{FNRTSTROUTPUT} */
149 static DECLCALLBACK(size_t) strOutput(void *pvArg, const char *pachChars, size_t cbChars);
150
151 /* Make non-copyable (RTCNonCopyable causes warnings): */
152 RTCRestOutputToString(RTCRestOutputToString const &);
153 RTCRestOutputToString *operator=(RTCRestOutputToString const &);
154};
155
156
157/* forward decl: */
158class RTCRestJsonPrimaryCursor;
159
160/**
161 * JSON cursor structure.
162 *
163 * This reduces the number of parameters passed around when deserializing JSON
164 * input and also helps constructing full object name for logging and error reporting.
165 */
166struct RTCRestJsonCursor
167{
168 /** Handle to the value being parsed. */
169 RTJSONVAL m_hValue;
170 /** Name of the value. */
171 const char *m_pszName;
172 /** Pointer to the parent, NULL if primary. */
173 struct RTCRestJsonCursor const *m_pParent;
174 /** Pointer to the primary cursor structure. */
175 RTCRestJsonPrimaryCursor *m_pPrimary;
176
177 RTCRestJsonCursor(struct RTCRestJsonCursor const &a_rParent)
178 : m_hValue(NIL_RTJSONVAL), m_pszName(NULL), m_pParent(&a_rParent), m_pPrimary(a_rParent.m_pPrimary)
179 { }
180
181 RTCRestJsonCursor(RTJSONVAL hValue, const char *pszName, struct RTCRestJsonCursor *pParent)
182 : m_hValue(hValue), m_pszName(pszName), m_pParent(pParent), m_pPrimary(pParent->m_pPrimary)
183 { }
184
185 RTCRestJsonCursor(RTJSONVAL hValue, const char *pszName)
186 : m_hValue(hValue), m_pszName(pszName), m_pParent(NULL), m_pPrimary(NULL)
187 { }
188
189 ~RTCRestJsonCursor()
190 {
191 if (m_hValue != NIL_RTJSONVAL)
192 {
193 RTJsonValueRelease(m_hValue);
194 m_hValue = NIL_RTJSONVAL;
195 }
196 }
197};
198
199
200/**
201 * The primary JSON cursor class.
202 */
203class RTCRestJsonPrimaryCursor
204{
205public:
206 /** The cursor for the first level. */
207 RTCRestJsonCursor m_Cursor;
208 /** Error info keeper. */
209 PRTERRINFO m_pErrInfo;
210
211 /** Creates a primary json cursor with optiona error info. */
212 RTCRestJsonPrimaryCursor(RTJSONVAL hValue, const char *pszName, PRTERRINFO pErrInfo = NULL)
213 : m_Cursor(hValue, pszName)
214 , m_pErrInfo(pErrInfo)
215 {
216 m_Cursor.m_pPrimary = this;
217 }
218
219 virtual ~RTCRestJsonPrimaryCursor()
220 { }
221
222 /**
223 * Add an error message.
224 *
225 * @returns a_rc
226 * @param a_rCursor The cursor reporting the error.
227 * @param a_rc The status code.
228 * @param a_pszFormat Format string.
229 * @param ... Format string arguments.
230 */
231 virtual int addError(RTCRestJsonCursor const &a_rCursor, int a_rc, const char *a_pszFormat, ...);
232
233 /**
234 * Reports that the current field is not known.
235 *
236 * @returns Status to propagate.
237 * @param a_rCursor The cursor for the field.
238 */
239 virtual int unknownField(RTCRestJsonCursor const &a_rCursor);
240
241 /**
242 * Copies the full path into pszDst.
243 *
244 * @returns pszDst
245 * @param a_rCursor The cursor to start walking at.
246 * @param a_pszDst Where to put the path.
247 * @param a_cbDst Size of the destination buffer.
248 */
249 virtual char *getPath(RTCRestJsonCursor const &a_rCursor, char *a_pszDst, size_t a_cbDst) const;
250};
251
252
253/**
254 * Abstract base class for REST data objects.
255 */
256class RTCRestObjectBase
257{
258public:
259 RTCRestObjectBase() {}
260 virtual ~RTCRestObjectBase() {}
261
262 /** @todo Add some kind of state? */
263
264 /**
265 * Resets the object to all default values.
266 */
267 virtual void resetToDefaults() = 0;
268
269 /**
270 * Serialize the object as JSON.
271 *
272 * @returns a_rDst
273 * @param a_rDst The destination for the serialization.
274 */
275 virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) = 0;
276
277 /**
278 * Deserialize object from the given JSON iterator.
279 *
280 * @returns IPRT status code.
281 * @param a_rCursor The JSON cursor.
282 */
283 virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) = 0;
284
285 /** @name Helpers for deserializing primitive types and strings.
286 * @{ */
287 static int deserialize_RTCString_FromJson(RTCRestJsonCursor const &a_rCursor, RTCString *a_pDst);
288 static int deserialize_int64_t_FromJson(RTCRestJsonCursor const &a_rCursor, int64_t *a_piDst);
289 static int deserialize_int32_t_FromJson(RTCRestJsonCursor const &a_rCursor, int32_t *a_piDst);
290 static int deserialize_int16_t_FromJson(RTCRestJsonCursor const &a_rCursor, int16_t *a_piDst);
291 static int deserialize_bool_FromJson(RTCRestJsonCursor const &a_rCursor, bool *a_pfDst);
292 static int deserialize_double_FromJson(RTCRestJsonCursor const &a_rCursor, double *a_prdDst);
293 /** @} */
294
295 /** @name Helpers for serializing floating point types.
296 * @{ */
297 static RTCRestOutputBase &serialize_double_AsJson(RTCRestOutputBase &a_rDst, double const *a_prdValue);
298 /** @} */
299};
300
301
302/**
303 * Limited array class.
304 */
305template<class Type> class RTCRestArray : public RTCRestObjectBase
306{
307public:
308 RTCRestArray() {};
309 ~RTCRestArray() {};
310/** @todo more later. */
311
312 virtual void resetToDefaults();
313 virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst);
314 virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor)
315 {
316 RT_NOREF(a_rCursor);
317 return VERR_NOT_IMPLEMENTED;
318 }
319};
320
321
322/**
323 * Limited map class.
324 */
325template<class Type> class RTCRestStringMap : public RTCRestObjectBase
326{
327public:
328 RTCRestStringMap() {};
329 ~RTCRestStringMap() {};
330/** @todo more later. */
331
332 virtual void resetToDefaults();
333 virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst);
334 virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor)
335 {
336 RT_NOREF(a_rCursor);
337 return VERR_NOT_IMPLEMENTED;
338 }
339};
340
341
342/**
343 * Base class for REST client requests.
344 */
345class RTCRestClientRequestBase
346{
347public:
348 RTCRestClientRequestBase() {}
349 virtual ~RTCRestClientRequestBase() {};
350
351 /**
352 * Reset all members to default values.
353 */
354 virtual void resetToDefaults() = 0;
355
356 /**
357 * Prepares the HTTP handle for transmitting this request.
358 *
359 * @returns IPRT status code.
360 * @param a_hHttp The HTTP handle to prepare for transmitting.
361 */
362 virtual int xmitPrepare(RTHTTP a_hHttp) = 0;
363
364 /**
365 * Always called after the request has been transmitted.
366 *
367 * @param a_rcStatus Negative numbers are IPRT errors, positive are HTTP status codes.
368 * @param a_hHttp The HTTP handle the request was performed on.
369 */
370 virtual void xmitComplete(int a_rcStatus, RTHTTP a_hHttp) = 0;
371};
372
373
374/**
375 * Base class for REST client responses.
376 */
377class RTCRestClientResponseBase
378{
379public:
380 /** Default constructor. */
381 RTCRestClientResponseBase()
382 : m_rcStatus(VERR_WRONG_ORDER)
383 {}
384
385 /** Destructor. */
386 virtual ~RTCRestClientResponseBase()
387 {}
388
389 /** Copy constructor. */
390 RTCRestClientResponseBase(RTCRestClientResponseBase const &a_rThat)
391 : m_rcStatus(a_rThat.m_rcStatus)
392 {}
393
394 /** Copy assignment operator. */
395 RTCRestClientResponseBase &operator=(RTCRestClientResponseBase const &a_rThat)
396 {
397 m_rcStatus = a_rThat.m_rcStatus;
398 return *this;
399 }
400
401 /**
402 * Prepares the HTTP handle for receiving the response.
403 *
404 * This may install callbacks and such like.
405 *
406 * @returns IPRT status code.
407 * @param a_hHttp The HTTP handle to prepare for receiving.
408 */
409 virtual int receivePrepare(RTHTTP a_hHttp)
410 {
411 RT_NOREF(a_hHttp);
412 return VINF_SUCCESS;
413 }
414
415 virtual int consumeHeader(const char *a_pvData, size_t a_cbData) ///< ??
416 {
417 RT_NOREF(a_pvData, a_cbData);
418 return VINF_SUCCESS;
419 }
420
421 virtual int consumeBody(const char *a_pvData, size_t a_cbData) ///< ??
422 {
423 RT_NOREF(a_pvData, a_cbData);
424 return VINF_SUCCESS;
425 }
426
427 /**
428 * Called when the HTTP request has been completely received.
429 *
430 * @returns IPRT status code?
431 * @param a_rcStatus Negative numbers are IPRT errors, positive are HTTP status codes.
432 * @param a_hHttp The HTTP handle the request was performed on.
433 */
434 virtual int receiveComplete(int a_rcStatus, RTHTTP a_hHttp)
435 {
436 RT_NOREF_PV(a_hHttp);
437 m_rcStatus = a_rcStatus;
438 return a_rcStatus;
439 }
440
441 /**
442 * Getter for m_rcStatus.
443 * @returns Negative numbers are IPRT errors, positive are HTTP status codes.
444 */
445 int getStatus() { return m_rcStatus; }
446
447private:
448 /** Negative numbers are IPRT errors, positive are HTTP status codes. */
449 int m_rcStatus;
450};
451
452
453/**
454 * Base class for REST client responses.
455 */
456class RTCRestClientApiBase
457{
458public:
459 RTCRestClientApiBase()
460 : m_hHttp(NIL_RTHTTP)
461 {}
462 virtual ~RTCRestClientApiBase();
463
464 bool isConnected();
465
466protected:
467 /** Handle to the HTTP connection object. */
468 RTHTTP m_hHttp;
469
470 /* Make non-copyable (RTCNonCopyable causes warnings): */
471 RTCRestClientApiBase(RTCRestOutputToString const &);
472 RTCRestClientApiBase *operator=(RTCRestOutputToString const &);
473};
474
475/** @} */
476
477#endif
478
Note: See TracBrowser for help on using the repository browser.

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