VirtualBox

Changeset 80835 in vbox


Ignore:
Timestamp:
Sep 16, 2019 8:30:40 PM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
133405
Message:

Main/glue: Added bstr testcase and fixed printf bugs. Introduced jolt, joltNoThrow, reserve and reserveNoThrow for the low level allocation operations needed by printf.

Location:
trunk
Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/com/string.h

    r80793 r80835  
    386386
    387387    /**
    388      *  Returns a non-const raw pointer that allows to modify the string directly.
    389      *  As opposed to raw(), this DOES return NULL if the member string is empty
    390      *  because we cannot return a mutable pointer to the global variable with the
    391      *  empty string.
    392      *
    393      *  @warning
    394      *      Be sure not to modify data beyond the allocated memory! The
    395      *      guaranteed size of the allocated memory is at least #length()
    396      *      bytes after creation and after every assignment operation.
     388     * Returns a non-const raw pointer that allows modifying the string directly.
     389     *
     390     * @note As opposed to raw(), this DOES return NULL if the member string is
     391     *       empty because we cannot return a mutable pointer to the global variable
     392     *       with the empty string.
     393     *
     394     * @note If modifying the string size (only shrinking it is allows), #jolt() or
     395     *       #joltNoThrow() must be called!
     396     *
     397     * @note Do not modify memory beyond the #length() of the string!
     398     *
     399     * @sa   joltNoThrow(), mutalbleRaw(), reserve(), reserveNoThrow()
    397400     */
    398401    BSTR mutableRaw() { return m_bstr; }
     402
     403    /**
     404     * Correct the embedded length after using mutableRaw().
     405     *
     406     * This is needed on COM (Windows) to update the embedded string length.  It is
     407     * a stub on hosts using XPCOM.
     408     *
     409     * @param   cwcNew      The new string length, if handy, otherwise a negative
     410     *                      number.
     411     * @sa      joltNoThrow(), mutalbleRaw(), reserve(), reserveNoThrow()
     412     */
     413#ifndef VBOX_WITH_XPCOM
     414    void jolt(ssize_t cwcNew = -1);
     415#else
     416    void jolt(ssize_t cwcNew = -1)
     417    {
     418        Assert(cwcNew < 0 || (cwcNew == 0 && !m_bstr) || m_bstr[cwcNew] == '\0'); RT_NOREF(cwcNew);
     419    }
     420#endif
     421
     422    /**
     423     * Correct the embedded length after using mutableRaw().
     424     *
     425     * This is needed on COM (Windows) to update the embedded string length.  It is
     426     * a stub on hosts using XPCOM.
     427     *
     428     * @returns S_OK on success, E_OUTOFMEMORY if shrinking the string failed.
     429     * @param   cwcNew      The new string length, if handy, otherwise a negative
     430     *                      number.
     431     * @sa      jolt(), mutalbleRaw(), reserve(), reserveNoThrow()
     432     */
     433#ifndef VBOX_WITH_XPCOM
     434    HRESULT joltNoThrow(ssize_t cwcNew = -1) RT_NOEXCEPT;
     435#else
     436    HRESULT joltNoThrow(ssize_t cwcNew = -1) RT_NOEXCEPT
     437    {
     438        Assert(cwcNew < 0 || (cwcNew == 0 && !m_bstr) || m_bstr[cwcNew] == '\0'); RT_NOREF(cwcNew);
     439        return S_OK;
     440    }
     441#endif
     442
     443    /**
     444     * Make sure at that least @a cwc of buffer space is reserved.
     445     *
     446     * Requests that the contained memory buffer have at least cb bytes allocated.
     447     * This may expand or shrink the string's storage, but will never truncate the
     448     * contained string.  In other words, cb will be ignored if it's smaller than
     449     * length() + 1.
     450     *
     451     * @param   cwcMin  The new minimum string length that the can be stored. This
     452     *                  does not include the terminator.
     453     * @param   fForce  Force this size.
     454     *
     455     * @throws  std::bad_alloc  On allocation error.  The object is left unchanged.
     456     */
     457    void reserve(size_t cwcMin, bool fForce = false);
     458
     459    /**
     460     * A C like version of the #reserve() method, i.e. return code instead of throw.
     461     *
     462     * @returns S_OK or E_OUTOFMEMORY.
     463     * @param   cwcMin  The new minimum string length that the can be stored.  This
     464     *                  does not include the terminator.
     465    * @param   fForce  Force this size.
     466     */
     467    HRESULT reserveNoThrow(size_t cwcMin, bool fForce = false) RT_NOEXCEPT;
    399468
    400469    /**
  • trunk/src/VBox/Main/glue/string.cpp

    r80793 r80835  
    112112                if (cwcAlloc <= cwcBoth)
    113113                    cwcAlloc = RT_ALIGN_Z(cwcBoth + 1, 512);
    114                 if (pArgs->cwcAlloc)
    115                     AssertMsgReturnStmt(::SysReAllocStringLen(&pThis->m_bstr, NULL, (unsigned)cwcAlloc),
    116                                         ("cwcAlloc=%#zx\n", cwcAlloc), pArgs->hrc = E_OUTOFMEMORY, 0);
    117                 else
    118                 {
    119                     Assert(pThis->m_bstr == NULL);
    120                     pThis->m_bstr = ::SysAllocStringLen(NULL, (unsigned)cwcAlloc);
    121                     AssertMsgReturnStmt(pThis->m_bstr, ("cwcAlloc=%#zx\n", cwcAlloc), pArgs->hrc = E_OUTOFMEMORY, 0);
    122                 }
     114                pArgs->hrc = pThis->reserveNoThrow(cwcAlloc, true /*fForce*/);
     115                AssertMsgReturn(pArgs->hrc == S_OK, ("cwcAlloc=%#zx\n", cwcAlloc), 0);
    123116                pArgs->cwcAlloc = cwcAlloc;
    124117            }
     
    134127        rc = ::RTStrToUtf16Ex(pachChars, cbChars, &pwszDst, pArgs->cwcAlloc - pArgs->offDst, &cwcAppend);
    135128        AssertRCReturnStmt(rc, pArgs->hrc = E_UNEXPECTED, 0);
     129        pArgs->offDst += cwcAppend;
    136130    }
    137131    return cbChars;
     
    142136    cleanup();
    143137    BSTRNOTHROW Args = { this, 0, 0, S_OK };
    144     RTStrFormatV(printfOutputCallbackNoThrow, this, NULL, NULL, pszFormat, va);
     138    RTStrFormatV(printfOutputCallbackNoThrow, &Args, NULL, NULL, pszFormat, va);
    145139    if (Args.hrc == S_OK)
    146140    {
    147 #ifdef RT_OS_WINDOWS
    148         if (Args.offDst + 1 == Args.cwcAlloc)
     141        Args.hrc = joltNoThrow(Args.offDst);
     142        if (Args.hrc == S_OK)
    149143            return S_OK;
    150 
    151         /* Official way: Reallocate the string.   We could of course just update the size-prefix if we dare... */
    152         if (SysReAllocStringLen(&m_bstr, NULL, (unsigned)(Args.offDst + 1)))
    153             return S_OK;
    154         AssertMsgFailed(("offDst=%#zx\n", Args.offDst));
    155         Args.hrc = E_OUTOFMEMORY;
    156 #else
    157         return S_OK;
    158 #endif
    159144    }
    160145    cleanup();
     
    244229
    245230
     231#ifndef VBOX_WITH_XPCOM
     232
     233HRESULT Bstr::joltNoThrow(ssize_t cwcNew /* = -1*/)
     234{
     235    if (m_bstr)
     236    {
     237        size_t const cwcAlloc  = ::SysStringLen(m_bstr);
     238        size_t const cwcActual = cwcNew < 0 ? ::RTUtf16Len(m_bstr) : (size_t)cwcNew;
     239        Assert(cwcNew < 0 || cwcActual == ::RTUtf16Len(m_bstr));
     240        if (cwcActual != cwcAlloc)
     241        {
     242            Assert(cwcActual <= cwcAlloc);
     243            Assert((unsigned int)cwcActual == cwcActual);
     244
     245            /* Official way: Reallocate the string.   We could of course just update the size-prefix if we dared... */
     246            if (!::SysReAllocStringLen(&m_bstr, NULL, (unsigned int)cwcActual))
     247            {
     248                AssertFailed();
     249                return E_OUTOFMEMORY;
     250            }
     251        }
     252    }
     253    else
     254        Assert(cwcNew <= 0);
     255    return S_OK;
     256}
     257
     258
     259void Bstr::jolt(ssize_t cwcNew /* = -1*/)
     260{
     261    HRESULT hrc = joltNoThrow(cwcNew);
     262    if (hrc != S_OK)
     263        throw std::bad_alloc();
     264}
     265
     266#endif /* !VBOX_WITH_XPCOM */
     267
     268
     269HRESULT Bstr::reserveNoThrow(size_t cwcMin, bool fForce /*= false*/) RT_NOEXCEPT
     270{
     271    /* If not forcing the string to the cwcMin length, check cwcMin against the
     272       current string length: */
     273    if (!fForce)
     274    {
     275        size_t cwcCur = m_bstr ? ::SysStringLen(m_bstr) : 0;
     276        if (cwcCur >= cwcMin)
     277            return S_OK;
     278    }
     279
     280    /* The documentation for SysReAllocStringLen hints about it being allergic
     281       to NULL in some way or another, so we call SysAllocStringLen directly
     282       when appropriate: */
     283    if (m_bstr)
     284        AssertReturn(::SysReAllocStringLen(&m_bstr, NULL, (unsigned int)cwcMin) != FALSE, E_OUTOFMEMORY);
     285    else if (cwcMin > 0)
     286    {
     287        m_bstr = ::SysAllocStringLen(NULL, (unsigned int)cwcMin);
     288        AssertReturn(m_bstr, E_OUTOFMEMORY);
     289    }
     290
     291    return S_OK;
     292}
     293
     294
     295void Bstr::reserve(size_t cwcMin, bool fForce /*= false*/)
     296{
     297    HRESULT hrc = reserveNoThrow(cwcMin, fForce);
     298    if (hrc != S_OK)
     299        throw std::bad_alloc();
     300}
     301
     302
    246303/* static */
    247304const Utf8Str Utf8Str::Empty; /* default ctor is OK */
  • trunk/src/VBox/Main/testcase/Makefile.kmk

    r76553 r80835  
    3636        $(if $(VBOX_WITH_GUEST_CONTROL),tstGuestCtrlContextID,) \
    3737        tstMediumLock \
     38        tstBstr \
    3839        tstGuid
    3940  PROGRAMS.linux += \
     
    254255
    255256#
     257# tstBstr
     258#
     259tstBstr_TEMPLATE = VBOXMAINCLIENTTSTEXE
     260tstBstr_SOURCES  = tstBstr.cpp
     261
     262
     263#
    256264# tstGuid
    257265#
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