VirtualBox

Ignore:
Timestamp:
Sep 2, 2018 1:43:59 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
124770
Message:

IPRT/rest: Implemented header collection (x-obmcs-header-collection) and multi-query array mapping. Renamed RTCRestObjectBase::getType() to typeName() to avoid clashing with generated code. bugref:9167

Location:
trunk/src/VBox/Runtime/common/rest
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/rest/RTCRestArrayBase.cpp

    r74008 r74023  
    245245
    246246
     247RTCRestObjectBase::kTypeClass RTCRestArrayBase::typeClass(void) const
     248{
     249    return kTypeClass_Array;
     250}
     251
     252
     253const char *RTCRestArrayBase::typeName(void) const
     254{
     255    return "RTCRestArray<ElementType>";
     256}
     257
     258
    247259
    248260/*********************************************************************************************************************************
  • trunk/src/VBox/Runtime/common/rest/RTCRestClientRequestBase.cpp

    r74020 r74023  
    146146            else
    147147            {
    148                 AssertFailedReturn(VERR_NOT_IMPLEMENTED);
     148                /*
     149                 * Enumerate array and add 'name=element' for each element in it.
     150                 */
     151                AssertReturn(a_papQueryParamObjs[i]->typeClass() == RTCRestObjectBase::kTypeClass_Array,
     152                             VERR_REST_INTERAL_ERROR_2);
     153                RTCRestArrayBase const *pArray = (RTCRestArrayBase const *)a_papQueryParamObjs[i];
     154                for (size_t i = 0; i < pArray->size(); i++)
     155                {
     156                    RTCRestObjectBase const *pObj = pArray->atBase(i);
     157                    int rc = pObj->toString(&strTmpVal, a_paQueryParams[i].fFlags & ~RTCRestObjectBase::kCollectionFormat_Mask);
     158                    AssertRCReturn(rc, rc);
     159
     160                    rc = a_pStrQuery->appendPrintfNoThrow("%c%RMpq=%RMpq", chSep, a_paQueryParams[i].pszName, strTmpVal.c_str());
     161                    AssertRCReturn(rc, rc);
     162
     163                    chSep = '&';
     164                }
    149165            }
    150166        }
     
    170186                      ("Required header parameter '%s' is not set!\n", a_paHeaderParams[i].pszName));
    171187
    172             int rc = a_papHeaderParamObjs[i]->toString(&strTmpVal, a_paHeaderParams[i].fFlags);
    173             AssertRCReturn(rc, rc);
    174 
    175             rc = RTHttpAppendHeader(a_hHttp, a_paHeaderParams[i].pszName, strTmpVal.c_str(), 0);
    176             AssertRCReturn(rc, rc);
     188            if (!a_paHeaderParams[i].fMapCollection)
     189            {
     190                int rc = a_papHeaderParamObjs[i]->toString(&strTmpVal, a_paHeaderParams[i].fFlags);
     191                AssertRCReturn(rc, rc);
     192
     193                rc = RTHttpAppendHeader(a_hHttp, a_paHeaderParams[i].pszName, strTmpVal.c_str(), 0);
     194                AssertRCReturn(rc, rc);
     195            }
     196            else if (!a_papHeaderParamObjs[i]->isNull())
     197            {
     198                /*
     199                 * Enumerate the map and produce a series of head fields on the form:
     200                 *      (a_paHeaderParams[i].pszName + key): value.toString()
     201                 */
     202                AssertReturn(a_papHeaderParamObjs[i]->typeClass() == RTCRestObjectBase::kTypeClass_StringMap,
     203                             VERR_REST_INTERAL_ERROR_1);
     204                RTCRestStringMapBase const *pMap    = (RTCRestStringMapBase const *)a_papHeaderParamObjs[i];
     205                const size_t                cchName = strlen(a_paHeaderParams[i].pszName);
     206                RTCString                   strTmpName;
     207                for (RTCRestStringMapBase::ConstIterator it = pMap->begin(); it != pMap->end(); ++it)
     208                {
     209                    int rc = strTmpName.assignNoThrow(a_paHeaderParams[i].pszName, cchName);
     210                    AssertRCReturn(rc, rc);
     211                    rc = strTmpName.appendNoThrow(it.getKey());
     212                    AssertRCReturn(rc, rc);
     213
     214                    rc = it.getValue()->toString(&strTmpVal, a_paHeaderParams[i].fFlags);
     215                    AssertRCReturn(rc, rc);
     216
     217                    rc = RTHttpAppendHeader(a_hHttp, strTmpName.c_str(), strTmpVal.c_str(), 0);
     218                    AssertRCReturn(rc, rc);
     219                }
     220            }
     221            else
     222                Assert(!a_paHeaderParams[i].fRequired);
    177223        }
    178224    }
  • trunk/src/VBox/Runtime/common/rest/RTCRestClientResponseBase.cpp

    r74009 r74023  
    231231            {
    232232                size_t const cchThisName = a_paFieldDescs[i].cchName;
    233                 if (  !(a_paFieldDescs[i].fFlags & kHdrField_MapCollection)
    234                     ?    cchThisName == cchName
    235                       && RTStrNICmpAscii(a_pchData, a_paFieldDescs[i].pszName, cchThisName) == 0
    236                     :    cchThisName <= cchName
    237                       && RTStrNICmpAscii(a_pchData, a_paFieldDescs[i].pszName, cchThisName - 1) == 0)
     233                if (   (!(a_paFieldDescs[i].fFlags & kHdrField_MapCollection) ? cchThisName == cchName : cchThisName < cchName)
     234                    && RTStrNICmpAscii(a_pchData, a_paFieldDescs[i].pszName, cchThisName) == 0)
    238235                {
    239236                    /* Get and clean the value. */
    240                     int rc = VINF_SUCCESS;
    241237                    if (!fHaveValue)
    242238                    {
    243                         rc = strValue.assignNoThrow(&a_pchData[offValue], cchValue);
     239                        int rc = strValue.assignNoThrow(&a_pchData[offValue], cchValue);
    244240                        if (RT_SUCCESS(rc))
    245241                        {
     
    257253                     * Create field to deserialize.
    258254                     */
    259                     RTCRestObjectBase *pObj = NULL;
    260                     if (!(a_paFieldDescs[i].fFlags & (kHdrField_MapCollection | kHdrField_ArrayCollection)))
     255                    RTCRestStringMapBase *pMap = NULL;
     256                    RTCRestObjectBase    *pObj = NULL;
     257                    if (!(a_paFieldDescs[i].fFlags & kHdrField_MapCollection))
    261258                    {
    262259                        /* Only once. */
     
    269266                            {
    270267                                addError(VERR_NO_MEMORY, "out of memory");
    271                                 continue;
     268                                break;
    272269                            }
    273270                        }
     
    280277                    else
    281278                    {
    282                         Assert(a_paFieldDescs[i].pszName[cchThisName - 1] == '*');
    283                         AssertMsgFailed(("impl field collections"));
    284                         continue;
     279                        /* Make sure we've got a map to work with. */
     280                        if (!*a_pappFieldValues[i])
     281                            *a_pappFieldValues[i] = pObj = a_paFieldDescs[i].pfnCreateInstance();
     282                        else
     283                            pObj = *a_pappFieldValues[i];
     284                        AssertBreak(pObj->typeClass() == RTCRestObjectBase::kTypeClass_StringMap);
     285                        pMap = (RTCRestStringMapBase *)pObj;
     286
     287                        /* Insert the header field name (sans prefix) into the map.  We then use the
     288                           new value object for the deserialization of the header field value below.  */
     289                        int rc = pMap->putNewValue(&pObj, &a_pchData[cchThisName], cchName - cchThisName);
     290                        if (RT_SUCCESS(rc))
     291                        { /* likely */ }
     292                        else if (rc == VERR_ALREADY_EXISTS)
     293                        {
     294                            addError(VERR_REST_RESPONSE_REPEAT_HEADER_FIELD, "Already saw header field '%s'", a_paFieldDescs[i].pszName);
     295                            continue;
     296                        }
     297                        else
     298                        {
     299                            addError(rc, "out of memory");
     300                            break;
     301                        }
    285302                    }
    286303
     
    289306                     */
    290307                    RTERRINFOSTATIC ErrInfo;
    291                     rc = pObj->fromString(strValue, a_paFieldDescs[i].pszName, RTErrInfoInitStatic(&ErrInfo),
    292                                           a_paFieldDescs[i].fFlags & RTCRestObjectBase::kCollectionFormat_Mask);
     308                    int rc = pObj->fromString(strValue, a_paFieldDescs[i].pszName, RTErrInfoInitStatic(&ErrInfo),
     309                                              a_paFieldDescs[i].fFlags & RTCRestObjectBase::kCollectionFormat_Mask);
    293310                    if (RT_SUCCESS(rc))
    294311                    { /* likely */ }
     
    405422            if (RT_SUCCESS(rc))
    406423            {
    407                 PrimaryJsonCursorForBody PrimaryCursor(hValue, a_pDst->getType(), this); /* note: consumes hValue */
     424                PrimaryJsonCursorForBody PrimaryCursor(hValue, a_pDst->typeName(), this); /* note: consumes hValue */
    408425                a_pDst->deserializeFromJson(PrimaryCursor.m_Cursor);
    409426            }
    410427            else if (RTErrInfoIsSet(&ErrInfo.Core))
    411428                addError(rc, "Error %Rrc parsing server response as JSON (type %s): %s",
    412                          rc, a_pDst->getType(), ErrInfo.Core.pszMsg);
     429                         rc, a_pDst->typeName(), ErrInfo.Core.pszMsg);
    413430            else
    414                 addError(rc, "Error %Rrc parsing server response as JSON (type %s)", rc, a_pDst->getType());
     431                addError(rc, "Error %Rrc parsing server response as JSON (type %s)", rc, a_pDst->typeName());
    415432        }
    416433        else if (rc == VERR_INVALID_UTF8_ENCODING)
    417434            addError(VERR_REST_RESPONSE_INVALID_UTF8_ENCODING, "Invalid UTF-8 body encoding (object type %s; Content-Type: %s)",
    418                      a_pDst->getType(), m_strContentType.c_str());
     435                     a_pDst->typeName(), m_strContentType.c_str());
    419436        else if (rc == VERR_BUFFER_UNDERFLOW)
    420437            addError(VERR_REST_RESPONSE_EMBEDDED_ZERO_CHAR, "Embedded zero character in response (object type %s; Content-Type: %s)",
    421                      a_pDst->getType(), m_strContentType.c_str());
     438                     a_pDst->typeName(), m_strContentType.c_str());
    422439        else
    423440            addError(rc, "Unexpected body validation error (object type %s; Content-Type: %s): %Rrc",
    424                      a_pDst->getType(), m_strContentType.c_str(), rc);
     441                     a_pDst->typeName(), m_strContentType.c_str(), rc);
    425442    }
    426443    else
    427444        addError(VERR_REST_RESPONSE_CONTENT_TYPE_NOT_SUPPORTED, "Unsupported content type for '%s': %s",
    428                  a_pDst->getType(), m_strContentType.c_str());
    429 }
    430 
     445                 a_pDst->typeName(), m_strContentType.c_str());
     446}
     447
  • trunk/src/VBox/Runtime/common/rest/RTCRestStringMapBase.cpp

    r74008 r74023  
    204204
    205205
     206RTCRestObjectBase::kTypeClass RTCRestStringMapBase::typeClass(void) const
     207{
     208    return kTypeClass_StringMap;
     209}
     210
     211
     212const char *RTCRestStringMapBase::typeName(void) const
     213{
     214    return "RTCRestStringMap<ValueType>";
     215}
     216
     217
    206218/*********************************************************************************************************************************
    207219*   Generic map methods                                                                                                          *
     
    269281{
    270282    return remove(a_rStrKey.c_str());
     283}
     284
     285
     286int RTCRestStringMapBase::putNewValue(RTCRestObjectBase **a_ppValue, const char *a_pszKey, size_t a_cchKey /*= RTSTR_MAX*/,
     287                                      bool a_fReplace /*= false*/)
     288{
     289    RTCRestObjectBase *pValue = createValue();
     290    if (pValue)
     291    {
     292        int rc = putWorker(a_pszKey, pValue, a_fReplace, a_cchKey);
     293        if (RT_SUCCESS(rc))
     294            *a_ppValue = pValue;
     295        else
     296        {
     297            delete pValue;
     298            *a_ppValue = NULL;
     299        }
     300        return rc;
     301    }
     302    *a_ppValue = NULL;
     303    return VERR_NO_MEMORY;
     304}
     305
     306
     307int RTCRestStringMapBase::putNewValue(RTCRestObjectBase **a_ppValue, RTCString const &a_rStrKey, bool a_fReplace /*= false*/)
     308{
     309    return putNewValue(a_ppValue, a_rStrKey.c_str(), a_rStrKey.length(), a_fReplace);
    271310}
    272311
     
    301340
    302341
    303 int RTCRestStringMapBase::putWorker(const char *a_pszKey, RTCRestObjectBase *a_pValue, bool a_fReplace)
     342int RTCRestStringMapBase::putWorker(const char *a_pszKey, RTCRestObjectBase *a_pValue, bool a_fReplace,
     343                                    size_t a_cchKey /*= RTSTR_MAX*/)
    304344{
    305345    int rc;
     
    307347    if (pEntry)
    308348    {
    309         rc = pEntry->strKey.assignNoThrow(a_pszKey);
     349        rc = pEntry->strKey.assignNoThrow(a_pszKey, a_cchKey);
    310350        if (RT_SUCCESS(rc))
    311351        {
     
    347387
    348388
    349 int RTCRestStringMapBase::putCopyWorker(const char *a_pszKey, RTCRestObjectBase const &a_rValue, bool a_fReplace)
     389int RTCRestStringMapBase::putCopyWorker(const char *a_pszKey, RTCRestObjectBase const &a_rValue, bool a_fReplace,
     390                                        size_t a_cchKey /*= RTSTR_MAX*/)
    350391{
    351392    int rc;
     
    353394    if (pValueCopy)
    354395    {
    355         rc = putWorker(a_pszKey, pValueCopy, a_fReplace);
     396        rc = putWorker(a_pszKey, pValueCopy, a_fReplace, a_cchKey);
    356397        if (RT_SUCCESS(rc))
    357398        { /* likely */ }
  • trunk/src/VBox/Runtime/common/rest/rest-primary-object-types.cpp

    r74013 r74023  
    118118
    119119
     120RTCRestObjectBase::kTypeClass RTCRestObjectBase::typeClass() const
     121{
     122    return kTypeClass_Object;
     123}
     124
     125
    120126/*********************************************************************************************************************************
    121127*   RTCRestBool implementation                                                                                                   *
     
    277283
    278284
    279 const char *RTCRestBool::getType()
     285RTCRestObjectBase::kTypeClass RTCRestBool::typeClass() const
     286{
     287    return kTypeClass_Bool;
     288}
     289
     290
     291const char *RTCRestBool::typeName() const
    280292{
    281293    return "bool";
     
    434446
    435447
    436 const char *RTCRestInt64::getType()
     448RTCRestObjectBase::kTypeClass RTCRestInt64::typeClass() const
     449{
     450    return kTypeClass_Int64;
     451}
     452
     453
     454const char *RTCRestInt64::typeName() const
    437455{
    438456    return "int64_t";
     
    597615
    598616
    599 const char *RTCRestInt32::getType()
     617RTCRestObjectBase::kTypeClass RTCRestInt32::typeClass() const
     618{
     619    return kTypeClass_Int32;
     620}
     621
     622
     623const char *RTCRestInt32::typeName() const
    600624{
    601625    return "int32_t";
     
    760784
    761785
    762 const char *RTCRestInt16::getType()
     786RTCRestObjectBase::kTypeClass RTCRestInt16::typeClass() const
     787{
     788    return kTypeClass_Int16;
     789}
     790
     791
     792const char *RTCRestInt16::typeName() const
    763793{
    764794    return "int16_t";
     
    920950
    921951
    922 const char *RTCRestDouble::getType()
     952RTCRestObjectBase::kTypeClass RTCRestDouble::typeClass() const
     953{
     954    return kTypeClass_Double;
     955}
     956
     957
     958const char *RTCRestDouble::typeName() const
    923959{
    924960    return "double";
     
    10711107
    10721108
    1073 const char *RTCRestString::getType()
     1109RTCRestObjectBase::kTypeClass RTCRestString::typeClass() const
     1110{
     1111    return kTypeClass_String;
     1112}
     1113
     1114
     1115const char *RTCRestString::typeName() const
    10741116{
    10751117    return "RTCString";
Note: See TracChangeset for help on using the changeset viewer.

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