1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2006 The Android Open Source Project
3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be
5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file.
6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkAtomics.h"
10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkString.h"
11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkUtils.h"
12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include <stdarg.h>
13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include <stdio.h>
14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// number of bytes (on the stack) to receive the printf result
16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic const size_t kBufferSize = 1024;
17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_BUILD_FOR_WIN
19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    #define VSNPRINTF(buffer, size, format, args) \
20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        _vsnprintf_s(buffer, size, _TRUNCATE, format, args)
21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    #define SNPRINTF    _snprintf
22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#else
23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    #define VSNPRINTF   vsnprintf
24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    #define SNPRINTF    snprintf
25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define ARGS_TO_BUFFER(format, buffer, size, written)      \
28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    do {                                                   \
29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        va_list args;                                      \
30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        va_start(args, format);                            \
31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        written = VSNPRINTF(buffer, size, format, args);   \
32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(written >= 0 && written < SkToInt(size)); \
33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        va_end(args);                                      \
34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } while (0)
35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_BUILD_FOR_WIN
37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define V_SKSTRING_PRINTF(output, format)                               \
38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    do {                                                                \
39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        va_list args;                                                   \
40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        va_start(args, format);                                         \
41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        char buffer[kBufferSize];                                       \
42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int length = _vsnprintf_s(buffer, sizeof(buffer),               \
43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                  _TRUNCATE, format, args);             \
44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        va_end(args);                                                   \
45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (length >= 0 && length < (int)sizeof(buffer)) {              \
46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            output.set(buffer, length);                                 \
47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            break;                                                      \
48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }                                                               \
49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        va_start(args, format);                                         \
50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        length = _vscprintf(format, args);                              \
51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        va_end(args);                                                   \
52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkAutoTMalloc<char> autoTMalloc((size_t)length + 1);            \
53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        va_start(args, format);                                         \
54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDEBUGCODE(int check = ) _vsnprintf_s(autoTMalloc.get(),       \
55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                               length + 1, _TRUNCATE,   \
56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                               format, args);           \
57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        va_end(args);                                                   \
58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(check == length);                                      \
59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        output.set(autoTMalloc.get(), length);                          \
60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(output[length] == '\0');                               \
61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } while (false)
62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#else
63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define V_SKSTRING_PRINTF(output, format)                               \
64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    do {                                                                \
65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        va_list args;                                                   \
66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        va_start(args, format);                                         \
67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        char buffer[kBufferSize];                                       \
68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int length = vsnprintf(buffer, sizeof(buffer), format, args);   \
69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        va_end(args);                                                   \
70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (length < 0) {                                               \
71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            break;                                                      \
72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }                                                               \
73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (length < (int)sizeof(buffer)) {                             \
74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            output.set(buffer, length);                                 \
75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            break;                                                      \
76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }                                                               \
77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkAutoTMalloc<char> autoTMalloc((size_t)length + 1);            \
78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        va_start(args, format);                                         \
79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDEBUGCODE(int check = ) vsnprintf(autoTMalloc.get(),          \
80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                            length + 1, format, args);  \
81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        va_end(args);                                                   \
82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(check == length);                                      \
83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        output.set(autoTMalloc.get(), length);                          \
84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(output[length] == '\0');                               \
85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } while (false)
86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot///////////////////////////////////////////////////////////////////////////////
89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkStrEndsWith(const char string[], const char suffixStr[]) {
91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(string);
92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(suffixStr);
93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t  strLen = strlen(string);
94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t  suffixLen = strlen(suffixStr);
95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return  strLen >= suffixLen &&
96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            !strncmp(string + strLen - suffixLen, suffixStr, suffixLen);
97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkStrEndsWith(const char string[], const char suffixChar) {
100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(string);
101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t  strLen = strlen(string);
102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (0 == strLen) {
103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return false;
104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } else {
105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return (suffixChar == string[strLen-1]);
106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotint SkStrStartsWithOneOf(const char string[], const char prefixes[]) {
110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int index = 0;
111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    do {
112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const char* limit = strchr(prefixes, '\0');
113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!strncmp(string, prefixes, limit - prefixes)) {
114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return index;
115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        prefixes = limit + 1;
117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        index++;
118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } while (prefixes[0]);
119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return -1;
120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotchar* SkStrAppendU32(char string[], uint32_t dec) {
123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDEBUGCODE(char* start = string;)
124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char    buffer[SkStrAppendU32_MaxSize];
126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char*   p = buffer + sizeof(buffer);
127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    do {
129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        *--p = SkToU8('0' + dec % 10);
130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        dec /= 10;
131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } while (dec != 0);
132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(p >= buffer);
134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char* stop = buffer + sizeof(buffer);
135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    while (p < stop) {
136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        *string++ = *p++;
137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(string - start <= SkStrAppendU32_MaxSize);
139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return string;
140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotchar* SkStrAppendS32(char string[], int32_t dec) {
143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    uint32_t udec = dec;
144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (dec < 0) {
145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        *string++ = '-';
146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        udec = ~udec + 1;  // udec = -udec, but silences some warnings that are trying to be helpful
147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return SkStrAppendU32(string, udec);
149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotchar* SkStrAppendU64(char string[], uint64_t dec, int minDigits) {
152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDEBUGCODE(char* start = string;)
153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char    buffer[SkStrAppendU64_MaxSize];
155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char*   p = buffer + sizeof(buffer);
156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    do {
158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        *--p = SkToU8('0' + (int32_t) (dec % 10));
159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        dec /= 10;
160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        minDigits--;
161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } while (dec != 0);
162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    while (minDigits > 0) {
164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        *--p = '0';
165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        minDigits--;
166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(p >= buffer);
169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t cp_len = buffer + sizeof(buffer) - p;
170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    memcpy(string, p, cp_len);
171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    string += cp_len;
172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(string - start <= SkStrAppendU64_MaxSize);
174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return string;
175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotchar* SkStrAppendS64(char string[], int64_t dec, int minDigits) {
178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    uint64_t udec = dec;
179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (dec < 0) {
180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        *string++ = '-';
181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        udec = ~udec + 1;  // udec = -udec, but silences some warnings that are trying to be helpful
182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return SkStrAppendU64(string, udec, minDigits);
184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotchar* SkStrAppendFloat(char string[], float value) {
187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // since floats have at most 8 significant digits, we limit our %g to that.
188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static const char gFormat[] = "%.8g";
189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // make it 1 larger for the terminating 0
190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char buffer[SkStrAppendScalar_MaxSize + 1];
191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int len = SNPRINTF(buffer, sizeof(buffer), gFormat, value);
192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    memcpy(string, buffer, len);
193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(len <= SkStrAppendScalar_MaxSize);
194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return string + len;
195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot///////////////////////////////////////////////////////////////////////////////
198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst SkString::Rec SkString::gEmptyRec(0, 0);
200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define SizeOfRec()     (gEmptyRec.data() - (const char*)&gEmptyRec)
202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic uint32_t trim_size_t_to_u32(size_t value) {
204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (sizeof(size_t) > sizeof(uint32_t)) {
205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (value > SK_MaxU32) {
206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            value = SK_MaxU32;
207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return (uint32_t)value;
210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic size_t check_add32(size_t base, size_t extra) {
213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(base <= SK_MaxU32);
214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (sizeof(size_t) > sizeof(uint32_t)) {
215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (base + extra > SK_MaxU32) {
216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            extra = SK_MaxU32 - base;
217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return extra;
220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<SkString::Rec> SkString::Rec::Make(const char text[], size_t len) {
223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (0 == len) {
224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return sk_sp<SkString::Rec>(const_cast<Rec*>(&gEmptyRec));
225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    len = trim_size_t_to_u32(len);
228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // add 1 for terminating 0, then align4 so we can have some slop when growing the string
229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const size_t actualLength = SizeOfRec() + SkAlign4(len + 1);
230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT_RELEASE(len < actualLength);  // Check for overflow.
231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void* storage = ::operator new (actualLength);
233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<Rec> rec(new (storage) Rec(SkToU32(len), 1));
234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (text) {
235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        memcpy(rec->data(), text, len);
236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    rec->data()[len] = 0;
238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return rec;
239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkString::Rec::ref() const {
242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (this == &SkString::gEmptyRec) {
243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return;
244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkAssertResult(this->fRefCnt.fetch_add(+1, std::memory_order_relaxed));
246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkString::Rec::unref() const {
249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (this == &SkString::gEmptyRec) {
250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return;
251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int32_t oldRefCnt = this->fRefCnt.fetch_add(-1, std::memory_order_acq_rel);
253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(oldRefCnt);
254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (1 == oldRefCnt) {
255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        delete this;
256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkString::Rec::unique() const {
260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return fRefCnt.load(std::memory_order_acquire) == 1;
261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_DEBUG
264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkString::validate() const {
265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // make sure know one has written over our global
266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(0 == gEmptyRec.fLength);
267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(0 == gEmptyRec.fRefCnt.load(std::memory_order_relaxed));
268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(0 == gEmptyRec.data()[0]);
269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (fRec.get() != &gEmptyRec) {
271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(fRec->fLength > 0);
272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(fRec->fRefCnt.load(std::memory_order_relaxed) > 0);
273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(0 == fRec->data()[fRec->fLength]);
274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot///////////////////////////////////////////////////////////////////////////////
279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkString::SkString() : fRec(const_cast<Rec*>(&gEmptyRec)) {
281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkString::SkString(size_t len) {
284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fRec = Rec::Make(nullptr, len);
285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkString::SkString(const char text[]) {
288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t  len = text ? strlen(text) : 0;
289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fRec = Rec::Make(text, len);
291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkString::SkString(const char text[], size_t len) {
294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fRec = Rec::Make(text, len);
295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkString::SkString(const SkString& src) {
298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    src.validate();
299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fRec = src.fRec;
301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkString::SkString(SkString&& src) {
304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    src.validate();
305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fRec = std::move(src.fRec);
307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    src.fRec.reset(const_cast<Rec*>(&gEmptyRec));
308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkString::~SkString() {
311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->validate();
312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkString::equals(const SkString& src) const {
315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return fRec == src.fRec || this->equals(src.c_str(), src.size());
316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkString::equals(const char text[]) const {
319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return this->equals(text, text ? strlen(text) : 0);
320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkString::equals(const char text[], size_t len) const {
323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(len == 0 || text != nullptr);
324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return fRec->fLength == len && !memcmp(fRec->data(), text, len);
326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkString& SkString::operator=(const SkString& src) {
329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->validate();
330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (fRec != src.fRec) {
332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkString    tmp(src);
333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->swap(tmp);
334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return *this;
336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkString& SkString::operator=(SkString&& src) {
339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->validate();
340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (fRec != src.fRec) {
342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->swap(src);
343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return *this;
345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkString& SkString::operator=(const char text[]) {
348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->validate();
349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkString tmp(text);
351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->swap(tmp);
352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return *this;
354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkString::reset() {
357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->validate();
358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fRec.reset(const_cast<Rec*>(&gEmptyRec));
359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotchar* SkString::writable_str() {
362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->validate();
363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (fRec->fLength) {
365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!fRec->unique()) {
366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fRec = Rec::Make(fRec->data(), fRec->fLength);
367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return fRec->data();
370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkString::set(const char text[]) {
373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->set(text, text ? strlen(text) : 0);
374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkString::set(const char text[], size_t len) {
377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    len = trim_size_t_to_u32(len);
378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool unique = fRec->unique();
379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (0 == len) {
380fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->reset();
381fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } else if (unique && len <= fRec->fLength) {
382fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // should we resize if len <<<< fLength, to save RAM? (e.g. len < (fLength>>1))?
383fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // just use less of the buffer without allocating a smaller one
384fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        char* p = this->writable_str();
385fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (text) {
386fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            memcpy(p, text, len);
387fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
388fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        p[len] = 0;
389fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fRec->fLength = SkToU32(len);
390fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } else if (unique && (fRec->fLength >> 2) == (len >> 2)) {
391fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // we have spare room in the current allocation, so don't alloc a larger one
392fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        char* p = this->writable_str();
393fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (text) {
394fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            memcpy(p, text, len);
395fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
396fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        p[len] = 0;
397fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fRec->fLength = SkToU32(len);
398fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } else {
399fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkString tmp(text, len);
400fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->swap(tmp);
401fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
402fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
403fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
404fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkString::setUTF16(const uint16_t src[]) {
405fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int count = 0;
406fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
407fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    while (src[count]) {
408fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        count += 1;
409fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
410fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->setUTF16(src, count);
411fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
412fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
413fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkString::setUTF16(const uint16_t src[], size_t count) {
414fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    count = trim_size_t_to_u32(count);
415fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
416fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (0 == count) {
417fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->reset();
418fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } else if (count <= fRec->fLength) {
419fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // should we resize if len <<<< fLength, to save RAM? (e.g. len < (fLength>>1))
420fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (count < fRec->fLength) {
421fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            this->resize(count);
422fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
423fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        char* p = this->writable_str();
424fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (size_t i = 0; i < count; i++) {
425fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            p[i] = SkToU8(src[i]);
426fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
427fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        p[count] = 0;
428fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } else {
429fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkString tmp(count); // puts a null terminator at the end of the string
430fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        char*    p = tmp.writable_str();
431fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
432fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (size_t i = 0; i < count; i++) {
433fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            p[i] = SkToU8(src[i]);
434fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
435fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->swap(tmp);
436fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
437fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
438fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
439fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkString::insert(size_t offset, const char text[]) {
440fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->insert(offset, text, text ? strlen(text) : 0);
441fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
442fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
443fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkString::insert(size_t offset, const char text[], size_t len) {
444fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (len) {
445fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        size_t length = fRec->fLength;
446fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (offset > length) {
447fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            offset = length;
448fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
449fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
450fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Check if length + len exceeds 32bits, we trim len
451fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        len = check_add32(length, len);
452fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (0 == len) {
453fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return;
454fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
455fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
456fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        /*  If we're the only owner, and we have room in our allocation for the insert,
457fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            do it in place, rather than allocating a new buffer.
458fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
459fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            To know we have room, compare the allocated sizes
460fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            beforeAlloc = SkAlign4(length + 1)
461fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            afterAlloc  = SkAligh4(length + 1 + len)
462fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            but SkAlign4(x) is (x + 3) >> 2 << 2
463fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            which is equivalent for testing to (length + 1 + 3) >> 2 == (length + 1 + 3 + len) >> 2
464fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            and we can then eliminate the +1+3 since that doesn't affec the answer
465fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        */
466fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fRec->unique() && (length >> 2) == ((length + len) >> 2)) {
467fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            char* dst = this->writable_str();
468fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
469fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (offset < length) {
470fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                memmove(dst + offset + len, dst + offset, length - offset);
471fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
472fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            memcpy(dst + offset, text, len);
473fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
474fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            dst[length + len] = 0;
475fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fRec->fLength = SkToU32(length + len);
476fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else {
477fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            /*  Seems we should use realloc here, since that is safe if it fails
478fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                (we have the original data), and might be faster than alloc/copy/free.
479fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            */
480fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkString    tmp(fRec->fLength + len);
481fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            char*       dst = tmp.writable_str();
482fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
483fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (offset > 0) {
484fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                memcpy(dst, fRec->data(), offset);
485fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
486fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            memcpy(dst + offset, text, len);
487fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (offset < fRec->fLength) {
488fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                memcpy(dst + offset + len, fRec->data() + offset,
489fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                       fRec->fLength - offset);
490fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
491fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
492fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            this->swap(tmp);
493fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
494fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
495fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
496fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
497fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkString::insertUnichar(size_t offset, SkUnichar uni) {
498fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char    buffer[kMaxBytesInUTF8Sequence];
499fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t  len = SkUTF8_FromUnichar(uni, buffer);
500fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
501fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (len) {
502fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->insert(offset, buffer, len);
503fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
504fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
505fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
506fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkString::insertS32(size_t offset, int32_t dec) {
507fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char    buffer[SkStrAppendS32_MaxSize];
508fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char*   stop = SkStrAppendS32(buffer, dec);
509fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->insert(offset, buffer, stop - buffer);
510fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
511fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
512fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkString::insertS64(size_t offset, int64_t dec, int minDigits) {
513fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char    buffer[SkStrAppendS64_MaxSize];
514fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char*   stop = SkStrAppendS64(buffer, dec, minDigits);
515fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->insert(offset, buffer, stop - buffer);
516fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
517fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
518fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkString::insertU32(size_t offset, uint32_t dec) {
519fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char    buffer[SkStrAppendU32_MaxSize];
520fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char*   stop = SkStrAppendU32(buffer, dec);
521fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->insert(offset, buffer, stop - buffer);
522fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
523fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
524fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkString::insertU64(size_t offset, uint64_t dec, int minDigits) {
525fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char    buffer[SkStrAppendU64_MaxSize];
526fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char*   stop = SkStrAppendU64(buffer, dec, minDigits);
527fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->insert(offset, buffer, stop - buffer);
528fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
529fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
530fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkString::insertHex(size_t offset, uint32_t hex, int minDigits) {
531fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    minDigits = SkTPin(minDigits, 0, 8);
532fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
533fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char    buffer[8];
534fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char*   p = buffer + sizeof(buffer);
535fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
536fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    do {
537fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        *--p = SkHexadecimalDigits::gUpper[hex & 0xF];
538fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        hex >>= 4;
539fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        minDigits -= 1;
540fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } while (hex != 0);
541fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
542fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    while (--minDigits >= 0) {
543fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        *--p = '0';
544fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
545fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
546fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(p >= buffer);
547fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->insert(offset, p, buffer + sizeof(buffer) - p);
548fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
549fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
550fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkString::insertScalar(size_t offset, SkScalar value) {
551fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char    buffer[SkStrAppendScalar_MaxSize];
552fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char*   stop = SkStrAppendScalar(buffer, value);
553fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->insert(offset, buffer, stop - buffer);
554fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
555fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
556fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkString::printf(const char format[], ...) {
557fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    V_SKSTRING_PRINTF((*this), format);
558fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
559fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
560fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkString::appendf(const char format[], ...) {
561fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char    buffer[kBufferSize];
562fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int length;
563fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    ARGS_TO_BUFFER(format, buffer, kBufferSize, length);
564fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
565fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->append(buffer, length);
566fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
567fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
568fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkString::appendVAList(const char format[], va_list args) {
569fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char    buffer[kBufferSize];
570fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int length = VSNPRINTF(buffer, kBufferSize, format, args);
571fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(length >= 0 && length < SkToInt(kBufferSize));
572fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
573fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->append(buffer, length);
574fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
575fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
576fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkString::prependf(const char format[], ...) {
577fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char    buffer[kBufferSize];
578fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int length;
579fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    ARGS_TO_BUFFER(format, buffer, kBufferSize, length);
580fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
581fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->prepend(buffer, length);
582fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
583fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
584fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkString::prependVAList(const char format[], va_list args) {
585fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char    buffer[kBufferSize];
586fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int length = VSNPRINTF(buffer, kBufferSize, format, args);
587fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(length >= 0 && length < SkToInt(kBufferSize));
588fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
589fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->prepend(buffer, length);
590fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
591fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
592fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
593fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot///////////////////////////////////////////////////////////////////////////////
594fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
595fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkString::remove(size_t offset, size_t length) {
596fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t size = this->size();
597fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
598fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (offset < size) {
599fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (length > size - offset) {
600fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            length = size - offset;
601fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
602fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(length <= size);
603fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(offset <= size - length);
604fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (length > 0) {
605fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkString    tmp(size - length);
606fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            char*       dst = tmp.writable_str();
607fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            const char* src = this->c_str();
608fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
609fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (offset) {
610fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                memcpy(dst, src, offset);
611fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
612fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            size_t tail = size - (offset + length);
613fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (tail) {
614fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                memcpy(dst + offset, src + (offset + length), tail);
615fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
616fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkASSERT(dst[tmp.size()] == 0);
617fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            this->swap(tmp);
618fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
619fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
620fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
621fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
622fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkString::swap(SkString& other) {
623fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    this->validate();
624fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    other.validate();
625fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
626fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkTSwap(fRec, other.fRec);
627fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
628fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
629fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot///////////////////////////////////////////////////////////////////////////////
630fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
631fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkString SkStringPrintf(const char* format, ...) {
632fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkString formattedOutput;
633fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    V_SKSTRING_PRINTF(formattedOutput, format);
634fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return formattedOutput;
635fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
636fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
637fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkStrSplit(const char* str, const char* delimiters, SkStrSplitMode splitMode,
638fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkTArray<SkString>* out) {
639fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (splitMode == kCoalesce_SkStrSplitMode) {
640fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Skip any delimiters.
641fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        str += strspn(str, delimiters);
642fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
643fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!*str) {
644fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return;
645fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
646fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
647fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    while (true) {
648fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Find a token.
649fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const size_t len = strcspn(str, delimiters);
650fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (splitMode == kStrict_SkStrSplitMode || len > 0) {
651fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            out->push_back().set(str, len);
652fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            str += len;
653fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
654fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
655fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!*str) {
656fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return;
657fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
658fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (splitMode == kCoalesce_SkStrSplitMode) {
659fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // Skip any delimiters.
660fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            str += strspn(str, delimiters);
661fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else {
662fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // Skip one delimiter.
663fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            str += 1;
664fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
665fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
666fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
667fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
668fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#undef VSNPRINTF
669fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#undef SNPRINTF
670