gfx/skia/trunk/src/core/SkString.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/skia/trunk/src/core/SkString.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,650 @@
     1.4 +
     1.5 +/*
     1.6 + * Copyright 2006 The Android Open Source Project
     1.7 + *
     1.8 + * Use of this source code is governed by a BSD-style license that can be
     1.9 + * found in the LICENSE file.
    1.10 + */
    1.11 +
    1.12 +
    1.13 +#include "SkString.h"
    1.14 +#include "SkFixed.h"
    1.15 +#include "SkThread.h"
    1.16 +#include "SkUtils.h"
    1.17 +#include <stdarg.h>
    1.18 +#include <stdio.h>
    1.19 +
    1.20 +// number of bytes (on the stack) to receive the printf result
    1.21 +static const size_t kBufferSize = 1024;
    1.22 +
    1.23 +#ifdef SK_BUILD_FOR_WIN
    1.24 +    #define VSNPRINTF(buffer, size, format, args) \
    1.25 +        _vsnprintf_s(buffer, size, _TRUNCATE, format, args)
    1.26 +    #define SNPRINTF    _snprintf
    1.27 +#else
    1.28 +    #define VSNPRINTF   vsnprintf
    1.29 +    #define SNPRINTF    snprintf
    1.30 +#endif
    1.31 +
    1.32 +#define ARGS_TO_BUFFER(format, buffer, size)        \
    1.33 +    do {                                            \
    1.34 +        va_list args;                               \
    1.35 +        va_start(args, format);                     \
    1.36 +        VSNPRINTF(buffer, size, format, args);      \
    1.37 +        va_end(args);                               \
    1.38 +    } while (0)
    1.39 +
    1.40 +///////////////////////////////////////////////////////////////////////////////
    1.41 +
    1.42 +bool SkStrEndsWith(const char string[], const char suffixStr[]) {
    1.43 +    SkASSERT(string);
    1.44 +    SkASSERT(suffixStr);
    1.45 +    size_t  strLen = strlen(string);
    1.46 +    size_t  suffixLen = strlen(suffixStr);
    1.47 +    return  strLen >= suffixLen &&
    1.48 +            !strncmp(string + strLen - suffixLen, suffixStr, suffixLen);
    1.49 +}
    1.50 +
    1.51 +bool SkStrEndsWith(const char string[], const char suffixChar) {
    1.52 +    SkASSERT(string);
    1.53 +    size_t  strLen = strlen(string);
    1.54 +    if (0 == strLen) {
    1.55 +        return false;
    1.56 +    } else {
    1.57 +        return (suffixChar == string[strLen-1]);
    1.58 +    }
    1.59 +}
    1.60 +
    1.61 +int SkStrStartsWithOneOf(const char string[], const char prefixes[]) {
    1.62 +    int index = 0;
    1.63 +    do {
    1.64 +        const char* limit = strchr(prefixes, '\0');
    1.65 +        if (!strncmp(string, prefixes, limit - prefixes)) {
    1.66 +            return index;
    1.67 +        }
    1.68 +        prefixes = limit + 1;
    1.69 +        index++;
    1.70 +    } while (prefixes[0]);
    1.71 +    return -1;
    1.72 +}
    1.73 +
    1.74 +char* SkStrAppendU32(char string[], uint32_t dec) {
    1.75 +    SkDEBUGCODE(char* start = string;)
    1.76 +
    1.77 +    char    buffer[SkStrAppendU32_MaxSize];
    1.78 +    char*   p = buffer + sizeof(buffer);
    1.79 +
    1.80 +    do {
    1.81 +        *--p = SkToU8('0' + dec % 10);
    1.82 +        dec /= 10;
    1.83 +    } while (dec != 0);
    1.84 +
    1.85 +    SkASSERT(p >= buffer);
    1.86 +    char* stop = buffer + sizeof(buffer);
    1.87 +    while (p < stop) {
    1.88 +        *string++ = *p++;
    1.89 +    }
    1.90 +    SkASSERT(string - start <= SkStrAppendU32_MaxSize);
    1.91 +    return string;
    1.92 +}
    1.93 +
    1.94 +char* SkStrAppendS32(char string[], int32_t dec) {
    1.95 +    if (dec < 0) {
    1.96 +        *string++ = '-';
    1.97 +        dec = -dec;
    1.98 +    }
    1.99 +    return SkStrAppendU32(string, static_cast<uint32_t>(dec));
   1.100 +}
   1.101 +
   1.102 +char* SkStrAppendU64(char string[], uint64_t dec, int minDigits) {
   1.103 +    SkDEBUGCODE(char* start = string;)
   1.104 +
   1.105 +    char    buffer[SkStrAppendU64_MaxSize];
   1.106 +    char*   p = buffer + sizeof(buffer);
   1.107 +
   1.108 +    do {
   1.109 +        *--p = SkToU8('0' + (int32_t) (dec % 10));
   1.110 +        dec /= 10;
   1.111 +        minDigits--;
   1.112 +    } while (dec != 0);
   1.113 +
   1.114 +    while (minDigits > 0) {
   1.115 +        *--p = '0';
   1.116 +        minDigits--;
   1.117 +    }
   1.118 +
   1.119 +    SkASSERT(p >= buffer);
   1.120 +    size_t cp_len = buffer + sizeof(buffer) - p;
   1.121 +    memcpy(string, p, cp_len);
   1.122 +    string += cp_len;
   1.123 +
   1.124 +    SkASSERT(string - start <= SkStrAppendU64_MaxSize);
   1.125 +    return string;
   1.126 +}
   1.127 +
   1.128 +char* SkStrAppendS64(char string[], int64_t dec, int minDigits) {
   1.129 +    if (dec < 0) {
   1.130 +        *string++ = '-';
   1.131 +        dec = -dec;
   1.132 +    }
   1.133 +    return SkStrAppendU64(string, static_cast<uint64_t>(dec), minDigits);
   1.134 +}
   1.135 +
   1.136 +char* SkStrAppendFloat(char string[], float value) {
   1.137 +    // since floats have at most 8 significant digits, we limit our %g to that.
   1.138 +    static const char gFormat[] = "%.8g";
   1.139 +    // make it 1 larger for the terminating 0
   1.140 +    char buffer[SkStrAppendScalar_MaxSize + 1];
   1.141 +    int len = SNPRINTF(buffer, sizeof(buffer), gFormat, value);
   1.142 +    memcpy(string, buffer, len);
   1.143 +    SkASSERT(len <= SkStrAppendScalar_MaxSize);
   1.144 +    return string + len;
   1.145 +}
   1.146 +
   1.147 +char* SkStrAppendFixed(char string[], SkFixed x) {
   1.148 +    SkDEBUGCODE(char* start = string;)
   1.149 +    if (x < 0) {
   1.150 +        *string++ = '-';
   1.151 +        x = -x;
   1.152 +    }
   1.153 +
   1.154 +    unsigned frac = x & 0xFFFF;
   1.155 +    x >>= 16;
   1.156 +    if (frac == 0xFFFF) {
   1.157 +        // need to do this to "round up", since 65535/65536 is closer to 1 than to .9999
   1.158 +        x += 1;
   1.159 +        frac = 0;
   1.160 +    }
   1.161 +    string = SkStrAppendS32(string, x);
   1.162 +
   1.163 +    // now handle the fractional part (if any)
   1.164 +    if (frac) {
   1.165 +        static const uint16_t   gTens[] = { 1000, 100, 10, 1 };
   1.166 +        const uint16_t*         tens = gTens;
   1.167 +
   1.168 +        x = SkFixedRoundToInt(frac * 10000);
   1.169 +        SkASSERT(x <= 10000);
   1.170 +        if (x == 10000) {
   1.171 +            x -= 1;
   1.172 +        }
   1.173 +        *string++ = '.';
   1.174 +        do {
   1.175 +            unsigned powerOfTen = *tens++;
   1.176 +            *string++ = SkToU8('0' + x / powerOfTen);
   1.177 +            x %= powerOfTen;
   1.178 +        } while (x != 0);
   1.179 +    }
   1.180 +
   1.181 +    SkASSERT(string - start <= SkStrAppendScalar_MaxSize);
   1.182 +    return string;
   1.183 +}
   1.184 +
   1.185 +///////////////////////////////////////////////////////////////////////////////
   1.186 +
   1.187 +// the 3 values are [length] [refcnt] [terminating zero data]
   1.188 +const SkString::Rec SkString::gEmptyRec = { 0, 0, 0 };
   1.189 +
   1.190 +#define SizeOfRec()     (gEmptyRec.data() - (const char*)&gEmptyRec)
   1.191 +
   1.192 +static uint32_t trim_size_t_to_u32(size_t value) {
   1.193 +    if (sizeof(size_t) > sizeof(uint32_t)) {
   1.194 +        if (value > SK_MaxU32) {
   1.195 +            value = SK_MaxU32;
   1.196 +        }
   1.197 +    }
   1.198 +    return (uint32_t)value;
   1.199 +}
   1.200 +
   1.201 +static size_t check_add32(size_t base, size_t extra) {
   1.202 +    SkASSERT(base <= SK_MaxU32);
   1.203 +    if (sizeof(size_t) > sizeof(uint32_t)) {
   1.204 +        if (base + extra > SK_MaxU32) {
   1.205 +            extra = SK_MaxU32 - base;
   1.206 +        }
   1.207 +    }
   1.208 +    return extra;
   1.209 +}
   1.210 +
   1.211 +SkString::Rec* SkString::AllocRec(const char text[], size_t len) {
   1.212 +    Rec* rec;
   1.213 +
   1.214 +    if (0 == len) {
   1.215 +        rec = const_cast<Rec*>(&gEmptyRec);
   1.216 +    } else {
   1.217 +        len = trim_size_t_to_u32(len);
   1.218 +
   1.219 +        // add 1 for terminating 0, then align4 so we can have some slop when growing the string
   1.220 +        rec = (Rec*)sk_malloc_throw(SizeOfRec() + SkAlign4(len + 1));
   1.221 +        rec->fLength = SkToU32(len);
   1.222 +        rec->fRefCnt = 1;
   1.223 +        if (text) {
   1.224 +            memcpy(rec->data(), text, len);
   1.225 +        }
   1.226 +        rec->data()[len] = 0;
   1.227 +    }
   1.228 +    return rec;
   1.229 +}
   1.230 +
   1.231 +SkString::Rec* SkString::RefRec(Rec* src) {
   1.232 +    if (src != &gEmptyRec) {
   1.233 +        sk_atomic_inc(&src->fRefCnt);
   1.234 +    }
   1.235 +    return src;
   1.236 +}
   1.237 +
   1.238 +#ifdef SK_DEBUG
   1.239 +void SkString::validate() const {
   1.240 +    // make sure know one has written over our global
   1.241 +    SkASSERT(0 == gEmptyRec.fLength);
   1.242 +    SkASSERT(0 == gEmptyRec.fRefCnt);
   1.243 +    SkASSERT(0 == gEmptyRec.data()[0]);
   1.244 +
   1.245 +    if (fRec != &gEmptyRec) {
   1.246 +        SkASSERT(fRec->fLength > 0);
   1.247 +        SkASSERT(fRec->fRefCnt > 0);
   1.248 +        SkASSERT(0 == fRec->data()[fRec->fLength]);
   1.249 +    }
   1.250 +    SkASSERT(fStr == c_str());
   1.251 +}
   1.252 +#endif
   1.253 +
   1.254 +///////////////////////////////////////////////////////////////////////////////
   1.255 +
   1.256 +SkString::SkString() : fRec(const_cast<Rec*>(&gEmptyRec)) {
   1.257 +#ifdef SK_DEBUG
   1.258 +    fStr = fRec->data();
   1.259 +#endif
   1.260 +}
   1.261 +
   1.262 +SkString::SkString(size_t len) {
   1.263 +    fRec = AllocRec(NULL, len);
   1.264 +#ifdef SK_DEBUG
   1.265 +    fStr = fRec->data();
   1.266 +#endif
   1.267 +}
   1.268 +
   1.269 +SkString::SkString(const char text[]) {
   1.270 +    size_t  len = text ? strlen(text) : 0;
   1.271 +
   1.272 +    fRec = AllocRec(text, len);
   1.273 +#ifdef SK_DEBUG
   1.274 +    fStr = fRec->data();
   1.275 +#endif
   1.276 +}
   1.277 +
   1.278 +SkString::SkString(const char text[], size_t len) {
   1.279 +    fRec = AllocRec(text, len);
   1.280 +#ifdef SK_DEBUG
   1.281 +    fStr = fRec->data();
   1.282 +#endif
   1.283 +}
   1.284 +
   1.285 +SkString::SkString(const SkString& src) {
   1.286 +    src.validate();
   1.287 +
   1.288 +    fRec = RefRec(src.fRec);
   1.289 +#ifdef SK_DEBUG
   1.290 +    fStr = fRec->data();
   1.291 +#endif
   1.292 +}
   1.293 +
   1.294 +SkString::~SkString() {
   1.295 +    this->validate();
   1.296 +
   1.297 +    if (fRec->fLength) {
   1.298 +        SkASSERT(fRec->fRefCnt > 0);
   1.299 +        if (sk_atomic_dec(&fRec->fRefCnt) == 1) {
   1.300 +            sk_free(fRec);
   1.301 +        }
   1.302 +    }
   1.303 +}
   1.304 +
   1.305 +bool SkString::equals(const SkString& src) const {
   1.306 +    return fRec == src.fRec || this->equals(src.c_str(), src.size());
   1.307 +}
   1.308 +
   1.309 +bool SkString::equals(const char text[]) const {
   1.310 +    return this->equals(text, text ? strlen(text) : 0);
   1.311 +}
   1.312 +
   1.313 +bool SkString::equals(const char text[], size_t len) const {
   1.314 +    SkASSERT(len == 0 || text != NULL);
   1.315 +
   1.316 +    return fRec->fLength == len && !memcmp(fRec->data(), text, len);
   1.317 +}
   1.318 +
   1.319 +SkString& SkString::operator=(const SkString& src) {
   1.320 +    this->validate();
   1.321 +
   1.322 +    if (fRec != src.fRec) {
   1.323 +        SkString    tmp(src);
   1.324 +        this->swap(tmp);
   1.325 +    }
   1.326 +    return *this;
   1.327 +}
   1.328 +
   1.329 +SkString& SkString::operator=(const char text[]) {
   1.330 +    this->validate();
   1.331 +
   1.332 +    SkString tmp(text);
   1.333 +    this->swap(tmp);
   1.334 +
   1.335 +    return *this;
   1.336 +}
   1.337 +
   1.338 +void SkString::reset() {
   1.339 +    this->validate();
   1.340 +
   1.341 +    if (fRec->fLength) {
   1.342 +        SkASSERT(fRec->fRefCnt > 0);
   1.343 +        if (sk_atomic_dec(&fRec->fRefCnt) == 1) {
   1.344 +            sk_free(fRec);
   1.345 +        }
   1.346 +    }
   1.347 +
   1.348 +    fRec = const_cast<Rec*>(&gEmptyRec);
   1.349 +#ifdef SK_DEBUG
   1.350 +    fStr = fRec->data();
   1.351 +#endif
   1.352 +}
   1.353 +
   1.354 +char* SkString::writable_str() {
   1.355 +    this->validate();
   1.356 +
   1.357 +    if (fRec->fLength) {
   1.358 +        if (fRec->fRefCnt > 1) {
   1.359 +            Rec* rec = AllocRec(fRec->data(), fRec->fLength);
   1.360 +            if (sk_atomic_dec(&fRec->fRefCnt) == 1) {
   1.361 +                // In this case after our check of fRecCnt > 1, we suddenly
   1.362 +                // did become the only owner, so now we have two copies of the
   1.363 +                // data (fRec and rec), so we need to delete one of them.
   1.364 +                sk_free(fRec);
   1.365 +            }
   1.366 +            fRec = rec;
   1.367 +        #ifdef SK_DEBUG
   1.368 +            fStr = fRec->data();
   1.369 +        #endif
   1.370 +        }
   1.371 +    }
   1.372 +    return fRec->data();
   1.373 +}
   1.374 +
   1.375 +void SkString::set(const char text[]) {
   1.376 +    this->set(text, text ? strlen(text) : 0);
   1.377 +}
   1.378 +
   1.379 +void SkString::set(const char text[], size_t len) {
   1.380 +    len = trim_size_t_to_u32(len);
   1.381 +
   1.382 +    if (0 == len) {
   1.383 +        this->reset();
   1.384 +    } else if (1 == fRec->fRefCnt && len <= fRec->fLength) {
   1.385 +        // should we resize if len <<<< fLength, to save RAM? (e.g. len < (fLength>>1))?
   1.386 +        // just use less of the buffer without allocating a smaller one
   1.387 +        char* p = this->writable_str();
   1.388 +        if (text) {
   1.389 +            memcpy(p, text, len);
   1.390 +        }
   1.391 +        p[len] = 0;
   1.392 +        fRec->fLength = SkToU32(len);
   1.393 +    } else if (1 == fRec->fRefCnt && (fRec->fLength >> 2) == (len >> 2)) {
   1.394 +        // we have spare room in the current allocation, so don't alloc a larger one
   1.395 +        char* p = this->writable_str();
   1.396 +        if (text) {
   1.397 +            memcpy(p, text, len);
   1.398 +        }
   1.399 +        p[len] = 0;
   1.400 +        fRec->fLength = SkToU32(len);
   1.401 +    } else {
   1.402 +        SkString tmp(text, len);
   1.403 +        this->swap(tmp);
   1.404 +    }
   1.405 +}
   1.406 +
   1.407 +void SkString::setUTF16(const uint16_t src[]) {
   1.408 +    int count = 0;
   1.409 +
   1.410 +    while (src[count]) {
   1.411 +        count += 1;
   1.412 +    }
   1.413 +    this->setUTF16(src, count);
   1.414 +}
   1.415 +
   1.416 +void SkString::setUTF16(const uint16_t src[], size_t count) {
   1.417 +    count = trim_size_t_to_u32(count);
   1.418 +
   1.419 +    if (0 == count) {
   1.420 +        this->reset();
   1.421 +    } else if (count <= fRec->fLength) {
   1.422 +        // should we resize if len <<<< fLength, to save RAM? (e.g. len < (fLength>>1))
   1.423 +        if (count < fRec->fLength) {
   1.424 +            this->resize(count);
   1.425 +        }
   1.426 +        char* p = this->writable_str();
   1.427 +        for (size_t i = 0; i < count; i++) {
   1.428 +            p[i] = SkToU8(src[i]);
   1.429 +        }
   1.430 +        p[count] = 0;
   1.431 +    } else {
   1.432 +        SkString tmp(count); // puts a null terminator at the end of the string
   1.433 +        char*    p = tmp.writable_str();
   1.434 +
   1.435 +        for (size_t i = 0; i < count; i++) {
   1.436 +            p[i] = SkToU8(src[i]);
   1.437 +        }
   1.438 +        this->swap(tmp);
   1.439 +    }
   1.440 +}
   1.441 +
   1.442 +void SkString::insert(size_t offset, const char text[]) {
   1.443 +    this->insert(offset, text, text ? strlen(text) : 0);
   1.444 +}
   1.445 +
   1.446 +void SkString::insert(size_t offset, const char text[], size_t len) {
   1.447 +    if (len) {
   1.448 +        size_t length = fRec->fLength;
   1.449 +        if (offset > length) {
   1.450 +            offset = length;
   1.451 +        }
   1.452 +
   1.453 +        // Check if length + len exceeds 32bits, we trim len
   1.454 +        len = check_add32(length, len);
   1.455 +        if (0 == len) {
   1.456 +            return;
   1.457 +        }
   1.458 +
   1.459 +        /*  If we're the only owner, and we have room in our allocation for the insert,
   1.460 +            do it in place, rather than allocating a new buffer.
   1.461 +
   1.462 +            To know we have room, compare the allocated sizes
   1.463 +            beforeAlloc = SkAlign4(length + 1)
   1.464 +            afterAlloc  = SkAligh4(length + 1 + len)
   1.465 +            but SkAlign4(x) is (x + 3) >> 2 << 2
   1.466 +            which is equivalent for testing to (length + 1 + 3) >> 2 == (length + 1 + 3 + len) >> 2
   1.467 +            and we can then eliminate the +1+3 since that doesn't affec the answer
   1.468 +        */
   1.469 +        if (1 == fRec->fRefCnt && (length >> 2) == ((length + len) >> 2)) {
   1.470 +            char* dst = this->writable_str();
   1.471 +
   1.472 +            if (offset < length) {
   1.473 +                memmove(dst + offset + len, dst + offset, length - offset);
   1.474 +            }
   1.475 +            memcpy(dst + offset, text, len);
   1.476 +
   1.477 +            dst[length + len] = 0;
   1.478 +            fRec->fLength = SkToU32(length + len);
   1.479 +        } else {
   1.480 +            /*  Seems we should use realloc here, since that is safe if it fails
   1.481 +                (we have the original data), and might be faster than alloc/copy/free.
   1.482 +            */
   1.483 +            SkString    tmp(fRec->fLength + len);
   1.484 +            char*       dst = tmp.writable_str();
   1.485 +
   1.486 +            if (offset > 0) {
   1.487 +                memcpy(dst, fRec->data(), offset);
   1.488 +            }
   1.489 +            memcpy(dst + offset, text, len);
   1.490 +            if (offset < fRec->fLength) {
   1.491 +                memcpy(dst + offset + len, fRec->data() + offset,
   1.492 +                       fRec->fLength - offset);
   1.493 +            }
   1.494 +
   1.495 +            this->swap(tmp);
   1.496 +        }
   1.497 +    }
   1.498 +}
   1.499 +
   1.500 +void SkString::insertUnichar(size_t offset, SkUnichar uni) {
   1.501 +    char    buffer[kMaxBytesInUTF8Sequence];
   1.502 +    size_t  len = SkUTF8_FromUnichar(uni, buffer);
   1.503 +
   1.504 +    if (len) {
   1.505 +        this->insert(offset, buffer, len);
   1.506 +    }
   1.507 +}
   1.508 +
   1.509 +void SkString::insertS32(size_t offset, int32_t dec) {
   1.510 +    char    buffer[SkStrAppendS32_MaxSize];
   1.511 +    char*   stop = SkStrAppendS32(buffer, dec);
   1.512 +    this->insert(offset, buffer, stop - buffer);
   1.513 +}
   1.514 +
   1.515 +void SkString::insertS64(size_t offset, int64_t dec, int minDigits) {
   1.516 +    char    buffer[SkStrAppendS64_MaxSize];
   1.517 +    char*   stop = SkStrAppendS64(buffer, dec, minDigits);
   1.518 +    this->insert(offset, buffer, stop - buffer);
   1.519 +}
   1.520 +
   1.521 +void SkString::insertU32(size_t offset, uint32_t dec) {
   1.522 +    char    buffer[SkStrAppendU32_MaxSize];
   1.523 +    char*   stop = SkStrAppendU32(buffer, dec);
   1.524 +    this->insert(offset, buffer, stop - buffer);
   1.525 +}
   1.526 +
   1.527 +void SkString::insertU64(size_t offset, uint64_t dec, int minDigits) {
   1.528 +    char    buffer[SkStrAppendU64_MaxSize];
   1.529 +    char*   stop = SkStrAppendU64(buffer, dec, minDigits);
   1.530 +    this->insert(offset, buffer, stop - buffer);
   1.531 +}
   1.532 +
   1.533 +void SkString::insertHex(size_t offset, uint32_t hex, int minDigits) {
   1.534 +    minDigits = SkPin32(minDigits, 0, 8);
   1.535 +
   1.536 +    static const char gHex[] = "0123456789ABCDEF";
   1.537 +
   1.538 +    char    buffer[8];
   1.539 +    char*   p = buffer + sizeof(buffer);
   1.540 +
   1.541 +    do {
   1.542 +        *--p = gHex[hex & 0xF];
   1.543 +        hex >>= 4;
   1.544 +        minDigits -= 1;
   1.545 +    } while (hex != 0);
   1.546 +
   1.547 +    while (--minDigits >= 0) {
   1.548 +        *--p = '0';
   1.549 +    }
   1.550 +
   1.551 +    SkASSERT(p >= buffer);
   1.552 +    this->insert(offset, p, buffer + sizeof(buffer) - p);
   1.553 +}
   1.554 +
   1.555 +void SkString::insertScalar(size_t offset, SkScalar value) {
   1.556 +    char    buffer[SkStrAppendScalar_MaxSize];
   1.557 +    char*   stop = SkStrAppendScalar(buffer, value);
   1.558 +    this->insert(offset, buffer, stop - buffer);
   1.559 +}
   1.560 +
   1.561 +void SkString::printf(const char format[], ...) {
   1.562 +    char    buffer[kBufferSize];
   1.563 +    ARGS_TO_BUFFER(format, buffer, kBufferSize);
   1.564 +
   1.565 +    this->set(buffer, strlen(buffer));
   1.566 +}
   1.567 +
   1.568 +void SkString::appendf(const char format[], ...) {
   1.569 +    char    buffer[kBufferSize];
   1.570 +    ARGS_TO_BUFFER(format, buffer, kBufferSize);
   1.571 +
   1.572 +    this->append(buffer, strlen(buffer));
   1.573 +}
   1.574 +
   1.575 +void SkString::appendVAList(const char format[], va_list args) {
   1.576 +    char    buffer[kBufferSize];
   1.577 +    VSNPRINTF(buffer, kBufferSize, format, args);
   1.578 +
   1.579 +    this->append(buffer, strlen(buffer));
   1.580 +}
   1.581 +
   1.582 +void SkString::prependf(const char format[], ...) {
   1.583 +    char    buffer[kBufferSize];
   1.584 +    ARGS_TO_BUFFER(format, buffer, kBufferSize);
   1.585 +
   1.586 +    this->prepend(buffer, strlen(buffer));
   1.587 +}
   1.588 +
   1.589 +///////////////////////////////////////////////////////////////////////////////
   1.590 +
   1.591 +void SkString::remove(size_t offset, size_t length) {
   1.592 +    size_t size = this->size();
   1.593 +
   1.594 +    if (offset < size) {
   1.595 +        if (offset + length > size) {
   1.596 +            length = size - offset;
   1.597 +        }
   1.598 +        if (length > 0) {
   1.599 +            SkASSERT(size > length);
   1.600 +            SkString    tmp(size - length);
   1.601 +            char*       dst = tmp.writable_str();
   1.602 +            const char* src = this->c_str();
   1.603 +
   1.604 +            if (offset) {
   1.605 +                SkASSERT(offset <= tmp.size());
   1.606 +                memcpy(dst, src, offset);
   1.607 +            }
   1.608 +            size_t tail = size - offset - length;
   1.609 +            SkASSERT((int32_t)tail >= 0);
   1.610 +            if (tail) {
   1.611 +        //      SkASSERT(offset + length <= tmp.size());
   1.612 +                memcpy(dst + offset, src + offset + length, tail);
   1.613 +            }
   1.614 +            SkASSERT(dst[tmp.size()] == 0);
   1.615 +            this->swap(tmp);
   1.616 +        }
   1.617 +    }
   1.618 +}
   1.619 +
   1.620 +void SkString::swap(SkString& other) {
   1.621 +    this->validate();
   1.622 +    other.validate();
   1.623 +
   1.624 +    SkTSwap<Rec*>(fRec, other.fRec);
   1.625 +#ifdef SK_DEBUG
   1.626 +    SkTSwap<const char*>(fStr, other.fStr);
   1.627 +#endif
   1.628 +}
   1.629 +
   1.630 +///////////////////////////////////////////////////////////////////////////////
   1.631 +
   1.632 +SkString SkStringPrintf(const char* format, ...) {
   1.633 +    SkString formattedOutput;
   1.634 +    char buffer[kBufferSize];
   1.635 +    ARGS_TO_BUFFER(format, buffer, kBufferSize);
   1.636 +    formattedOutput.set(buffer);
   1.637 +    return formattedOutput;
   1.638 +}
   1.639 +
   1.640 +void SkStrSplit(const char* str, const char* delimiters, SkTArray<SkString>* out) {
   1.641 +    const char* end = str + strlen(str);
   1.642 +    while (str != end) {
   1.643 +        // Find a token.
   1.644 +        const size_t len = strcspn(str, delimiters);
   1.645 +        out->push_back().set(str, len);
   1.646 +        str += len;
   1.647 +        // Skip any delimiters.
   1.648 +        str += strspn(str, delimiters);
   1.649 +    }
   1.650 +}
   1.651 +
   1.652 +#undef VSNPRINTF
   1.653 +#undef SNPRINTF

mercurial