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, 17 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
RevLine 
[73875]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/*
[98103]7 * Copyright (C) 2018-2023 Oracle and/or its affiliates.
[73875]8 *
[96407]9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
[73875]11 *
[96407]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 *
[73875]25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
[96407]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
[73875]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.
[96407]33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
[73875]35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
[73977]41#define LOG_GROUP RTLOGGROUP_REST
[73875]42#include <iprt/cpp/restbase.h>
43
[74149]44#include <iprt/ctype.h>
[73875]45#include <iprt/err.h>
46#include <iprt/string.h>
[74414]47#include <iprt/cpp/restoutput.h>
[73875]48
49#include <stdio.h>
[73920]50#include <stdlib.h>
51#include <errno.h>
[73875]52
53
54
[73895]55/*********************************************************************************************************************************
56* RTCRestObjectBase implementation *
57*********************************************************************************************************************************/
58
59/** Default constructor. */
[74425]60RTCRestObjectBase::RTCRestObjectBase() RT_NOEXCEPT
[74008]61 : m_fNullIndicator(false)
[73875]62{
[73895]63}
64
65
[74008]66/** Copy constructor. */
[74425]67RTCRestObjectBase::RTCRestObjectBase(RTCRestObjectBase const &a_rThat) RT_NOEXCEPT
[74008]68 : m_fNullIndicator(a_rThat.m_fNullIndicator)
69{
70}
71
72
[73895]73/** Destructor. */
74RTCRestObjectBase::~RTCRestObjectBase()
75{
76 /* nothing to do */
77}
78
79
[81670]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
[74425]88int RTCRestObjectBase::setNull() RT_NOEXCEPT
[74008]89{
90 int rc = resetToDefault();
91 m_fNullIndicator = true;
92 return rc;
93}
94
95
[74425]96void RTCRestObjectBase::setNotNull() RT_NOEXCEPT
[74008]97{
98 m_fNullIndicator = false;
99}
100
101
[74425]102int RTCRestObjectBase::toString(RTCString *a_pDst, uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) const RT_NOEXCEPT
[73895]103{
104 /*
105 * Just wrap the JSON serialization method.
106 */
[73956]107 RTCRestOutputToString Tmp(a_pDst, RT_BOOL(a_fFlags & kToString_Append));
[73895]108 serializeAsJson(Tmp);
109 return Tmp.finalize() ? VINF_SUCCESS : VERR_NO_MEMORY;
110}
111
112
[73900]113RTCString RTCRestObjectBase::toString() const
[73895]114{
115 RTCString strRet;
116 toString(&strRet, 0);
117 return strRet;
118}
119
120
[73920]121int RTCRestObjectBase::fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo /*= NULL*/,
[74425]122 uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) RT_NOEXCEPT
[73920]123{
[73956]124 RT_NOREF(a_fFlags);
[73895]125
[73920]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
[74023]140
[73895]141/*********************************************************************************************************************************
142* RTCRestBool implementation *
143*********************************************************************************************************************************/
144
[73933]145/** Factory method. */
[74425]146/*static*/ DECLCALLBACK(RTCRestObjectBase *) RTCRestBool::createInstance(void) RT_NOEXCEPT
[73933]147{
148 return new (std::nothrow) RTCRestBool();
149}
150
151
[74402]152/**
153 * @copydoc RTCRestObjectBase::FNDESERIALIZEINSTANCEFROMJSON
154 */
155/*static*/ DECLCALLBACK(int)
[74425]156RTCRestBool::deserializeInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT
[74402]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
[74008]166/** Default constructor. */
[74425]167RTCRestBool::RTCRestBool() RT_NOEXCEPT
[74008]168 : RTCRestObjectBase()
169 , m_fValue(false)
[73895]170{
171}
172
173
174/** Copy constructor. */
[74425]175RTCRestBool::RTCRestBool(RTCRestBool const &a_rThat) RT_NOEXCEPT
[73902]176 : RTCRestObjectBase(a_rThat)
177 , m_fValue(a_rThat.m_fValue)
[73895]178{
179}
180
181
182/** From value constructor. */
[74425]183RTCRestBool::RTCRestBool(bool fValue) RT_NOEXCEPT
[73895]184 : m_fValue(fValue)
185{
186}
187
188
189/** Destructor. */
190RTCRestBool::~RTCRestBool()
191{
192 /* nothing to do */
193}
194
195
196/** Copy assignment operator. */
[74425]197RTCRestBool &RTCRestBool::operator=(RTCRestBool const &a_rThat) RT_NOEXCEPT
[73895]198{
[74008]199 m_fNullIndicator = a_rThat.m_fNullIndicator;
[73895]200 m_fValue = a_rThat.m_fValue;
201 return *this;
202}
203
204
[74425]205int RTCRestBool::assignCopy(RTCRestBool const &a_rThat) RT_NOEXCEPT
[73895]206{
[74008]207 m_fNullIndicator = a_rThat.m_fNullIndicator;
[73977]208 m_fValue = a_rThat.m_fValue;
209 return VINF_SUCCESS;
210}
211
212
[74425]213void RTCRestBool::assignValue(bool a_fValue) RT_NOEXCEPT
[74013]214{
215 m_fValue = a_fValue;
216 m_fNullIndicator = false;
217}
218
219
[74425]220RTCRestObjectBase *RTCRestBool::baseClone() const RT_NOEXCEPT
[74386]221{
222 return new (std::nothrow) RTCRestBool(*this);
223}
224
225
[74425]226int RTCRestBool::resetToDefault() RT_NOEXCEPT
[73977]227{
[73895]228 m_fValue = false;
[74008]229 m_fNullIndicator = false;
[73977]230 return VINF_SUCCESS;
[73895]231}
232
233
[74425]234RTCRestOutputBase &RTCRestBool::serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT
[73895]235{
[74008]236 a_rDst.printf(!m_fNullIndicator ? m_fValue ? "true" : "false" : "null");
[73895]237 return a_rDst;
238}
239
240
[74425]241int RTCRestBool::deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT
[73895]242{
[74161]243 m_fValue = false;
244 m_fNullIndicator = false;
245
[73875]246 RTJSONVALTYPE enmType = RTJsonValueGetType(a_rCursor.m_hValue);
[73895]247
248 if (enmType == RTJSONVALTYPE_TRUE)
[73875]249 {
[73895]250 m_fValue = true;
251 return VINF_SUCCESS;
[73875]252 }
253
[73895]254 if (enmType == RTJSONVALTYPE_FALSE)
[73875]255 return VINF_SUCCESS;
256
[73895]257 if (enmType == RTJSONVALTYPE_NULL)
[74008]258 {
259 m_fNullIndicator = true;
260 return VINF_SUCCESS;
261 }
[73895]262
[74161]263 return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_REST_WRONG_JSON_TYPE_FOR_BOOL, "wrong JSON type %s for boolean",
[73875]264 RTJsonValueTypeName(RTJsonValueGetType(a_rCursor.m_hValue)));
265}
266
267
[74425]268int RTCRestBool::toString(RTCString *a_pDst, uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) const RT_NOEXCEPT
[73875]269{
[73956]270 if (!(a_fFlags & kToString_Append))
271 {
[74008]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 {
[73956]283 if (m_fValue)
[74008]284 return a_pDst->appendNoThrow(RT_STR_TUPLE("true"));
285 return a_pDst->appendNoThrow(RT_STR_TUPLE("false"));
[73956]286 }
[74008]287 return a_pDst->appendNoThrow(RT_STR_TUPLE("null"));
[73895]288}
289
290
[73920]291int RTCRestBool::fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo /*= NULL*/,
[74425]292 uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) RT_NOEXCEPT
[73920]293{
[73956]294 RT_NOREF(a_fFlags);
295
[73920]296 if (a_rValue.startsWithWord("true", RTCString::CaseInsensitive))
[74008]297 {
[73920]298 m_fValue = true;
[74008]299 m_fNullIndicator = false;
300 }
[73920]301 else if (a_rValue.startsWithWord("false", RTCString::CaseInsensitive))
[74008]302 {
[73920]303 m_fValue = false;
[74008]304 m_fNullIndicator = false;
305 }
306 else if (a_rValue.startsWithWord("null", RTCString::CaseInsensitive))
307 {
308 m_fValue = false;
309 m_fNullIndicator = true;
310 }
[73920]311 else
[74161]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());
[73920]314 return VINF_SUCCESS;
315}
316
317
[74425]318RTCRestObjectBase::kTypeClass RTCRestBool::typeClass() const RT_NOEXCEPT
[73895]319{
[74023]320 return kTypeClass_Bool;
321}
322
323
[74425]324const char *RTCRestBool::typeName() const RT_NOEXCEPT
[74023]325{
[73895]326 return "bool";
327}
328
329
[73933]330
[73895]331/*********************************************************************************************************************************
332* RTCRestInt64 implementation *
333*********************************************************************************************************************************/
334
[73933]335/** Factory method. */
[74425]336/*static*/ DECLCALLBACK(RTCRestObjectBase *) RTCRestInt64::createInstance(void) RT_NOEXCEPT
[73933]337{
338 return new (std::nothrow) RTCRestInt64();
339}
340
341
[74402]342/**
343 * @copydoc RTCRestObjectBase::FNDESERIALIZEINSTANCEFROMJSON
344 */
345/*static*/ DECLCALLBACK(int)
[74425]346RTCRestInt64::deserializeInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT
[74402]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
[74170]356/** Default constructor. */
[74425]357RTCRestInt64::RTCRestInt64() RT_NOEXCEPT
[74008]358 : RTCRestObjectBase()
359 , m_iValue(0)
[73895]360{
361}
362
363
364/** Copy constructor. */
[74425]365RTCRestInt64::RTCRestInt64(RTCRestInt64 const &a_rThat) RT_NOEXCEPT
[73902]366 : RTCRestObjectBase(a_rThat)
367 , m_iValue(a_rThat.m_iValue)
[73895]368{
369}
370
371
372/** From value constructor. */
[74425]373RTCRestInt64::RTCRestInt64(int64_t iValue) RT_NOEXCEPT
[74008]374 : RTCRestObjectBase()
375 , m_iValue(iValue)
[73895]376{
377}
378
379
380/** Destructor. */
381RTCRestInt64::~RTCRestInt64()
382{
383 /* nothing to do */
384}
385
386
387/** Copy assignment operator. */
[74425]388RTCRestInt64 &RTCRestInt64::operator=(RTCRestInt64 const &a_rThat) RT_NOEXCEPT
[73895]389{
[74008]390 m_fNullIndicator = a_rThat.m_fNullIndicator;
[73895]391 m_iValue = a_rThat.m_iValue;
392 return *this;
393}
394
395
[74425]396int RTCRestInt64::assignCopy(RTCRestInt64 const &a_rThat) RT_NOEXCEPT
[73895]397{
[74008]398 m_fNullIndicator = a_rThat.m_fNullIndicator;
[73977]399 m_iValue = a_rThat.m_iValue;
400 return VINF_SUCCESS;
401}
402
403
[74425]404void RTCRestInt64::assignValue(int64_t a_iValue) RT_NOEXCEPT
[74013]405{
406 m_iValue = a_iValue;
407 m_fNullIndicator = false;
408}
409
410
[74425]411RTCRestObjectBase *RTCRestInt64::baseClone() const RT_NOEXCEPT
[74386]412{
413 return new (std::nothrow) RTCRestInt64(*this);
414}
415
416
[74425]417int RTCRestInt64::resetToDefault() RT_NOEXCEPT
[73977]418{
[73895]419 m_iValue = 0;
[74008]420 m_fNullIndicator = false;
[73977]421 return VINF_SUCCESS;
[73895]422}
423
424
[74425]425RTCRestOutputBase &RTCRestInt64::serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT
[73895]426{
[74008]427 if (!m_fNullIndicator)
428 a_rDst.printf("%RI64", m_iValue);
429 else
[74414]430 a_rDst.nullValue();
[73895]431 return a_rDst;
432}
433
434
[74425]435int RTCRestInt64::deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT
[73895]436{
[74008]437 m_iValue = 0;
438 m_fNullIndicator = false;
439
[73875]440 RTJSONVALTYPE enmType = RTJsonValueGetType(a_rCursor.m_hValue);
[74027]441 if (enmType == RTJSONVALTYPE_INTEGER)
[73875]442 {
[73895]443 int rc = RTJsonValueQueryInteger(a_rCursor.m_hValue, &m_iValue);
[73875]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
[74008]449 if (enmType == RTJSONVALTYPE_NULL)
450 {
451 m_fNullIndicator = true;
452 return VINF_SUCCESS;
453 }
454
[73875]455 /* This is probably non-sense... */
[74008]456 if (enmType == RTJSONVALTYPE_TRUE)
[73895]457 m_iValue = 1;
[73875]458
[74161]459 return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_REST_WRONG_JSON_TYPE_FOR_INTEGER, "wrong JSON type %s for 64-bit integer",
[73875]460 RTJsonValueTypeName(RTJsonValueGetType(a_rCursor.m_hValue)));
461}
462
463
[74425]464int RTCRestInt64::toString(RTCString *a_pDst, uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) const RT_NOEXCEPT
[73875]465{
[73956]466 if (!(a_fFlags & kToString_Append))
[74008]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"));
[73895]475}
476
477
[73920]478int RTCRestInt64::fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo /*= NULL*/,
[74425]479 uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) RT_NOEXCEPT
[73920]480{
[73956]481 RT_NOREF(a_fFlags);
[73920]482
[74008]483 m_iValue = 0;
484 m_fNullIndicator = false;
485
[74161]486/** @todo RTStrStripL and RTStrToInt64Full has a different idea what consitutes spaces... */
487 int rc = RTStrToInt64Full(RTStrStripL(a_rValue.c_str()), 0, &m_iValue);
[73920]488 if (rc == VINF_SUCCESS || rc == VERR_TRAILING_SPACES)
489 return VINF_SUCCESS;
[74008]490
491 if (a_rValue.startsWithWord("null", RTCString::CaseInsensitive))
492 {
493 m_iValue = 0;
494 m_fNullIndicator = true;
495 return VINF_SUCCESS;
496 }
497
[73920]498 return RTErrInfoSetF(a_pErrInfo, rc, "%s: error %Rrc parsing '%s' as int64_t", a_pszName, rc, a_rValue.c_str());
499}
500
501
[74425]502RTCRestObjectBase::kTypeClass RTCRestInt64::typeClass() const RT_NOEXCEPT
[73895]503{
[74023]504 return kTypeClass_Int64;
505}
506
507
[74425]508const char *RTCRestInt64::typeName() const RT_NOEXCEPT
[74023]509{
[73895]510 return "int64_t";
511}
512
513
514
515/*********************************************************************************************************************************
516* RTCRestInt32 implementation *
517*********************************************************************************************************************************/
518
[73933]519/** Factory method. */
[74425]520/*static*/ DECLCALLBACK(RTCRestObjectBase *) RTCRestInt32::createInstance(void) RT_NOEXCEPT
[73933]521{
522 return new (std::nothrow) RTCRestInt32();
523}
524
525
[74402]526/**
527 * @copydoc RTCRestObjectBase::FNDESERIALIZEINSTANCEFROMJSON
528 */
529/*static*/ DECLCALLBACK(int)
[74425]530RTCRestInt32::deserializeInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT
[74402]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
[74170]540/** Default constructor. */
[74425]541RTCRestInt32::RTCRestInt32() RT_NOEXCEPT
[74008]542 : RTCRestObjectBase()
543 , m_iValue(0)
[73895]544{
545}
546
547
548/** Copy constructor. */
[74425]549RTCRestInt32::RTCRestInt32(RTCRestInt32 const &a_rThat) RT_NOEXCEPT
[73902]550 : RTCRestObjectBase(a_rThat)
551 , m_iValue(a_rThat.m_iValue)
[73895]552{
553}
554
555
556/** From value constructor. */
[74425]557RTCRestInt32::RTCRestInt32(int32_t iValue) RT_NOEXCEPT
[74008]558 : RTCRestObjectBase()
559 , m_iValue(iValue)
[73895]560{
561}
562
563
564/** Destructor. */
[85084]565RTCRestInt32::~RTCRestInt32() RT_NOEXCEPT
[73895]566{
567 /* nothing to do */
568}
569
570
571/** Copy assignment operator. */
[74425]572RTCRestInt32 &RTCRestInt32::operator=(RTCRestInt32 const &a_rThat) RT_NOEXCEPT
[73895]573{
[74008]574 m_fNullIndicator = a_rThat.m_fNullIndicator;
[73895]575 m_iValue = a_rThat.m_iValue;
576 return *this;
577}
578
579
[74425]580int RTCRestInt32::assignCopy(RTCRestInt32 const &a_rThat) RT_NOEXCEPT
[73895]581{
[74008]582 m_fNullIndicator = a_rThat.m_fNullIndicator;
[73977]583 m_iValue = a_rThat.m_iValue;
584 return VINF_SUCCESS;
585}
586
587
[74425]588RTCRestObjectBase *RTCRestInt32::baseClone() const RT_NOEXCEPT
[74386]589{
590 return new (std::nothrow) RTCRestInt32(*this);
591}
592
593
[74425]594int RTCRestInt32::resetToDefault() RT_NOEXCEPT
[73977]595{
[73895]596 m_iValue = 0;
[74008]597 m_fNullIndicator = false;
[73977]598 return VINF_SUCCESS;
[73895]599}
600
601
[74425]602void RTCRestInt32::assignValue(int32_t a_iValue) RT_NOEXCEPT
[74013]603{
604 m_iValue = a_iValue;
605 m_fNullIndicator = false;
606}
607
608
[74425]609RTCRestOutputBase &RTCRestInt32::serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT
[73895]610{
[74008]611 if (!m_fNullIndicator)
612 a_rDst.printf("%RI32", m_iValue);
613 else
[74414]614 a_rDst.nullValue();
[73895]615 return a_rDst;
616}
617
618
[74425]619int RTCRestInt32::deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT
[73895]620{
[74008]621 m_iValue = 0;
622 m_fNullIndicator = false;
623
[73875]624 RTJSONVALTYPE enmType = RTJsonValueGetType(a_rCursor.m_hValue);
[74027]625 if (enmType == RTJSONVALTYPE_INTEGER)
[73875]626 {
[73895]627 int64_t iTmp = m_iValue;
[73875]628 int rc = RTJsonValueQueryInteger(a_rCursor.m_hValue, &iTmp);
629 if (RT_SUCCESS(rc))
630 {
[73895]631 m_iValue = (int32_t)iTmp;
632 if (m_iValue == iTmp)
[73875]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
[74008]639 if (enmType == RTJSONVALTYPE_NULL)
640 {
641 m_fNullIndicator = true;
642 return VINF_SUCCESS;
643 }
644
[73875]645 /* This is probably non-sense... */
[74008]646 if (enmType == RTJSONVALTYPE_TRUE)
[73895]647 m_iValue = 1;
[73875]648
[74161]649 return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_REST_WRONG_JSON_TYPE_FOR_INTEGER, "wrong JSON type %s for 32-bit integer",
[73875]650 RTJsonValueTypeName(RTJsonValueGetType(a_rCursor.m_hValue)));
651}
652
653
[74425]654int RTCRestInt32::toString(RTCString *a_pDst, uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) const RT_NOEXCEPT
[73875]655{
[73956]656 if (!(a_fFlags & kToString_Append))
[74008]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"));
[73895]665}
666
667
[73920]668int RTCRestInt32::fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo /*= NULL*/,
[74425]669 uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) RT_NOEXCEPT
[73920]670{
[73956]671 RT_NOREF(a_fFlags);
[73920]672
[74008]673 m_iValue = 0;
674 m_fNullIndicator = false;
675
[74161]676/** @todo RTStrStripL and RTStrToInt32Full has a different idea what consitutes spaces... */
677 int rc = RTStrToInt32Full(RTStrStripL(a_rValue.c_str()), 0, &m_iValue);
[73920]678 if (rc == VINF_SUCCESS || rc == VERR_TRAILING_SPACES)
679 return VINF_SUCCESS;
[74008]680
681 if (a_rValue.startsWithWord("null", RTCString::CaseInsensitive))
682 {
683 m_iValue = 0;
684 m_fNullIndicator = true;
685 return VINF_SUCCESS;
686 }
687
[73920]688 return RTErrInfoSetF(a_pErrInfo, rc, "%s: error %Rrc parsing '%s' as int32_t", a_pszName, rc, a_rValue.c_str());
689}
690
691
[74425]692RTCRestObjectBase::kTypeClass RTCRestInt32::typeClass() const RT_NOEXCEPT
[73895]693{
[74023]694 return kTypeClass_Int32;
695}
696
697
[74425]698const char *RTCRestInt32::typeName() const RT_NOEXCEPT
[74023]699{
[73895]700 return "int32_t";
701}
702
703
704
705/*********************************************************************************************************************************
706* RTCRestInt16 implementation *
707*********************************************************************************************************************************/
708
[73933]709/** Factory method. */
[74425]710/*static*/ DECLCALLBACK(RTCRestObjectBase *) RTCRestInt16::createInstance(void) RT_NOEXCEPT
[73933]711{
712 return new (std::nothrow) RTCRestInt16();
713}
714
715
[74402]716/**
717 * @copydoc RTCRestObjectBase::FNDESERIALIZEINSTANCEFROMJSON
718 */
719/*static*/ DECLCALLBACK(int)
[74425]720RTCRestInt16::deserializeInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT
[74402]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
[74170]730/** Default constructor. */
[74425]731RTCRestInt16::RTCRestInt16() RT_NOEXCEPT
[74008]732 : RTCRestObjectBase()
733 , m_iValue(0)
[73895]734{
735}
736
737
738/** Copy constructor. */
[74425]739RTCRestInt16::RTCRestInt16(RTCRestInt16 const &a_rThat) RT_NOEXCEPT
[73902]740 : RTCRestObjectBase(a_rThat)
741 , m_iValue(a_rThat.m_iValue)
[73895]742{
743}
744
745
746/** From value constructor. */
[74425]747RTCRestInt16::RTCRestInt16(int16_t iValue) RT_NOEXCEPT
[74008]748 : RTCRestObjectBase()
749 , m_iValue(iValue)
[73895]750{
751}
752
753
754/** Destructor. */
755RTCRestInt16::~RTCRestInt16()
756{
757 /* nothing to do */
758}
759
760
761/** Copy assignment operator. */
[74425]762RTCRestInt16 &RTCRestInt16::operator=(RTCRestInt16 const &a_rThat) RT_NOEXCEPT
[73895]763{
[74008]764 m_fNullIndicator = a_rThat.m_fNullIndicator;
[73895]765 m_iValue = a_rThat.m_iValue;
766 return *this;
767}
768
769
[74425]770int RTCRestInt16::assignCopy(RTCRestInt16 const &a_rThat) RT_NOEXCEPT
[73895]771{
[74008]772 m_fNullIndicator = a_rThat.m_fNullIndicator;
[73977]773 m_iValue = a_rThat.m_iValue;
774 return VINF_SUCCESS;
775}
776
777
[74425]778void RTCRestInt16::assignValue(int16_t a_iValue) RT_NOEXCEPT
[74013]779{
780 m_iValue = a_iValue;
781 m_fNullIndicator = false;
782}
783
784
[74425]785RTCRestObjectBase *RTCRestInt16::baseClone() const RT_NOEXCEPT
[74386]786{
787 return new (std::nothrow) RTCRestInt16(*this);
788}
789
790
[74425]791int RTCRestInt16::resetToDefault() RT_NOEXCEPT
[73977]792{
[73895]793 m_iValue = 0;
[74008]794 m_fNullIndicator = false;
[73977]795 return VINF_SUCCESS;
[73895]796}
797
798
[74425]799RTCRestOutputBase &RTCRestInt16::serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT
[73895]800{
[74008]801 if (!m_fNullIndicator)
802 a_rDst.printf("%RI16", m_iValue);
803 else
[74414]804 a_rDst.nullValue();
[73895]805 return a_rDst;
806}
807
808
[74425]809int RTCRestInt16::deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT
[73895]810{
[74008]811 m_iValue = 0;
812 m_fNullIndicator = false;
813
[73875]814 RTJSONVALTYPE enmType = RTJsonValueGetType(a_rCursor.m_hValue);
[74027]815 if (enmType == RTJSONVALTYPE_INTEGER)
[73875]816 {
[73895]817 int64_t iTmp = m_iValue;
[73875]818 int rc = RTJsonValueQueryInteger(a_rCursor.m_hValue, &iTmp);
819 if (RT_SUCCESS(rc))
820 {
[73895]821 m_iValue = (int16_t)iTmp;
822 if (m_iValue == iTmp)
[73875]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
[74008]829 if (enmType == RTJSONVALTYPE_NULL)
830 {
831 m_fNullIndicator = true;
832 return VINF_SUCCESS;
833 }
834
[73875]835 /* This is probably non-sense... */
[74008]836 if (enmType == RTJSONVALTYPE_TRUE)
[73895]837 m_iValue = 1;
[73875]838
[74161]839 return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_REST_WRONG_JSON_TYPE_FOR_INTEGER, "wrong JSON type %s for 16-bit integer",
[73875]840 RTJsonValueTypeName(RTJsonValueGetType(a_rCursor.m_hValue)));
841}
842
843
[74425]844int RTCRestInt16::toString(RTCString *a_pDst, uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) const RT_NOEXCEPT
[73875]845{
[73956]846 if (!(a_fFlags & kToString_Append))
[74008]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"));
[73895]855}
[73875]856
857
[73920]858int RTCRestInt16::fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo /*= NULL*/,
[74425]859 uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) RT_NOEXCEPT
[73920]860{
[73956]861 RT_NOREF(a_fFlags);
[73920]862
[74008]863 m_iValue = 0;
864 m_fNullIndicator = false;
865
[74161]866/** @todo RTStrStripL and RTStrToInt16Full has a different idea what consitutes spaces... */
867 int rc = RTStrToInt16Full(RTStrStripL(a_rValue.c_str()), 0, &m_iValue);
[73920]868 if (rc == VINF_SUCCESS || rc == VERR_TRAILING_SPACES)
869 return VINF_SUCCESS;
[74008]870
871 if (a_rValue.startsWithWord("null", RTCString::CaseInsensitive))
872 {
873 m_iValue = 0;
874 m_fNullIndicator = true;
875 return VINF_SUCCESS;
876 }
877
[73920]878 return RTErrInfoSetF(a_pErrInfo, rc, "%s: error %Rrc parsing '%s' as int16_t", a_pszName, rc, a_rValue.c_str());
879}
880
881
[74425]882RTCRestObjectBase::kTypeClass RTCRestInt16::typeClass() const RT_NOEXCEPT
[73895]883{
[74023]884 return kTypeClass_Int16;
885}
886
887
[74425]888const char *RTCRestInt16::typeName() const RT_NOEXCEPT
[74023]889{
[73895]890 return "int16_t";
891}
[73875]892
[73895]893
894
895/*********************************************************************************************************************************
896* RTCRestDouble implementation *
897*********************************************************************************************************************************/
898
[73933]899/** Factory method. */
[74425]900/*static*/ DECLCALLBACK(RTCRestObjectBase *) RTCRestDouble::createInstance(void) RT_NOEXCEPT
[73933]901{
902 return new (std::nothrow) RTCRestDouble();
903}
904
[74402]905
906/**
907 * @copydoc RTCRestObjectBase::FNDESERIALIZEINSTANCEFROMJSON
908 */
909/*static*/ DECLCALLBACK(int)
[74425]910RTCRestDouble::deserializeInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT
[74402]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
[74170]920/** Default constructor. */
[74425]921RTCRestDouble::RTCRestDouble() RT_NOEXCEPT
[74008]922 : RTCRestObjectBase()
923 , m_rdValue(0.0)
[73895]924{
[73875]925}
926
927
[73895]928/** Copy constructor. */
[74425]929RTCRestDouble::RTCRestDouble(RTCRestDouble const &a_rThat) RT_NOEXCEPT
[73902]930 : RTCRestObjectBase(a_rThat)
931 , m_rdValue(a_rThat.m_rdValue)
[73875]932{
[73895]933}
934
935
936/** From value constructor. */
[74425]937RTCRestDouble::RTCRestDouble(double rdValue) RT_NOEXCEPT
[74008]938 : RTCRestObjectBase()
939 , m_rdValue(rdValue)
[73895]940{
941}
942
943
944/** Destructor. */
945RTCRestDouble::~RTCRestDouble()
946{
947 /* nothing to do */
948}
949
950
[73977]951/** Copy assignment operator. */
[74425]952RTCRestDouble &RTCRestDouble::operator=(RTCRestDouble const &a_rThat) RT_NOEXCEPT
[73895]953{
[74008]954 m_fNullIndicator = a_rThat.m_fNullIndicator;
[73977]955 m_rdValue = a_rThat.m_rdValue;
956 return *this;
957}
958
959
[74425]960int RTCRestDouble::assignCopy(RTCRestDouble const &a_rThat) RT_NOEXCEPT
[73977]961{
[74008]962 m_fNullIndicator = a_rThat.m_fNullIndicator;
[73977]963 m_rdValue = a_rThat.m_rdValue;
964 return VINF_SUCCESS;
965}
966
967
[74425]968void RTCRestDouble::assignValue(double a_rdValue) RT_NOEXCEPT
[74013]969{
970 m_rdValue = a_rdValue;
971 m_fNullIndicator = false;
972}
973
974
[74425]975RTCRestObjectBase *RTCRestDouble::baseClone() const RT_NOEXCEPT
[74386]976{
977 return new (std::nothrow) RTCRestDouble(*this);
978}
979
980
[74425]981int RTCRestDouble::resetToDefault() RT_NOEXCEPT
[73977]982{
[73895]983 m_rdValue = 0.0;
[74008]984 m_fNullIndicator = false;
[73977]985 return VINF_SUCCESS;
[73895]986}
987
988
[74425]989RTCRestOutputBase &RTCRestDouble::serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT
[73895]990{
[74008]991 if (!m_fNullIndicator)
992 {
993
994 /* Just a simple approximation here. */
[74028]995 /** @todo Not 100% sure printf %g produces the right result for JSON floating point, but it'll have to do for now... */
[74008]996 char szValue[128];
[73895]997#ifdef _MSC_VER
[74170]998 _snprintf(szValue, sizeof(szValue), "%.18g", m_rdValue);
[73895]999#else
[74170]1000 snprintf(szValue, sizeof(szValue), "%.18g", m_rdValue);
[73895]1001#endif
[74170]1002 size_t cchValue = strlen(szValue);
[77262]1003 while (cchValue > 0 && szValue[cchValue - 1] == '0')
[74170]1004 cchValue--;
1005 szValue[cchValue] = '\0';
1006
[74008]1007 a_rDst.printf("%s", szValue);
1008 }
1009 else
[74414]1010 a_rDst.nullValue();
[73895]1011 return a_rDst;
1012}
1013
1014
[74425]1015int RTCRestDouble::deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT
[73895]1016{
[74028]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;
[93301]1036 if ((int64_t)m_rdValue == iTmp)
[74028]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
[74161]1053 return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_REST_WRONG_JSON_TYPE_FOR_DOUBLE, "wrong JSON type %s for a double",
[74028]1054 RTJsonValueTypeName(RTJsonValueGetType(a_rCursor.m_hValue)));
[73875]1055}
1056
1057
[74425]1058int RTCRestDouble::toString(RTCString *a_pDst, uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) const RT_NOEXCEPT
[73875]1059{
[74008]1060 if (!m_fNullIndicator)
1061 {
1062 /* Just a simple approximation here. */
[74028]1063 /** @todo Not 100% sure printf %g produces the right result for JSON floating point, but it'll have to do for now... */
[74008]1064 char szValue[128];
[73875]1065#ifdef _MSC_VER
[74170]1066 _snprintf(szValue, sizeof(szValue), "%.18g", m_rdValue);
[73875]1067#else
[74170]1068 snprintf(szValue, sizeof(szValue), "%.18g", m_rdValue);
[73875]1069#endif
[74170]1070 size_t cchValue = strlen(szValue);
[77262]1071 while (cchValue > 0 && szValue[cchValue - 1] == '0')
[74170]1072 cchValue--;
1073 szValue[cchValue] = '\0';
[73895]1074
[74008]1075 if (!(a_fFlags & kToString_Append))
1076 return a_pDst->assignNoThrow(szValue, cchValue);
1077 return a_pDst->appendNoThrow(szValue, cchValue);
1078 }
1079
[73956]1080 if (!(a_fFlags & kToString_Append))
[74008]1081 return a_pDst->assignNoThrow(RT_STR_TUPLE("null"));
1082 return a_pDst->appendNoThrow(RT_STR_TUPLE("null"));
[73895]1083}
1084
1085
[73920]1086int RTCRestDouble::fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo /*= NULL*/,
[74425]1087 uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) RT_NOEXCEPT
[73920]1088{
[73956]1089 RT_NOREF(a_fFlags);
[73920]1090
[74170]1091 if (a_rValue.startsWithWord("null", RTCString::CaseInsensitive))
1092 {
1093 m_rdValue = 0.0;
1094 m_fNullIndicator = true;
1095 return VINF_SUCCESS;
1096 }
1097
[74008]1098 m_fNullIndicator = false;
1099
[73920]1100 const char *pszValue = RTStrStripL(a_rValue.c_str());
1101 errno = 0;
1102 char *pszNext = NULL;
1103 m_rdValue = strtod(pszValue, &pszNext);
[74170]1104 if (errno == 0 && pszNext != pszValue)
1105 {
1106 if (!pszNext || *pszNext == '\0')
1107 return VINF_SUCCESS;
[74008]1108
[74170]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());
[74008]1116 }
1117
[74170]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());
[73920]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
[74425]1126RTCRestObjectBase::kTypeClass RTCRestDouble::typeClass() const RT_NOEXCEPT
[73895]1127{
[74023]1128 return kTypeClass_Double;
1129}
1130
1131
[74425]1132const char *RTCRestDouble::typeName() const RT_NOEXCEPT
[74023]1133{
[73895]1134 return "double";
1135}
1136
1137
1138
1139/*********************************************************************************************************************************
1140* RTCRestString implementation *
1141*********************************************************************************************************************************/
1142
[73933]1143/** Factory method. */
[74425]1144/*static*/ DECLCALLBACK(RTCRestObjectBase *) RTCRestString::createInstance(void) RT_NOEXCEPT
[73933]1145{
1146 return new (std::nothrow) RTCRestString();
1147}
1148
1149
[74402]1150/**
1151 * @copydoc RTCRestObjectBase::FNDESERIALIZEINSTANCEFROMJSON
1152 */
1153/*static*/ DECLCALLBACK(int)
[74425]1154RTCRestString::deserializeInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT
[74402]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
[74170]1164/** Default constructor. */
[74425]1165RTCRestString::RTCRestString() RT_NOEXCEPT
[74386]1166 : RTCRestObjectBase()
1167 , RTCString()
[73895]1168{
1169}
1170
1171
1172/** Copy constructor. */
1173RTCRestString::RTCRestString(RTCRestString const &a_rThat)
[74386]1174 : RTCRestObjectBase(a_rThat)
1175 , RTCString(a_rThat)
[73895]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)
[74386]1189 : RTCRestObjectBase()
1190 , RTCString(a_pszSrc)
[73895]1191{
1192}
1193
1194
1195/** Destructor. */
1196RTCRestString::~RTCRestString()
1197{
1198 /* nothing to do */
1199}
1200
1201
[74425]1202int RTCRestString::assignCopy(RTCRestString const &a_rThat) RT_NOEXCEPT
[74008]1203{
[74176]1204 int rc = assignNoThrow(a_rThat);
[74008]1205 m_fNullIndicator = a_rThat.m_fNullIndicator;
[74176]1206 return rc;
[74008]1207}
1208
1209
[74425]1210int RTCRestString::assignCopy(RTCString const &a_rThat) RT_NOEXCEPT
[73895]1211{
[74008]1212 m_fNullIndicator = false;
[73977]1213 return assignNoThrow(a_rThat);
1214}
1215
1216
[74425]1217int RTCRestString::assignCopy(const char *a_pszThat) RT_NOEXCEPT
[73977]1218{
[74008]1219 m_fNullIndicator = false;
[73977]1220 return assignNoThrow(a_pszThat);
1221}
1222
1223
[74425]1224int RTCRestString::setNull() RT_NOEXCEPT
[74008]1225{
1226 RTCString::setNull();
1227 m_fNullIndicator = true;
1228 return VINF_SUCCESS;
1229}
1230
1231
[74425]1232RTCRestObjectBase *RTCRestString::baseClone() const RT_NOEXCEPT
[74386]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
[74425]1246int RTCRestString::resetToDefault() RT_NOEXCEPT
[73977]1247{
[74008]1248 RTCString::setNull();
1249 m_fNullIndicator = false;
[73977]1250 return VINF_SUCCESS;
[73895]1251}
1252
1253
[74425]1254RTCRestOutputBase &RTCRestString::serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT
[73895]1255{
[74008]1256 if (!m_fNullIndicator)
[74176]1257 a_rDst.printf("%RMjs", m_psz ? m_psz : "");
[74008]1258 else
[74414]1259 a_rDst.nullValue();
[73875]1260 return a_rDst;
1261}
1262
[73895]1263
[74425]1264int RTCRestString::deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT
[73895]1265{
[74008]1266 m_fNullIndicator = false;
1267
[73895]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);
[73920]1273 int rc = assignNoThrow(pszValue, cchValue);
[73895]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
[74008]1279 RTCString::setNull();
1280
1281 if (enmType == RTJSONVALTYPE_NULL)
[73895]1282 {
[74008]1283 m_fNullIndicator = true;
[73895]1284 return VINF_SUCCESS;
1285 }
1286
[74161]1287 return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_REST_WRONG_JSON_TYPE_FOR_STRING, "wrong JSON type %s for string",
[73895]1288 RTJsonValueTypeName(RTJsonValueGetType(a_rCursor.m_hValue)));
1289}
1290
1291
[74425]1292int RTCRestString::toString(RTCString *a_pDst, uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) const RT_NOEXCEPT
[73895]1293{
[74008]1294 /* Note! m_fNullIndicator == true: empty string. */
[73956]1295 if (!(a_fFlags & kToString_Append))
1296 return a_pDst->assignNoThrow(*this);
1297 return a_pDst->appendNoThrow(*this);
[73895]1298}
1299
1300
[73920]1301int RTCRestString::fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo /*= NULL*/,
[74425]1302 uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) RT_NOEXCEPT
[73920]1303{
[73956]1304 RT_NOREF(a_fFlags); RT_NOREF(a_pszName); RT_NOREF(a_pErrInfo);
[73920]1305
[74008]1306 /* Note! Unable to set m_fNullIndicator = true here. */
1307 m_fNullIndicator = false;
[73920]1308 return assignNoThrow(a_rValue);
1309}
1310
1311
[74425]1312RTCRestObjectBase::kTypeClass RTCRestString::typeClass() const RT_NOEXCEPT
[73895]1313{
[74023]1314 return kTypeClass_String;
1315}
1316
1317
[74425]1318const char *RTCRestString::typeName() const RT_NOEXCEPT
[74023]1319{
[73895]1320 return "RTCString";
1321}
1322
[74040]1323
[74176]1324int RTCRestString::assignNoThrow(const RTCString &a_rSrc) RT_NOEXCEPT
1325{
1326 m_fNullIndicator = false;
1327 return RTCString::assignNoThrow(a_rSrc);
1328}
[74040]1329
[74176]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
[74040]1461/*********************************************************************************************************************************
[74149]1462* RTCRestDate implementation *
1463*********************************************************************************************************************************/
[74425]1464/*static*/ DECLCALLBACK(RTCRestObjectBase *) RTCRestDate::createInstance(void) RT_NOEXCEPT
[74402]1465{
1466 return new (std::nothrow) RTCRestDate();
1467}
[74149]1468
[74402]1469
1470/**
1471 * @copydoc RTCRestObjectBase::FNDESERIALIZEINSTANCEFROMJSON
1472 */
1473/*static*/ DECLCALLBACK(int)
[74425]1474RTCRestDate::deserializeInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT
[74402]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
[74425]1484RTCRestDate::RTCRestDate() RT_NOEXCEPT
[74149]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
[74425]1527int RTCRestDate::assignCopy(RTCRestDate const &a_rThat) RT_NOEXCEPT
[74149]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
[74425]1538RTCRestObjectBase *RTCRestDate::baseClone() const RT_NOEXCEPT
[74386]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
[74425]1552int RTCRestDate::resetToDefault() RT_NOEXCEPT
[74149]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
[74425]1564RTCRestOutputBase &RTCRestDate::serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT
[74149]1565{
1566 if (m_fNullIndicator)
[74414]1567 a_rDst.nullValue();
[74149]1568 else
1569 a_rDst.printf("%RMjs", m_strFormatted.c_str());
1570 return a_rDst;
1571}
1572
1573
[74425]1574int RTCRestDate::deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT
[74149]1575{
[74181]1576 setNull();
1577
[74149]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
[74161]1601 return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_REST_WRONG_JSON_TYPE_FOR_DATE, "wrong JSON type for date: %s",
[74149]1602 RTJsonValueTypeName(RTJsonValueGetType(a_rCursor.m_hValue)));
1603}
1604
1605
[74425]1606int RTCRestDate::toString(RTCString *a_pDst, uint32_t a_fFlags /*= 0*/) const RT_NOEXCEPT
[74149]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*/,
[74425]1621 uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) RT_NOEXCEPT
[74149]1622{
[74181]1623 setNull();
[74149]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
[74425]1646RTCRestObjectBase::kTypeClass RTCRestDate::typeClass(void) const RT_NOEXCEPT
[74149]1647{
1648 return kTypeClass_Date;
1649}
1650
1651
[74425]1652const char *RTCRestDate::typeName(void) const RT_NOEXCEPT
[74149]1653{
1654 return "RTCRestDate";
1655}
1656
1657
[74425]1658int RTCRestDate::assignValue(PCRTTIMESPEC a_pTimeSpec, kFormat a_enmFormat) RT_NOEXCEPT
[74149]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
[74425]1668int RTCRestDate::assignValueRfc2822(PCRTTIMESPEC a_pTimeSpec) RT_NOEXCEPT
[74149]1669{
1670 AssertPtrReturn(a_pTimeSpec, VERR_INVALID_PARAMETER);
1671 m_TimeSpec = *a_pTimeSpec;
1672 return explodeAndFormat(kFormat_Rfc2822);
1673}
1674
1675
[74425]1676int RTCRestDate::assignValueRfc7131(PCRTTIMESPEC a_pTimeSpec) RT_NOEXCEPT
[74149]1677{
1678 AssertPtrReturn(a_pTimeSpec, VERR_INVALID_PARAMETER);
1679 m_TimeSpec = *a_pTimeSpec;
1680 return explodeAndFormat(kFormat_Rfc7131);
1681}
1682
1683
[74425]1684int RTCRestDate::assignValueRfc3339(PCRTTIMESPEC a_pTimeSpec) RT_NOEXCEPT
[74149]1685{
1686 AssertPtrReturn(a_pTimeSpec, VERR_INVALID_PARAMETER);
1687 m_TimeSpec = *a_pTimeSpec;
1688 return explodeAndFormat(kFormat_Rfc3339);
1689}
1690
1691
[74425]1692int RTCRestDate::assignNow(kFormat a_enmFormat) RT_NOEXCEPT
[74149]1693{
1694 RTTIMESPEC Now;
1695 return assignValue(RTTimeNow(&Now), a_enmFormat);
1696}
1697
1698
[74425]1699int RTCRestDate::assignNowRfc2822() RT_NOEXCEPT
[74149]1700{
1701 RTTIMESPEC Now;
1702 return assignValueRfc2822(RTTimeNow(&Now));
1703}
1704
1705
[74425]1706int RTCRestDate::assignNowRfc7131() RT_NOEXCEPT
[74149]1707{
1708 RTTIMESPEC Now;
1709 return assignValueRfc7131(RTTimeNow(&Now));
1710}
1711
1712
[74425]1713int RTCRestDate::assignNowRfc3339() RT_NOEXCEPT
[74149]1714{
1715 RTTIMESPEC Now;
1716 return assignValueRfc3339(RTTimeNow(&Now));
1717}
1718
1719
[74425]1720int RTCRestDate::setFormat(kFormat a_enmFormat) RT_NOEXCEPT
[74149]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
[74425]1751int RTCRestDate::explodeAndFormat(kFormat a_enmFormat) RT_NOEXCEPT
[74149]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 */
[74425]1766int RTCRestDate::format(kFormat a_enmFormat) RT_NOEXCEPT
[74149]1767{
[74181]1768 m_fNullIndicator = false;
1769 m_fTimeSpecOkay = true;
1770 m_enmFormat = a_enmFormat;
[74149]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 */
[74425]1815int RTCRestDate::decodeFormattedString(kFormat enmFormat /*= kFormat_Invalid*/) RT_NOEXCEPT
[74149]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/*********************************************************************************************************************************
[74040]1920* RTCRestStringEnumBase implementation *
1921*********************************************************************************************************************************/
1922
1923/** Default constructor. */
[74425]1924RTCRestStringEnumBase::RTCRestStringEnumBase() RT_NOEXCEPT
[74040]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
[74425]1958int RTCRestStringEnumBase::assignCopy(RTCRestStringEnumBase const &a_rThat) RT_NOEXCEPT
[74040]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
[74425]1966int RTCRestStringEnumBase::resetToDefault() RT_NOEXCEPT
[74040]1967{
1968 m_iEnumValue = 0; /*invalid*/
1969 m_strValue.setNull();
1970 return VINF_SUCCESS;
1971}
1972
1973
[74425]1974RTCRestOutputBase &RTCRestStringEnumBase::serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT
[74040]1975{
1976 if (!m_fNullIndicator)
1977 a_rDst.printf("%RMjs", getString());
1978 else
[74414]1979 a_rDst.nullValue();
[74040]1980 return a_rDst;
1981}
1982
1983
[74425]1984int RTCRestStringEnumBase::deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT
[74040]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
[74161]2007 return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_REST_WRONG_JSON_TYPE_FOR_STRING, "wrong JSON type %s for string/enum",
[74040]2008 RTJsonValueTypeName(RTJsonValueGetType(a_rCursor.m_hValue)));
2009}
2010
2011
[74425]2012int RTCRestStringEnumBase::toString(RTCString *a_pDst, uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) const RT_NOEXCEPT
[74040]2013{
2014 if (!m_fNullIndicator)
2015 {
2016 if (m_iEnumValue > 0)
2017 {
2018 size_t cEntries = 0;
2019 ENUMMAPENTRY const *paEntries = getMappingTable(&cEntries);
[74093]2020 AssertReturn((unsigned)(m_iEnumValue - 1) < cEntries, VERR_REST_INTERNAL_ERROR_3);
[74040]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*/,
[74425]2038 uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) RT_NOEXCEPT
[74040]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
[74425]2067RTCRestObjectBase::kTypeClass RTCRestStringEnumBase::typeClass(void) const RT_NOEXCEPT
[74040]2068{
2069 return kTypeClass_StringEnum;
2070}
2071
2072
[74425]2073int RTCRestStringEnumBase::setByString(const char *a_pszValue, size_t a_cchValue /*= RTSTR_MAX*/) RT_NOEXCEPT
[74040]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
[74425]2094int RTCRestStringEnumBase::setByString(RTCString const &a_rValue) RT_NOEXCEPT
[74040]2095{
2096 return setByString(a_rValue.c_str(), a_rValue.length());
2097}
2098
2099
[74425]2100const char *RTCRestStringEnumBase::getString() const RT_NOEXCEPT
[74040]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
[74425]2120int RTCRestStringEnumBase::stringToEnum(const char *a_pszValue, size_t a_cchValue) RT_NOEXCEPT
[74040]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
[74425]2135int RTCRestStringEnumBase::stringToEnum(RTCString const &a_rStrValue) RT_NOEXCEPT
[74040]2136{
2137 return stringToEnum(a_rStrValue.c_str(), a_rStrValue.length());
2138}
2139
2140
[74425]2141const char *RTCRestStringEnumBase::enumToString(int a_iEnumValue, size_t *a_pcchString) RT_NOEXCEPT
[74040]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
[74425]2167bool RTCRestStringEnumBase::setWorker(int a_iEnumValue) RT_NOEXCEPT
[74040]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
[74347]2187
[74425]2188RTCRestObjectBase *RTCRestStringEnumBase::cloneWorker(RTCRestStringEnumBase *a_pDst) const RT_NOEXCEPT
[74386]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}
[74347]2199
[74386]2200
2201
[74347]2202/*********************************************************************************************************************************
[74356]2203* RTCRestDataObject *
[74347]2204*********************************************************************************************************************************/
2205
[74425]2206RTCRestDataObject::RTCRestDataObject() RT_NOEXCEPT
[74347]2207 : RTCRestObjectBase()
2208 , m_fIsSet(0)
2209{
2210}
2211
2212
2213RTCRestDataObject::~RTCRestDataObject()
2214{
2215}
2216
2217
[74425]2218RTCRestDataObject::RTCRestDataObject(RTCRestDataObject const &a_rThat) RT_NOEXCEPT
[74347]2219 : RTCRestObjectBase(a_rThat)
2220 , m_fIsSet(a_rThat.m_fIsSet)
2221{
2222}
2223
2224
[74425]2225RTCRestDataObject &RTCRestDataObject::operator=(RTCRestDataObject const &a_rThat) RT_NOEXCEPT
[74347]2226{
2227 m_fNullIndicator = a_rThat.m_fNullIndicator;
2228 m_fIsSet = a_rThat.m_fIsSet;
2229 return *this;
2230}
2231
2232
[74425]2233int RTCRestDataObject::assignCopy(RTCRestDataObject const &a_rThat) RT_NOEXCEPT
[74347]2234{
2235 m_fNullIndicator = a_rThat.m_fNullIndicator;
2236 m_fIsSet = a_rThat.m_fIsSet;
2237 return VINF_SUCCESS;
2238}
2239
2240
[74425]2241int RTCRestDataObject::resetToDefault() RT_NOEXCEPT
[74347]2242{
2243 m_fNullIndicator = false;
2244 m_fIsSet = 0;
2245 return VINF_SUCCESS;
2246}
2247
2248
[74425]2249RTCRestOutputBase &RTCRestDataObject::serializeMembersAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT
[74347]2250{
2251 RT_NOREF(a_rDst);
[74414]2252 return a_rDst;
[74347]2253}
2254
2255
[74425]2256RTCRestOutputBase &RTCRestDataObject::serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT
[74347]2257{
2258 if (!m_fNullIndicator)
2259 {
[74414]2260 uint32_t const uOldState = a_rDst.beginObject();
2261 serializeMembersAsJson(a_rDst);
2262 a_rDst.endObject(uOldState);
[74347]2263 }
2264 else
[74414]2265 a_rDst.nullValue();
[74347]2266 return a_rDst;
2267}
2268
2269
[74425]2270int RTCRestDataObject::deserializeMemberFromJson(RTCRestJsonCursor const &a_rCursor, size_t a_cchName) RT_NOEXCEPT
[74347]2271{
2272 RT_NOREF(a_rCursor, a_cchName);
2273 return VERR_NOT_FOUND;
2274}
2275
2276
[74425]2277int RTCRestDataObject::deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT
[74347]2278{
[87619]2279 if (RTJsonValueGetType(a_rCursor.m_hValue) == RTJSONVALTYPE_NULL)
2280 {
2281 setNull();
2282 return VINF_SUCCESS;
2283 }
2284
[74347]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
[74425]2358RTCRestObjectBase::kTypeClass RTCRestDataObject::typeClass(void) const RT_NOEXCEPT
[74347]2359{
2360 return kTypeClass_DataObject;
2361}
2362
[74386]2363
2364
2365/*********************************************************************************************************************************
2366* RTCRestPolyDataObject *
2367*********************************************************************************************************************************/
2368
[74425]2369RTCRestPolyDataObject::RTCRestPolyDataObject() RT_NOEXCEPT
[74386]2370 : RTCRestDataObject()
2371{
2372}
2373
2374
[74425]2375RTCRestPolyDataObject::RTCRestPolyDataObject(RTCRestPolyDataObject const &a_rThat) RT_NOEXCEPT
[74386]2376 : RTCRestDataObject(a_rThat)
2377{
2378}
2379
2380
2381RTCRestPolyDataObject::~RTCRestPolyDataObject()
2382{
2383}
2384
2385
[74425]2386int RTCRestPolyDataObject::resetToDefault() RT_NOEXCEPT
[74386]2387{
2388 return RTCRestDataObject::resetToDefault();
2389}
2390
2391
[74425]2392bool RTCRestPolyDataObject::isChild() const RT_NOEXCEPT
[74386]2393{
2394 return false;
2395}
2396
2397
[74425]2398RTCRestPolyDataObject &RTCRestPolyDataObject::operator=(RTCRestPolyDataObject const &a_rThat) RT_NOEXCEPT
[74386]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