SkString.cpp revision 05b6b4d746867a9fb02e14edfe1bf3685abeb813
10910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/* libs/graphics/sgl/SkString.cpp
20910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project**
30910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project** Copyright 2006, The Android Open Source Project
40910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project**
505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger** Licensed under the Apache License, Version 2.0 (the "License");
605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger** you may not use this file except in compliance with the License.
705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger** You may obtain a copy of the License at
80910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project**
905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger**     http://www.apache.org/licenses/LICENSE-2.0
100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project**
1105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger** Unless required by applicable law or agreed to in writing, software
1205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger** distributed under the License is distributed on an "AS IS" BASIS,
1305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger** See the License for the specific language governing permissions and
150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project** limitations under the License.
160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/
170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkString.h"
190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkFixed.h"
200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkUtils.h"
210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include <stdarg.h>
2205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#include <stdio.h>
2305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
2405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger// number of bytes (on the stack) to receive the printf result
2505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergerstatic const size_t kBufferSize = 256;
2605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
2705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#ifdef SK_BUILD_FOR_WIN
2805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    #define VSNPRINTF   _vsnprintf
2905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    #define SNPRINTF    _snprintf
3005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#else
3105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    #define VSNPRINTF   vsnprintf
3205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    #define SNPRINTF    snprintf
3305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#endif
3405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
3505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#define ARGS_TO_BUFFER(format, buffer, size)        \
3605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    do {                                            \
3705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        va_list args;                               \
3805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        va_start(args, format);                     \
3905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        VSNPRINTF(buffer, size, format, args);      \
4005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        va_end(args);                               \
4105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    } while (0)
4205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
4305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkStrStartsWith(const char string[], const char prefix[])
460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(string);
480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(prefix);
490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return !strncmp(string, prefix, strlen(prefix));
500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkStrEndsWith(const char string[], const char suffix[])
530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(string);
550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(suffix);
560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    size_t  strLen = strlen(string);
570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    size_t  suffixLen = strlen(suffix);
580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return  strLen >= suffixLen &&
590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            !strncmp(string + strLen - suffixLen, suffix, suffixLen);
600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectint SkStrStartsWithOneOf(const char string[], const char prefixes[])
630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int index = 0;
650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    do {
660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const char* limit = strchr(prefixes, '\0');
670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (!strncmp(string, prefixes, limit - prefixes))
680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return index;
690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        prefixes = limit + 1;
700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        index++;
710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    } while (prefixes[0]);
720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return -1;
730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectchar* SkStrAppendS32(char string[], int32_t dec)
760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(char* start = string;)
780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    char    buffer[SkStrAppendS32_MaxSize];
800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    char*   p = buffer + sizeof(buffer);
810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool    neg = false;
820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (dec < 0)
840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        neg = true;
860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        dec = -dec;
870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    do {
890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *--p = SkToU8('0' + dec % 10);
900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        dec /= 10;
910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    } while (dec != 0);
920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (neg)
930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *--p = '-';
940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(p >= buffer);
960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    char* stop = buffer + sizeof(buffer);
970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    while (p < stop)
980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *string++ = *p++;
990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(string - start <= SkStrAppendS32_MaxSize);
1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return string;
1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerchar* SkStrAppendS64(char string[], int64_t dec, int minDigits)
10540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger{
10640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkDEBUGCODE(char* start = string;)
10740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
10840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    char    buffer[SkStrAppendS64_MaxSize];
10940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    char*   p = buffer + sizeof(buffer);
11040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    bool    neg = false;
11140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
11240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (dec < 0) {
11340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        neg = true;
11440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        dec = -dec;
11540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
11640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    do {
11740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        *--p = SkToU8('0' + dec % 10);
11840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        dec /= 10;
11940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        minDigits--;
12040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    } while (dec != 0);
12140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    while (minDigits > 0) {
12240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        *--p = '0';
12340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        minDigits--;
12440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
12540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (neg)
12640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        *--p = '-';
12740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
12840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkASSERT(p >= buffer);
12940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    size_t cp_len = buffer + sizeof(buffer) - p;
13040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    memcpy(string, p, cp_len);
13140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    string += cp_len;
13240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
13340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkASSERT(string - start <= SkStrAppendS64_MaxSize);
13440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return string;
13540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
13640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
13705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#ifdef SK_CAN_USE_FLOAT
13805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergerchar* SkStrAppendFloat(char string[], float value)
1390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
14005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    // since floats have at most 8 significant digits, we limit our %g to that.
14105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    static const char gFormat[] = "%.8g";
14205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    // make it 1 larger for the terminating 0
14305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    char buffer[SkStrAppendScalar_MaxSize + 1];
14405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    int len = SNPRINTF(buffer, sizeof(buffer), gFormat, value);
14505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    memcpy(string, buffer, len);
14605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    SkASSERT(len <= SkStrAppendScalar_MaxSize);
14705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    return string + len;
14805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger}
14905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#endif
1500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
15105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergerchar* SkStrAppendFixed(char string[], SkFixed x)
15205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger{
15305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    SkDEBUGCODE(char* start = string;)
1540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (x < 0)
1550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
1560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *string++ = '-';
1570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        x = -x;
1580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned frac = x & 0xFFFF;
1610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    x >>= 16;
1620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (frac == 0xFFFF) // need to do this to "round up", since 65535/65536 is closer to 1 than to .9999
1630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
1640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        x += 1;
1650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        frac = 0;
1660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    string = SkStrAppendS32(string, x);
1680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // now handle the fractional part (if any)
1700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (frac)
1710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
1720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        static const uint16_t   gTens[] = { 1000, 100, 10, 1 };
1730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const uint16_t*         tens = gTens;
1740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        x = SkFixedRound(frac * 10000);
1760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(x <= 10000);
1770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (x == 10000) {
1780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            x -= 1;
1790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
1800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *string++ = '.';
1810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        do {
1820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            unsigned powerOfTen = *tens++;
1830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            *string++ = SkToU8('0' + x / powerOfTen);
1840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            x %= powerOfTen;
1850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        } while (x != 0);
1860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
18705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
1880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(string - start <= SkStrAppendScalar_MaxSize);
1890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return string;
1900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project////////////////////////////////////////////////////////////////////////////////////
1930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define kMaxRefCnt_SkString     SK_MaxU16
1950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// the 3 values are [length] [refcnt] [terminating zero data]
1970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectconst SkString::Rec SkString::gEmptyRec = { 0, 0, 0 };
1980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SizeOfRec()     (gEmptyRec.data() - (const char*)&gEmptyRec)
2000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkString::Rec* SkString::AllocRec(const char text[], U16CPU len)
2020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
2030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    Rec* rec;
2040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (len == 0)
2060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec = const_cast<Rec*>(&gEmptyRec);
2070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    else
2080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
2090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // add 1 for terminating 0, then align4 so we can have some slop when growing the string
2100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec = (Rec*)sk_malloc_throw(SizeOfRec() + SkAlign4(len + 1));
2110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec->fLength = SkToU16(len);
2120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec->fRefCnt = 1;
2130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (text)
2140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            memcpy(rec->data(), text, len);
2150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec->data()[len] = 0;
2160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
2170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return rec;
2180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkString::Rec* SkString::RefRec(Rec* src)
2210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
2220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (src != &gEmptyRec)
2230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
2240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (src->fRefCnt == kMaxRefCnt_SkString) {
2250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            src = AllocRec(src->data(), src->fLength);
2260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        } else
2270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            src->fRefCnt += 1;
2280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
2290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return src;
2300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG
2330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkString::validate() const
2340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
2350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // make sure know one has written over our global
2360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(gEmptyRec.fLength == 0);
2370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(gEmptyRec.fRefCnt == 0);
2380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(gEmptyRec.data()[0] == 0);
2390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fRec != &gEmptyRec)
2410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
2420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(fRec->fLength > 0);
2430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(fRec->fRefCnt > 0);
2440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(fRec->data()[fRec->fLength] == 0);
2450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
2460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(fStr == c_str());
2470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
2490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////
2510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkString::SkString() : fRec(const_cast<Rec*>(&gEmptyRec)) {
2530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG
2540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fStr = fRec->data();
2550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
2560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkString::SkString(size_t len)
2590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
2600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(SkToU16(len) == len);  // can't handle larger than 64K
2610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fRec = AllocRec(NULL, (U16CPU)len);
2630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG
2640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fStr = fRec->data();
2650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
2660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkString::SkString(const char text[])
2690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
2700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    size_t  len = text ? strlen(text) : 0;
2710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fRec = AllocRec(text, (U16CPU)len);
2730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG
2740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fStr = fRec->data();
2750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
2760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkString::SkString(const char text[], size_t len)
2790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
2800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fRec = AllocRec(text, (U16CPU)len);
2810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG
2820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fStr = fRec->data();
2830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
2840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkString::SkString(const SkString& src)
2870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
2880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    src.validate();
2890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fRec = RefRec(src.fRec);
2910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG
2920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fStr = fRec->data();
2930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
2940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkString::~SkString()
2970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
2980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->validate();
2990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fRec->fLength)
3010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
3020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(fRec->fRefCnt > 0);
3030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (--fRec->fRefCnt == 0)
3040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            sk_free(fRec);
3050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
3060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkString::equals(const SkString& src) const
3090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
3100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return fRec == src.fRec || this->equals(src.c_str(), src.size());
3110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkString::equals(const char text[]) const
3140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
3150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return this->equals(text, text ? strlen(text) : 0);
3160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkString::equals(const char text[], size_t len) const
3190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
3200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(len == 0 || text != NULL);
3210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return fRec->fLength == len && !memcmp(fRec->data(), text, len);
3230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkString& SkString::operator=(const SkString& src)
3260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
3270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->validate();
3280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fRec != src.fRec)
3300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
3310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkString    tmp(src);
3320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        this->swap(tmp);
3330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
3340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return *this;
3350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkString::reset()
3380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
3390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->validate();
3400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fRec->fLength)
3420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
3430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(fRec->fRefCnt > 0);
3440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (--fRec->fRefCnt == 0)
3450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            sk_free(fRec);
3460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
3470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fRec = const_cast<Rec*>(&gEmptyRec);
3490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG
3500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fStr = fRec->data();
3510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
3520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectchar* SkString::writable_str()
3550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
3560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->validate();
3570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fRec->fLength)
3590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
3600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (fRec->fRefCnt > 1)
3610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
3620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fRec->fRefCnt -= 1;
3630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fRec = AllocRec(fRec->data(), fRec->fLength);
3640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        #ifdef SK_DEBUG
3650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fStr = fRec->data();
3660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        #endif
3670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
3680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
3690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return fRec->data();
3700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkString::set(const char text[])
3730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
3740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->set(text, text ? strlen(text) : 0);
3750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkString::set(const char text[], size_t len)
3780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
3790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (len == 0)
3800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        this->reset();
3810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    else if (fRec->fRefCnt == 1 && len <= fRec->fLength)    // should we resize if len <<<< fLength, to save RAM? (e.g. len < (fLength>>1))
3820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
3830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // just use less of the buffer without allocating a smaller one
3840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        char* p = this->writable_str();
3850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (text)
3860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            memcpy(p, text, len);
3870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        p[len] = 0;
3880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fRec->fLength = SkToU16(len);
3890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
3900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    else if (fRec->fRefCnt == 1 && ((unsigned)fRec->fLength >> 2) == (len >> 2))
3910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
3920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // we have spare room in the current allocation, so don't alloc a larger one
3930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        char* p = this->writable_str();
3940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (text)
3950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            memcpy(p, text, len);
3960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        p[len] = 0;
3970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fRec->fLength = SkToU16(len);
3980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
3990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    else
4000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
4010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkString tmp(text, len);
4020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        this->swap(tmp);
4030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
4040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
4050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkString::setUTF16(const uint16_t src[])
4070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
4080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int count = 0;
4090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    while (src[count])
4110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        count += 1;
4120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    setUTF16(src, count);
4130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
4140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkString::setUTF16(const uint16_t src[], size_t count)
4160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
4170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (count == 0)
4180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        this->reset();
4190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    else if (count <= fRec->fLength)    // should we resize if len <<<< fLength, to save RAM? (e.g. len < (fLength>>1))
4200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
4210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (count < fRec->fLength)
4220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            this->resize(count);
4230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        char* p = this->writable_str();
4240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        for (size_t i = 0; i < count; i++)
4250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            p[i] = SkToU8(src[i]);
4260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        p[count] = 0;
4270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
4280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    else
4290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
4300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkString    tmp(count); // puts a null terminator at the end of the string
4310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        char*       p = tmp.writable_str();
4320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        for (size_t i = 0; i < count; i++)
4340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            p[i] = SkToU8(src[i]);
4350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        this->swap(tmp);
4370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
4380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
4390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkString::insert(size_t offset, const char text[])
4410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
4420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->insert(offset, text, text ? strlen(text) : 0);
4430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
4440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkString::insert(size_t offset, const char text[], size_t len)
4460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
4470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (len)
4480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
4490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        size_t length = fRec->fLength;
4500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (offset > length)
4510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            offset = length;
4520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        /*  If we're the only owner, and we have room in our allocation for the insert,
4540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            do it in place, rather than allocating a new buffer.
4550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            To know we have room, compare the allocated sizes
4570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            beforeAlloc = SkAlign4(length + 1)
4580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            afterAlloc  = SkAligh4(length + 1 + len)
4590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            but SkAlign4(x) is (x + 3) >> 2 << 2
4600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            which is equivalent for testing to (length + 1 + 3) >> 2 == (length + 1 + 3 + len) >> 2
4610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            and we can then eliminate the +1+3 since that doesn't affec the answer
4620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        */
4630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (fRec->fRefCnt == 1 && (length >> 2) == ((length + len) >> 2))
4640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
4650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            char* dst = this->writable_str();
4660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (offset < length)
4680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                memmove(dst + offset + len, dst + offset, length - offset);
4690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            memcpy(dst + offset, text, len);
4700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            dst[length + len] = 0;
4720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fRec->fLength = SkToU16(length + len);
4730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
4740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        else
4750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
4760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            /*  Seems we should use realloc here, since that is safe if it fails
4770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                (we have the original data), and might be faster than alloc/copy/free.
4780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            */
4790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkString    tmp(fRec->fLength + len);
4800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            char*       dst = tmp.writable_str();
4810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (offset > 0)
4830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                memcpy(dst, fRec->data(), offset);
4840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            memcpy(dst + offset, text, len);
4850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (offset < fRec->fLength)
4860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                memcpy(dst + offset + len, fRec->data() + offset, fRec->fLength - offset);
4870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            this->swap(tmp);
4890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
4900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
4910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
4920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkString::insertUnichar(size_t offset, SkUnichar uni)
4940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
4950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    char    buffer[kMaxBytesInUTF8Sequence];
4960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    size_t  len = SkUTF8_FromUnichar(uni, buffer);
4970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (len)
4990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        this->insert(offset, buffer, len);
5000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
5010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkString::insertS32(size_t offset, int32_t dec)
5030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
5040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    char    buffer[SkStrAppendS32_MaxSize];
5050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    char*   stop = SkStrAppendS32(buffer, dec);
5060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->insert(offset, buffer, stop - buffer);
5070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
5080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
50940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergervoid SkString::insertS64(size_t offset, int64_t dec, int minDigits)
51040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger{
51140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    char    buffer[SkStrAppendS64_MaxSize];
51240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    char*   stop = SkStrAppendS64(buffer, dec, minDigits);
51340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    this->insert(offset, buffer, stop - buffer);
51440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
51540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
5160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkString::insertHex(size_t offset, uint32_t hex, int minDigits)
5170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
5180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    minDigits = SkPin32(minDigits, 0, 8);
51905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
5200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    static const char gHex[] = "0123456789ABCDEF";
5210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    char    buffer[8];
5230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    char*   p = buffer + sizeof(buffer);
5240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    do {
5260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *--p = gHex[hex & 0xF];
5270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        hex >>= 4;
5280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        minDigits -= 1;
5290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    } while (hex != 0);
5300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    while (--minDigits >= 0)
5310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *--p = '0';
5320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(p >= buffer);
5340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->insert(offset, p, buffer + sizeof(buffer) - p);
5350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
5360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkString::insertScalar(size_t offset, SkScalar value)
5380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
5390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    char    buffer[SkStrAppendScalar_MaxSize];
5400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    char*   stop = SkStrAppendScalar(buffer, value);
5410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->insert(offset, buffer, stop - buffer);
5420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
5430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkString::printf(const char format[], ...) {
5450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    char    buffer[kBufferSize];
5460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    ARGS_TO_BUFFER(format, buffer, kBufferSize);
5470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->set(buffer, strlen(buffer));
5490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
5500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkString::appendf(const char format[], ...) {
5520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    char    buffer[kBufferSize];
5530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    ARGS_TO_BUFFER(format, buffer, kBufferSize);
55405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
5550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->append(buffer, strlen(buffer));
5560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
5570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkString::prependf(const char format[], ...) {
5590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    char    buffer[kBufferSize];
5600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    ARGS_TO_BUFFER(format, buffer, kBufferSize);
56105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
5620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->prepend(buffer, strlen(buffer));
5630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
5640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#undef VSNPRINTF
5660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
56705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
5680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkString::remove(size_t offset, size_t length)
5700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
5710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    size_t size = this->size();
5720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (offset < size)
5740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
5750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (offset + length > size)
5760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            length = size - offset;
5770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (length > 0)
5780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
5790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(size > length);
5800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkString    tmp(size - length);
5810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            char*       dst = tmp.writable_str();
5820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            const char* src = this->c_str();
5830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (offset)
5850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            {
5860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkASSERT(offset <= tmp.size());
5870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                memcpy(dst, src, offset);
5880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
5890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            size_t tail = size - offset - length;
5900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT((int32_t)tail >= 0);
5910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (tail)
5920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            {
5930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        //      SkASSERT(offset + length <= tmp.size());
5940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                memcpy(dst + offset, src + offset + length, tail);
5950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
5960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(dst[tmp.size()] == 0);
5970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            this->swap(tmp);
5980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
5990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
6000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
6010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkString::swap(SkString& other)
6030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
6040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->validate();
6050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    other.validate();
6060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkTSwap<Rec*>(fRec, other.fRec);
6080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG
6090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkTSwap<const char*>(fStr, other.fStr);
6100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
6110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
6120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////////
6140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkAutoUCS2::SkAutoUCS2(const char utf8[])
6160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
6170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    size_t len = strlen(utf8);
6180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fUCS2 = (uint16_t*)sk_malloc_throw((len + 1) * sizeof(uint16_t));
6190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    uint16_t* dst = fUCS2;
6210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    for (;;)
6220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
6230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkUnichar   uni = SkUTF8_NextUnichar(&utf8);
6240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *dst++ = SkToU16(uni);
6250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (uni == 0)
6260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
6270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
6280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fCount = (int)(dst - fUCS2);
6290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
6300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkAutoUCS2::~SkAutoUCS2()
6320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
6330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    delete[] fUCS2;
6340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
635