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