VirtualBox

Changeset 26481 in vbox for trunk


Ignore:
Timestamp:
Feb 14, 2010 1:00:49 AM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
57648
Message:

IPRT: Added RTStrAAppend, RTStrAAppendN, RTStrAAppendExN[V]{,1}, RTStrAlloc, RTStrAllocEx and RTStrRealloc. Fixed bug in RTStrDupN.

Location:
trunk
Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/string.h

    r25014 r26481  
    181181
    182182/**
     183 * Appends a string onto an existing IPRT allocated string.
     184 *
     185 * @retval  VINF_SUCCESS
     186 * @retval  VERR_NO_STR_MEMORY if we failed to reallocate the string, @a *ppsz
     187 *          remains unchanged.
     188 *
     189 * @param   ppsz                Pointer to the string pointer.  The string
     190 *                              pointer must either be NULL or point to a string
     191 *                              returned by an IPRT string API.  (In/Out)
     192 * @param   pszAppend           The string to append.  NULL and empty strings
     193 *                              are quietly ignored.
     194 */
     195RTDECL(int) RTStrAAppend(char **ppsz, const char *pszAppend);
     196
     197/**
     198 * Appends N bytes from a strings onto an existing IPRT allocated string.
     199 *
     200 * @retval  VINF_SUCCESS
     201 * @retval  VERR_NO_STR_MEMORY if we failed to reallocate the string, @a *ppsz
     202 *          remains unchanged.
     203 *
     204 * @param   ppsz                Pointer to the string pointer.  The string
     205 *                              pointer must either be NULL or point to a string
     206 *                              returned by an IPRT string API.  (In/Out)
     207 * @param   pszAppend           The string to append.  Can be NULL if cchAppend
     208 *                              is NULL.
     209 * @param   cchAppend           The number of chars (not code points) to append
     210 *                              from pszAppend.   Must not be more than
     211 *                              @a pszAppend contains, except for the special
     212 *                              value RTSTR_MAX that can be used to indicate all
     213 *                              of @a pszAppend without having to strlen it.
     214 */
     215RTDECL(int) RTStrAAppendN(char **ppsz, const char *pszAppend, size_t cchAppend);
     216
     217/**
     218 * Appends one or more strings onto an existing IPRT allocated string.
     219 *
     220 * This is a very flexible and efficient alternative to using RTStrAPrintf to
     221 * combine several strings together.
     222 *
     223 * @retval  VINF_SUCCESS
     224 * @retval  VERR_NO_STR_MEMORY if we failed to reallocate the string, @a *ppsz
     225 *          remains unchanged.
     226 *
     227 * @param   ppsz                Pointer to the string pointer.  The string
     228 *                              pointer must either be NULL or point to a string
     229 *                              returned by an IPRT string API.  (In/Out)
     230 * @param   cPairs              The number of string / length pairs in the
     231 *                              @a va.
     232 * @param   va                  List of string (const char *) and length
     233 *                              (size_t) pairs.  The strings will be appended to
     234 *                              the string in the first argument.
     235 */
     236RTDECL(int) RTStrAAppendExNV(char **ppsz, size_t cPairs, va_list va);
     237
     238/**
     239 * Appends one or more strings onto an existing IPRT allocated string.
     240 *
     241 * This is a very flexible and efficient alternative to using RTStrAPrintf to
     242 * combine several strings together.
     243 *
     244 * @retval  VINF_SUCCESS
     245 * @retval  VERR_NO_STR_MEMORY if we failed to reallocate the string, @a *ppsz
     246 *          remains unchanged.
     247 *
     248 * @param   ppsz                Pointer to the string pointer.  The string
     249 *                              pointer must either be NULL or point to a string
     250 *                              returned by an IPRT string API.  (In/Out)
     251 * @param   cPairs              The number of string / length pairs in the
     252 *                              ellipsis.
     253 * @param   ...                 List of string (const char *) and length
     254 *                              (size_t) pairs.  The strings will be appended to
     255 *                              the string in the first argument.
     256 */
     257RTDECL(int) RTStrAAppendExN(char **ppsz, size_t cPairs, ...);
     258
     259/**
     260 * Allocates memory for string storage.
     261 *
     262 * You should normally not use this function, except if there is some very
     263 * custom string handling you need doing that isn't covered by any of the other
     264 * APIs.
     265 *
     266 * @returns Pointer to the allocated string.  The first byte is always set
     267 *          to the string terminator char, the contents of the remainder of the
     268 *          memory is undefined.  The string must be freed by calling RTStrFree.
     269 *
     270 *          NULL is returned if the allocation failed.  Please translate this to
     271 *          VERR_NO_STR_MEMORY and not VERR_NO_MEMORY.  Also consider
     272 *          RTStrAllocEx if an IPRT status code is required.
     273 *
     274 * @param   cb                  How many bytes to allocate.  If this is zero, we
     275 *                              will allocate a terminator byte anyway.
     276 */
     277RTDECL(char *) RTStrAlloc(size_t cb);
     278
     279/**
     280 * Allocates memory for string storage, with status code.
     281 *
     282 * You should normally not use this function, except if there is some very
     283 * custom string handling you need doing that isn't covered by any of the other
     284 * APIs.
     285 *
     286 * @retval  VINF_SUCCESS
     287 * @retval  VERR_NO_STR_MEMORY
     288 *
     289 * @param   ppsz                Where to return the allocated string.  This will
     290 *                              be set to NULL on failure.  On success, the
     291 *                              returned memory will always start with a
     292 *                              terminator char so that it is considered a valid
     293 *                              C string, the contents of rest of the memory is
     294 *                              undefined.
     295 * @param   cb                  How many bytes to allocate.  If this is zero, we
     296 *                              will allocate a terminator byte anyway.
     297 */
     298RTDECL(int) RTStrAllocEx(char **ppsz, size_t cb);
     299
     300/**
     301 * Reallocates the specifed string.
     302 *
     303 * You should normally not have use this function, except perhaps to truncate a
     304 * really long string you've got from some IPRT string API.
     305 *
     306 * @returns VINF_SUCCESS.
     307 * @retval  VERR_NO_STR_MEMORY if we failed to reallocate the string, @a *ppsz
     308 *          remains unchanged.
     309 *
     310 * @param   ppsz                Pointer to the string variable containing the
     311 *                              input and output string.
     312 *
     313 *                              When not freeing the string, the result will
     314 *                              always have the last byte set to the terminator
     315 *                              character so that when used for string
     316 *                              truncation the result will be a valid C string
     317 *                              (your job to keep it a valid UTF-8 string).
     318 *
     319 *                              When the input string is NULL and we're supposed
     320 *                              to reallocate, the returned string will also
     321 *                              have the first byte set to the terminator char
     322 *                              so it will be a valid C string.
     323 *
     324 * @param   cbNew               When @a cbNew is zero, we'll behave like
     325 *                              RTStrFree and @a *ppsz will be set to NULL.
     326 *
     327 *                              When not zero, this will be the new size of the
     328 *                              memory backing the string, i.e. it includes the
     329 *                              terminator char.
     330 */
     331RTDECL(int) RTStrRealloc(char **ppsz, size_t cbNew);
     332
     333/**
    183334 * Validates the UTF-8 encoding of the string.
    184335 *
  • trunk/src/VBox/Runtime/common/string/stringalloc.cpp

    r26480 r26481  
    3636#include "internal/iprt.h"
    3737
    38 #include <iprt/alloc.h>
     38#include <iprt/alloca.h>
    3939#include <iprt/assert.h>
     40#include <iprt/mem.h>
    4041#include <iprt/err.h>
    4142#include "internal/string.h"
    4243
    4344
    44 /**
    45  * Free string allocated by any of the non-UCS-2 string functions.
    46  *
    47  * @returns iprt status code.
    48  * @param   pszString      Pointer to buffer with string to free.
    49  *                         NULL is accepted.
    50  */
     45
     46RTDECL(char *) RTStrAlloc(size_t cb)
     47{
     48    char *psz = (char *)RTMemAlloc(RT_MAX(cb, 1));
     49    if (psz)
     50        *psz = '\0';
     51    return psz;
     52}
     53RT_EXPORT_SYMBOL(RTStrAlloc);
     54
     55
     56RTDECL(int) RTStrAllocEx(char **ppsz, size_t cb)
     57{
     58    char *psz = *ppsz = (char *)RTMemAlloc(RT_MAX(cb, 1));
     59    if (psz)
     60    {
     61        *psz = '\0';
     62        return VINF_SUCCESS;
     63    }
     64    return VERR_NO_STR_MEMORY;
     65}
     66RT_EXPORT_SYMBOL(RTStrAlloc);
     67
     68
     69RTDECL(int) RTStrRealloc(char **ppsz, size_t cbNew)
     70{
     71    char *pszOld = *ppsz;
     72    if (!cbNew)
     73    {
     74        RTMemFree(pszOld);
     75        *ppsz = NULL;
     76    }
     77    else if (pszOld)
     78    {
     79        char *pszNew = (char *)RTMemRealloc(pszOld, cbNew);
     80        if (!pszNew)
     81            return VERR_NO_STR_MEMORY;
     82        pszNew[cbNew - 1] = '\0';
     83        *ppsz = pszNew;
     84    }
     85    else
     86    {
     87        char *pszNew = (char *)RTMemAlloc(cbNew);
     88        if (!pszNew)
     89            return VERR_NO_STR_MEMORY;
     90        pszNew[0] = '\0';
     91        pszNew[cbNew - 1] = '\0';
     92        *ppsz = pszNew;
     93    }
     94    return VINF_SUCCESS;
     95}
     96
    5197RTDECL(void)  RTStrFree(char *pszString)
    5298{
     
    57103
    58104
    59 /**
    60  * Allocates a new copy of the given UTF-8 string.
    61  *
    62  * @returns Pointer to the allocated UTF-8 string.
    63  * @param   pszString       UTF-8 string to duplicate.
    64  */
    65105RTDECL(char *) RTStrDup(const char *pszString)
    66106{
     
    75115
    76116
    77 /**
    78  * Allocates a new copy of the given UTF-8 string.
    79  *
    80  * @returns iprt status code.
    81  * @param   ppszString      Receives pointer of the allocated UTF-8 string.
    82  *                          The returned pointer must be freed using RTStrFree().
    83  * @param   pszString       UTF-8 string to duplicate.
    84  */
    85117RTDECL(int)  RTStrDupEx(char **ppszString, const char *pszString)
    86118{
     
    101133
    102134
    103 /**
    104  * Allocates a new copy of the given UTF-8 substring.
    105  *
    106  * @returns Pointer to the allocated UTF-8 substring.
    107  * @param   pszString       UTF-8 string to duplicate.
    108  * @param   cchMax          The max number of chars to duplicate, not counting
    109  *                          the terminator.
    110  */
    111135RTDECL(char *) RTStrDupN(const char *pszString, size_t cchMax)
    112136{
     
    114138    char  *pszEnd = (char *)memchr(pszString, '\0', cchMax);
    115139    size_t cch    = pszEnd ? (uintptr_t)pszEnd - (uintptr_t)pszString : cchMax;
    116     char  *pszDst = (char *)RTMemAlloc(cch);
     140    char  *pszDst = (char *)RTMemAlloc(cch + 1);
    117141    if (pszDst)
    118142    {
     
    124148RT_EXPORT_SYMBOL(RTStrDupN);
    125149
     150
     151RTDECL(int) RTStrAAppend(char **ppsz, const char *pszAppend)
     152{
     153    if (!pszAppend)
     154        return VINF_SUCCESS;
     155    return RTStrAAppendN(ppsz, pszAppend, RTSTR_MAX);
     156}
     157
     158
     159RTDECL(int) RTStrAAppendN(char **ppsz, const char *pszAppend, size_t cchAppend)
     160{
     161    if (!cchAppend)
     162        return VINF_SUCCESS;
     163    if (cchAppend == RTSTR_MAX)
     164        cchAppend = strlen(pszAppend);
     165    else
     166        Assert(cchAppend == RTStrNLen(pszAppend, cchAppend));
     167
     168    size_t const cchOrg = *ppsz ? strlen(*ppsz) : 0;
     169    char *pszNew = (char *)RTMemRealloc(*ppsz, cchOrg + cchAppend + 1);
     170    if (!pszNew)
     171        return VERR_NO_STR_MEMORY;
     172
     173    memcpy(&pszNew[cchOrg], pszAppend, cchAppend);
     174    pszNew[cchOrg + cchAppend] = '\0';
     175
     176    *ppsz = pszNew;
     177    return VINF_SUCCESS;
     178}
     179
     180
     181RTDECL(int) RTStrAAppendExNV(char **ppsz, size_t cPairs, va_list va)
     182{
     183    AssertPtr(ppsz);
     184    if (!cPairs)
     185        return VINF_SUCCESS;
     186
     187    /*
     188     * Determin the length of each string and calc the new total.
     189     */
     190    struct RTStrAAppendExNVStruct
     191    {
     192        const char *psz;
     193        size_t      cch;
     194    } *paPairs = (struct RTStrAAppendExNVStruct *)alloca(cPairs * sizeof(*paPairs));
     195    AssertReturn(paPairs, VERR_NO_STR_MEMORY);
     196
     197    size_t  cchOrg      = *ppsz ? strlen(*ppsz) : 0;
     198    size_t  cchNewTotal = cchOrg;
     199    for (size_t i = 0; i < cPairs; i++)
     200    {
     201        const char *psz = va_arg(va, const char *);
     202        size_t      cch = va_arg(va, size_t);
     203        AssertPtrNull(psz);
     204        Assert(cch == RTSTR_MAX || cch == RTStrNLen(psz, cch));
     205
     206        if (cch == RTSTR_MAX)
     207            cch = psz ? strlen(psz) : 0;
     208        cchNewTotal += cch;
     209
     210        paPairs[i].cch = cch;
     211        paPairs[i].psz = psz;
     212    }
     213    cchNewTotal++;                      /* '\0' */
     214
     215    /*
     216     * Try reallocate the string.
     217     */
     218    char *pszNew = (char *)RTMemRealloc(*ppsz, cchNewTotal);
     219    if (!pszNew)
     220        return VERR_NO_STR_MEMORY;
     221
     222    /*
     223     * Do the appending.
     224     */
     225    size_t off = cchOrg;
     226    for (size_t i = 0; i < cPairs; i++)
     227    {
     228        memcpy(&pszNew[off], paPairs[i].psz, paPairs[i].cch);
     229        off += paPairs[i].cch;
     230    }
     231    Assert(off + 1 == cchNewTotal);
     232    pszNew[off] = '\0';
     233
     234    /* done */
     235    *ppsz = pszNew;
     236    return VINF_SUCCESS;
     237}
     238RT_EXPORT_SYMBOL(RTStrAAppendExNV);
     239
     240
     241RTDECL(int) RTStrAAppendExN(char **ppsz, size_t cPairs, ...)
     242{
     243    va_list va;
     244    va_start(va, cPairs);
     245    int rc = RTStrAAppendExNV(ppsz, cPairs, va);
     246    va_end(va);
     247    return rc;
     248}
     249RT_EXPORT_SYMBOL(RTStrAAppendExN);
     250
  • trunk/src/VBox/Runtime/testcase/Makefile.kmk

    r26476 r26481  
    9898        tstSems \
    9999        tstRTSemXRoads \
     100        tstRTStrAlloc \
    100101        tstRTStrCache \
    101102        tstRTStrFormat \
     
    393394tstRTSemXRoads_SOURCES = tstRTSemXRoads.cpp
    394395
     396tstRTStrAlloc_TEMPLATE = VBOXR3TSTEXE
     397tstRTStrAlloc_SOURCES = tstRTStrAlloc.cpp
     398
    395399tstRTStrCache_TEMPLATE = VBOXR3TSTEXE
    396400tstRTStrCache_SOURCES = tstRTStrCache.cpp
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