VirtualBox

Ignore:
Timestamp:
Aug 27, 2018 9:54:04 AM (6 years ago)
Author:
vboxsync
Message:

iprt/cpp/ministring.h: Added a much of NoThrow variants of the assign, append and replace methods, returning an IPRT status code instead of throwing stuff.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/string/ministring.cpp

    r69111 r73907  
    6666}
    6767
     68int RTCString::assignNoThrow(const RTCString &a_rSrc) RT_NOEXCEPT
     69{
     70    AssertReturn(&a_rSrc != this, VINF_SUCCESS);
     71    size_t const cchSrc = a_rSrc.length();
     72    if (cchSrc > 0)
     73    {
     74        int rc = reserveNoThrow(cchSrc + 1);
     75        if (RT_SUCCESS(rc))
     76        {
     77            memcpy(m_psz, a_rSrc.c_str(), cchSrc);
     78            m_psz[cchSrc] = '\0';
     79            m_cch = cchSrc;
     80            return VINF_SUCCESS;
     81        }
     82        return rc;
     83    }
     84    setNull();
     85    return VINF_SUCCESS;
     86
     87}
     88
    6889RTCString &RTCString::assign(const char *a_pszSrc)
    6990{
     
    82103    setNull();
    83104    return *this;
     105}
     106
     107int RTCString::assignNoThrow(const char *a_pszSrc) RT_NOEXCEPT
     108{
     109    if (a_pszSrc)
     110    {
     111        size_t cchSrc = strlen(a_pszSrc);
     112        if (cchSrc)
     113        {
     114            int rc = reserveNoThrow(cchSrc + 1);
     115            if (RT_SUCCESS(rc))
     116            {
     117                memcpy(m_psz, a_pszSrc, cchSrc);
     118                m_psz[cchSrc] = '\0';
     119                m_cch = cchSrc;
     120                return VINF_SUCCESS;
     121            }
     122            return rc;
     123        }
     124    }
     125    setNull();
     126    return VINF_SUCCESS;
    84127}
    85128
     
    102145}
    103146
     147int RTCString::assignNoThrow(const RTCString &a_rSrc, size_t a_offSrc, size_t a_cchSrc /*= npos*/) RT_NOEXCEPT
     148{
     149    AssertReturn(&a_rSrc != this, VINF_SUCCESS);
     150    if (a_offSrc < a_rSrc.length())
     151    {
     152        size_t cchMax = a_rSrc.length() - a_offSrc;
     153        if (a_cchSrc > cchMax)
     154            a_cchSrc = cchMax;
     155        int rc = reserveNoThrow(a_cchSrc + 1);
     156        if (RT_SUCCESS(rc))
     157        {
     158            memcpy(m_psz, a_rSrc.c_str() + a_offSrc, a_cchSrc);
     159            m_psz[a_cchSrc] = '\0';
     160            m_cch = a_cchSrc;
     161            return VINF_SUCCESS;
     162        }
     163        return rc;
     164    }
     165    setNull();
     166    return VINF_SUCCESS;
     167}
     168
    104169RTCString &RTCString::assign(const char *a_pszSrc, size_t a_cchSrc)
    105170{
     
    117182}
    118183
     184int RTCString::assignNoThrow(const char *a_pszSrc, size_t a_cchSrc) RT_NOEXCEPT
     185{
     186    if (a_cchSrc)
     187    {
     188        a_cchSrc = RTStrNLen(a_pszSrc, a_cchSrc);
     189        int rc = reserveNoThrow(a_cchSrc + 1);
     190        if (RT_SUCCESS(rc))
     191        {
     192            memcpy(m_psz, a_pszSrc, a_cchSrc);
     193            m_psz[a_cchSrc] = '\0';
     194            m_cch = a_cchSrc;
     195            return VINF_SUCCESS;
     196        }
     197        return rc;
     198    }
     199    setNull();
     200    return VINF_SUCCESS;
     201}
     202
    119203RTCString &RTCString::assign(size_t a_cTimes, char a_ch)
    120204{
     
    122206    memset(m_psz, a_ch, a_cTimes);
    123207    return *this;
     208}
     209
     210
     211int RTCString::assignNoThrow(size_t a_cTimes, char a_ch) RT_NOEXCEPT
     212{
     213    int rc = reserveNoThrow(a_cTimes + 1);
     214    if (RT_SUCCESS(rc))
     215    {
     216        memset(m_psz, a_ch, a_cTimes);
     217        return VINF_SUCCESS;
     218    }
     219    return rc;
    124220}
    125221
     
    132228    va_end(va);
    133229    return *this;
     230}
     231
     232int RTCString::printfNoThrow(const char *pszFormat, ...) RT_NOEXCEPT
     233{
     234    va_list va;
     235    va_start(va, pszFormat);
     236    int rc = printfVNoThrow(pszFormat, va);
     237    va_end(va);
     238    return rc;
    134239}
    135240
     
    149254    if (cbChars)
    150255    {
    151         size_t cchBoth = pThis->m_cch + cbChars;
     256        size_t const cchBoth = pThis->m_cch + cbChars;
    152257        if (cchBoth >= pThis->m_cbAllocated)
    153258        {
     
    178283}
    179284
     285struct RTCSTRINGOTHROW
     286{
     287    RTCString  *pThis;
     288    int         rc;
     289};
     290
     291/**
     292 * Callback used with RTStrFormatV by RTCString::printfVNoThrow.
     293 *
     294 * @returns The number of bytes added (not used).
     295 *
     296 * @param   pvArg           Pointer to a RTCSTRINGOTHROW structure.
     297 * @param   pachChars       The characters to append.
     298 * @param   cbChars         The number of characters.  0 on the final callback.
     299 */
     300/*static*/ DECLCALLBACK(size_t)
     301RTCString::printfOutputCallbackNoThrow(void *pvArg, const char *pachChars, size_t cbChars) RT_NOEXCEPT
     302{
     303    RTCString *pThis = ((RTCSTRINGOTHROW *)pvArg)->pThis;
     304    if (cbChars)
     305    {
     306        size_t const cchBoth = pThis->m_cch + cbChars;
     307        if (cchBoth >= pThis->m_cbAllocated)
     308        {
     309            /* Double the buffer size, if it's less that _4M. Align sizes like
     310               for append. */
     311            size_t cbAlloc = RT_ALIGN_Z(pThis->m_cbAllocated, IPRT_MINISTRING_APPEND_ALIGNMENT);
     312            cbAlloc += RT_MIN(cbAlloc, _4M);
     313            if (cbAlloc <= cchBoth)
     314                cbAlloc = RT_ALIGN_Z(cchBoth + 1, IPRT_MINISTRING_APPEND_ALIGNMENT);
     315            int rc = pThis->reserveNoThrow(cbAlloc);
     316            if (RT_SUCCESS(rc))
     317            { /* likely */ }
     318            else
     319            {
     320                ((RTCSTRINGOTHROW *)pvArg)->rc = rc;
     321                return cbChars;
     322            }
     323        }
     324
     325        memcpy(&pThis->m_psz[pThis->m_cch], pachChars, cbChars);
     326        pThis->m_cch = cchBoth;
     327        pThis->m_psz[cchBoth] = '\0';
     328    }
     329    return cbChars;
     330}
     331
     332int RTCString::printfVNoThrow(const char *pszFormat, va_list va) RT_NOEXCEPT
     333{
     334    cleanup();
     335    RTCSTRINGOTHROW Args = { this, VINF_SUCCESS };
     336    RTStrFormatV(printfOutputCallback, &Args, NULL, NULL, pszFormat, va);
     337    return Args.rc;
     338}
     339
    180340RTCString &RTCString::append(const RTCString &that)
    181341{
     
    184344}
    185345
     346int RTCString::appendNoThrow(const RTCString &that) RT_NOEXCEPT
     347{
     348    Assert(&that != this);
     349    return appendWorkerNoThrow(that.c_str(), that.length());
     350}
     351
    186352RTCString &RTCString::append(const char *pszThat)
    187353{
    188354    return appendWorker(pszThat, strlen(pszThat));
     355}
     356
     357int RTCString::appendNoThrow(const char *pszThat) RT_NOEXCEPT
     358{
     359    return appendWorkerNoThrow(pszThat, strlen(pszThat));
    189360}
    190361
     
    199370}
    200371
     372int RTCString::appendNoThrow(const RTCString &rThat, size_t offStart, size_t cchMax /*= RTSTR_MAX*/) RT_NOEXCEPT
     373{
     374    if (offStart < rThat.length())
     375    {
     376        size_t cchLeft = rThat.length() - offStart;
     377        return appendWorkerNoThrow(rThat.c_str() + offStart, RT_MIN(cchLeft, cchMax));
     378    }
     379    return VINF_SUCCESS;
     380}
     381
    201382RTCString &RTCString::append(const char *pszThat, size_t cchMax)
    202383{
    203384    return appendWorker(pszThat, RTStrNLen(pszThat, cchMax));
     385}
     386
     387int RTCString::appendNoThrow(const char *pszThat, size_t cchMax) RT_NOEXCEPT
     388{
     389    return appendWorkerNoThrow(pszThat, RTStrNLen(pszThat, cchMax));
    204390}
    205391
     
    227413}
    228414
     415int RTCString::appendWorkerNoThrow(const char *pszSrc, size_t cchSrc) RT_NOEXCEPT
     416{
     417    if (cchSrc)
     418    {
     419        size_t cchThis = length();
     420        size_t cchBoth = cchThis + cchSrc;
     421
     422        if (cchBoth >= m_cbAllocated)
     423        {
     424            int rc = reserveNoThrow(RT_ALIGN_Z(cchBoth + 1, IPRT_MINISTRING_APPEND_ALIGNMENT));
     425            if (RT_SUCCESS(rc))
     426            { /* likely */ }
     427            else
     428                return rc;
     429        }
     430
     431        memcpy(&m_psz[cchThis], pszSrc, cchSrc);
     432        m_psz[cchBoth] = '\0';
     433        m_cch = cchBoth;
     434    }
     435    return VINF_SUCCESS;
     436}
     437
    229438RTCString &RTCString::append(char ch)
    230439{
     
    248457}
    249458
     459int RTCString::appendNoThrow(char ch) RT_NOEXCEPT
     460{
     461    Assert((unsigned char)ch < 0x80);                  /* Don't create invalid UTF-8. */
     462    if (ch)
     463    {
     464        // allocate in chunks of 20 in case this gets called several times
     465        if (m_cch + 1 >= m_cbAllocated)
     466        {
     467            int rc = reserveNoThrow(RT_ALIGN_Z(m_cch + 2, IPRT_MINISTRING_APPEND_ALIGNMENT));
     468            if (RT_SUCCESS(rc))
     469            { /* likely */ }
     470            else
     471                return rc;
     472        }
     473
     474        m_psz[m_cch] = ch;
     475        m_psz[++m_cch] = '\0';
     476    }
     477    return VINF_SUCCESS;
     478}
     479
    250480RTCString &RTCString::appendCodePoint(RTUNICP uc)
    251481{
     
    278508}
    279509
     510int RTCString::appendCodePointNoThrow(RTUNICP uc) RT_NOEXCEPT
     511{
     512    /*
     513     * Single byte encoding.
     514     */
     515    if (uc < 0x80)
     516        return RTCString::appendNoThrow((char)uc);
     517
     518    /*
     519     * Multibyte encoding.
     520     * Assume max encoding length when resizing the string, that's simpler.
     521     */
     522    AssertReturn(uc <= UINT32_C(0x7fffffff), VERR_INVALID_UTF8_ENCODING);
     523
     524    if (m_cch + 6 >= m_cbAllocated)
     525    {
     526        int rc = reserveNoThrow(RT_ALIGN_Z(m_cch + 6 + 1, IPRT_MINISTRING_APPEND_ALIGNMENT));
     527        if (RT_SUCCESS(rc))
     528        { /* likely */ }
     529        else
     530            return rc;
     531    }
     532
     533    char *pszNext = RTStrPutCp(&m_psz[m_cch], uc);
     534    m_cch = pszNext - m_psz;
     535    *pszNext = '\0';
     536
     537    return VINF_SUCCESS;
     538}
     539
     540
    280541RTCString &RTCString::erase(size_t offStart /*= 0*/, size_t cchLength /*= npos*/)
    281542{
     
    306567}
    307568
     569int RTCString::replaceNoThrow(size_t offStart, size_t cchLength, const RTCString &rStrReplacement) RT_NOEXCEPT
     570{
     571    return replaceWorkerNoThrow(offStart, cchLength, rStrReplacement.c_str(), rStrReplacement.length());
     572}
     573
    308574RTCString &RTCString::replace(size_t offStart, size_t cchLength, const RTCString &rStrReplacement,
    309575                              size_t offReplacement, size_t cchReplacement)
     
    325591}
    326592
     593int RTCString::replaceNoThrow(size_t offStart, size_t cchLength, const RTCString &rStrReplacement,
     594                              size_t offReplacement, size_t cchReplacement)
     595{
     596    Assert(this != &rStrReplacement);
     597    if (cchReplacement > 0)
     598    {
     599        if (offReplacement < rStrReplacement.length())
     600        {
     601            size_t cchMaxReplacement = rStrReplacement.length() - offReplacement;
     602            return replaceWorkerNoThrow(offStart, cchLength, rStrReplacement.c_str() + offReplacement,
     603                                        RT_MIN(cchReplacement, cchMaxReplacement));
     604        }
     605        return VERR_OUT_OF_RANGE;
     606    }
     607    return replaceWorkerNoThrow(offStart, cchLength, "", 0);
     608}
     609
    327610RTCString &RTCString::replace(size_t offStart, size_t cchLength, const char *pszReplacement)
    328611{
     
    330613}
    331614
     615int RTCString::replaceNoThrow(size_t offStart, size_t cchLength, const char *pszReplacement) RT_NOEXCEPT
     616{
     617    return replaceWorkerNoThrow(offStart, cchLength, pszReplacement, strlen(pszReplacement));
     618}
     619
    332620RTCString &RTCString::replace(size_t offStart, size_t cchLength, const char *pszReplacement, size_t cchReplacement)
    333621{
    334622    return replaceWorker(offStart, cchLength, pszReplacement, RTStrNLen(pszReplacement, cchReplacement));
     623}
     624
     625int RTCString::replaceNoThrow(size_t offStart, size_t cchLength, const char *pszReplacement, size_t cchReplacement) RT_NOEXCEPT
     626{
     627    return replaceWorkerNoThrow(offStart, cchLength, pszReplacement, RTStrNLen(pszReplacement, cchReplacement));
    335628}
    336629
     
    375668
    376669    return *this;
     670}
     671
     672int RTCString::replaceWorkerNoThrow(size_t offStart, size_t cchLength, const char *pszSrc, size_t cchSrc) RT_NOEXCEPT
     673{
     674    /*
     675     * Our non-standard handling of out_of_range situations.
     676     */
     677    size_t const cchOldLength = length();
     678    AssertMsgReturn(offStart < cchOldLength, ("offStart=%zu (cchLength=%zu); length()=%zu\n", offStart, cchLength, cchOldLength),
     679                    VERR_OUT_OF_RANGE);
     680
     681    /*
     682     * Correct the length parameter.
     683     */
     684    size_t cchMaxLength = cchOldLength - offStart;
     685    if (cchMaxLength < cchLength)
     686        cchLength = cchMaxLength;
     687
     688    /*
     689     * Adjust string allocation if necessary.
     690     */
     691    size_t cchNew = cchOldLength - cchLength + cchSrc;
     692    if (cchNew >= m_cbAllocated)
     693    {
     694        int rc = reserveNoThrow(RT_ALIGN_Z(cchNew + 1, IPRT_MINISTRING_APPEND_ALIGNMENT));
     695        if (RT_SUCCESS(rc))
     696        { /* likely */ }
     697        else
     698            return rc;
     699    }
     700
     701    /*
     702     * Make the change.
     703     */
     704    size_t cchAfter = cchOldLength - offStart - cchLength;
     705    if (cchAfter > 0)
     706        memmove(&m_psz[offStart + cchSrc], &m_psz[offStart + cchLength], cchAfter);
     707    memcpy(&m_psz[offStart], pszSrc, cchSrc);
     708    m_psz[cchNew] = '\0';
     709    m_cch = cchNew;
     710
     711    return VINF_SUCCESS;
    377712}
    378713
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