43 va_copy(argsCopy,
args);
46 SkDebugf(
"SkString: vsnprintf reported error.");
48 return {stackBuffer, 0};
50 if (outLength <
SIZE) {
52 return {stackBuffer, outLength};
58 heapBuffer->
set(
nullptr, outLength);
59 char* heapBufferDest = heapBuffer->
data();
60 SkDEBUGCODE(
int checkLength =) std::vsnprintf(heapBufferDest, outLength + 1,
format, argsCopy);
63 return {heapBufferDest, outLength};
71 size_t strLen = strlen(
string);
72 size_t suffixLen = strlen(suffixStr);
73 return strLen >= suffixLen &&
74 !strncmp(
string + strLen - suffixLen, suffixStr, suffixLen);
79 size_t strLen = strlen(
string);
83 return (suffixChar ==
string[strLen-1]);
90 const char* limit = strchr(prefixes,
'\0');
91 if (!strncmp(
string, prefixes, limit - prefixes)) {
96 }
while (prefixes[0]);
107 *--p =
SkToU8(
'0' + dec % 10);
113 memcpy(
string, p, cp_len);
136 *--p =
SkToU8(
'0' + (int32_t) (dec % 10));
141 while (minDigits > 0) {
148 memcpy(
string, p, cp_len);
168 strcpy(
string,
"nan");
173 strcpy(
string,
"inf");
176 strcpy(
string,
"-inf");
182 static const char gFormat[] =
"%.8g";
186 memcpy(
string,
buffer, len);
193const SkString::Rec SkString::gEmptyRec(0, 0);
195#define SizeOfRec() (gEmptyRec.data() - (const char*)&gEmptyRec)
198 if (
sizeof(
size_t) >
sizeof(uint32_t)) {
199 if (
value > UINT32_MAX) {
203 return (uint32_t)
value;
208 if (
sizeof(
size_t) >
sizeof(uint32_t)) {
209 if (
base + extra > UINT32_MAX) {
210 extra = UINT32_MAX -
base;
223 uint32_t stringLen = safe.
castTo<uint32_t>(
len);
225 size_t allocationSize = safe.
add(len,
SizeOfRec() +
sizeof(char));
227 allocationSize = safe.
alignUp(allocationSize, 4);
231 void* storage = ::operator
new (allocationSize);
232 sk_sp<Rec> rec(
new (storage) Rec(stringLen, 1));
234 memcpy(rec->data(),
text, len);
236 rec->data()[
len] = 0;
240void SkString::Rec::ref()
const {
241 if (
this == &SkString::gEmptyRec) {
244 SkAssertResult(this->fRefCnt.fetch_add(+1, std::memory_order_relaxed));
247void SkString::Rec::unref()
const {
248 if (
this == &SkString::gEmptyRec) {
251 int32_t oldRefCnt = this->fRefCnt.fetch_add(-1, std::memory_order_acq_rel);
253 if (1 == oldRefCnt) {
258bool SkString::Rec::unique()
const {
259 return fRefCnt.load(std::memory_order_acquire) == 1;
263int32_t SkString::Rec::getRefCnt()
const {
264 return fRefCnt.load(std::memory_order_relaxed);
267const SkString& SkString::validate()
const {
270 SkASSERT(0 == gEmptyRec.getRefCnt());
273 if (fRec.
get() != &gEmptyRec) {
276 SkASSERT(0 == fRec->data()[fRec->fLength]);
282 const_cast<const SkString*
>(
this)->validate();
293 fRec = Rec::Make(
nullptr, len);
297 size_t len =
text ? strlen(
text) : 0;
299 fRec = Rec::Make(
text, len);
303 fRec = Rec::Make(
text, len);
309 src.fRec.reset(
const_cast<Rec*
>(&gEmptyRec));
313 fRec = Rec::Make(src.c_str(), src.size());
317 fRec = Rec::Make(src.data(), src.length());
325 return fRec == src.fRec || this->
equals(src.
c_str(), src.size());
347 if (fRec != src.fRec) {
360 fRec.
reset(
const_cast<Rec*
>(&gEmptyRec));
367 if (!fRec->unique()) {
368 fRec = Rec::Make(fRec->data(), fRec->fLength);
378 }
else if (fRec->unique() && ((len >> 2) <= (fRec->fLength >> 2))) {
380 char* p = this->
data();
385 char* dest = newString.
data();
386 int copyLen = std::min<uint32_t>(len, this->
size());
387 memcpy(dest, this->
c_str(), copyLen);
388 dest[copyLen] =
'\0';
389 this->
swap(newString);
401 }
else if (fRec->unique() && ((len >> 2) <= (fRec->fLength >> 2))) {
403 char* p = this->
data();
405 memcpy(p,
text, len);
421 size_t length = fRec->fLength;
442 if (fRec->unique() && (
length >> 2) == ((
length + len) >> 2)) {
443 char* dst = this->
data();
457 char* dst = tmp.
data();
460 memcpy(dst, fRec->data(),
offset);
463 if (offset < fRec->fLength) {
507 minDigits =
SkTPin(minDigits, 0, 8);
518 while (--minDigits >= 0) {
545 if (
result.fText == stackBuffer) {
603 char* dst = tmp.
data();
604 const char* src = this->
c_str();
624 swap(fRec, other.fRec);
635 return formattedOutput;
#define SkAssertResult(cond)
#define SkASSERT_RELEASE(cond)
#define SK_PRINTF_LIKE(A, B)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static bool SkIsFinite(T x, Pack... values)
static int sk_careful_memcmp(const void *a, const void *b, size_t len)
static size_t check_add32(size_t base, size_t extra)
char * SkStrAppendScalar(char string[], SkScalar value)
char * SkStrAppendU32(char string[], uint32_t dec)
char * SkStrAppendS64(char string[], int64_t dec, int minDigits)
static const size_t kBufferSize
char * SkStrAppendS32(char string[], int32_t dec)
bool SkStrEndsWith(const char string[], const char suffixStr[])
char * SkStrAppendU64(char string[], uint64_t dec, int minDigits)
static uint32_t trim_size_t_to_u32(size_t value)
static StringBuffer apply_format_string(const char *format, va_list args, char(&stackBuffer)[SIZE], SkString *heapBuffer) SK_PRINTF_LIKE(1
int SkStrStartsWithOneOf(const char string[], const char prefixes[])
static constexpr int kSkStrAppendS32_MaxSize
char * SkStrAppendU64(char buffer[], uint64_t, int minDigits)
static constexpr int kSkStrAppendS64_MaxSize
static constexpr int kSkStrAppendU32_MaxSize
char * SkStrAppendScalar(char buffer[], SkScalar)
SK_API SkString static SkString SkStringPrintf()
char * SkStrAppendS64(char buffer[], int64_t, int minDigits)
static constexpr int kSkStrAppendScalar_MaxSize
static constexpr int kSkStrAppendU64_MaxSize
char * SkStrAppendU32(char buffer[], uint32_t)
char * SkStrAppendS32(char buffer[], int32_t)
static constexpr const T & SkTPin(const T &x, const T &lo, const T &hi)
constexpr uint8_t SkToU8(S x)
constexpr uint32_t SkToU32(S x)
size_t add(size_t x, size_t y)
size_t alignUp(size_t x, size_t alignment)
void insertScalar(size_t offset, SkScalar)
void insertUnichar(size_t offset, SkUnichar)
void printf(const char format[],...) SK_PRINTF_LIKE(2
void void void void void void void remove(size_t offset, size_t length)
void insertU64(size_t offset, uint64_t value, int minDigits=0)
void void void void appendVAList(const char format[], va_list) SK_PRINTF_LIKE(2
void void printVAList(const char format[], va_list) SK_PRINTF_LIKE(2
void void void void void void prependVAList(const char format[], va_list) SK_PRINTF_LIKE(2
void insertU32(size_t offset, uint32_t value)
const char * data() const
void insertS32(size_t offset, int32_t value)
void set(const SkString &src)
bool equals(const SkString &) const
void append(const char text[])
void swap(SkString &other)
void insert(size_t offset, const char text[])
SkString & operator=(const SkString &)
void prepend(const char text[])
const char * c_str() const
void insertS64(size_t offset, int64_t value, int minDigits=0)
void void void void void prependf(const char format[],...) SK_PRINTF_LIKE(2
void insertHex(size_t offset, uint32_t value, int minDigits=0)
void void void appendf(const char format[],...) SK_PRINTF_LIKE(2
void reset(T *ptr=nullptr)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
static const uint8_t buffer[]
uint32_t uint32_t * format
SK_SPI size_t ToUTF8(SkUnichar uni, char utf8[kMaxBytesInUTF8Sequence]=nullptr)
constexpr unsigned kMaxBytesInUTF8Sequence