VirtualBox

Changeset 73933 in vbox for trunk


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
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/cpp/restbase.h

    r73930 r73933  
    295295        kCollectionFormat_ssv,              /**< Space-separated list. */
    296296        kCollectionFormat_tsv,              /**< Tab-separated list. */
    297         kCollectionFormat_pipes             /**< Pipe-separated list. */
     297        kCollectionFormat_pipes,            /**< Pipe-separated list. */
     298        kCollectionFormat_Mask = 7          /**< Collection type mask. */
    298299    };
    299300
     
    328329     */
    329330    virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
    330                                   uint32_t a_fFlags = kCollectionFormat_Unspecified);
     331                           uint32_t a_fFlags = kCollectionFormat_Unspecified);
    331332
    332333    /**
     
    334335     */
    335336    virtual const char *getType(void) = 0;
     337
     338    /**
     339     * Factory method.
     340     * @returns Pointer to new object on success, NULL if out of memory.
     341     */
     342    typedef DECLCALLBACK(RTCRestObjectBase *) FNCREATEINSTANCE(void);
     343    /** Pointer to factory method. */
     344    typedef FNCREATEINSTANCE *PFNCREATEINSTANCE;
    336345};
    337346
     
    363372    virtual const char *getType(void) RT_OVERRIDE;
    364373
     374    /** Factory method. */
     375    static DECLCALLBACK(RTCRestObjectBase *) createInstance(void);
     376
    365377public:
    366378    /** The value. */
     
    395407    virtual const char *getType(void) RT_OVERRIDE;
    396408
     409    /** Factory method. */
     410    static DECLCALLBACK(RTCRestObjectBase *) createInstance(void);
     411
    397412public:
    398413    /** The value. */
     
    427442    virtual const char *getType(void) RT_OVERRIDE;
    428443
     444    /** Factory method. */
     445    static DECLCALLBACK(RTCRestObjectBase *) createInstance(void);
     446
    429447public:
    430448    /** The value. */
     
    459477    virtual const char *getType(void) RT_OVERRIDE;
    460478
     479    /** Factory method. */
     480    static DECLCALLBACK(RTCRestObjectBase *) createInstance(void);
     481
    461482public:
    462483    /** The value. */
     
    491512    virtual const char *getType(void) RT_OVERRIDE;
    492513
     514    /** Factory method. */
     515    static DECLCALLBACK(RTCRestObjectBase *) createInstance(void);
     516
    493517public:
    494518    /** The value. */
     
    522546                           uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_OVERRIDE;
    523547    virtual const char *getType(void) RT_OVERRIDE;
     548
     549    /** Factory method. */
     550    static DECLCALLBACK(RTCRestObjectBase *) createInstance(void);
    524551};
    525552
     
    528555 * Limited array class.
    529556 */
    530 template<class Type> class RTCRestArray : public RTCRestObjectBase
     557template<class ElementType> class RTCRestArray : public RTCRestObjectBase
    531558{
    532559public:
     
    535562/** @todo more later. */
    536563
    537     virtual void resetToDefault() RT_OVERRIDE;
    538     virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_OVERRIDE;
     564    virtual void resetToDefault() RT_OVERRIDE
     565    {
     566    }
     567
     568    virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_OVERRIDE
     569    {
     570        RT_NOREF(a_rDst);
     571        return a_rDst;
     572    }
     573
    539574    virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_OVERRIDE
    540575    {
     
    542577        return VERR_NOT_IMPLEMENTED;
    543578    }
     579
    544580    virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
    545                            uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_OVERRIDE;
    546     virtual const char *getType(void) RT_OVERRIDE;
     581                           uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_OVERRIDE
     582    {
     583        RT_NOREF(a_rValue, a_pszName, a_pErrInfo, a_fFlags);
     584        return VERR_NOT_IMPLEMENTED;
     585    }
     586
     587    virtual const char *getType(void) RT_OVERRIDE
     588    {
     589        return "RTCRestArray<ElementType>";
     590    }
     591
     592    /** Factory method. */
     593    static DECLCALLBACK(RTCRestObjectBase *) createInstance(void)
     594    {
     595        return new RTCRestArray<ElementType>();
     596    }
     597
     598    /** Factory method for elements. */
     599    static DECLCALLBACK(RTCRestObjectBase *) createElementInstance(void)
     600    {
     601        return new ElementType();
     602    }
    547603};
    548604
     
    551607 * Limited map class.
    552608 */
    553 template<class Type> class RTCRestStringMap : public RTCRestObjectBase
     609template<class ElementType> class RTCRestStringMap : public RTCRestObjectBase
    554610{
    555611public:
     
    558614/** @todo more later. */
    559615
    560     virtual void resetToDefault() RT_OVERRIDE;
    561     virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_OVERRIDE;
     616    virtual void resetToDefault() RT_OVERRIDE
     617    {
     618    }
     619
     620    virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_OVERRIDE
     621    {
     622        RT_NOREF(a_rDst);
     623        return a_rDst;
     624    }
     625
    562626    virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_OVERRIDE
    563627    {
     
    565629        return VERR_NOT_IMPLEMENTED;
    566630    }
     631
    567632    virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
    568                            uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_OVERRIDE;
    569     virtual const char *getType(void) RT_OVERRIDE;
     633                           uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_OVERRIDE
     634    {
     635        RT_NOREF(a_rValue, a_pszName, a_pErrInfo, a_fFlags);
     636        return VERR_NOT_IMPLEMENTED;
     637    }
     638
     639    virtual const char *getType(void) RT_OVERRIDE
     640    {
     641        return "RTCRestStringMap<ElementType>";
     642    }
     643
     644    /** Factory method. */
     645    static DECLCALLBACK(RTCRestObjectBase *) createInstance(void)
     646    {
     647        return new RTCRestStringMap<ElementType>();
     648    }
     649
     650    /** Factory method for elements. */
     651    static DECLCALLBACK(RTCRestObjectBase *) createElementInstance(void)
     652    {
     653        return new ElementType();
     654    }
    570655};
    571656
     
    743828     * @param   ...         Message arguments.
    744829     */
    745     int         addError(int a_rc, const char *a_pszFormat, ...);
     830    int addError(int a_rc, const char *a_pszFormat, ...);
     831
     832    /** Field flags. */
     833    enum
     834    {
     835        /** Collection map, name is a prefix followed by '*'. */
     836        kHdrField_MapCollection   = RT_BIT_32(24),
     837        /** Array collection, i.e. the heade field may appear more than once. */
     838        kHdrField_ArrayCollection = RT_BIT_32(25),
     839    };
     840
     841    /** Header field descriptor. */
     842    typedef struct
     843    {
     844        /** The header field name. */
     845        const char *pszName;
     846        /** The length of the field name.*/
     847        uint32_t    cchName;
     848        /** Flags, TBD. */
     849        uint32_t    fFlags;
     850        /** Object factory. */
     851        RTCRestObjectBase::PFNCREATEINSTANCE pfnCreateInstance;
     852    } HEADERFIELDDESC;
     853
     854    /**
     855     * Helper that extracts fields from the HTTP headers.
     856     *
     857     * @param   a_paFieldsDesc      Pointer to an array of field descriptors.
     858     * @param   a_pappFieldValues   Pointer to a parallel array of value pointer pointers.
     859     * @param   a_cFields           Number of field descriptors..
     860     * @param   a_pchData           The header blob to search.
     861     * @param   a_cbData            The size of the header blob to search.
     862     */
     863    void extracHeaderFieldsFromBlob(HEADERFIELDDESC const *a_paFieldDescs, RTCRestObjectBase ***a_pappFieldValues,
     864                                    size_t a_cFields, const char *a_pchData, size_t a_cbData);
    746865
    747866    /**
  • trunk/include/iprt/err.h

    r73930 r73933  
    32143214/** Server response contains embedded zero character(s). */
    32153215#define VERR_REST_RESPONSE_EMBEDDED_ZERO_CHAR           (-25702)
     3216/** Server response contains unexpected repetitive header field. */
     3217#define VERR_REST_RESPONSE_REPEAT_HEADER_FIELD          (-25703)
    32163218/** @} */
    32173219
  • 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