VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/rest/rest-primary-object-types.cpp

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 65.9 KB
Line 
1/* $Id: rest-primary-object-types.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * IPRT - C++ REST, RTCRestObjectBase implementation.
4 */
5
6/*
7 * Copyright (C) 2018-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#define LOG_GROUP RTLOGGROUP_REST
42#include <iprt/cpp/restbase.h>
43
44#include <iprt/ctype.h>
45#include <iprt/err.h>
46#include <iprt/string.h>
47#include <iprt/cpp/restoutput.h>
48
49#include <stdio.h>
50#include <stdlib.h>
51#include <errno.h>
52
53
54
55/*********************************************************************************************************************************
56* RTCRestObjectBase implementation *
57*********************************************************************************************************************************/
58
59/** Default constructor. */
60RTCRestObjectBase::RTCRestObjectBase() RT_NOEXCEPT
61 : m_fNullIndicator(false)
62{
63}
64
65
66/** Copy constructor. */
67RTCRestObjectBase::RTCRestObjectBase(RTCRestObjectBase const &a_rThat) RT_NOEXCEPT
68 : m_fNullIndicator(a_rThat.m_fNullIndicator)
69{
70}
71
72
73/** Destructor. */
74RTCRestObjectBase::~RTCRestObjectBase()
75{
76 /* nothing to do */
77}
78
79
80/** Copy assignment operator. */
81RTCRestObjectBase &RTCRestObjectBase::operator=(RTCRestObjectBase const &a_rThat) RT_NOEXCEPT
82{
83 m_fNullIndicator = a_rThat.m_fNullIndicator;
84 return *this;
85}
86
87
88int RTCRestObjectBase::setNull() RT_NOEXCEPT
89{
90 int rc = resetToDefault();
91 m_fNullIndicator = true;
92 return rc;
93}
94
95
96void RTCRestObjectBase::setNotNull() RT_NOEXCEPT
97{
98 m_fNullIndicator = false;
99}
100
101
102int RTCRestObjectBase::toString(RTCString *a_pDst, uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) const RT_NOEXCEPT
103{
104 /*
105 * Just wrap the JSON serialization method.
106 */
107 RTCRestOutputToString Tmp(a_pDst, RT_BOOL(a_fFlags & kToString_Append));
108 serializeAsJson(Tmp);
109 return Tmp.finalize() ? VINF_SUCCESS : VERR_NO_MEMORY;
110}
111
112
113RTCString RTCRestObjectBase::toString() const
114{
115 RTCString strRet;
116 toString(&strRet, 0);
117 return strRet;
118}
119
120
121int RTCRestObjectBase::fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo /*= NULL*/,
122 uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) RT_NOEXCEPT
123{
124 RT_NOREF(a_fFlags);
125
126 /*
127 * Just wrap the JSON serialization method.
128 */
129 RTJSONVAL hValue = NIL_RTJSONVAL;
130 int rc = RTJsonParseFromString(&hValue, a_rValue.c_str(), a_pErrInfo);
131 if (RT_SUCCESS(rc))
132 {
133 RTCRestJsonPrimaryCursor PrimaryCursor(hValue, a_pszName, a_pErrInfo);
134 rc = deserializeFromJson(PrimaryCursor.m_Cursor);
135 }
136 return rc;
137}
138
139
140
141/*********************************************************************************************************************************
142* RTCRestBool implementation *
143*********************************************************************************************************************************/
144
145/** Factory method. */
146/*static*/ DECLCALLBACK(RTCRestObjectBase *) RTCRestBool::createInstance(void) RT_NOEXCEPT
147{
148 return new (std::nothrow) RTCRestBool();
149}
150
151
152/**
153 * @copydoc RTCRestObjectBase::FNDESERIALIZEINSTANCEFROMJSON
154 */
155/*static*/ DECLCALLBACK(int)
156RTCRestBool::deserializeInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT
157{
158 RTCRestObjectBase *pObj = createInstance();
159 *a_ppInstance = pObj;
160 if (pObj)
161 return pObj->deserializeFromJson(a_rCursor);
162 return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_NO_MEMORY, "Out of memory");
163}
164
165
166/** Default constructor. */
167RTCRestBool::RTCRestBool() RT_NOEXCEPT
168 : RTCRestObjectBase()
169 , m_fValue(false)
170{
171}
172
173
174/** Copy constructor. */
175RTCRestBool::RTCRestBool(RTCRestBool const &a_rThat) RT_NOEXCEPT
176 : RTCRestObjectBase(a_rThat)
177 , m_fValue(a_rThat.m_fValue)
178{
179}
180
181
182/** From value constructor. */
183RTCRestBool::RTCRestBool(bool fValue) RT_NOEXCEPT
184 : m_fValue(fValue)
185{
186}
187
188
189/** Destructor. */
190RTCRestBool::~RTCRestBool()
191{
192 /* nothing to do */
193}
194
195
196/** Copy assignment operator. */
197RTCRestBool &RTCRestBool::operator=(RTCRestBool const &a_rThat) RT_NOEXCEPT
198{
199 m_fNullIndicator = a_rThat.m_fNullIndicator;
200 m_fValue = a_rThat.m_fValue;
201 return *this;
202}
203
204
205int RTCRestBool::assignCopy(RTCRestBool const &a_rThat) RT_NOEXCEPT
206{
207 m_fNullIndicator = a_rThat.m_fNullIndicator;
208 m_fValue = a_rThat.m_fValue;
209 return VINF_SUCCESS;
210}
211
212
213void RTCRestBool::assignValue(bool a_fValue) RT_NOEXCEPT
214{
215 m_fValue = a_fValue;
216 m_fNullIndicator = false;
217}
218
219
220RTCRestObjectBase *RTCRestBool::baseClone() const RT_NOEXCEPT
221{
222 return new (std::nothrow) RTCRestBool(*this);
223}
224
225
226int RTCRestBool::resetToDefault() RT_NOEXCEPT
227{
228 m_fValue = false;
229 m_fNullIndicator = false;
230 return VINF_SUCCESS;
231}
232
233
234RTCRestOutputBase &RTCRestBool::serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT
235{
236 a_rDst.printf(!m_fNullIndicator ? m_fValue ? "true" : "false" : "null");
237 return a_rDst;
238}
239
240
241int RTCRestBool::deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT
242{
243 m_fValue = false;
244 m_fNullIndicator = false;
245
246 RTJSONVALTYPE enmType = RTJsonValueGetType(a_rCursor.m_hValue);
247
248 if (enmType == RTJSONVALTYPE_TRUE)
249 {
250 m_fValue = true;
251 return VINF_SUCCESS;
252 }
253
254 if (enmType == RTJSONVALTYPE_FALSE)
255 return VINF_SUCCESS;
256
257 if (enmType == RTJSONVALTYPE_NULL)
258 {
259 m_fNullIndicator = true;
260 return VINF_SUCCESS;
261 }
262
263 return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_REST_WRONG_JSON_TYPE_FOR_BOOL, "wrong JSON type %s for boolean",
264 RTJsonValueTypeName(RTJsonValueGetType(a_rCursor.m_hValue)));
265}
266
267
268int RTCRestBool::toString(RTCString *a_pDst, uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) const RT_NOEXCEPT
269{
270 if (!(a_fFlags & kToString_Append))
271 {
272 if (!m_fNullIndicator)
273 {
274 if (m_fValue)
275 return a_pDst->assignNoThrow(RT_STR_TUPLE("true"));
276 return a_pDst->assignNoThrow(RT_STR_TUPLE("false"));
277 }
278 return a_pDst->assignNoThrow(RT_STR_TUPLE("null"));
279 }
280
281 if (!m_fNullIndicator)
282 {
283 if (m_fValue)
284 return a_pDst->appendNoThrow(RT_STR_TUPLE("true"));
285 return a_pDst->appendNoThrow(RT_STR_TUPLE("false"));
286 }
287 return a_pDst->appendNoThrow(RT_STR_TUPLE("null"));
288}
289
290
291int RTCRestBool::fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo /*= NULL*/,
292 uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) RT_NOEXCEPT
293{
294 RT_NOREF(a_fFlags);
295
296 if (a_rValue.startsWithWord("true", RTCString::CaseInsensitive))
297 {
298 m_fValue = true;
299 m_fNullIndicator = false;
300 }
301 else if (a_rValue.startsWithWord("false", RTCString::CaseInsensitive))
302 {
303 m_fValue = false;
304 m_fNullIndicator = false;
305 }
306 else if (a_rValue.startsWithWord("null", RTCString::CaseInsensitive))
307 {
308 m_fValue = false;
309 m_fNullIndicator = true;
310 }
311 else
312 return RTErrInfoSetF(a_pErrInfo, VERR_REST_UNABLE_TO_PARSE_STRING_AS_BOOL,
313 "%s: unable to parse '%s' as bool", a_pszName, a_rValue.c_str());
314 return VINF_SUCCESS;
315}
316
317
318RTCRestObjectBase::kTypeClass RTCRestBool::typeClass() const RT_NOEXCEPT
319{
320 return kTypeClass_Bool;
321}
322
323
324const char *RTCRestBool::typeName() const RT_NOEXCEPT
325{
326 return "bool";
327}
328
329
330
331/*********************************************************************************************************************************
332* RTCRestInt64 implementation *
333*********************************************************************************************************************************/
334
335/** Factory method. */
336/*static*/ DECLCALLBACK(RTCRestObjectBase *) RTCRestInt64::createInstance(void) RT_NOEXCEPT
337{
338 return new (std::nothrow) RTCRestInt64();
339}
340
341
342/**
343 * @copydoc RTCRestObjectBase::FNDESERIALIZEINSTANCEFROMJSON
344 */
345/*static*/ DECLCALLBACK(int)
346RTCRestInt64::deserializeInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT
347{
348 RTCRestObjectBase *pObj = createInstance();
349 *a_ppInstance = pObj;
350 if (pObj)
351 return pObj->deserializeFromJson(a_rCursor);
352 return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_NO_MEMORY, "Out of memory");
353}
354
355
356/** Default constructor. */
357RTCRestInt64::RTCRestInt64() RT_NOEXCEPT
358 : RTCRestObjectBase()
359 , m_iValue(0)
360{
361}
362
363
364/** Copy constructor. */
365RTCRestInt64::RTCRestInt64(RTCRestInt64 const &a_rThat) RT_NOEXCEPT
366 : RTCRestObjectBase(a_rThat)
367 , m_iValue(a_rThat.m_iValue)
368{
369}
370
371
372/** From value constructor. */
373RTCRestInt64::RTCRestInt64(int64_t iValue) RT_NOEXCEPT
374 : RTCRestObjectBase()
375 , m_iValue(iValue)
376{
377}
378
379
380/** Destructor. */
381RTCRestInt64::~RTCRestInt64()
382{
383 /* nothing to do */
384}
385
386
387/** Copy assignment operator. */
388RTCRestInt64 &RTCRestInt64::operator=(RTCRestInt64 const &a_rThat) RT_NOEXCEPT
389{
390 m_fNullIndicator = a_rThat.m_fNullIndicator;
391 m_iValue = a_rThat.m_iValue;
392 return *this;
393}
394
395
396int RTCRestInt64::assignCopy(RTCRestInt64 const &a_rThat) RT_NOEXCEPT
397{
398 m_fNullIndicator = a_rThat.m_fNullIndicator;
399 m_iValue = a_rThat.m_iValue;
400 return VINF_SUCCESS;
401}
402
403
404void RTCRestInt64::assignValue(int64_t a_iValue) RT_NOEXCEPT
405{
406 m_iValue = a_iValue;
407 m_fNullIndicator = false;
408}
409
410
411RTCRestObjectBase *RTCRestInt64::baseClone() const RT_NOEXCEPT
412{
413 return new (std::nothrow) RTCRestInt64(*this);
414}
415
416
417int RTCRestInt64::resetToDefault() RT_NOEXCEPT
418{
419 m_iValue = 0;
420 m_fNullIndicator = false;
421 return VINF_SUCCESS;
422}
423
424
425RTCRestOutputBase &RTCRestInt64::serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT
426{
427 if (!m_fNullIndicator)
428 a_rDst.printf("%RI64", m_iValue);
429 else
430 a_rDst.nullValue();
431 return a_rDst;
432}
433
434
435int RTCRestInt64::deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT
436{
437 m_iValue = 0;
438 m_fNullIndicator = false;
439
440 RTJSONVALTYPE enmType = RTJsonValueGetType(a_rCursor.m_hValue);
441 if (enmType == RTJSONVALTYPE_INTEGER)
442 {
443 int rc = RTJsonValueQueryInteger(a_rCursor.m_hValue, &m_iValue);
444 if (RT_SUCCESS(rc))
445 return rc;
446 return a_rCursor.m_pPrimary->addError(a_rCursor, rc, "RTJsonValueQueryInteger failed with %Rrc", rc);
447 }
448
449 if (enmType == RTJSONVALTYPE_NULL)
450 {
451 m_fNullIndicator = true;
452 return VINF_SUCCESS;
453 }
454
455 /* This is probably non-sense... */
456 if (enmType == RTJSONVALTYPE_TRUE)
457 m_iValue = 1;
458
459 return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_REST_WRONG_JSON_TYPE_FOR_INTEGER, "wrong JSON type %s for 64-bit integer",
460 RTJsonValueTypeName(RTJsonValueGetType(a_rCursor.m_hValue)));
461}
462
463
464int RTCRestInt64::toString(RTCString *a_pDst, uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) const RT_NOEXCEPT
465{
466 if (!(a_fFlags & kToString_Append))
467 {
468 if (!m_fNullIndicator)
469 return a_pDst->printfNoThrow("%RI64", m_iValue);
470 return a_pDst->assignNoThrow(RT_STR_TUPLE("null"));
471 }
472 if (!m_fNullIndicator)
473 return a_pDst->appendPrintfNoThrow("%RI64", m_iValue);
474 return a_pDst->appendNoThrow(RT_STR_TUPLE("null"));
475}
476
477
478int RTCRestInt64::fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo /*= NULL*/,
479 uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) RT_NOEXCEPT
480{
481 RT_NOREF(a_fFlags);
482
483 m_iValue = 0;
484 m_fNullIndicator = false;
485
486/** @todo RTStrStripL and RTStrToInt64Full has a different idea what consitutes spaces... */
487 int rc = RTStrToInt64Full(RTStrStripL(a_rValue.c_str()), 0, &m_iValue);
488 if (rc == VINF_SUCCESS || rc == VERR_TRAILING_SPACES)
489 return VINF_SUCCESS;
490
491 if (a_rValue.startsWithWord("null", RTCString::CaseInsensitive))
492 {
493 m_iValue = 0;
494 m_fNullIndicator = true;
495 return VINF_SUCCESS;
496 }
497
498 return RTErrInfoSetF(a_pErrInfo, rc, "%s: error %Rrc parsing '%s' as int64_t", a_pszName, rc, a_rValue.c_str());
499}
500
501
502RTCRestObjectBase::kTypeClass RTCRestInt64::typeClass() const RT_NOEXCEPT
503{
504 return kTypeClass_Int64;
505}
506
507
508const char *RTCRestInt64::typeName() const RT_NOEXCEPT
509{
510 return "int64_t";
511}
512
513
514
515/*********************************************************************************************************************************
516* RTCRestInt32 implementation *
517*********************************************************************************************************************************/
518
519/** Factory method. */
520/*static*/ DECLCALLBACK(RTCRestObjectBase *) RTCRestInt32::createInstance(void) RT_NOEXCEPT
521{
522 return new (std::nothrow) RTCRestInt32();
523}
524
525
526/**
527 * @copydoc RTCRestObjectBase::FNDESERIALIZEINSTANCEFROMJSON
528 */
529/*static*/ DECLCALLBACK(int)
530RTCRestInt32::deserializeInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT
531{
532 RTCRestObjectBase *pObj = createInstance();
533 *a_ppInstance = pObj;
534 if (pObj)
535 return pObj->deserializeFromJson(a_rCursor);
536 return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_NO_MEMORY, "Out of memory");
537}
538
539
540/** Default constructor. */
541RTCRestInt32::RTCRestInt32() RT_NOEXCEPT
542 : RTCRestObjectBase()
543 , m_iValue(0)
544{
545}
546
547
548/** Copy constructor. */
549RTCRestInt32::RTCRestInt32(RTCRestInt32 const &a_rThat) RT_NOEXCEPT
550 : RTCRestObjectBase(a_rThat)
551 , m_iValue(a_rThat.m_iValue)
552{
553}
554
555
556/** From value constructor. */
557RTCRestInt32::RTCRestInt32(int32_t iValue) RT_NOEXCEPT
558 : RTCRestObjectBase()
559 , m_iValue(iValue)
560{
561}
562
563
564/** Destructor. */
565RTCRestInt32::~RTCRestInt32() RT_NOEXCEPT
566{
567 /* nothing to do */
568}
569
570
571/** Copy assignment operator. */
572RTCRestInt32 &RTCRestInt32::operator=(RTCRestInt32 const &a_rThat) RT_NOEXCEPT
573{
574 m_fNullIndicator = a_rThat.m_fNullIndicator;
575 m_iValue = a_rThat.m_iValue;
576 return *this;
577}
578
579
580int RTCRestInt32::assignCopy(RTCRestInt32 const &a_rThat) RT_NOEXCEPT
581{
582 m_fNullIndicator = a_rThat.m_fNullIndicator;
583 m_iValue = a_rThat.m_iValue;
584 return VINF_SUCCESS;
585}
586
587
588RTCRestObjectBase *RTCRestInt32::baseClone() const RT_NOEXCEPT
589{
590 return new (std::nothrow) RTCRestInt32(*this);
591}
592
593
594int RTCRestInt32::resetToDefault() RT_NOEXCEPT
595{
596 m_iValue = 0;
597 m_fNullIndicator = false;
598 return VINF_SUCCESS;
599}
600
601
602void RTCRestInt32::assignValue(int32_t a_iValue) RT_NOEXCEPT
603{
604 m_iValue = a_iValue;
605 m_fNullIndicator = false;
606}
607
608
609RTCRestOutputBase &RTCRestInt32::serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT
610{
611 if (!m_fNullIndicator)
612 a_rDst.printf("%RI32", m_iValue);
613 else
614 a_rDst.nullValue();
615 return a_rDst;
616}
617
618
619int RTCRestInt32::deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT
620{
621 m_iValue = 0;
622 m_fNullIndicator = false;
623
624 RTJSONVALTYPE enmType = RTJsonValueGetType(a_rCursor.m_hValue);
625 if (enmType == RTJSONVALTYPE_INTEGER)
626 {
627 int64_t iTmp = m_iValue;
628 int rc = RTJsonValueQueryInteger(a_rCursor.m_hValue, &iTmp);
629 if (RT_SUCCESS(rc))
630 {
631 m_iValue = (int32_t)iTmp;
632 if (m_iValue == iTmp)
633 return rc;
634 return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_OUT_OF_RANGE, "value %RI64 does not fit in 32 bits", iTmp);
635 }
636 return a_rCursor.m_pPrimary->addError(a_rCursor, rc, "RTJsonValueQueryInteger failed with %Rrc", rc);
637 }
638
639 if (enmType == RTJSONVALTYPE_NULL)
640 {
641 m_fNullIndicator = true;
642 return VINF_SUCCESS;
643 }
644
645 /* This is probably non-sense... */
646 if (enmType == RTJSONVALTYPE_TRUE)
647 m_iValue = 1;
648
649 return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_REST_WRONG_JSON_TYPE_FOR_INTEGER, "wrong JSON type %s for 32-bit integer",
650 RTJsonValueTypeName(RTJsonValueGetType(a_rCursor.m_hValue)));
651}
652
653
654int RTCRestInt32::toString(RTCString *a_pDst, uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) const RT_NOEXCEPT
655{
656 if (!(a_fFlags & kToString_Append))
657 {
658 if (!m_fNullIndicator)
659 return a_pDst->printfNoThrow("%RI32", m_iValue);
660 return a_pDst->assignNoThrow(RT_STR_TUPLE("null"));
661 }
662 if (!m_fNullIndicator)
663 return a_pDst->appendPrintfNoThrow("%RI32", m_iValue);
664 return a_pDst->appendNoThrow(RT_STR_TUPLE("null"));
665}
666
667
668int RTCRestInt32::fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo /*= NULL*/,
669 uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) RT_NOEXCEPT
670{
671 RT_NOREF(a_fFlags);
672
673 m_iValue = 0;
674 m_fNullIndicator = false;
675
676/** @todo RTStrStripL and RTStrToInt32Full has a different idea what consitutes spaces... */
677 int rc = RTStrToInt32Full(RTStrStripL(a_rValue.c_str()), 0, &m_iValue);
678 if (rc == VINF_SUCCESS || rc == VERR_TRAILING_SPACES)
679 return VINF_SUCCESS;
680
681 if (a_rValue.startsWithWord("null", RTCString::CaseInsensitive))
682 {
683 m_iValue = 0;
684 m_fNullIndicator = true;
685 return VINF_SUCCESS;
686 }
687
688 return RTErrInfoSetF(a_pErrInfo, rc, "%s: error %Rrc parsing '%s' as int32_t", a_pszName, rc, a_rValue.c_str());
689}
690
691
692RTCRestObjectBase::kTypeClass RTCRestInt32::typeClass() const RT_NOEXCEPT
693{
694 return kTypeClass_Int32;
695}
696
697
698const char *RTCRestInt32::typeName() const RT_NOEXCEPT
699{
700 return "int32_t";
701}
702
703
704
705/*********************************************************************************************************************************
706* RTCRestInt16 implementation *
707*********************************************************************************************************************************/
708
709/** Factory method. */
710/*static*/ DECLCALLBACK(RTCRestObjectBase *) RTCRestInt16::createInstance(void) RT_NOEXCEPT
711{
712 return new (std::nothrow) RTCRestInt16();
713}
714
715
716/**
717 * @copydoc RTCRestObjectBase::FNDESERIALIZEINSTANCEFROMJSON
718 */
719/*static*/ DECLCALLBACK(int)
720RTCRestInt16::deserializeInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT
721{
722 RTCRestObjectBase *pObj = createInstance();
723 *a_ppInstance = pObj;
724 if (pObj)
725 return pObj->deserializeFromJson(a_rCursor);
726 return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_NO_MEMORY, "Out of memory");
727}
728
729
730/** Default constructor. */
731RTCRestInt16::RTCRestInt16() RT_NOEXCEPT
732 : RTCRestObjectBase()
733 , m_iValue(0)
734{
735}
736
737
738/** Copy constructor. */
739RTCRestInt16::RTCRestInt16(RTCRestInt16 const &a_rThat) RT_NOEXCEPT
740 : RTCRestObjectBase(a_rThat)
741 , m_iValue(a_rThat.m_iValue)
742{
743}
744
745
746/** From value constructor. */
747RTCRestInt16::RTCRestInt16(int16_t iValue) RT_NOEXCEPT
748 : RTCRestObjectBase()
749 , m_iValue(iValue)
750{
751}
752
753
754/** Destructor. */
755RTCRestInt16::~RTCRestInt16()
756{
757 /* nothing to do */
758}
759
760
761/** Copy assignment operator. */
762RTCRestInt16 &RTCRestInt16::operator=(RTCRestInt16 const &a_rThat) RT_NOEXCEPT
763{
764 m_fNullIndicator = a_rThat.m_fNullIndicator;
765 m_iValue = a_rThat.m_iValue;
766 return *this;
767}
768
769
770int RTCRestInt16::assignCopy(RTCRestInt16 const &a_rThat) RT_NOEXCEPT
771{
772 m_fNullIndicator = a_rThat.m_fNullIndicator;
773 m_iValue = a_rThat.m_iValue;
774 return VINF_SUCCESS;
775}
776
777
778void RTCRestInt16::assignValue(int16_t a_iValue) RT_NOEXCEPT
779{
780 m_iValue = a_iValue;
781 m_fNullIndicator = false;
782}
783
784
785RTCRestObjectBase *RTCRestInt16::baseClone() const RT_NOEXCEPT
786{
787 return new (std::nothrow) RTCRestInt16(*this);
788}
789
790
791int RTCRestInt16::resetToDefault() RT_NOEXCEPT
792{
793 m_iValue = 0;
794 m_fNullIndicator = false;
795 return VINF_SUCCESS;
796}
797
798
799RTCRestOutputBase &RTCRestInt16::serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT
800{
801 if (!m_fNullIndicator)
802 a_rDst.printf("%RI16", m_iValue);
803 else
804 a_rDst.nullValue();
805 return a_rDst;
806}
807
808
809int RTCRestInt16::deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT
810{
811 m_iValue = 0;
812 m_fNullIndicator = false;
813
814 RTJSONVALTYPE enmType = RTJsonValueGetType(a_rCursor.m_hValue);
815 if (enmType == RTJSONVALTYPE_INTEGER)
816 {
817 int64_t iTmp = m_iValue;
818 int rc = RTJsonValueQueryInteger(a_rCursor.m_hValue, &iTmp);
819 if (RT_SUCCESS(rc))
820 {
821 m_iValue = (int16_t)iTmp;
822 if (m_iValue == iTmp)
823 return rc;
824 return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_OUT_OF_RANGE, "value %RI64 does not fit in 16 bits", iTmp);
825 }
826 return a_rCursor.m_pPrimary->addError(a_rCursor, rc, "RTJsonValueQueryInteger failed with %Rrc", rc);
827 }
828
829 if (enmType == RTJSONVALTYPE_NULL)
830 {
831 m_fNullIndicator = true;
832 return VINF_SUCCESS;
833 }
834
835 /* This is probably non-sense... */
836 if (enmType == RTJSONVALTYPE_TRUE)
837 m_iValue = 1;
838
839 return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_REST_WRONG_JSON_TYPE_FOR_INTEGER, "wrong JSON type %s for 16-bit integer",
840 RTJsonValueTypeName(RTJsonValueGetType(a_rCursor.m_hValue)));
841}
842
843
844int RTCRestInt16::toString(RTCString *a_pDst, uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) const RT_NOEXCEPT
845{
846 if (!(a_fFlags & kToString_Append))
847 {
848 if (!m_fNullIndicator)
849 return a_pDst->printfNoThrow("%RI16", m_iValue);
850 return a_pDst->assignNoThrow(RT_STR_TUPLE("null"));
851 }
852 if (!m_fNullIndicator)
853 return a_pDst->appendPrintfNoThrow("%RI16", m_iValue);
854 return a_pDst->appendNoThrow(RT_STR_TUPLE("null"));
855}
856
857
858int RTCRestInt16::fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo /*= NULL*/,
859 uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) RT_NOEXCEPT
860{
861 RT_NOREF(a_fFlags);
862
863 m_iValue = 0;
864 m_fNullIndicator = false;
865
866/** @todo RTStrStripL and RTStrToInt16Full has a different idea what consitutes spaces... */
867 int rc = RTStrToInt16Full(RTStrStripL(a_rValue.c_str()), 0, &m_iValue);
868 if (rc == VINF_SUCCESS || rc == VERR_TRAILING_SPACES)
869 return VINF_SUCCESS;
870
871 if (a_rValue.startsWithWord("null", RTCString::CaseInsensitive))
872 {
873 m_iValue = 0;
874 m_fNullIndicator = true;
875 return VINF_SUCCESS;
876 }
877
878 return RTErrInfoSetF(a_pErrInfo, rc, "%s: error %Rrc parsing '%s' as int16_t", a_pszName, rc, a_rValue.c_str());
879}
880
881
882RTCRestObjectBase::kTypeClass RTCRestInt16::typeClass() const RT_NOEXCEPT
883{
884 return kTypeClass_Int16;
885}
886
887
888const char *RTCRestInt16::typeName() const RT_NOEXCEPT
889{
890 return "int16_t";
891}
892
893
894
895/*********************************************************************************************************************************
896* RTCRestDouble implementation *
897*********************************************************************************************************************************/
898
899/** Factory method. */
900/*static*/ DECLCALLBACK(RTCRestObjectBase *) RTCRestDouble::createInstance(void) RT_NOEXCEPT
901{
902 return new (std::nothrow) RTCRestDouble();
903}
904
905
906/**
907 * @copydoc RTCRestObjectBase::FNDESERIALIZEINSTANCEFROMJSON
908 */
909/*static*/ DECLCALLBACK(int)
910RTCRestDouble::deserializeInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT
911{
912 RTCRestObjectBase *pObj = createInstance();
913 *a_ppInstance = pObj;
914 if (pObj)
915 return pObj->deserializeFromJson(a_rCursor);
916 return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_NO_MEMORY, "Out of memory");
917}
918
919
920/** Default constructor. */
921RTCRestDouble::RTCRestDouble() RT_NOEXCEPT
922 : RTCRestObjectBase()
923 , m_rdValue(0.0)
924{
925}
926
927
928/** Copy constructor. */
929RTCRestDouble::RTCRestDouble(RTCRestDouble const &a_rThat) RT_NOEXCEPT
930 : RTCRestObjectBase(a_rThat)
931 , m_rdValue(a_rThat.m_rdValue)
932{
933}
934
935
936/** From value constructor. */
937RTCRestDouble::RTCRestDouble(double rdValue) RT_NOEXCEPT
938 : RTCRestObjectBase()
939 , m_rdValue(rdValue)
940{
941}
942
943
944/** Destructor. */
945RTCRestDouble::~RTCRestDouble()
946{
947 /* nothing to do */
948}
949
950
951/** Copy assignment operator. */
952RTCRestDouble &RTCRestDouble::operator=(RTCRestDouble const &a_rThat) RT_NOEXCEPT
953{
954 m_fNullIndicator = a_rThat.m_fNullIndicator;
955 m_rdValue = a_rThat.m_rdValue;
956 return *this;
957}
958
959
960int RTCRestDouble::assignCopy(RTCRestDouble const &a_rThat) RT_NOEXCEPT
961{
962 m_fNullIndicator = a_rThat.m_fNullIndicator;
963 m_rdValue = a_rThat.m_rdValue;
964 return VINF_SUCCESS;
965}
966
967
968void RTCRestDouble::assignValue(double a_rdValue) RT_NOEXCEPT
969{
970 m_rdValue = a_rdValue;
971 m_fNullIndicator = false;
972}
973
974
975RTCRestObjectBase *RTCRestDouble::baseClone() const RT_NOEXCEPT
976{
977 return new (std::nothrow) RTCRestDouble(*this);
978}
979
980
981int RTCRestDouble::resetToDefault() RT_NOEXCEPT
982{
983 m_rdValue = 0.0;
984 m_fNullIndicator = false;
985 return VINF_SUCCESS;
986}
987
988
989RTCRestOutputBase &RTCRestDouble::serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT
990{
991 if (!m_fNullIndicator)
992 {
993
994 /* Just a simple approximation here. */
995 /** @todo Not 100% sure printf %g produces the right result for JSON floating point, but it'll have to do for now... */
996 char szValue[128];
997#ifdef _MSC_VER
998 _snprintf(szValue, sizeof(szValue), "%.18g", m_rdValue);
999#else
1000 snprintf(szValue, sizeof(szValue), "%.18g", m_rdValue);
1001#endif
1002 size_t cchValue = strlen(szValue);
1003 while (cchValue > 0 && szValue[cchValue - 1] == '0')
1004 cchValue--;
1005 szValue[cchValue] = '\0';
1006
1007 a_rDst.printf("%s", szValue);
1008 }
1009 else
1010 a_rDst.nullValue();
1011 return a_rDst;
1012}
1013
1014
1015int RTCRestDouble::deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT
1016{
1017 m_rdValue = 0.0;
1018 m_fNullIndicator = false;
1019
1020 RTJSONVALTYPE enmType = RTJsonValueGetType(a_rCursor.m_hValue);
1021 if (enmType == RTJSONVALTYPE_NUMBER)
1022 {
1023 int rc = RTJsonValueQueryNumber(a_rCursor.m_hValue, &m_rdValue);
1024 if (RT_SUCCESS(rc))
1025 return rc;
1026 return a_rCursor.m_pPrimary->addError(a_rCursor, rc, "RTJsonValueQueryNumber failed with %Rrc", rc);
1027 }
1028
1029 if (enmType == RTJSONVALTYPE_INTEGER)
1030 {
1031 int64_t iTmp = 0;
1032 int rc = RTJsonValueQueryInteger(a_rCursor.m_hValue, &iTmp);
1033 if (RT_SUCCESS(rc))
1034 {
1035 m_rdValue = iTmp;
1036 if ((int64_t)m_rdValue == iTmp)
1037 return rc;
1038 return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_OUT_OF_RANGE, "value %RI64 does not fit in a double", iTmp);
1039 }
1040 return a_rCursor.m_pPrimary->addError(a_rCursor, rc, "RTJsonValueQueryInteger failed with %Rrc", rc);
1041 }
1042
1043 if (enmType == RTJSONVALTYPE_NULL)
1044 {
1045 m_fNullIndicator = true;
1046 return VINF_SUCCESS;
1047 }
1048
1049 /* This is probably non-sense... */
1050 if (enmType == RTJSONVALTYPE_TRUE)
1051 m_rdValue = 1.0;
1052
1053 return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_REST_WRONG_JSON_TYPE_FOR_DOUBLE, "wrong JSON type %s for a double",
1054 RTJsonValueTypeName(RTJsonValueGetType(a_rCursor.m_hValue)));
1055}
1056
1057
1058int RTCRestDouble::toString(RTCString *a_pDst, uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) const RT_NOEXCEPT
1059{
1060 if (!m_fNullIndicator)
1061 {
1062 /* Just a simple approximation here. */
1063 /** @todo Not 100% sure printf %g produces the right result for JSON floating point, but it'll have to do for now... */
1064 char szValue[128];
1065#ifdef _MSC_VER
1066 _snprintf(szValue, sizeof(szValue), "%.18g", m_rdValue);
1067#else
1068 snprintf(szValue, sizeof(szValue), "%.18g", m_rdValue);
1069#endif
1070 size_t cchValue = strlen(szValue);
1071 while (cchValue > 0 && szValue[cchValue - 1] == '0')
1072 cchValue--;
1073 szValue[cchValue] = '\0';
1074
1075 if (!(a_fFlags & kToString_Append))
1076 return a_pDst->assignNoThrow(szValue, cchValue);
1077 return a_pDst->appendNoThrow(szValue, cchValue);
1078 }
1079
1080 if (!(a_fFlags & kToString_Append))
1081 return a_pDst->assignNoThrow(RT_STR_TUPLE("null"));
1082 return a_pDst->appendNoThrow(RT_STR_TUPLE("null"));
1083}
1084
1085
1086int RTCRestDouble::fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo /*= NULL*/,
1087 uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) RT_NOEXCEPT
1088{
1089 RT_NOREF(a_fFlags);
1090
1091 if (a_rValue.startsWithWord("null", RTCString::CaseInsensitive))
1092 {
1093 m_rdValue = 0.0;
1094 m_fNullIndicator = true;
1095 return VINF_SUCCESS;
1096 }
1097
1098 m_fNullIndicator = false;
1099
1100 const char *pszValue = RTStrStripL(a_rValue.c_str());
1101 errno = 0;
1102 char *pszNext = NULL;
1103 m_rdValue = strtod(pszValue, &pszNext);
1104 if (errno == 0 && pszNext != pszValue)
1105 {
1106 if (!pszNext || *pszNext == '\0')
1107 return VINF_SUCCESS;
1108
1109 while (RT_C_IS_SPACE(*pszNext))
1110 pszNext++;
1111 if (*pszNext == '\0')
1112 return VINF_SUCCESS;
1113
1114 return RTErrInfoSetF(a_pErrInfo, VERR_TRAILING_CHARS, "%s: error VERR_TRAILING_CHARS parsing '%s' as double",
1115 a_pszName, a_rValue.c_str());
1116 }
1117
1118 if (!RT_C_IS_DIGIT(*pszValue) && *pszValue != '.')
1119 return RTErrInfoSetF(a_pErrInfo, VERR_NO_DIGITS, "%s: error VERR_NO_DIGITS parsing '%s' as double",
1120 a_pszName, a_rValue.c_str());
1121 int rc = RTErrConvertFromErrno(errno);
1122 return RTErrInfoSetF(a_pErrInfo, rc, "%s: error %Rrc parsing '%s' as double", a_pszName, rc, a_rValue.c_str());
1123}
1124
1125
1126RTCRestObjectBase::kTypeClass RTCRestDouble::typeClass() const RT_NOEXCEPT
1127{
1128 return kTypeClass_Double;
1129}
1130
1131
1132const char *RTCRestDouble::typeName() const RT_NOEXCEPT
1133{
1134 return "double";
1135}
1136
1137
1138
1139/*********************************************************************************************************************************
1140* RTCRestString implementation *
1141*********************************************************************************************************************************/
1142
1143/** Factory method. */
1144/*static*/ DECLCALLBACK(RTCRestObjectBase *) RTCRestString::createInstance(void) RT_NOEXCEPT
1145{
1146 return new (std::nothrow) RTCRestString();
1147}
1148
1149
1150/**
1151 * @copydoc RTCRestObjectBase::FNDESERIALIZEINSTANCEFROMJSON
1152 */
1153/*static*/ DECLCALLBACK(int)
1154RTCRestString::deserializeInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT
1155{
1156 RTCRestObjectBase *pObj = createInstance();
1157 *a_ppInstance = pObj;
1158 if (pObj)
1159 return pObj->deserializeFromJson(a_rCursor);
1160 return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_NO_MEMORY, "Out of memory");
1161}
1162
1163
1164/** Default constructor. */
1165RTCRestString::RTCRestString() RT_NOEXCEPT
1166 : RTCRestObjectBase()
1167 , RTCString()
1168{
1169}
1170
1171
1172/** Copy constructor. */
1173RTCRestString::RTCRestString(RTCRestString const &a_rThat)
1174 : RTCRestObjectBase(a_rThat)
1175 , RTCString(a_rThat)
1176{
1177}
1178
1179
1180/** From value constructor. */
1181RTCRestString::RTCRestString(RTCString const &a_rThat)
1182 : RTCString(a_rThat)
1183{
1184}
1185
1186
1187/** From value constructor. */
1188RTCRestString::RTCRestString(const char *a_pszSrc)
1189 : RTCRestObjectBase()
1190 , RTCString(a_pszSrc)
1191{
1192}
1193
1194
1195/** Destructor. */
1196RTCRestString::~RTCRestString()
1197{
1198 /* nothing to do */
1199}
1200
1201
1202int RTCRestString::assignCopy(RTCRestString const &a_rThat) RT_NOEXCEPT
1203{
1204 int rc = assignNoThrow(a_rThat);
1205 m_fNullIndicator = a_rThat.m_fNullIndicator;
1206 return rc;
1207}
1208
1209
1210int RTCRestString::assignCopy(RTCString const &a_rThat) RT_NOEXCEPT
1211{
1212 m_fNullIndicator = false;
1213 return assignNoThrow(a_rThat);
1214}
1215
1216
1217int RTCRestString::assignCopy(const char *a_pszThat) RT_NOEXCEPT
1218{
1219 m_fNullIndicator = false;
1220 return assignNoThrow(a_pszThat);
1221}
1222
1223
1224int RTCRestString::setNull() RT_NOEXCEPT
1225{
1226 RTCString::setNull();
1227 m_fNullIndicator = true;
1228 return VINF_SUCCESS;
1229}
1230
1231
1232RTCRestObjectBase *RTCRestString::baseClone() const RT_NOEXCEPT
1233{
1234 RTCRestString *pClone = new (std::nothrow) RTCRestString();
1235 if (pClone)
1236 {
1237 int rc = pClone->assignCopy(*this);
1238 if (RT_SUCCESS(rc))
1239 return pClone;
1240 delete pClone;
1241 }
1242 return NULL;
1243}
1244
1245
1246int RTCRestString::resetToDefault() RT_NOEXCEPT
1247{
1248 RTCString::setNull();
1249 m_fNullIndicator = false;
1250 return VINF_SUCCESS;
1251}
1252
1253
1254RTCRestOutputBase &RTCRestString::serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT
1255{
1256 if (!m_fNullIndicator)
1257 a_rDst.printf("%RMjs", m_psz ? m_psz : "");
1258 else
1259 a_rDst.nullValue();
1260 return a_rDst;
1261}
1262
1263
1264int RTCRestString::deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT
1265{
1266 m_fNullIndicator = false;
1267
1268 RTJSONVALTYPE enmType = RTJsonValueGetType(a_rCursor.m_hValue);
1269 if (enmType == RTJSONVALTYPE_STRING)
1270 {
1271 const char *pszValue = RTJsonValueGetString(a_rCursor.m_hValue);
1272 const size_t cchValue = strlen(pszValue);
1273 int rc = assignNoThrow(pszValue, cchValue);
1274 if (RT_SUCCESS(rc))
1275 return VINF_SUCCESS;
1276 return a_rCursor.m_pPrimary->addError(a_rCursor, rc, "no memory for %zu char long string", cchValue);
1277 }
1278
1279 RTCString::setNull();
1280
1281 if (enmType == RTJSONVALTYPE_NULL)
1282 {
1283 m_fNullIndicator = true;
1284 return VINF_SUCCESS;
1285 }
1286
1287 return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_REST_WRONG_JSON_TYPE_FOR_STRING, "wrong JSON type %s for string",
1288 RTJsonValueTypeName(RTJsonValueGetType(a_rCursor.m_hValue)));
1289}
1290
1291
1292int RTCRestString::toString(RTCString *a_pDst, uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) const RT_NOEXCEPT
1293{
1294 /* Note! m_fNullIndicator == true: empty string. */
1295 if (!(a_fFlags & kToString_Append))
1296 return a_pDst->assignNoThrow(*this);
1297 return a_pDst->appendNoThrow(*this);
1298}
1299
1300
1301int RTCRestString::fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo /*= NULL*/,
1302 uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) RT_NOEXCEPT
1303{
1304 RT_NOREF(a_fFlags); RT_NOREF(a_pszName); RT_NOREF(a_pErrInfo);
1305
1306 /* Note! Unable to set m_fNullIndicator = true here. */
1307 m_fNullIndicator = false;
1308 return assignNoThrow(a_rValue);
1309}
1310
1311
1312RTCRestObjectBase::kTypeClass RTCRestString::typeClass() const RT_NOEXCEPT
1313{
1314 return kTypeClass_String;
1315}
1316
1317
1318const char *RTCRestString::typeName() const RT_NOEXCEPT
1319{
1320 return "RTCString";
1321}
1322
1323
1324int RTCRestString::assignNoThrow(const RTCString &a_rSrc) RT_NOEXCEPT
1325{
1326 m_fNullIndicator = false;
1327 return RTCString::assignNoThrow(a_rSrc);
1328}
1329
1330
1331int RTCRestString::assignNoThrow(const char *a_pszSrc) RT_NOEXCEPT
1332{
1333 m_fNullIndicator = false;
1334 return RTCString::assignNoThrow(a_pszSrc);
1335}
1336
1337
1338int RTCRestString::assignNoThrow(const RTCString &a_rSrc, size_t a_offSrc, size_t a_cchSrc /*= npos*/) RT_NOEXCEPT
1339{
1340 m_fNullIndicator = false;
1341 return RTCString::assignNoThrow(a_rSrc, a_offSrc, a_cchSrc);
1342}
1343
1344
1345int RTCRestString::assignNoThrow(const char *a_pszSrc, size_t a_cchSrc) RT_NOEXCEPT
1346{
1347 m_fNullIndicator = false;
1348 return RTCString::assignNoThrow(a_pszSrc, a_cchSrc);
1349}
1350
1351
1352int RTCRestString::assignNoThrow(size_t a_cTimes, char a_ch) RT_NOEXCEPT
1353{
1354 m_fNullIndicator = false;
1355 return RTCString::assignNoThrow(a_cTimes, a_ch);
1356}
1357
1358
1359int RTCRestString::printfNoThrow(const char *pszFormat, ...) RT_NOEXCEPT
1360{
1361 m_fNullIndicator = false;
1362 va_list va;
1363 va_start(va, pszFormat);
1364 int rc = RTCString::printfVNoThrow(pszFormat, va);
1365 va_end(va);
1366 return rc;
1367}
1368
1369
1370int RTCRestString::printfVNoThrow(const char *pszFormat, va_list va) RT_NOEXCEPT
1371{
1372 m_fNullIndicator = false;
1373 return RTCString::printfVNoThrow(pszFormat, va);
1374}
1375
1376
1377RTCRestString &RTCRestString::operator=(const char *a_pcsz)
1378{
1379 m_fNullIndicator = false;
1380 RTCString::operator=(a_pcsz);
1381 return *this;
1382}
1383
1384
1385RTCRestString &RTCRestString::operator=(const RTCString &a_rThat)
1386{
1387 m_fNullIndicator = false;
1388 RTCString::operator=(a_rThat);
1389 return *this;
1390}
1391
1392
1393RTCRestString &RTCRestString::operator=(const RTCRestString &a_rThat)
1394{
1395 m_fNullIndicator = a_rThat.m_fNullIndicator;
1396 RTCString::operator=(a_rThat);
1397 return *this;
1398}
1399
1400
1401RTCRestString &RTCRestString::assign(const RTCString &a_rSrc)
1402{
1403 m_fNullIndicator = false;
1404 RTCString::assign(a_rSrc);
1405 return *this;
1406}
1407
1408
1409RTCRestString &RTCRestString::assign(const char *a_pszSrc)
1410{
1411 m_fNullIndicator = false;
1412 RTCString::assign(a_pszSrc);
1413 return *this;
1414}
1415
1416
1417RTCRestString &RTCRestString::assign(const RTCString &a_rSrc, size_t a_offSrc, size_t a_cchSrc /*= npos*/)
1418{
1419 m_fNullIndicator = false;
1420 RTCString::assign(a_rSrc, a_offSrc, a_cchSrc);
1421 return *this;
1422}
1423
1424
1425RTCRestString &RTCRestString::assign(const char *a_pszSrc, size_t a_cchSrc)
1426{
1427 m_fNullIndicator = false;
1428 RTCString::assign(a_pszSrc, a_cchSrc);
1429 return *this;
1430}
1431
1432
1433RTCRestString &RTCRestString::assign(size_t a_cTimes, char a_ch)
1434{
1435 m_fNullIndicator = false;
1436 RTCString::assign(a_cTimes, a_ch);
1437 return *this;
1438}
1439
1440
1441RTCRestString &RTCRestString::printf(const char *pszFormat, ...)
1442{
1443 m_fNullIndicator = false;
1444 va_list va;
1445 va_start(va, pszFormat);
1446 RTCString::printfV(pszFormat, va);
1447 va_end(va);
1448 return *this;
1449}
1450
1451
1452RTCRestString &RTCRestString::printfV(const char *pszFormat, va_list va)
1453{
1454 m_fNullIndicator = false;
1455 RTCString::printfV(pszFormat, va);
1456 return *this;
1457}
1458
1459
1460
1461/*********************************************************************************************************************************
1462* RTCRestDate implementation *
1463*********************************************************************************************************************************/
1464/*static*/ DECLCALLBACK(RTCRestObjectBase *) RTCRestDate::createInstance(void) RT_NOEXCEPT
1465{
1466 return new (std::nothrow) RTCRestDate();
1467}
1468
1469
1470/**
1471 * @copydoc RTCRestObjectBase::FNDESERIALIZEINSTANCEFROMJSON
1472 */
1473/*static*/ DECLCALLBACK(int)
1474RTCRestDate::deserializeInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT
1475{
1476 RTCRestObjectBase *pObj = createInstance();
1477 *a_ppInstance = pObj;
1478 if (pObj)
1479 return pObj->deserializeFromJson(a_rCursor);
1480 return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_NO_MEMORY, "Out of memory");
1481}
1482
1483
1484RTCRestDate::RTCRestDate() RT_NOEXCEPT
1485 : RTCRestObjectBase()
1486 , m_fTimeSpecOkay(false)
1487 , m_enmFormat(kFormat_Invalid)
1488 , m_strFormatted()
1489{
1490 RTTimeSpecSetNano(&m_TimeSpec, 0);
1491 RT_ZERO(m_Exploded);
1492
1493 /* Since we need to know the format, all date-time values default to 'null'. */
1494 m_fNullIndicator = true;
1495}
1496
1497
1498RTCRestDate::RTCRestDate(RTCRestDate const &a_rThat)
1499 : RTCRestObjectBase(a_rThat)
1500 , m_fTimeSpecOkay(a_rThat.m_fTimeSpecOkay)
1501 , m_enmFormat(a_rThat.m_enmFormat)
1502 , m_strFormatted(a_rThat.m_strFormatted)
1503{
1504 m_TimeSpec = a_rThat.m_TimeSpec;
1505 m_Exploded = a_rThat.m_Exploded;
1506}
1507
1508
1509RTCRestDate::~RTCRestDate()
1510{
1511 /* nothing to do */
1512}
1513
1514
1515RTCRestDate &RTCRestDate::operator=(RTCRestDate const &a_rThat)
1516{
1517 RTCRestObjectBase::operator=(a_rThat);
1518 m_TimeSpec = a_rThat.m_TimeSpec;
1519 m_Exploded = a_rThat.m_Exploded;
1520 m_fTimeSpecOkay = a_rThat.m_fTimeSpecOkay;
1521 m_enmFormat = a_rThat.m_enmFormat;
1522 m_strFormatted = a_rThat.m_strFormatted;
1523 return *this;
1524}
1525
1526
1527int RTCRestDate::assignCopy(RTCRestDate const &a_rThat) RT_NOEXCEPT
1528{
1529 m_fNullIndicator = a_rThat.m_fNullIndicator;
1530 m_TimeSpec = a_rThat.m_TimeSpec;
1531 m_Exploded = a_rThat.m_Exploded;
1532 m_fTimeSpecOkay = a_rThat.m_fTimeSpecOkay;
1533 m_enmFormat = a_rThat.m_enmFormat;
1534 return m_strFormatted.assignNoThrow(a_rThat.m_strFormatted);
1535}
1536
1537
1538RTCRestObjectBase *RTCRestDate::baseClone() const RT_NOEXCEPT
1539{
1540 RTCRestDate *pClone = new (std::nothrow) RTCRestDate();
1541 if (pClone)
1542 {
1543 int rc = pClone->assignCopy(*this);
1544 if (RT_SUCCESS(rc))
1545 return pClone;
1546 delete pClone;
1547 }
1548 return NULL;
1549}
1550
1551
1552int RTCRestDate::resetToDefault() RT_NOEXCEPT
1553{
1554 m_fNullIndicator = true;
1555 RTTimeSpecSetNano(&m_TimeSpec, 0);
1556 RT_ZERO(m_Exploded);
1557 m_fTimeSpecOkay = false;
1558 m_strFormatted.setNull();
1559 /*m_enmFormat - leave as hint. */
1560 return VINF_SUCCESS;
1561}
1562
1563
1564RTCRestOutputBase &RTCRestDate::serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT
1565{
1566 if (m_fNullIndicator)
1567 a_rDst.nullValue();
1568 else
1569 a_rDst.printf("%RMjs", m_strFormatted.c_str());
1570 return a_rDst;
1571}
1572
1573
1574int RTCRestDate::deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT
1575{
1576 setNull();
1577
1578 RTJSONVALTYPE enmType = RTJsonValueGetType(a_rCursor.m_hValue);
1579 if (enmType == RTJSONVALTYPE_STRING)
1580 {
1581 int rc = m_strFormatted.assignNoThrow(RTJsonValueGetString(a_rCursor.m_hValue));
1582 AssertRCReturn(rc, rc);
1583
1584 m_fNullIndicator = false;
1585 rc = decodeFormattedString(m_enmFormat);
1586 if (RT_SUCCESS(rc))
1587 return rc;
1588 if (m_enmFormat != kFormat_Invalid)
1589 {
1590 rc = decodeFormattedString();
1591 if (RT_SUCCESS(rc))
1592 return rc;
1593 }
1594 return a_rCursor.m_pPrimary->addError(a_rCursor, VWRN_REST_UNABLE_TO_DECODE_DATE,
1595 "Unable to decode date value: %s", m_strFormatted.c_str());
1596 }
1597
1598 if (enmType == RTJSONVALTYPE_NULL)
1599 return VINF_SUCCESS;
1600
1601 return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_REST_WRONG_JSON_TYPE_FOR_DATE, "wrong JSON type for date: %s",
1602 RTJsonValueTypeName(RTJsonValueGetType(a_rCursor.m_hValue)));
1603}
1604
1605
1606int RTCRestDate::toString(RTCString *a_pDst, uint32_t a_fFlags /*= 0*/) const RT_NOEXCEPT
1607{
1608 if (m_fNullIndicator)
1609 {
1610 if (a_fFlags & kToString_Append)
1611 return a_pDst->appendNoThrow(RT_STR_TUPLE("null"));
1612 return a_pDst->assignNoThrow(RT_STR_TUPLE("null"));
1613 }
1614 if (a_fFlags & kToString_Append)
1615 return a_pDst->appendNoThrow(m_strFormatted);
1616 return a_pDst->assignNoThrow(m_strFormatted);
1617}
1618
1619
1620int RTCRestDate::fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo /*= NULL*/,
1621 uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) RT_NOEXCEPT
1622{
1623 setNull();
1624 if (a_rValue.startsWithWord("null", RTCString::CaseInsensitive))
1625 return VINF_SUCCESS;
1626
1627 int rc = m_strFormatted.assignNoThrow(a_rValue);
1628 AssertRCReturn(rc, rc);
1629
1630 m_fNullIndicator = false;
1631 rc = decodeFormattedString(m_enmFormat);
1632 if (RT_SUCCESS(rc))
1633 return rc;
1634 if (m_enmFormat != kFormat_Invalid)
1635 {
1636 rc = decodeFormattedString();
1637 if (RT_SUCCESS(rc))
1638 return rc;
1639 }
1640 RT_NOREF(a_fFlags);
1641 return RTErrInfoSetF(a_pErrInfo, VERR_REST_UNABLE_TO_DECODE_DATE,
1642 "Unable to decode date value (%s): %s", a_pszName, m_strFormatted.c_str());
1643}
1644
1645
1646RTCRestObjectBase::kTypeClass RTCRestDate::typeClass(void) const RT_NOEXCEPT
1647{
1648 return kTypeClass_Date;
1649}
1650
1651
1652const char *RTCRestDate::typeName(void) const RT_NOEXCEPT
1653{
1654 return "RTCRestDate";
1655}
1656
1657
1658int RTCRestDate::assignValue(PCRTTIMESPEC a_pTimeSpec, kFormat a_enmFormat) RT_NOEXCEPT
1659{
1660 AssertPtrReturn(a_pTimeSpec, VERR_INVALID_PARAMETER);
1661 AssertReturn(a_enmFormat > kFormat_Invalid && a_enmFormat < kFormat_End, VERR_INVALID_PARAMETER);
1662
1663 m_TimeSpec = *a_pTimeSpec;
1664 return explodeAndFormat(a_enmFormat);
1665}
1666
1667
1668int RTCRestDate::assignValueRfc2822(PCRTTIMESPEC a_pTimeSpec) RT_NOEXCEPT
1669{
1670 AssertPtrReturn(a_pTimeSpec, VERR_INVALID_PARAMETER);
1671 m_TimeSpec = *a_pTimeSpec;
1672 return explodeAndFormat(kFormat_Rfc2822);
1673}
1674
1675
1676int RTCRestDate::assignValueRfc7131(PCRTTIMESPEC a_pTimeSpec) RT_NOEXCEPT
1677{
1678 AssertPtrReturn(a_pTimeSpec, VERR_INVALID_PARAMETER);
1679 m_TimeSpec = *a_pTimeSpec;
1680 return explodeAndFormat(kFormat_Rfc7131);
1681}
1682
1683
1684int RTCRestDate::assignValueRfc3339(PCRTTIMESPEC a_pTimeSpec) RT_NOEXCEPT
1685{
1686 AssertPtrReturn(a_pTimeSpec, VERR_INVALID_PARAMETER);
1687 m_TimeSpec = *a_pTimeSpec;
1688 return explodeAndFormat(kFormat_Rfc3339);
1689}
1690
1691
1692int RTCRestDate::assignNow(kFormat a_enmFormat) RT_NOEXCEPT
1693{
1694 RTTIMESPEC Now;
1695 return assignValue(RTTimeNow(&Now), a_enmFormat);
1696}
1697
1698
1699int RTCRestDate::assignNowRfc2822() RT_NOEXCEPT
1700{
1701 RTTIMESPEC Now;
1702 return assignValueRfc2822(RTTimeNow(&Now));
1703}
1704
1705
1706int RTCRestDate::assignNowRfc7131() RT_NOEXCEPT
1707{
1708 RTTIMESPEC Now;
1709 return assignValueRfc7131(RTTimeNow(&Now));
1710}
1711
1712
1713int RTCRestDate::assignNowRfc3339() RT_NOEXCEPT
1714{
1715 RTTIMESPEC Now;
1716 return assignValueRfc3339(RTTimeNow(&Now));
1717}
1718
1719
1720int RTCRestDate::setFormat(kFormat a_enmFormat) RT_NOEXCEPT
1721{
1722 /*
1723 * If this is a null object, just set the format as a hint for upcoming deserialization.
1724 */
1725 if (m_fNullIndicator)
1726 {
1727 AssertReturn(a_enmFormat >= kFormat_Invalid && a_enmFormat < kFormat_End, VERR_INVALID_PARAMETER);
1728 m_enmFormat = a_enmFormat;
1729 return VINF_SUCCESS;
1730 }
1731
1732 /*
1733 * If the tiem spec is okay, just reformat the string value accordingly.
1734 */
1735 if (m_fTimeSpecOkay)
1736 {
1737 AssertReturn(a_enmFormat > kFormat_Invalid && a_enmFormat < kFormat_End, VERR_INVALID_PARAMETER);
1738 if (a_enmFormat == m_enmFormat)
1739 return VINF_SUCCESS;
1740 return format(a_enmFormat);
1741 }
1742
1743 /*
1744 * Try decode
1745 */
1746 AssertReturn(a_enmFormat > kFormat_Invalid && a_enmFormat < kFormat_End, VERR_INVALID_PARAMETER);
1747 return decodeFormattedString(a_enmFormat);
1748}
1749
1750
1751int RTCRestDate::explodeAndFormat(kFormat a_enmFormat) RT_NOEXCEPT
1752{
1753 RTTimeExplode(&m_Exploded, &m_TimeSpec);
1754 return format(a_enmFormat);
1755}
1756
1757
1758/**
1759 * Formats the m_Exploded value.
1760 *
1761 * Sets m_strFormatted, m_fTimeSpecOkay, and m_enmFormat, clears m_fNullIndicator.
1762 *
1763 * @returns VINF_SUCCESS or VERR_NO_STR_MEMORY.
1764 * @param a_enmFormat The format to use.
1765 */
1766int RTCRestDate::format(kFormat a_enmFormat) RT_NOEXCEPT
1767{
1768 m_fNullIndicator = false;
1769 m_fTimeSpecOkay = true;
1770 m_enmFormat = a_enmFormat;
1771 int rc;
1772 switch (a_enmFormat)
1773 {
1774 case kFormat_Rfc2822:
1775 case kFormat_Rfc7131:
1776 rc = m_strFormatted.reserveNoThrow(RTTIME_RFC2822_LEN);
1777 AssertRCReturn(rc, rc);
1778 RTTimeToRfc2822(&m_Exploded, m_strFormatted.mutableRaw(), m_strFormatted.capacity(),
1779 a_enmFormat == kFormat_Rfc7131 ? RTTIME_RFC2822_F_GMT : 0);
1780 m_strFormatted.jolt();
1781 return VINF_SUCCESS;
1782
1783 case kFormat_Rfc3339:
1784 case kFormat_Rfc3339_Fraction_2:
1785 case kFormat_Rfc3339_Fraction_3:
1786 case kFormat_Rfc3339_Fraction_6:
1787 case kFormat_Rfc3339_Fraction_9:
1788 rc = m_strFormatted.reserveNoThrow(RTTIME_STR_LEN);
1789 AssertRCReturn(rc, rc);
1790 RTTimeToStringEx(&m_Exploded, m_strFormatted.mutableRaw(), m_strFormatted.capacity(),
1791 a_enmFormat == kFormat_Rfc3339 ? 0
1792 : a_enmFormat == kFormat_Rfc3339_Fraction_2 ? 2
1793 : a_enmFormat == kFormat_Rfc3339_Fraction_3 ? 3
1794 : a_enmFormat == kFormat_Rfc3339_Fraction_6 ? 6 : 9);
1795 m_strFormatted.jolt();
1796 return VINF_SUCCESS;
1797
1798 /* no default */
1799 case kFormat_Invalid:
1800 case kFormat_End:
1801 break;
1802 }
1803 AssertFailedReturn(VERR_REST_INTERNAL_ERROR_7);
1804}
1805
1806
1807/**
1808 * Internal worker that attempts to decode m_strFormatted.
1809 *
1810 * Sets m_fTimeSpecOkay.
1811 *
1812 * @returns IPRT status code.
1813 * @param enmFormat Specific format to try, kFormat_Invalid (default) to try guess it.
1814 */
1815int RTCRestDate::decodeFormattedString(kFormat enmFormat /*= kFormat_Invalid*/) RT_NOEXCEPT
1816{
1817 /*
1818 * Take empty string to mean null.
1819 */
1820 const char *pszTmp = RTStrStripL(m_strFormatted.c_str());
1821 if (*pszTmp == '\0')
1822 {
1823 setNull();
1824 return VINF_SUCCESS;
1825 }
1826
1827 switch (enmFormat)
1828 {
1829 case kFormat_Invalid:
1830 {
1831 size_t cch = strlen(pszTmp);
1832 if (cch >= 6)
1833 {
1834 if ( !RT_C_IS_DIGIT(pszTmp[0])
1835 || RT_C_IS_SPACE(pszTmp[5])
1836 || RT_C_IS_SPACE(pszTmp[2])
1837 || RT_C_IS_SPACE(pszTmp[1])
1838 || RT_C_IS_SPACE(pszTmp[3])
1839 || RT_C_IS_SPACE(pszTmp[4]))
1840 return decodeFormattedString(kFormat_Rfc2822);
1841 return decodeFormattedString(kFormat_Rfc3339);
1842 }
1843 return VERR_REST_UNABLE_TO_DECODE_DATE;
1844 }
1845
1846 /*
1847 * Examples:
1848 * Fri, 31 Aug 2018 00:00:00 +0200
1849 * Mon, 3 Sep 2018 00:00:00 GMT
1850 * Mon, 3 Sep 2018 00:00:00 -0000
1851 * 3 Sep 2018 00:00:00 -0000 (?)
1852 * 3 Sep 2018 00:00:00 GMT (?)
1853 */
1854 case kFormat_Rfc2822:
1855 case kFormat_Rfc7131:
1856 if (RTTimeFromRfc2822(&m_Exploded, pszTmp))
1857 {
1858 RTTimeImplode(&m_TimeSpec, &m_Exploded);
1859
1860 pszTmp = strchr(pszTmp, '\0');
1861 if (pszTmp[-1] == 'T' || pszTmp[-1] == 't')
1862 m_enmFormat = kFormat_Rfc7131;
1863 else
1864 m_enmFormat = kFormat_Rfc2822;
1865 m_fTimeSpecOkay = true;
1866 return VINF_SUCCESS;
1867 }
1868 return VERR_REST_UNABLE_TO_DECODE_DATE;
1869
1870 /*
1871 * Examples:
1872 * 2018-08-31T00:00:00+0200
1873 * 2018-09-03T00:00:00Z
1874 * 2018-09-03T00:00:00+0000
1875 * 2018-09-03T00:00:00.123456789Z
1876 */
1877 case kFormat_Rfc3339:
1878 case kFormat_Rfc3339_Fraction_2:
1879 case kFormat_Rfc3339_Fraction_3:
1880 case kFormat_Rfc3339_Fraction_6:
1881 case kFormat_Rfc3339_Fraction_9:
1882 if (RTTimeFromString(&m_Exploded, pszTmp))
1883 {
1884 RTTimeImplode(&m_TimeSpec, &m_Exploded);
1885
1886 pszTmp = strchr(pszTmp, '.');
1887 if (!pszTmp)
1888 m_enmFormat = kFormat_Rfc3339;
1889 else
1890 {
1891 size_t cchFraction = 0;
1892 pszTmp++;
1893 while (RT_C_IS_DIGIT(pszTmp[cchFraction]))
1894 cchFraction++;
1895 if (cchFraction == 0)
1896 m_enmFormat = kFormat_Rfc3339;
1897 else if (cchFraction <= 2)
1898 m_enmFormat = kFormat_Rfc3339_Fraction_2;
1899 else if (cchFraction <= 3)
1900 m_enmFormat = kFormat_Rfc3339_Fraction_3;
1901 else if (cchFraction <= 6)
1902 m_enmFormat = kFormat_Rfc3339_Fraction_6;
1903 else
1904 m_enmFormat = kFormat_Rfc3339_Fraction_9;
1905 }
1906 m_fTimeSpecOkay = true;
1907 return VINF_SUCCESS;
1908 }
1909 return VERR_REST_UNABLE_TO_DECODE_DATE;
1910
1911 /* no default */
1912 case kFormat_End:
1913 break;
1914 }
1915 AssertFailedReturn(VERR_INVALID_PARAMETER);
1916}
1917
1918
1919/*********************************************************************************************************************************
1920* RTCRestStringEnumBase implementation *
1921*********************************************************************************************************************************/
1922
1923/** Default constructor. */
1924RTCRestStringEnumBase::RTCRestStringEnumBase() RT_NOEXCEPT
1925 : RTCRestObjectBase()
1926 , m_iEnumValue(0 /*invalid*/)
1927 , m_strValue()
1928{
1929}
1930
1931
1932/** Destructor. */
1933RTCRestStringEnumBase::~RTCRestStringEnumBase()
1934{
1935 /* nothing to do */
1936}
1937
1938
1939/** Copy constructor. */
1940RTCRestStringEnumBase::RTCRestStringEnumBase(RTCRestStringEnumBase const &a_rThat)
1941 : RTCRestObjectBase(a_rThat)
1942 , m_iEnumValue(a_rThat.m_iEnumValue)
1943 , m_strValue(a_rThat.m_strValue)
1944{
1945}
1946
1947
1948/** Copy assignment operator. */
1949RTCRestStringEnumBase &RTCRestStringEnumBase::operator=(RTCRestStringEnumBase const &a_rThat)
1950{
1951 RTCRestObjectBase::operator=(a_rThat);
1952 m_iEnumValue = a_rThat.m_iEnumValue;
1953 m_strValue = a_rThat.m_strValue;
1954 return *this;
1955}
1956
1957
1958int RTCRestStringEnumBase::assignCopy(RTCRestStringEnumBase const &a_rThat) RT_NOEXCEPT
1959{
1960 m_fNullIndicator = a_rThat.m_fNullIndicator;
1961 m_iEnumValue = a_rThat.m_iEnumValue;
1962 return m_strValue.assignNoThrow(a_rThat.m_strValue);
1963}
1964
1965
1966int RTCRestStringEnumBase::resetToDefault() RT_NOEXCEPT
1967{
1968 m_iEnumValue = 0; /*invalid*/
1969 m_strValue.setNull();
1970 return VINF_SUCCESS;
1971}
1972
1973
1974RTCRestOutputBase &RTCRestStringEnumBase::serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT
1975{
1976 if (!m_fNullIndicator)
1977 a_rDst.printf("%RMjs", getString());
1978 else
1979 a_rDst.nullValue();
1980 return a_rDst;
1981}
1982
1983
1984int RTCRestStringEnumBase::deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT
1985{
1986 m_fNullIndicator = false;
1987 m_iEnumValue = 0;
1988
1989 RTJSONVALTYPE enmType = RTJsonValueGetType(a_rCursor.m_hValue);
1990 if (enmType == RTJSONVALTYPE_STRING)
1991 {
1992 const char *pszValue = RTJsonValueGetString(a_rCursor.m_hValue);
1993 const size_t cchValue = strlen(pszValue);
1994 int rc = setByString(pszValue, cchValue);
1995 if (RT_SUCCESS(rc))
1996 return rc;
1997 return a_rCursor.m_pPrimary->addError(a_rCursor, rc, "no memory for %zu char long string", cchValue);
1998 }
1999
2000 m_strValue.setNull();
2001 if (enmType == RTJSONVALTYPE_NULL)
2002 {
2003 m_fNullIndicator = true;
2004 return VINF_SUCCESS;
2005 }
2006
2007 return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_REST_WRONG_JSON_TYPE_FOR_STRING, "wrong JSON type %s for string/enum",
2008 RTJsonValueTypeName(RTJsonValueGetType(a_rCursor.m_hValue)));
2009}
2010
2011
2012int RTCRestStringEnumBase::toString(RTCString *a_pDst, uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) const RT_NOEXCEPT
2013{
2014 if (!m_fNullIndicator)
2015 {
2016 if (m_iEnumValue > 0)
2017 {
2018 size_t cEntries = 0;
2019 ENUMMAPENTRY const *paEntries = getMappingTable(&cEntries);
2020 AssertReturn((unsigned)(m_iEnumValue - 1) < cEntries, VERR_REST_INTERNAL_ERROR_3);
2021 Assert(paEntries[m_iEnumValue - 1].iValue == m_iEnumValue);
2022
2023 if (a_fFlags & kToString_Append)
2024 return a_pDst->appendNoThrow(paEntries[m_iEnumValue - 1].pszName, paEntries[m_iEnumValue - 1].cchName);
2025 return a_pDst->assignNoThrow(paEntries[m_iEnumValue - 1].pszName, paEntries[m_iEnumValue - 1].cchName);
2026 }
2027 if (a_fFlags & kToString_Append)
2028 return a_pDst->appendNoThrow(m_strValue);
2029 return a_pDst->assignNoThrow(m_strValue);
2030 }
2031 if (a_fFlags & kToString_Append)
2032 return a_pDst->appendNoThrow(RT_STR_TUPLE("null"));
2033 return a_pDst->assignNoThrow(RT_STR_TUPLE("null"));
2034}
2035
2036
2037int RTCRestStringEnumBase::fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo /*= NULL*/,
2038 uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) RT_NOEXCEPT
2039{
2040 int iEnumValue = stringToEnum(a_rValue);
2041 if (iEnumValue > 0)
2042 {
2043 m_iEnumValue = iEnumValue;
2044 m_strValue.setNull();
2045 return VINF_SUCCESS;
2046 }
2047
2048 /* No translation. Check for null... */
2049 m_iEnumValue = 0;
2050 if (a_rValue.startsWithWord("null", RTCString::CaseInsensitive))
2051 {
2052 m_strValue.setNull();
2053 setNull();
2054 return VINF_SUCCESS;
2055 }
2056
2057 /* Try copy the string. */
2058 int rc = m_strValue.assignNoThrow(a_rValue);
2059 if (RT_SUCCESS(rc))
2060 return VWRN_NOT_FOUND;
2061
2062 RT_NOREF(a_pszName, a_pErrInfo, a_fFlags);
2063 return rc;
2064}
2065
2066
2067RTCRestObjectBase::kTypeClass RTCRestStringEnumBase::typeClass(void) const RT_NOEXCEPT
2068{
2069 return kTypeClass_StringEnum;
2070}
2071
2072
2073int RTCRestStringEnumBase::setByString(const char *a_pszValue, size_t a_cchValue /*= RTSTR_MAX*/) RT_NOEXCEPT
2074{
2075 if (a_cchValue == RTSTR_MAX)
2076 a_cchValue = strlen(a_pszValue);
2077 int iEnumValue = stringToEnum(a_pszValue, a_cchValue);
2078 if (iEnumValue > 0)
2079 {
2080 m_iEnumValue = iEnumValue;
2081 m_strValue.setNull();
2082 return VINF_SUCCESS;
2083 }
2084
2085 /* No translation. */
2086 m_iEnumValue = 0;
2087 int rc = m_strValue.assignNoThrow(a_pszValue, a_cchValue);
2088 if (RT_SUCCESS(rc))
2089 return VWRN_NOT_FOUND;
2090 return rc;
2091}
2092
2093
2094int RTCRestStringEnumBase::setByString(RTCString const &a_rValue) RT_NOEXCEPT
2095{
2096 return setByString(a_rValue.c_str(), a_rValue.length());
2097}
2098
2099
2100const char *RTCRestStringEnumBase::getString() const RT_NOEXCEPT
2101{
2102 /* We ASSUME a certain mapping table layout here. */
2103 if (m_iEnumValue > 0)
2104 {
2105 size_t cEntries = 0;
2106 ENUMMAPENTRY const *paEntries = getMappingTable(&cEntries);
2107 AssertReturn((unsigned)(m_iEnumValue - 1) < cEntries, "<internal-error-#1>");
2108 Assert(paEntries[m_iEnumValue - 1].iValue == m_iEnumValue);
2109 return paEntries[m_iEnumValue - 1].pszName;
2110 }
2111
2112 AssertReturn(m_iEnumValue == 0, "<internal-error-#2>");
2113 if (m_strValue.isEmpty())
2114 return "invalid";
2115
2116 return m_strValue.c_str();
2117}
2118
2119
2120int RTCRestStringEnumBase::stringToEnum(const char *a_pszValue, size_t a_cchValue) RT_NOEXCEPT
2121{
2122 if (a_cchValue == RTSTR_MAX)
2123 a_cchValue = strlen(a_pszValue);
2124
2125 size_t cEntries = 0;
2126 ENUMMAPENTRY const *paEntries = getMappingTable(&cEntries);
2127 for (size_t i = 0; i < cEntries; i++)
2128 if ( paEntries[i].cchName == a_cchValue
2129 && memcmp(paEntries[i].pszName, a_pszValue, a_cchValue) == 0)
2130 return paEntries[i].iValue;
2131 return 0;
2132}
2133
2134
2135int RTCRestStringEnumBase::stringToEnum(RTCString const &a_rStrValue) RT_NOEXCEPT
2136{
2137 return stringToEnum(a_rStrValue.c_str(), a_rStrValue.length());
2138}
2139
2140
2141const char *RTCRestStringEnumBase::enumToString(int a_iEnumValue, size_t *a_pcchString) RT_NOEXCEPT
2142{
2143 /* We ASSUME a certain mapping table layout here. */
2144 if (a_iEnumValue > 0)
2145 {
2146 size_t cEntries = 0;
2147 ENUMMAPENTRY const *paEntries = getMappingTable(&cEntries);
2148 if ((unsigned)(a_iEnumValue - 1) < cEntries)
2149 {
2150 Assert(paEntries[a_iEnumValue - 1].iValue == a_iEnumValue);
2151 if (a_pcchString)
2152 *a_pcchString = paEntries[a_iEnumValue - 1].cchName;
2153 return paEntries[a_iEnumValue - 1].pszName;
2154 }
2155 }
2156 /* Zero is the special invalid value. */
2157 else if (a_iEnumValue == 0)
2158 {
2159 if (a_pcchString)
2160 *a_pcchString = 7;
2161 return "invalid";
2162 }
2163 return NULL;
2164}
2165
2166
2167bool RTCRestStringEnumBase::setWorker(int a_iEnumValue) RT_NOEXCEPT
2168{
2169 /* We ASSUME a certain mapping table layout here. */
2170 if (a_iEnumValue > 0)
2171 {
2172 size_t cEntries = 0;
2173 ENUMMAPENTRY const *paEntries = getMappingTable(&cEntries);
2174 AssertReturn((unsigned)(a_iEnumValue - 1) < cEntries, false);
2175 Assert(paEntries[a_iEnumValue - 1].iValue == a_iEnumValue);
2176 RT_NOREF(paEntries);
2177 }
2178 /* Zero is the special invalid value. */
2179 else if (a_iEnumValue != 0)
2180 AssertFailedReturn(false);
2181
2182 m_iEnumValue = a_iEnumValue;
2183 m_strValue.setNull();
2184 return true;
2185}
2186
2187
2188RTCRestObjectBase *RTCRestStringEnumBase::cloneWorker(RTCRestStringEnumBase *a_pDst) const RT_NOEXCEPT
2189{
2190 if (a_pDst)
2191 {
2192 int rc = a_pDst->assignCopy(*this);
2193 if (RT_SUCCESS(rc))
2194 return a_pDst;
2195 delete a_pDst;
2196 }
2197 return NULL;
2198}
2199
2200
2201
2202/*********************************************************************************************************************************
2203* RTCRestDataObject *
2204*********************************************************************************************************************************/
2205
2206RTCRestDataObject::RTCRestDataObject() RT_NOEXCEPT
2207 : RTCRestObjectBase()
2208 , m_fIsSet(0)
2209{
2210}
2211
2212
2213RTCRestDataObject::~RTCRestDataObject()
2214{
2215}
2216
2217
2218RTCRestDataObject::RTCRestDataObject(RTCRestDataObject const &a_rThat) RT_NOEXCEPT
2219 : RTCRestObjectBase(a_rThat)
2220 , m_fIsSet(a_rThat.m_fIsSet)
2221{
2222}
2223
2224
2225RTCRestDataObject &RTCRestDataObject::operator=(RTCRestDataObject const &a_rThat) RT_NOEXCEPT
2226{
2227 m_fNullIndicator = a_rThat.m_fNullIndicator;
2228 m_fIsSet = a_rThat.m_fIsSet;
2229 return *this;
2230}
2231
2232
2233int RTCRestDataObject::assignCopy(RTCRestDataObject const &a_rThat) RT_NOEXCEPT
2234{
2235 m_fNullIndicator = a_rThat.m_fNullIndicator;
2236 m_fIsSet = a_rThat.m_fIsSet;
2237 return VINF_SUCCESS;
2238}
2239
2240
2241int RTCRestDataObject::resetToDefault() RT_NOEXCEPT
2242{
2243 m_fNullIndicator = false;
2244 m_fIsSet = 0;
2245 return VINF_SUCCESS;
2246}
2247
2248
2249RTCRestOutputBase &RTCRestDataObject::serializeMembersAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT
2250{
2251 RT_NOREF(a_rDst);
2252 return a_rDst;
2253}
2254
2255
2256RTCRestOutputBase &RTCRestDataObject::serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT
2257{
2258 if (!m_fNullIndicator)
2259 {
2260 uint32_t const uOldState = a_rDst.beginObject();
2261 serializeMembersAsJson(a_rDst);
2262 a_rDst.endObject(uOldState);
2263 }
2264 else
2265 a_rDst.nullValue();
2266 return a_rDst;
2267}
2268
2269
2270int RTCRestDataObject::deserializeMemberFromJson(RTCRestJsonCursor const &a_rCursor, size_t a_cchName) RT_NOEXCEPT
2271{
2272 RT_NOREF(a_rCursor, a_cchName);
2273 return VERR_NOT_FOUND;
2274}
2275
2276
2277int RTCRestDataObject::deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT
2278{
2279 if (RTJsonValueGetType(a_rCursor.m_hValue) == RTJSONVALTYPE_NULL)
2280 {
2281 setNull();
2282 return VINF_SUCCESS;
2283 }
2284
2285 /*
2286 * Make sure the object starts out with default values.
2287 */
2288 if (m_fIsSet == 0)
2289 m_fNullIndicator = false;
2290 else
2291 resetToDefault();
2292
2293 /*
2294 * Iterate the object values.
2295 */
2296 RTJSONIT hIterator;
2297 int rcRet = RTJsonIteratorBeginObject(a_rCursor.m_hValue, &hIterator);
2298 if (RT_SUCCESS(rcRet))
2299 {
2300 for (;;)
2301 {
2302 RTCRestJsonCursor SubCursor(a_rCursor);
2303 int rc = RTJsonIteratorQueryValue(hIterator, &SubCursor.m_hValue, &SubCursor.m_pszName);
2304 if (RT_SUCCESS(rc))
2305 {
2306 size_t const cchName = strlen(SubCursor.m_pszName);
2307
2308 rc = deserializeMemberFromJson(SubCursor, cchName);
2309 if (rc == VINF_SUCCESS)
2310 { /* likely */ }
2311 else if (rc == VERR_NOT_FOUND)
2312 {
2313 rc = SubCursor.m_pPrimary->unknownField(SubCursor);
2314 if (rcRet == VINF_SUCCESS)
2315 rcRet = rc;
2316 }
2317 else if (RT_SUCCESS(rc))
2318 {
2319 if (rcRet == VINF_SUCCESS)
2320 rcRet = rc;
2321 }
2322 else if (RT_SUCCESS(rcRet))
2323 rcRet = rc;
2324 }
2325 else
2326 rcRet = a_rCursor.m_pPrimary->addError(a_rCursor, rc, "RTJsonIteratorQueryValue failed: %Rrc", rc);
2327
2328 /*
2329 * Advance.
2330 */
2331 rc = RTJsonIteratorNext(hIterator);
2332 if (RT_SUCCESS(rc))
2333 { /* likely */ }
2334 else if (rc == VERR_JSON_ITERATOR_END)
2335 break;
2336 else
2337 {
2338 rcRet = a_rCursor.m_pPrimary->addError(a_rCursor, rc, "RTJsonIteratorNext failed: %Rrc", rc);
2339 break;
2340 }
2341 }
2342
2343 RTJsonIteratorFree(hIterator);
2344 }
2345 else if ( rcRet == VERR_JSON_VALUE_INVALID_TYPE
2346 && RTJsonValueGetType(a_rCursor.m_hValue) == RTJSONVALTYPE_NULL)
2347 {
2348 m_fNullIndicator = true;
2349 rcRet = VINF_SUCCESS;
2350 }
2351 else
2352 rcRet = a_rCursor.m_pPrimary->addError(a_rCursor, rcRet, "RTJsonIteratorBeginObject failed: %Rrc (type %s)",
2353 rcRet, RTJsonValueTypeName(RTJsonValueGetType(a_rCursor.m_hValue)));
2354 return rcRet;
2355}
2356
2357
2358RTCRestObjectBase::kTypeClass RTCRestDataObject::typeClass(void) const RT_NOEXCEPT
2359{
2360 return kTypeClass_DataObject;
2361}
2362
2363
2364
2365/*********************************************************************************************************************************
2366* RTCRestPolyDataObject *
2367*********************************************************************************************************************************/
2368
2369RTCRestPolyDataObject::RTCRestPolyDataObject() RT_NOEXCEPT
2370 : RTCRestDataObject()
2371{
2372}
2373
2374
2375RTCRestPolyDataObject::RTCRestPolyDataObject(RTCRestPolyDataObject const &a_rThat) RT_NOEXCEPT
2376 : RTCRestDataObject(a_rThat)
2377{
2378}
2379
2380
2381RTCRestPolyDataObject::~RTCRestPolyDataObject()
2382{
2383}
2384
2385
2386int RTCRestPolyDataObject::resetToDefault() RT_NOEXCEPT
2387{
2388 return RTCRestDataObject::resetToDefault();
2389}
2390
2391
2392bool RTCRestPolyDataObject::isChild() const RT_NOEXCEPT
2393{
2394 return false;
2395}
2396
2397
2398RTCRestPolyDataObject &RTCRestPolyDataObject::operator=(RTCRestPolyDataObject const &a_rThat) RT_NOEXCEPT
2399{
2400 RTCRestDataObject::operator=(a_rThat);
2401 return *this;
2402}
2403
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use