180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2006 The Android Open Source Project
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkString.h"
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkFixed.h"
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkThread.h"
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkUtils.h"
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include <stdarg.h>
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include <stdio.h>
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// number of bytes (on the stack) to receive the printf result
187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic const size_t kBufferSize = 1024;
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_BUILD_FOR_WIN
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define VSNPRINTF(buffer, size, format, args) \
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        _vsnprintf_s(buffer, size, _TRUNCATE, format, args)
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define SNPRINTF    _snprintf
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define VSNPRINTF   vsnprintf
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define SNPRINTF    snprintf
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define ARGS_TO_BUFFER(format, buffer, size)        \
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    do {                                            \
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        va_list args;                               \
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        va_start(args, format);                     \
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        VSNPRINTF(buffer, size, format, args);      \
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        va_end(args);                               \
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } while (0)
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
39363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerbool SkStrEndsWith(const char string[], const char suffixStr[]) {
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(string);
41363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkASSERT(suffixStr);
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t  strLen = strlen(string);
43363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    size_t  suffixLen = strlen(suffixStr);
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return  strLen >= suffixLen &&
45363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            !strncmp(string + strLen - suffixLen, suffixStr, suffixLen);
46363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
47363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
48363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerbool SkStrEndsWith(const char string[], const char suffixChar) {
49363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkASSERT(string);
50363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    size_t  strLen = strlen(string);
51363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (0 == strLen) {
52363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return false;
53363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    } else {
54363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return (suffixChar == string[strLen-1]);
55363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint SkStrStartsWithOneOf(const char string[], const char prefixes[]) {
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int index = 0;
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    do {
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const char* limit = strchr(prefixes, '\0');
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (!strncmp(string, prefixes, limit - prefixes)) {
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return index;
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        prefixes = limit + 1;
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        index++;
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } while (prefixes[0]);
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return -1;
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerchar* SkStrAppendU32(char string[], uint32_t dec) {
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDEBUGCODE(char* start = string;)
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    char    buffer[SkStrAppendU32_MaxSize];
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char*   p = buffer + sizeof(buffer);
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    do {
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *--p = SkToU8('0' + dec % 10);
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dec /= 10;
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } while (dec != 0);
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(p >= buffer);
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char* stop = buffer + sizeof(buffer);
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (p < stop) {
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *string++ = *p++;
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
8758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkASSERT(string - start <= SkStrAppendU32_MaxSize);
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return string;
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerchar* SkStrAppendS32(char string[], int32_t dec) {
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (dec < 0) {
9358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        *string++ = '-';
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dec = -dec;
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
9658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return SkStrAppendU32(string, static_cast<uint32_t>(dec));
9758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
9858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
9958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerchar* SkStrAppendU64(char string[], uint64_t dec, int minDigits) {
10058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkDEBUGCODE(char* start = string;)
10158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
10258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    char    buffer[SkStrAppendU64_MaxSize];
10358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    char*   p = buffer + sizeof(buffer);
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    do {
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *--p = SkToU8('0' + (int32_t) (dec % 10));
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dec /= 10;
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        minDigits--;
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } while (dec != 0);
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (minDigits > 0) {
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *--p = '0';
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        minDigits--;
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(p >= buffer);
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t cp_len = buffer + sizeof(buffer) - p;
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    memcpy(string, p, cp_len);
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    string += cp_len;
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkASSERT(string - start <= SkStrAppendU64_MaxSize);
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return string;
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerchar* SkStrAppendS64(char string[], int64_t dec, int minDigits) {
12658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (dec < 0) {
12758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        *string++ = '-';
12858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        dec = -dec;
12958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
13058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return SkStrAppendU64(string, static_cast<uint64_t>(dec), minDigits);
13158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
13258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruchar* SkStrAppendFloat(char string[], float value) {
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // since floats have at most 8 significant digits, we limit our %g to that.
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static const char gFormat[] = "%.8g";
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // make it 1 larger for the terminating 0
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char buffer[SkStrAppendScalar_MaxSize + 1];
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int len = SNPRINTF(buffer, sizeof(buffer), gFormat, value);
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    memcpy(string, buffer, len);
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(len <= SkStrAppendScalar_MaxSize);
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return string + len;
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruchar* SkStrAppendFixed(char string[], SkFixed x) {
14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDEBUGCODE(char* start = string;)
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (x < 0) {
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *string++ = '-';
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        x = -x;
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned frac = x & 0xFFFF;
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    x >>= 16;
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (frac == 0xFFFF) {
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // need to do this to "round up", since 65535/65536 is closer to 1 than to .9999
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        x += 1;
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        frac = 0;
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    string = SkStrAppendS32(string, x);
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // now handle the fractional part (if any)
16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (frac) {
16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        static const uint16_t   gTens[] = { 1000, 100, 10, 1 };
16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const uint16_t*         tens = gTens;
16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        x = SkFixedRound(frac * 10000);
16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(x <= 10000);
16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (x == 10000) {
16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            x -= 1;
16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *string++ = '.';
17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        do {
17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            unsigned powerOfTen = *tens++;
17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *string++ = SkToU8('0' + x / powerOfTen);
17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            x %= powerOfTen;
17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } while (x != 0);
17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(string - start <= SkStrAppendScalar_MaxSize);
17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return string;
18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// the 3 values are [length] [refcnt] [terminating zero data]
18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruconst SkString::Rec SkString::gEmptyRec = { 0, 0, 0 };
18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SizeOfRec()     (gEmptyRec.data() - (const char*)&gEmptyRec)
18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
18958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic uint32_t trim_size_t_to_u32(size_t value) {
19058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (sizeof(size_t) > sizeof(uint32_t)) {
19158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        if (value > SK_MaxU32) {
19258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            value = SK_MaxU32;
19358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        }
19458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
19558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return (uint32_t)value;
19658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
19758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
19858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic size_t check_add32(size_t base, size_t extra) {
19958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkASSERT(base <= SK_MaxU32);
20058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (sizeof(size_t) > sizeof(uint32_t)) {
20158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        if (base + extra > SK_MaxU32) {
20258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            extra = SK_MaxU32 - base;
20358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        }
20458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
20558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return extra;
20658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
20758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
20880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkString::Rec* SkString::AllocRec(const char text[], size_t len) {
20980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Rec* rec;
21080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
21180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (0 == len) {
21280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        rec = const_cast<Rec*>(&gEmptyRec);
21380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
21458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        len = trim_size_t_to_u32(len);
21558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
21680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // add 1 for terminating 0, then align4 so we can have some slop when growing the string
21780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        rec = (Rec*)sk_malloc_throw(SizeOfRec() + SkAlign4(len + 1));
21858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        rec->fLength = SkToU32(len);
21980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        rec->fRefCnt = 1;
22080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (text) {
22180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            memcpy(rec->data(), text, len);
22280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        rec->data()[len] = 0;
22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
22580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return rec;
22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
22780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
22880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkString::Rec* SkString::RefRec(Rec* src) {
22980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (src != &gEmptyRec) {
23080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        sk_atomic_inc(&src->fRefCnt);
23180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
23280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return src;
23380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
23480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG
23680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkString::validate() const {
23780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // make sure know one has written over our global
23880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(0 == gEmptyRec.fLength);
23980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(0 == gEmptyRec.fRefCnt);
24080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(0 == gEmptyRec.data()[0]);
24180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
24280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fRec != &gEmptyRec) {
24380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(fRec->fLength > 0);
24480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(fRec->fRefCnt > 0);
24580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(0 == fRec->data()[fRec->fLength]);
24680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
24780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(fStr == c_str());
24880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
24980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
25080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
25180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
25280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
25380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkString::SkString() : fRec(const_cast<Rec*>(&gEmptyRec)) {
25480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG
25580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fStr = fRec->data();
25680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
25780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
25880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
25980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkString::SkString(size_t len) {
2607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fRec = AllocRec(NULL, len);
26180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG
26280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fStr = fRec->data();
26380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
26480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
26580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
26680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkString::SkString(const char text[]) {
26780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t  len = text ? strlen(text) : 0;
26880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2697839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fRec = AllocRec(text, len);
27080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG
27180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fStr = fRec->data();
27280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
27380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
27480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkString::SkString(const char text[], size_t len) {
2767839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fRec = AllocRec(text, len);
27780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG
27880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fStr = fRec->data();
27980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
28080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
28180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
28280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkString::SkString(const SkString& src) {
28380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    src.validate();
28480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
28580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fRec = RefRec(src.fRec);
28680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG
28780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fStr = fRec->data();
28880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
28980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
29080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
29180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkString::~SkString() {
29280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->validate();
29380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
29480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fRec->fLength) {
29580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(fRec->fRefCnt > 0);
29680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (sk_atomic_dec(&fRec->fRefCnt) == 1) {
29780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            sk_free(fRec);
29880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
29980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
30080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
30180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
30280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkString::equals(const SkString& src) const {
30380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fRec == src.fRec || this->equals(src.c_str(), src.size());
30480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
30580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
30680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkString::equals(const char text[]) const {
30780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return this->equals(text, text ? strlen(text) : 0);
30880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
30980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
31080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkString::equals(const char text[], size_t len) const {
31180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(len == 0 || text != NULL);
31280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
31380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fRec->fLength == len && !memcmp(fRec->data(), text, len);
31480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
31580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
31680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkString& SkString::operator=(const SkString& src) {
31780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->validate();
31880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
31980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fRec != src.fRec) {
32080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkString    tmp(src);
32180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->swap(tmp);
32280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
32380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return *this;
32480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
32580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
32680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkString& SkString::operator=(const char text[]) {
32780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->validate();
32880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
32980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkString tmp(text);
33080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->swap(tmp);
33180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
33280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return *this;
33380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
33480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
33580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkString::reset() {
33680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->validate();
33780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
33880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fRec->fLength) {
33980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(fRec->fRefCnt > 0);
34080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (sk_atomic_dec(&fRec->fRefCnt) == 1) {
34180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            sk_free(fRec);
34280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
34380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
34480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
34580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fRec = const_cast<Rec*>(&gEmptyRec);
34680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG
34780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fStr = fRec->data();
34880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
34980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
35080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
35180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruchar* SkString::writable_str() {
35280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->validate();
35380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
35480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fRec->fLength) {
35580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (fRec->fRefCnt > 1) {
35680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            Rec* rec = AllocRec(fRec->data(), fRec->fLength);
35780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (sk_atomic_dec(&fRec->fRefCnt) == 1) {
35880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                // In this case after our check of fRecCnt > 1, we suddenly
35980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                // did become the only owner, so now we have two copies of the
36080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                // data (fRec and rec), so we need to delete one of them.
36180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                sk_free(fRec);
36280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
36380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fRec = rec;
36480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        #ifdef SK_DEBUG
36580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fStr = fRec->data();
36680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        #endif
36780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
36880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
36980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fRec->data();
37080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
37180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
37280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkString::set(const char text[]) {
37380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->set(text, text ? strlen(text) : 0);
37480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
37580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
37680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkString::set(const char text[], size_t len) {
37758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    len = trim_size_t_to_u32(len);
37858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
37980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (0 == len) {
38080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->reset();
38180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else if (1 == fRec->fRefCnt && len <= fRec->fLength) {
38280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // should we resize if len <<<< fLength, to save RAM? (e.g. len < (fLength>>1))?
38380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // just use less of the buffer without allocating a smaller one
38480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        char* p = this->writable_str();
38580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (text) {
38680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            memcpy(p, text, len);
38780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
38880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        p[len] = 0;
38958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        fRec->fLength = SkToU32(len);
39080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else if (1 == fRec->fRefCnt && (fRec->fLength >> 2) == (len >> 2)) {
39180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // we have spare room in the current allocation, so don't alloc a larger one
39280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        char* p = this->writable_str();
39380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (text) {
39480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            memcpy(p, text, len);
39580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
39680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        p[len] = 0;
39758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        fRec->fLength = SkToU32(len);
39880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
39980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkString tmp(text, len);
40080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->swap(tmp);
40180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
40280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
40380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
40480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkString::setUTF16(const uint16_t src[]) {
40580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int count = 0;
40680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
40780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (src[count]) {
40880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        count += 1;
40980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
41058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    this->setUTF16(src, count);
41180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
41280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
41380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkString::setUTF16(const uint16_t src[], size_t count) {
41458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    count = trim_size_t_to_u32(count);
41558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
41680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (0 == count) {
41780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->reset();
41880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else if (count <= fRec->fLength) {
41980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // should we resize if len <<<< fLength, to save RAM? (e.g. len < (fLength>>1))
42080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (count < fRec->fLength) {
42180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            this->resize(count);
42280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
42380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        char* p = this->writable_str();
42480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (size_t i = 0; i < count; i++) {
42580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            p[i] = SkToU8(src[i]);
42680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
42780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        p[count] = 0;
42880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
42980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkString tmp(count); // puts a null terminator at the end of the string
43080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        char*    p = tmp.writable_str();
43180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
43280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (size_t i = 0; i < count; i++) {
43380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            p[i] = SkToU8(src[i]);
43480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
43580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->swap(tmp);
43680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
43780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
43880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
43980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkString::insert(size_t offset, const char text[]) {
44080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->insert(offset, text, text ? strlen(text) : 0);
44180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
44280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
44380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkString::insert(size_t offset, const char text[], size_t len) {
44480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (len) {
44580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        size_t length = fRec->fLength;
44680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (offset > length) {
44780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            offset = length;
44880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
44980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
45058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        // Check if length + len exceeds 32bits, we trim len
45158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        len = check_add32(length, len);
45258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        if (0 == len) {
45358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            return;
45458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        }
45558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
45680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        /*  If we're the only owner, and we have room in our allocation for the insert,
45780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            do it in place, rather than allocating a new buffer.
45880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
45980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            To know we have room, compare the allocated sizes
46080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            beforeAlloc = SkAlign4(length + 1)
46180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            afterAlloc  = SkAligh4(length + 1 + len)
46280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            but SkAlign4(x) is (x + 3) >> 2 << 2
46380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            which is equivalent for testing to (length + 1 + 3) >> 2 == (length + 1 + 3 + len) >> 2
46480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            and we can then eliminate the +1+3 since that doesn't affec the answer
46580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        */
46680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (1 == fRec->fRefCnt && (length >> 2) == ((length + len) >> 2)) {
46780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            char* dst = this->writable_str();
46880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
46980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (offset < length) {
47080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                memmove(dst + offset + len, dst + offset, length - offset);
47180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
47280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            memcpy(dst + offset, text, len);
47380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
47480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            dst[length + len] = 0;
47558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            fRec->fLength = SkToU32(length + len);
47680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
47780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            /*  Seems we should use realloc here, since that is safe if it fails
47880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                (we have the original data), and might be faster than alloc/copy/free.
47980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            */
48080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkString    tmp(fRec->fLength + len);
48180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            char*       dst = tmp.writable_str();
48280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
48380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (offset > 0) {
48480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                memcpy(dst, fRec->data(), offset);
48580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
48680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            memcpy(dst + offset, text, len);
48780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (offset < fRec->fLength) {
48880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                memcpy(dst + offset + len, fRec->data() + offset,
48980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                       fRec->fLength - offset);
49080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
49180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
49280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            this->swap(tmp);
49380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
49480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
49580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
49680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
49780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkString::insertUnichar(size_t offset, SkUnichar uni) {
49880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char    buffer[kMaxBytesInUTF8Sequence];
49980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t  len = SkUTF8_FromUnichar(uni, buffer);
50080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
50180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (len) {
50280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->insert(offset, buffer, len);
50380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
50480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
50580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
50680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkString::insertS32(size_t offset, int32_t dec) {
50780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char    buffer[SkStrAppendS32_MaxSize];
50880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char*   stop = SkStrAppendS32(buffer, dec);
50980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->insert(offset, buffer, stop - buffer);
51080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
51180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
51280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkString::insertS64(size_t offset, int64_t dec, int minDigits) {
51380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char    buffer[SkStrAppendS64_MaxSize];
51480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char*   stop = SkStrAppendS64(buffer, dec, minDigits);
51580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->insert(offset, buffer, stop - buffer);
51680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
51780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
51858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergervoid SkString::insertU32(size_t offset, uint32_t dec) {
51958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    char    buffer[SkStrAppendU32_MaxSize];
52058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    char*   stop = SkStrAppendU32(buffer, dec);
52158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    this->insert(offset, buffer, stop - buffer);
52258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
52358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
52458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergervoid SkString::insertU64(size_t offset, uint64_t dec, int minDigits) {
52558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    char    buffer[SkStrAppendU64_MaxSize];
52658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    char*   stop = SkStrAppendU64(buffer, dec, minDigits);
52758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    this->insert(offset, buffer, stop - buffer);
52858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
52958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
53080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkString::insertHex(size_t offset, uint32_t hex, int minDigits) {
53180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    minDigits = SkPin32(minDigits, 0, 8);
53280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
53380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static const char gHex[] = "0123456789ABCDEF";
53480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
53580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char    buffer[8];
53680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char*   p = buffer + sizeof(buffer);
53780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
53880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    do {
53980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *--p = gHex[hex & 0xF];
54080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        hex >>= 4;
54180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        minDigits -= 1;
54280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } while (hex != 0);
54380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
54480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (--minDigits >= 0) {
54580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *--p = '0';
54680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
54780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
54880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(p >= buffer);
54980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->insert(offset, p, buffer + sizeof(buffer) - p);
55080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
55180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
55280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkString::insertScalar(size_t offset, SkScalar value) {
55380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char    buffer[SkStrAppendScalar_MaxSize];
55480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char*   stop = SkStrAppendScalar(buffer, value);
55580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->insert(offset, buffer, stop - buffer);
55680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
55780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
55880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkString::printf(const char format[], ...) {
55980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char    buffer[kBufferSize];
56080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ARGS_TO_BUFFER(format, buffer, kBufferSize);
56180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
56280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->set(buffer, strlen(buffer));
56380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
56480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
56580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkString::appendf(const char format[], ...) {
56680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char    buffer[kBufferSize];
56780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ARGS_TO_BUFFER(format, buffer, kBufferSize);
56880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
56980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->append(buffer, strlen(buffer));
57080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
57180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
572910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergervoid SkString::appendVAList(const char format[], va_list args) {
573096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    char    buffer[kBufferSize];
574096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    VSNPRINTF(buffer, kBufferSize, format, args);
575096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
576096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    this->append(buffer, strlen(buffer));
577096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger}
578096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
57980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkString::prependf(const char format[], ...) {
58080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char    buffer[kBufferSize];
58180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ARGS_TO_BUFFER(format, buffer, kBufferSize);
58280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
58380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->prepend(buffer, strlen(buffer));
58480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
58580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
58680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
58780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
58880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkString::remove(size_t offset, size_t length) {
58980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t size = this->size();
59080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
59180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (offset < size) {
59280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (offset + length > size) {
59380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            length = size - offset;
59480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
59580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (length > 0) {
59680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(size > length);
59780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkString    tmp(size - length);
59880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            char*       dst = tmp.writable_str();
59980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            const char* src = this->c_str();
60080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
60180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (offset) {
60280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkASSERT(offset <= tmp.size());
60380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                memcpy(dst, src, offset);
60480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
60580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            size_t tail = size - offset - length;
60680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT((int32_t)tail >= 0);
60780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (tail) {
60880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        //      SkASSERT(offset + length <= tmp.size());
60980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                memcpy(dst + offset, src + offset + length, tail);
61080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
61180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(dst[tmp.size()] == 0);
61280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            this->swap(tmp);
61380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
61480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
61580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
61680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
61780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkString::swap(SkString& other) {
61880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->validate();
61980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    other.validate();
62080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
62180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkTSwap<Rec*>(fRec, other.fRec);
62280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG
62380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkTSwap<const char*>(fStr, other.fStr);
62480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
62580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
62680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
62780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
62880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
62980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkString SkStringPrintf(const char* format, ...) {
63080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkString formattedOutput;
63180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char buffer[kBufferSize];
63280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ARGS_TO_BUFFER(format, buffer, kBufferSize);
63380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    formattedOutput.set(buffer);
63480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return formattedOutput;
63580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
63680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
637910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergervoid SkStrSplit(const char* str, const char* delimiters, SkTArray<SkString>* out) {
638910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    const char* end = str + strlen(str);
639910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    while (str != end) {
640910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        // Find a token.
641910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        const size_t len = strcspn(str, delimiters);
642910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        out->push_back().set(str, len);
643910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        str += len;
644910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        // Skip any delimiters.
645910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        str += strspn(str, delimiters);
646910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    }
647910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger}
648910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger
64980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#undef VSNPRINTF
65080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#undef SNPRINTF
651