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