1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkString.h"
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkFixed.h"
124bce115b316ec0ecc17e7b24ad7b1086fa3a8796reed@google.com#include "SkThread.h"
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include <stdarg.h>
15fa06e528035dd9c4d01c1d1e17e9df1cfe99b855reed@google.com#include <stdio.h>
16fa06e528035dd9c4d01c1d1e17e9df1cfe99b855reed@google.com
17fa06e528035dd9c4d01c1d1e17e9df1cfe99b855reed@google.com// number of bytes (on the stack) to receive the printf result
1877cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.comstatic const size_t kBufferSize = 1024;
19fa06e528035dd9c4d01c1d1e17e9df1cfe99b855reed@google.com
20fa06e528035dd9c4d01c1d1e17e9df1cfe99b855reed@google.com#ifdef SK_BUILD_FOR_WIN
2147e0a09052eb4c93a4506ebf3c64070fafc3d4b3tomhudson@google.com    #define VSNPRINTF(buffer, size, format, args) \
2247e0a09052eb4c93a4506ebf3c64070fafc3d4b3tomhudson@google.com        _vsnprintf_s(buffer, size, _TRUNCATE, format, args)
23fa06e528035dd9c4d01c1d1e17e9df1cfe99b855reed@google.com    #define SNPRINTF    _snprintf
24fa06e528035dd9c4d01c1d1e17e9df1cfe99b855reed@google.com#else
25fa06e528035dd9c4d01c1d1e17e9df1cfe99b855reed@google.com    #define VSNPRINTF   vsnprintf
26fa06e528035dd9c4d01c1d1e17e9df1cfe99b855reed@google.com    #define SNPRINTF    snprintf
27fa06e528035dd9c4d01c1d1e17e9df1cfe99b855reed@google.com#endif
28fa06e528035dd9c4d01c1d1e17e9df1cfe99b855reed@google.com
29fa06e528035dd9c4d01c1d1e17e9df1cfe99b855reed@google.com#define ARGS_TO_BUFFER(format, buffer, size)        \
30fa06e528035dd9c4d01c1d1e17e9df1cfe99b855reed@google.com    do {                                            \
31fa06e528035dd9c4d01c1d1e17e9df1cfe99b855reed@google.com        va_list args;                               \
32fa06e528035dd9c4d01c1d1e17e9df1cfe99b855reed@google.com        va_start(args, format);                     \
33fa06e528035dd9c4d01c1d1e17e9df1cfe99b855reed@google.com        VSNPRINTF(buffer, size, format, args);      \
34fa06e528035dd9c4d01c1d1e17e9df1cfe99b855reed@google.com        va_end(args);                               \
35fa06e528035dd9c4d01c1d1e17e9df1cfe99b855reed@google.com    } while (0)
36fa06e528035dd9c4d01c1d1e17e9df1cfe99b855reed@google.com
37fa06e528035dd9c4d01c1d1e17e9df1cfe99b855reed@google.com///////////////////////////////////////////////////////////////////////////////
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
39e8ebeb1f8fde6525bbab988c6090a5d3ab19855bepoger@google.combool SkStrEndsWith(const char string[], const char suffixStr[]) {
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(string);
41e8ebeb1f8fde6525bbab988c6090a5d3ab19855bepoger@google.com    SkASSERT(suffixStr);
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    size_t  strLen = strlen(string);
43e8ebeb1f8fde6525bbab988c6090a5d3ab19855bepoger@google.com    size_t  suffixLen = strlen(suffixStr);
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return  strLen >= suffixLen &&
45e8ebeb1f8fde6525bbab988c6090a5d3ab19855bepoger@google.com            !strncmp(string + strLen - suffixLen, suffixStr, suffixLen);
46e8ebeb1f8fde6525bbab988c6090a5d3ab19855bepoger@google.com}
47e8ebeb1f8fde6525bbab988c6090a5d3ab19855bepoger@google.com
48e8ebeb1f8fde6525bbab988c6090a5d3ab19855bepoger@google.combool SkStrEndsWith(const char string[], const char suffixChar) {
49e8ebeb1f8fde6525bbab988c6090a5d3ab19855bepoger@google.com    SkASSERT(string);
50e8ebeb1f8fde6525bbab988c6090a5d3ab19855bepoger@google.com    size_t  strLen = strlen(string);
51e8ebeb1f8fde6525bbab988c6090a5d3ab19855bepoger@google.com    if (0 == strLen) {
52e8ebeb1f8fde6525bbab988c6090a5d3ab19855bepoger@google.com        return false;
53e8ebeb1f8fde6525bbab988c6090a5d3ab19855bepoger@google.com    } else {
54e8ebeb1f8fde6525bbab988c6090a5d3ab19855bepoger@google.com        return (suffixChar == string[strLen-1]);
55e8ebeb1f8fde6525bbab988c6090a5d3ab19855bepoger@google.com    }
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
584e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.orgint SkStrStartsWithOneOf(const char string[], const char prefixes[]) {
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int index = 0;
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    do {
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const char* limit = strchr(prefixes, '\0');
624e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org        if (!strncmp(string, prefixes, limit - prefixes)) {
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return index;
644e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org        }
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        prefixes = limit + 1;
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        index++;
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } while (prefixes[0]);
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return -1;
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
71d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.comchar* SkStrAppendU32(char string[], uint32_t dec) {
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(char* start = string;)
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
74d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.com    char    buffer[SkStrAppendU32_MaxSize];
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    char*   p = buffer + sizeof(buffer);
764e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    do {
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *--p = SkToU8('0' + dec % 10);
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dec /= 10;
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } while (dec != 0);
814e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(p >= buffer);
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    char* stop = buffer + sizeof(buffer);
844e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org    while (p < stop) {
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *string++ = *p++;
864e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org    }
87d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.com    SkASSERT(string - start <= SkStrAppendU32_MaxSize);
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return string;
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
91d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.comchar* SkStrAppendS32(char string[], int32_t dec) {
92d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org    if (dec < 0) {
93d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.com        *string++ = '-';
94d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org        dec = -dec;
95d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org    }
96d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.com    return SkStrAppendU32(string, static_cast<uint32_t>(dec));
97d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.com}
98d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.com
99d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.comchar* SkStrAppendU64(char string[], uint64_t dec, int minDigits) {
100d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.com    SkDEBUGCODE(char* start = string;)
101d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.com
102d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.com    char    buffer[SkStrAppendU64_MaxSize];
103d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.com    char*   p = buffer + sizeof(buffer);
1044e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org
105d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org    do {
106803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com        *--p = SkToU8('0' + (int32_t) (dec % 10));
107d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org        dec /= 10;
108d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org        minDigits--;
109d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org    } while (dec != 0);
1104e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org
111d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org    while (minDigits > 0) {
112d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org        *--p = '0';
113d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org        minDigits--;
114d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org    }
115d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org
116d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org    SkASSERT(p >= buffer);
117d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org    size_t cp_len = buffer + sizeof(buffer) - p;
118d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org    memcpy(string, p, cp_len);
119d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org    string += cp_len;
120d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org
121d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.com    SkASSERT(string - start <= SkStrAppendU64_MaxSize);
122d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org    return string;
123d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org}
124d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org
125d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.comchar* SkStrAppendS64(char string[], int64_t dec, int minDigits) {
126d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.com    if (dec < 0) {
127d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.com        *string++ = '-';
128d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.com        dec = -dec;
129d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.com    }
130d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.com    return SkStrAppendU64(string, static_cast<uint64_t>(dec), minDigits);
131d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.com}
132d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.com
1334e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.orgchar* SkStrAppendFloat(char string[], float value) {
1348072e4fdc8261b1ca8937aa5c31db967280eae2areed@google.com    // since floats have at most 8 significant digits, we limit our %g to that.
1358072e4fdc8261b1ca8937aa5c31db967280eae2areed@google.com    static const char gFormat[] = "%.8g";
1368072e4fdc8261b1ca8937aa5c31db967280eae2areed@google.com    // make it 1 larger for the terminating 0
1378072e4fdc8261b1ca8937aa5c31db967280eae2areed@google.com    char buffer[SkStrAppendScalar_MaxSize + 1];
1388072e4fdc8261b1ca8937aa5c31db967280eae2areed@google.com    int len = SNPRINTF(buffer, sizeof(buffer), gFormat, value);
1398072e4fdc8261b1ca8937aa5c31db967280eae2areed@google.com    memcpy(string, buffer, len);
140677cbedda7dc43844cbc58dbebbe52e37381be8evandebo@chromium.org    SkASSERT(len <= SkStrAppendScalar_MaxSize);
1418072e4fdc8261b1ca8937aa5c31db967280eae2areed@google.com    return string + len;
142677cbedda7dc43844cbc58dbebbe52e37381be8evandebo@chromium.org}
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1444e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.orgchar* SkStrAppendFixed(char string[], SkFixed x) {
145677cbedda7dc43844cbc58dbebbe52e37381be8evandebo@chromium.org    SkDEBUGCODE(char* start = string;)
1464e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org    if (x < 0) {
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *string++ = '-';
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        x = -x;
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned frac = x & 0xFFFF;
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    x >>= 16;
1534e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org    if (frac == 0xFFFF) {
1544e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org        // need to do this to "round up", since 65535/65536 is closer to 1 than to .9999
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        x += 1;
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        frac = 0;
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    string = SkStrAppendS32(string, x);
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now handle the fractional part (if any)
1614e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org    if (frac) {
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        static const uint16_t   gTens[] = { 1000, 100, 10, 1 };
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const uint16_t*         tens = gTens;
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1659fb00413ec55deb3a4953d4dff2dba3ec5cdb645mike@reedtribe.org        x = SkFixedRoundToInt(frac * 10000);
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(x <= 10000);
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (x == 10000) {
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x -= 1;
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *string++ = '.';
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        do {
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            unsigned powerOfTen = *tens++;
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            *string++ = SkToU8('0' + x / powerOfTen);
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x %= powerOfTen;
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } while (x != 0);
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
177fa06e528035dd9c4d01c1d1e17e9df1cfe99b855reed@google.com
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(string - start <= SkStrAppendScalar_MaxSize);
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return string;
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1824e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org///////////////////////////////////////////////////////////////////////////////
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// the 3 values are [length] [refcnt] [terminating zero data]
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkString::Rec SkString::gEmptyRec = { 0, 0, 0 };
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SizeOfRec()     (gEmptyRec.data() - (const char*)&gEmptyRec)
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1898cb108803425481bf58f1eeb388cf818701c5e77reed@google.comstatic uint32_t trim_size_t_to_u32(size_t value) {
1908cb108803425481bf58f1eeb388cf818701c5e77reed@google.com    if (sizeof(size_t) > sizeof(uint32_t)) {
1918cb108803425481bf58f1eeb388cf818701c5e77reed@google.com        if (value > SK_MaxU32) {
1928cb108803425481bf58f1eeb388cf818701c5e77reed@google.com            value = SK_MaxU32;
1938cb108803425481bf58f1eeb388cf818701c5e77reed@google.com        }
1948cb108803425481bf58f1eeb388cf818701c5e77reed@google.com    }
1958cb108803425481bf58f1eeb388cf818701c5e77reed@google.com    return (uint32_t)value;
1968cb108803425481bf58f1eeb388cf818701c5e77reed@google.com}
1978cb108803425481bf58f1eeb388cf818701c5e77reed@google.com
1988cb108803425481bf58f1eeb388cf818701c5e77reed@google.comstatic size_t check_add32(size_t base, size_t extra) {
1998cb108803425481bf58f1eeb388cf818701c5e77reed@google.com    SkASSERT(base <= SK_MaxU32);
2008cb108803425481bf58f1eeb388cf818701c5e77reed@google.com    if (sizeof(size_t) > sizeof(uint32_t)) {
2018cb108803425481bf58f1eeb388cf818701c5e77reed@google.com        if (base + extra > SK_MaxU32) {
2028cb108803425481bf58f1eeb388cf818701c5e77reed@google.com            extra = SK_MaxU32 - base;
2038cb108803425481bf58f1eeb388cf818701c5e77reed@google.com        }
2048cb108803425481bf58f1eeb388cf818701c5e77reed@google.com    }
2058cb108803425481bf58f1eeb388cf818701c5e77reed@google.com    return extra;
2068cb108803425481bf58f1eeb388cf818701c5e77reed@google.com}
2078cb108803425481bf58f1eeb388cf818701c5e77reed@google.com
2084bce115b316ec0ecc17e7b24ad7b1086fa3a8796reed@google.comSkString::Rec* SkString::AllocRec(const char text[], size_t len) {
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Rec* rec;
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2114bce115b316ec0ecc17e7b24ad7b1086fa3a8796reed@google.com    if (0 == len) {
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec = const_cast<Rec*>(&gEmptyRec);
2134e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org    } else {
2148cb108803425481bf58f1eeb388cf818701c5e77reed@google.com        len = trim_size_t_to_u32(len);
2158cb108803425481bf58f1eeb388cf818701c5e77reed@google.com
2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // add 1 for terminating 0, then align4 so we can have some slop when growing the string
2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec = (Rec*)sk_malloc_throw(SizeOfRec() + SkAlign4(len + 1));
2188cb108803425481bf58f1eeb388cf818701c5e77reed@google.com        rec->fLength = SkToU32(len);
2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec->fRefCnt = 1;
2204e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org        if (text) {
2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            memcpy(rec->data(), text, len);
2224e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org        }
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec->data()[len] = 0;
2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return rec;
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2284e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.orgSkString::Rec* SkString::RefRec(Rec* src) {
2294e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org    if (src != &gEmptyRec) {
2304bce115b316ec0ecc17e7b24ad7b1086fa3a8796reed@google.com        sk_atomic_inc(&src->fRefCnt);
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return src;
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
2364e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.orgvoid SkString::validate() const {
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // make sure know one has written over our global
2384bce115b316ec0ecc17e7b24ad7b1086fa3a8796reed@google.com    SkASSERT(0 == gEmptyRec.fLength);
2394bce115b316ec0ecc17e7b24ad7b1086fa3a8796reed@google.com    SkASSERT(0 == gEmptyRec.fRefCnt);
2404bce115b316ec0ecc17e7b24ad7b1086fa3a8796reed@google.com    SkASSERT(0 == gEmptyRec.data()[0]);
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2424e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org    if (fRec != &gEmptyRec) {
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(fRec->fLength > 0);
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(fRec->fRefCnt > 0);
2454bce115b316ec0ecc17e7b24ad7b1086fa3a8796reed@google.com        SkASSERT(0 == fRec->data()[fRec->fLength]);
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fStr == c_str());
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2514e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org///////////////////////////////////////////////////////////////////////////////
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkString::SkString() : fRec(const_cast<Rec*>(&gEmptyRec)) {
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fStr = fRec->data();
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2594e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.orgSkString::SkString(size_t len) {
2608686be2fc30528167df99bcfc98ed3d9d88a76d4bsalomon@google.com    fRec = AllocRec(NULL, len);
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fStr = fRec->data();
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2664e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.orgSkString::SkString(const char text[]) {
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    size_t  len = text ? strlen(text) : 0;
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2698686be2fc30528167df99bcfc98ed3d9d88a76d4bsalomon@google.com    fRec = AllocRec(text, len);
2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fStr = fRec->data();
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2754e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.orgSkString::SkString(const char text[], size_t len) {
2768686be2fc30528167df99bcfc98ed3d9d88a76d4bsalomon@google.com    fRec = AllocRec(text, len);
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fStr = fRec->data();
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2824e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.orgSkString::SkString(const SkString& src) {
2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    src.validate();
2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRec = RefRec(src.fRec);
2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fStr = fRec->data();
2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2914e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.orgSkString::~SkString() {
2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->validate();
2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2944e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org    if (fRec->fLength) {
2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(fRec->fRefCnt > 0);
2964bce115b316ec0ecc17e7b24ad7b1086fa3a8796reed@google.com        if (sk_atomic_dec(&fRec->fRefCnt) == 1) {
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            sk_free(fRec);
2984e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org        }
2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3024e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.orgbool SkString::equals(const SkString& src) const {
3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fRec == src.fRec || this->equals(src.c_str(), src.size());
3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3064e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.orgbool SkString::equals(const char text[]) const {
3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return this->equals(text, text ? strlen(text) : 0);
3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3104e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.orgbool SkString::equals(const char text[], size_t len) const {
3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(len == 0 || text != NULL);
3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fRec->fLength == len && !memcmp(fRec->data(), text, len);
3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3164e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.orgSkString& SkString::operator=(const SkString& src) {
3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->validate();
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3194e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org    if (fRec != src.fRec) {
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkString    tmp(src);
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->swap(tmp);
3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return *this;
3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
326fc296295257a9300098df56a1e3975580e13d329bsalomon@google.comSkString& SkString::operator=(const char text[]) {
327fc296295257a9300098df56a1e3975580e13d329bsalomon@google.com    this->validate();
328fc296295257a9300098df56a1e3975580e13d329bsalomon@google.com
329fc296295257a9300098df56a1e3975580e13d329bsalomon@google.com    SkString tmp(text);
330fc296295257a9300098df56a1e3975580e13d329bsalomon@google.com    this->swap(tmp);
331fc296295257a9300098df56a1e3975580e13d329bsalomon@google.com
332fc296295257a9300098df56a1e3975580e13d329bsalomon@google.com    return *this;
333fc296295257a9300098df56a1e3975580e13d329bsalomon@google.com}
334fc296295257a9300098df56a1e3975580e13d329bsalomon@google.com
3354e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.orgvoid SkString::reset() {
3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->validate();
3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3384e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org    if (fRec->fLength) {
3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(fRec->fRefCnt > 0);
3404bce115b316ec0ecc17e7b24ad7b1086fa3a8796reed@google.com        if (sk_atomic_dec(&fRec->fRefCnt) == 1) {
3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            sk_free(fRec);
3424e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org        }
3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRec = const_cast<Rec*>(&gEmptyRec);
3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fStr = fRec->data();
3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3514e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.orgchar* SkString::writable_str() {
3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->validate();
3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3544e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org    if (fRec->fLength) {
3554e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org        if (fRec->fRefCnt > 1) {
3564bce115b316ec0ecc17e7b24ad7b1086fa3a8796reed@google.com            Rec* rec = AllocRec(fRec->data(), fRec->fLength);
3574bce115b316ec0ecc17e7b24ad7b1086fa3a8796reed@google.com            if (sk_atomic_dec(&fRec->fRefCnt) == 1) {
3584bce115b316ec0ecc17e7b24ad7b1086fa3a8796reed@google.com                // In this case after our check of fRecCnt > 1, we suddenly
3594bce115b316ec0ecc17e7b24ad7b1086fa3a8796reed@google.com                // did become the only owner, so now we have two copies of the
3604bce115b316ec0ecc17e7b24ad7b1086fa3a8796reed@google.com                // data (fRec and rec), so we need to delete one of them.
3614bce115b316ec0ecc17e7b24ad7b1086fa3a8796reed@google.com                sk_free(fRec);
3624bce115b316ec0ecc17e7b24ad7b1086fa3a8796reed@google.com            }
3634bce115b316ec0ecc17e7b24ad7b1086fa3a8796reed@google.com            fRec = rec;
3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        #ifdef SK_DEBUG
3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fStr = fRec->data();
3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        #endif
3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fRec->data();
3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3724e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.orgvoid SkString::set(const char text[]) {
3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->set(text, text ? strlen(text) : 0);
3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3764e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.orgvoid SkString::set(const char text[], size_t len) {
3778cb108803425481bf58f1eeb388cf818701c5e77reed@google.com    len = trim_size_t_to_u32(len);
3788cb108803425481bf58f1eeb388cf818701c5e77reed@google.com
3794bce115b316ec0ecc17e7b24ad7b1086fa3a8796reed@google.com    if (0 == len) {
3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->reset();
3814bce115b316ec0ecc17e7b24ad7b1086fa3a8796reed@google.com    } else if (1 == fRec->fRefCnt && len <= fRec->fLength) {
3824e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org        // should we resize if len <<<< fLength, to save RAM? (e.g. len < (fLength>>1))?
3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // just use less of the buffer without allocating a smaller one
3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        char* p = this->writable_str();
3854e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org        if (text) {
3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            memcpy(p, text, len);
3874e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org        }
3888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        p[len] = 0;
3898cb108803425481bf58f1eeb388cf818701c5e77reed@google.com        fRec->fLength = SkToU32(len);
3904bce115b316ec0ecc17e7b24ad7b1086fa3a8796reed@google.com    } else if (1 == fRec->fRefCnt && (fRec->fLength >> 2) == (len >> 2)) {
3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // we have spare room in the current allocation, so don't alloc a larger one
3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        char* p = this->writable_str();
3934e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org        if (text) {
3948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            memcpy(p, text, len);
3954e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org        }
3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        p[len] = 0;
3978cb108803425481bf58f1eeb388cf818701c5e77reed@google.com        fRec->fLength = SkToU32(len);
3984e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org    } else {
3998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkString tmp(text, len);
4008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->swap(tmp);
4018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4044e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.orgvoid SkString::setUTF16(const uint16_t src[]) {
4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int count = 0;
4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4074e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org    while (src[count]) {
4088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        count += 1;
4094e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org    }
4108cb108803425481bf58f1eeb388cf818701c5e77reed@google.com    this->setUTF16(src, count);
4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4134e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.orgvoid SkString::setUTF16(const uint16_t src[], size_t count) {
4148cb108803425481bf58f1eeb388cf818701c5e77reed@google.com    count = trim_size_t_to_u32(count);
4158cb108803425481bf58f1eeb388cf818701c5e77reed@google.com
4164bce115b316ec0ecc17e7b24ad7b1086fa3a8796reed@google.com    if (0 == count) {
4178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->reset();
4184e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org    } else if (count <= fRec->fLength) {
4194e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org        // should we resize if len <<<< fLength, to save RAM? (e.g. len < (fLength>>1))
4204e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org        if (count < fRec->fLength) {
4218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            this->resize(count);
4224e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org        }
4238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        char* p = this->writable_str();
4244e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org        for (size_t i = 0; i < count; i++) {
4258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            p[i] = SkToU8(src[i]);
4264e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org        }
4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        p[count] = 0;
4284e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org    } else {
4294e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org        SkString tmp(count); // puts a null terminator at the end of the string
4304e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org        char*    p = tmp.writable_str();
4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4324e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org        for (size_t i = 0; i < count; i++) {
4338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            p[i] = SkToU8(src[i]);
4344e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org        }
4358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->swap(tmp);
4368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4394e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.orgvoid SkString::insert(size_t offset, const char text[]) {
4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->insert(offset, text, text ? strlen(text) : 0);
4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4434e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.orgvoid SkString::insert(size_t offset, const char text[], size_t len) {
4444e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org    if (len) {
4458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        size_t length = fRec->fLength;
4464e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org        if (offset > length) {
4478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            offset = length;
4484e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org        }
4498f6ef4010f6835c5ce9ede180e50a6a58512a81eskia.committer@gmail.com
4508cb108803425481bf58f1eeb388cf818701c5e77reed@google.com        // Check if length + len exceeds 32bits, we trim len
4518cb108803425481bf58f1eeb388cf818701c5e77reed@google.com        len = check_add32(length, len);
4528cb108803425481bf58f1eeb388cf818701c5e77reed@google.com        if (0 == len) {
4538cb108803425481bf58f1eeb388cf818701c5e77reed@google.com            return;
4548cb108803425481bf58f1eeb388cf818701c5e77reed@google.com        }
4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        /*  If we're the only owner, and we have room in our allocation for the insert,
4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            do it in place, rather than allocating a new buffer.
4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            To know we have room, compare the allocated sizes
4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            beforeAlloc = SkAlign4(length + 1)
4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            afterAlloc  = SkAligh4(length + 1 + len)
4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            but SkAlign4(x) is (x + 3) >> 2 << 2
4638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            which is equivalent for testing to (length + 1 + 3) >> 2 == (length + 1 + 3 + len) >> 2
4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            and we can then eliminate the +1+3 since that doesn't affec the answer
4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        */
4664bce115b316ec0ecc17e7b24ad7b1086fa3a8796reed@google.com        if (1 == fRec->fRefCnt && (length >> 2) == ((length + len) >> 2)) {
4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            char* dst = this->writable_str();
4688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4694e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org            if (offset < length) {
4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                memmove(dst + offset + len, dst + offset, length - offset);
4714e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org            }
4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            memcpy(dst + offset, text, len);
4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            dst[length + len] = 0;
4758cb108803425481bf58f1eeb388cf818701c5e77reed@google.com            fRec->fLength = SkToU32(length + len);
4764e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org        } else {
4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            /*  Seems we should use realloc here, since that is safe if it fails
4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                (we have the original data), and might be faster than alloc/copy/free.
4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            */
4808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkString    tmp(fRec->fLength + len);
4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            char*       dst = tmp.writable_str();
4828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4834e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org            if (offset > 0) {
4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                memcpy(dst, fRec->data(), offset);
4854e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org            }
4868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            memcpy(dst + offset, text, len);
4874e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org            if (offset < fRec->fLength) {
4884e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org                memcpy(dst + offset + len, fRec->data() + offset,
4894e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org                       fRec->fLength - offset);
4904e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org            }
4918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            this->swap(tmp);
4938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
4948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4974e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.orgvoid SkString::insertUnichar(size_t offset, SkUnichar uni) {
4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    char    buffer[kMaxBytesInUTF8Sequence];
4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    size_t  len = SkUTF8_FromUnichar(uni, buffer);
5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5014e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org    if (len) {
5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->insert(offset, buffer, len);
5034e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org    }
5048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5064e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.orgvoid SkString::insertS32(size_t offset, int32_t dec) {
5078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    char    buffer[SkStrAppendS32_MaxSize];
5088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    char*   stop = SkStrAppendS32(buffer, dec);
5098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->insert(offset, buffer, stop - buffer);
5108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5124e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.orgvoid SkString::insertS64(size_t offset, int64_t dec, int minDigits) {
513d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org    char    buffer[SkStrAppendS64_MaxSize];
514d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org    char*   stop = SkStrAppendS64(buffer, dec, minDigits);
515d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org    this->insert(offset, buffer, stop - buffer);
516d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org}
517d877fdbb6e64692285c3e6532d88b9458f65b3cdvandebo@chromium.org
518d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.comvoid SkString::insertU32(size_t offset, uint32_t dec) {
519d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.com    char    buffer[SkStrAppendU32_MaxSize];
520d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.com    char*   stop = SkStrAppendU32(buffer, dec);
521d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.com    this->insert(offset, buffer, stop - buffer);
522d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.com}
523d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.com
524d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.comvoid SkString::insertU64(size_t offset, uint64_t dec, int minDigits) {
525d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.com    char    buffer[SkStrAppendU64_MaxSize];
526d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.com    char*   stop = SkStrAppendU64(buffer, dec, minDigits);
527d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.com    this->insert(offset, buffer, stop - buffer);
528d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.com}
529d88a3d83364d2158a6fad9cb295012fac0e07ea3epoger@google.com
5304e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.orgvoid SkString::insertHex(size_t offset, uint32_t hex, int minDigits) {
5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    minDigits = SkPin32(minDigits, 0, 8);
532fa06e528035dd9c4d01c1d1e17e9df1cfe99b855reed@google.com
5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static const char gHex[] = "0123456789ABCDEF";
5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    char    buffer[8];
5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    char*   p = buffer + sizeof(buffer);
5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    do {
5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *--p = gHex[hex & 0xF];
5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        hex >>= 4;
5418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        minDigits -= 1;
5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } while (hex != 0);
5434e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org
5444e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org    while (--minDigits >= 0) {
5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *--p = '0';
5464e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org    }
5478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(p >= buffer);
5498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->insert(offset, p, buffer + sizeof(buffer) - p);
5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5524e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.orgvoid SkString::insertScalar(size_t offset, SkScalar value) {
5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    char    buffer[SkStrAppendScalar_MaxSize];
5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    char*   stop = SkStrAppendScalar(buffer, value);
5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->insert(offset, buffer, stop - buffer);
5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkString::printf(const char format[], ...) {
5598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    char    buffer[kBufferSize];
5608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ARGS_TO_BUFFER(format, buffer, kBufferSize);
5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->set(buffer, strlen(buffer));
5638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkString::appendf(const char format[], ...) {
5668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    char    buffer[kBufferSize];
5678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ARGS_TO_BUFFER(format, buffer, kBufferSize);
568fa06e528035dd9c4d01c1d1e17e9df1cfe99b855reed@google.com
5698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->append(buffer, strlen(buffer));
5708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
572ce0e4efabd00b38aaaeb33457dcdb6c98e6eec12commit-bot@chromium.orgvoid SkString::appendVAList(const char format[], va_list args) {
573f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    char    buffer[kBufferSize];
574f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    VSNPRINTF(buffer, kBufferSize, format, args);
575f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com
576f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    this->append(buffer, strlen(buffer));
577f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com}
578f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com
5798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkString::prependf(const char format[], ...) {
5808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    char    buffer[kBufferSize];
5818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ARGS_TO_BUFFER(format, buffer, kBufferSize);
582fa06e528035dd9c4d01c1d1e17e9df1cfe99b855reed@google.com
5838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->prepend(buffer, strlen(buffer));
5848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
58630ba436f04e61d4505fb854d5fc56079636e0788joshualittvoid SkString::prependVAList(const char format[], va_list args) {
58730ba436f04e61d4505fb854d5fc56079636e0788joshualitt    char    buffer[kBufferSize];
58830ba436f04e61d4505fb854d5fc56079636e0788joshualitt    VSNPRINTF(buffer, kBufferSize, format, args);
58930ba436f04e61d4505fb854d5fc56079636e0788joshualitt
59030ba436f04e61d4505fb854d5fc56079636e0788joshualitt    this->prepend(buffer, strlen(buffer));
59130ba436f04e61d4505fb854d5fc56079636e0788joshualitt}
59230ba436f04e61d4505fb854d5fc56079636e0788joshualitt
59330ba436f04e61d4505fb854d5fc56079636e0788joshualitt
594fa06e528035dd9c4d01c1d1e17e9df1cfe99b855reed@google.com///////////////////////////////////////////////////////////////////////////////
5958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5964e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.orgvoid SkString::remove(size_t offset, size_t length) {
5978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    size_t size = this->size();
5988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5994e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org    if (offset < size) {
600dfb9bc41a2e68714b123b47b3e163ab2524a223bbungeman        if (length > size - offset) {
6018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            length = size - offset;
6024e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org        }
603dfb9bc41a2e68714b123b47b3e163ab2524a223bbungeman        SkASSERT(length <= size);
604dfb9bc41a2e68714b123b47b3e163ab2524a223bbungeman        SkASSERT(offset <= size - length);
6054e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org        if (length > 0) {
6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkString    tmp(size - length);
6078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            char*       dst = tmp.writable_str();
6088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            const char* src = this->c_str();
6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6104e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org            if (offset) {
6118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                memcpy(dst, src, offset);
6128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
613dfb9bc41a2e68714b123b47b3e163ab2524a223bbungeman            size_t tail = size - (offset + length);
6144e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org            if (tail) {
615dfb9bc41a2e68714b123b47b3e163ab2524a223bbungeman                memcpy(dst + offset, src + (offset + length), tail);
6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
6178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(dst[tmp.size()] == 0);
6188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            this->swap(tmp);
6198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
6208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6234e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.orgvoid SkString::swap(SkString& other) {
6248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->validate();
6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    other.validate();
6268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkTSwap<Rec*>(fRec, other.fRec);
6288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
6298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkTSwap<const char*>(fStr, other.fStr);
6308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
6318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6334e1d3acc16edb0b502cff157978235f5af627a5amike@reedtribe.org///////////////////////////////////////////////////////////////////////////////
6348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6353a1f6a06cc706b35d9d6086ffbf5135cbf42bf8atomhudson@google.comSkString SkStringPrintf(const char* format, ...) {
6363a1f6a06cc706b35d9d6086ffbf5135cbf42bf8atomhudson@google.com    SkString formattedOutput;
6373a1f6a06cc706b35d9d6086ffbf5135cbf42bf8atomhudson@google.com    char buffer[kBufferSize];
6383a1f6a06cc706b35d9d6086ffbf5135cbf42bf8atomhudson@google.com    ARGS_TO_BUFFER(format, buffer, kBufferSize);
6393a1f6a06cc706b35d9d6086ffbf5135cbf42bf8atomhudson@google.com    formattedOutput.set(buffer);
6403a1f6a06cc706b35d9d6086ffbf5135cbf42bf8atomhudson@google.com    return formattedOutput;
6413a1f6a06cc706b35d9d6086ffbf5135cbf42bf8atomhudson@google.com}
6423a1f6a06cc706b35d9d6086ffbf5135cbf42bf8atomhudson@google.com
643d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.comvoid SkStrSplit(const char* str, const char* delimiters, SkTArray<SkString>* out) {
644d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    const char* end = str + strlen(str);
645d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    while (str != end) {
646d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com        // Find a token.
647d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com        const size_t len = strcspn(str, delimiters);
648d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com        out->push_back().set(str, len);
649d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com        str += len;
650d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com        // Skip any delimiters.
651d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com        str += strspn(str, delimiters);
652d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    }
653d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com}
654d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com
6553a1f6a06cc706b35d9d6086ffbf5135cbf42bf8atomhudson@google.com#undef VSNPRINTF
65647e0a09052eb4c93a4506ebf3c64070fafc3d4b3tomhudson@google.com#undef SNPRINTF
657