VirtualBox

Changeset 73933 in vbox for trunk/src/VBox/Runtime


Ignore:
Timestamp:
Aug 28, 2018 8:57:23 PM (6 years ago)
Author:
vboxsync
Message:

IPRT/rest: Adding genric factor methods for every class and use it to generalize response header field parsing. bugref:9167

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

Legend:

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

    r73930 r73933  
    180180}
    181181
     182
     183void RTCRestClientResponseBase::extracHeaderFieldsFromBlob(HEADERFIELDDESC const *a_paFieldDescs,
     184                                                           RTCRestObjectBase ***a_pappFieldValues,
     185                                                           size_t a_cFields, const char *a_pchData, size_t a_cbData)
     186
     187{
     188    RTCString strValue; /* (Keep it out here to encourage buffer allocation reuse and default construction call.) */
     189
     190    /*
     191     * Work our way through the header blob.
     192     */
     193    while (a_cbData >= 2)
     194    {
     195        /*
     196         * Determine length of the header name:value combo.
     197         * Note! Multi-line field values are not currently supported.
     198         */
     199        const char *pchEol = (const char *)memchr(a_pchData, '\n', a_cbData);
     200        while (pchEol && (pchEol == a_pchData || pchEol[-1] != '\r'))
     201            pchEol = (const char *)memchr(pchEol, '\n', a_cbData - (pchEol - a_pchData));
     202
     203        size_t const cchField       = pchEol ? pchEol - a_pchData + 1 : a_cbData;
     204        size_t const cchFieldNoCrLf = pchEol ? pchEol - a_pchData - 1 : a_cbData;
     205
     206        const char *pchColon = (const char *)memchr(a_pchData, ':', cchFieldNoCrLf);
     207        Assert(pchColon);
     208        if (pchColon)
     209        {
     210            size_t const cchName  = pchColon - a_pchData;
     211            size_t const offValue = cchName + (RT_C_IS_BLANK(pchColon[1]) ? 2 : 1);
     212            size_t const cchValue = cchFieldNoCrLf - offValue;
     213
     214            /*
     215             * Match headers.
     216             */
     217            bool fHaveValue = false;
     218            for (size_t i = 0; i < a_cFields; i++)
     219            {
     220                size_t const cchThisName = a_paFieldDescs[i].cchName;
     221                if (  !(a_paFieldDescs[i].fFlags & kHdrField_MapCollection)
     222                    ?    cchThisName == cchName
     223                      && RTStrNICmpAscii(a_pchData, a_paFieldDescs[i].pszName, cchThisName) == 0
     224                    :    cchThisName <= cchName
     225                      && RTStrNICmpAscii(a_pchData, a_paFieldDescs[i].pszName, cchThisName - 1) == 0)
     226                {
     227                    /* Get and clean the value. */
     228                    int rc = VINF_SUCCESS;
     229                    if (!fHaveValue)
     230                    {
     231                        rc = strValue.assignNoThrow(&a_pchData[offValue], cchValue);
     232                        if (RT_SUCCESS(rc))
     233                        {
     234                            RTStrPurgeEncoding(strValue.mutableRaw()); /** @todo this is probably a little wrong... */
     235                            fHaveValue = true;
     236                        }
     237                        else
     238                        {
     239                            addError(rc, "Error allocating %u bytes for header field %s", a_paFieldDescs[i].pszName);
     240                            break;
     241                        }
     242                    }
     243
     244                    /*
     245                     * Create field to deserialize.
     246                     */
     247                    RTCRestObjectBase *pObj = NULL;
     248                    if (!(a_paFieldDescs[i].fFlags & (kHdrField_MapCollection | kHdrField_ArrayCollection)))
     249                    {
     250                        /* Only once. */
     251                        if (!*a_pappFieldValues[i])
     252                        {
     253                            pObj = a_paFieldDescs[i].pfnCreateInstance();
     254                            if (pObj)
     255                                *a_pappFieldValues[i] = pObj;
     256                            else
     257                            {
     258                                addError(VERR_NO_MEMORY, "out of memory");
     259                                continue;
     260                            }
     261                        }
     262                        else
     263                        {
     264                            addError(VERR_REST_RESPONSE_REPEAT_HEADER_FIELD, "Already saw header field '%s'", a_paFieldDescs[i].pszName);
     265                            continue;
     266                        }
     267                    }
     268                    else
     269                    {
     270                        Assert(a_paFieldDescs[i].pszName[cchThisName - 1] == '*');
     271                        AssertMsgFailed(("impl field collections"));
     272                        continue;
     273                    }
     274
     275                    /*
     276                     * Deserialize it.
     277                     */
     278                    RTERRINFOSTATIC ErrInfo;
     279                    rc = pObj->fromString(strValue, a_paFieldDescs[i].pszName, RTErrInfoInitStatic(&ErrInfo),
     280                                          a_paFieldDescs[i].fFlags & RTCRestObjectBase::kCollectionFormat_Mask);
     281                    if (RT_SUCCESS(rc))
     282                    { /* likely */ }
     283                    else if (RTErrInfoIsSet(&ErrInfo.Core))
     284                        addError(rc, "Error %Rrc parsing header field '%s': %s",
     285                                 rc, a_paFieldDescs[i].pszName, ErrInfo.Core.pszMsg);
     286                    else
     287                        addError(rc, "Error %Rrc parsing header field '%s'", rc, a_paFieldDescs[i].pszName);
     288                }
     289            }
     290        }
     291
     292        /*
     293         * Advance to the next field.
     294         */
     295        a_cbData  -= cchField;
     296        a_pchData += cchField;
     297    }
     298}
    182299
    183300int RTCRestClientResponseBase::extractHeaderFromBlob(const char *a_pszField, size_t a_cchField,
  • trunk/src/VBox/Runtime/common/rest/rest-primary-object-types.cpp

    r73920 r73933  
    101101*********************************************************************************************************************************/
    102102
     103/** Factory method. */
     104/*static*/ DECLCALLBACK(RTCRestObjectBase *) RTCRestBool::createInstance(void)
     105{
     106    return new (std::nothrow) RTCRestBool();
     107}
     108
     109
    103110/** Default destructor. */
    104111RTCRestBool::RTCRestBool()
     
    206213
    207214
     215
    208216/*********************************************************************************************************************************
    209217*   RTCRestInt64 implementation                                                                                                  *
    210218*********************************************************************************************************************************/
     219
     220/** Factory method. */
     221/*static*/ DECLCALLBACK(RTCRestObjectBase *) RTCRestInt64::createInstance(void)
     222{
     223    return new (std::nothrow) RTCRestInt64();
     224}
     225
    211226
    212227/** Default destructor. */
     
    312327*   RTCRestInt32 implementation                                                                                                  *
    313328*********************************************************************************************************************************/
     329
     330/** Factory method. */
     331/*static*/ DECLCALLBACK(RTCRestObjectBase *) RTCRestInt32::createInstance(void)
     332{
     333    return new (std::nothrow) RTCRestInt32();
     334}
     335
    314336
    315337/** Default destructor. */
     
    422444*********************************************************************************************************************************/
    423445
     446/** Factory method. */
     447/*static*/ DECLCALLBACK(RTCRestObjectBase *) RTCRestInt16::createInstance(void)
     448{
     449    return new (std::nothrow) RTCRestInt16();
     450}
     451
     452
    424453/** Default destructor. */
    425454RTCRestInt16::RTCRestInt16()
     
    531560*********************************************************************************************************************************/
    532561
     562/** Factory method. */
     563/*static*/ DECLCALLBACK(RTCRestObjectBase *) RTCRestDouble::createInstance(void)
     564{
     565    return new (std::nothrow) RTCRestDouble();
     566}
     567
    533568/** Default destructor. */
    534569RTCRestDouble::RTCRestDouble()
     
    634669*********************************************************************************************************************************/
    635670
     671/** Factory method. */
     672/*static*/ DECLCALLBACK(RTCRestObjectBase *) RTCRestString::createInstance(void)
     673{
     674    return new (std::nothrow) RTCRestString();
     675}
     676
     677
    636678/** Default destructor. */
    637679RTCRestString::RTCRestString()
Note: See TracChangeset for help on using the changeset viewer.

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