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