SkString.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. /*
  2. * Copyright 2006 The Android Open Source Project
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #include "include/core/SkString.h"
  8. #include "include/private/SkTo.h"
  9. #include "src/core/SkSafeMath.h"
  10. #include "src/core/SkUtils.h"
  11. #include "src/utils/SkUTF.h"
  12. #include <cstdio>
  13. #include <new>
  14. #include <utility>
  15. #include <vector>
  16. // number of bytes (on the stack) to receive the printf result
  17. static const size_t kBufferSize = 1024;
  18. static const char* apply_format_string(const char* format, va_list args, char* stackBuffer,
  19. size_t stackBufferSize, int* length, SkString* heapBuffer) {
  20. va_list argsCopy;
  21. va_copy(argsCopy, args);
  22. *length = std::vsnprintf(stackBuffer, stackBufferSize, format, args);
  23. if (*length < 0) {
  24. SkDebugf("SkString: vsnprintf reported error.");
  25. va_end(argsCopy);
  26. *length = 0;
  27. return stackBuffer;
  28. }
  29. if (*length < SkToInt(stackBufferSize)) {
  30. va_end(argsCopy);
  31. return stackBuffer;
  32. }
  33. heapBuffer->resize(*length);
  34. SkDEBUGCODE(int check =)
  35. std::vsnprintf(heapBuffer->writable_str(), *length + 1, format, argsCopy);
  36. SkASSERT(check == *length);
  37. va_end(argsCopy);
  38. return heapBuffer->c_str();
  39. }
  40. #define ARGS_TO_BUFFER(format, buffer, size, written, result) \
  41. SkString overflow; \
  42. do { \
  43. va_list args; \
  44. va_start(args, format); \
  45. result = apply_format_string(format, args, buffer, size, &written, &overflow); \
  46. va_end(args); \
  47. } while (0)
  48. #define V_SKSTRING_PRINTF(output, format) \
  49. do { \
  50. char buffer[kBufferSize]; \
  51. va_list args; \
  52. va_start(args, format); \
  53. int length; \
  54. auto result = apply_format_string(format, args, buffer, kBufferSize, &length, &output); \
  55. SkASSERT(result == output.c_str() || result == buffer); \
  56. if (result == buffer) { \
  57. output.set(buffer, length); \
  58. } \
  59. } while (0)
  60. ///////////////////////////////////////////////////////////////////////////////
  61. bool SkStrEndsWith(const char string[], const char suffixStr[]) {
  62. SkASSERT(string);
  63. SkASSERT(suffixStr);
  64. size_t strLen = strlen(string);
  65. size_t suffixLen = strlen(suffixStr);
  66. return strLen >= suffixLen &&
  67. !strncmp(string + strLen - suffixLen, suffixStr, suffixLen);
  68. }
  69. bool SkStrEndsWith(const char string[], const char suffixChar) {
  70. SkASSERT(string);
  71. size_t strLen = strlen(string);
  72. if (0 == strLen) {
  73. return false;
  74. } else {
  75. return (suffixChar == string[strLen-1]);
  76. }
  77. }
  78. int SkStrStartsWithOneOf(const char string[], const char prefixes[]) {
  79. int index = 0;
  80. do {
  81. const char* limit = strchr(prefixes, '\0');
  82. if (!strncmp(string, prefixes, limit - prefixes)) {
  83. return index;
  84. }
  85. prefixes = limit + 1;
  86. index++;
  87. } while (prefixes[0]);
  88. return -1;
  89. }
  90. char* SkStrAppendU32(char string[], uint32_t dec) {
  91. SkDEBUGCODE(char* start = string;)
  92. char buffer[SkStrAppendU32_MaxSize];
  93. char* p = buffer + sizeof(buffer);
  94. do {
  95. *--p = SkToU8('0' + dec % 10);
  96. dec /= 10;
  97. } while (dec != 0);
  98. SkASSERT(p >= buffer);
  99. char* stop = buffer + sizeof(buffer);
  100. while (p < stop) {
  101. *string++ = *p++;
  102. }
  103. SkASSERT(string - start <= SkStrAppendU32_MaxSize);
  104. return string;
  105. }
  106. char* SkStrAppendS32(char string[], int32_t dec) {
  107. uint32_t udec = dec;
  108. if (dec < 0) {
  109. *string++ = '-';
  110. udec = ~udec + 1; // udec = -udec, but silences some warnings that are trying to be helpful
  111. }
  112. return SkStrAppendU32(string, udec);
  113. }
  114. char* SkStrAppendU64(char string[], uint64_t dec, int minDigits) {
  115. SkDEBUGCODE(char* start = string;)
  116. char buffer[SkStrAppendU64_MaxSize];
  117. char* p = buffer + sizeof(buffer);
  118. do {
  119. *--p = SkToU8('0' + (int32_t) (dec % 10));
  120. dec /= 10;
  121. minDigits--;
  122. } while (dec != 0);
  123. while (minDigits > 0) {
  124. *--p = '0';
  125. minDigits--;
  126. }
  127. SkASSERT(p >= buffer);
  128. size_t cp_len = buffer + sizeof(buffer) - p;
  129. memcpy(string, p, cp_len);
  130. string += cp_len;
  131. SkASSERT(string - start <= SkStrAppendU64_MaxSize);
  132. return string;
  133. }
  134. char* SkStrAppendS64(char string[], int64_t dec, int minDigits) {
  135. uint64_t udec = dec;
  136. if (dec < 0) {
  137. *string++ = '-';
  138. udec = ~udec + 1; // udec = -udec, but silences some warnings that are trying to be helpful
  139. }
  140. return SkStrAppendU64(string, udec, minDigits);
  141. }
  142. char* SkStrAppendFloat(char string[], float value) {
  143. // since floats have at most 8 significant digits, we limit our %g to that.
  144. static const char gFormat[] = "%.8g";
  145. // make it 1 larger for the terminating 0
  146. char buffer[SkStrAppendScalar_MaxSize + 1];
  147. int len = snprintf(buffer, sizeof(buffer), gFormat, value);
  148. memcpy(string, buffer, len);
  149. SkASSERT(len <= SkStrAppendScalar_MaxSize);
  150. return string + len;
  151. }
  152. ///////////////////////////////////////////////////////////////////////////////
  153. const SkString::Rec SkString::gEmptyRec(0, 0);
  154. #define SizeOfRec() (gEmptyRec.data() - (const char*)&gEmptyRec)
  155. static uint32_t trim_size_t_to_u32(size_t value) {
  156. if (sizeof(size_t) > sizeof(uint32_t)) {
  157. if (value > UINT32_MAX) {
  158. value = UINT32_MAX;
  159. }
  160. }
  161. return (uint32_t)value;
  162. }
  163. static size_t check_add32(size_t base, size_t extra) {
  164. SkASSERT(base <= UINT32_MAX);
  165. if (sizeof(size_t) > sizeof(uint32_t)) {
  166. if (base + extra > UINT32_MAX) {
  167. extra = UINT32_MAX - base;
  168. }
  169. }
  170. return extra;
  171. }
  172. sk_sp<SkString::Rec> SkString::Rec::Make(const char text[], size_t len) {
  173. if (0 == len) {
  174. return sk_sp<SkString::Rec>(const_cast<Rec*>(&gEmptyRec));
  175. }
  176. SkSafeMath safe;
  177. // We store a 32bit version of the length
  178. uint32_t stringLen = safe.castTo<uint32_t>(len);
  179. // Add SizeOfRec() for our overhead and 1 for null-termination
  180. size_t allocationSize = safe.add(len, SizeOfRec() + sizeof(char));
  181. // Align up to a multiple of 4
  182. allocationSize = safe.alignUp(allocationSize, 4);
  183. SkASSERT_RELEASE(safe.ok());
  184. void* storage = ::operator new (allocationSize);
  185. sk_sp<Rec> rec(new (storage) Rec(stringLen, 1));
  186. if (text) {
  187. memcpy(rec->data(), text, len);
  188. }
  189. rec->data()[len] = 0;
  190. return rec;
  191. }
  192. void SkString::Rec::ref() const {
  193. if (this == &SkString::gEmptyRec) {
  194. return;
  195. }
  196. SkAssertResult(this->fRefCnt.fetch_add(+1, std::memory_order_relaxed));
  197. }
  198. void SkString::Rec::unref() const {
  199. if (this == &SkString::gEmptyRec) {
  200. return;
  201. }
  202. int32_t oldRefCnt = this->fRefCnt.fetch_add(-1, std::memory_order_acq_rel);
  203. SkASSERT(oldRefCnt);
  204. if (1 == oldRefCnt) {
  205. delete this;
  206. }
  207. }
  208. bool SkString::Rec::unique() const {
  209. return fRefCnt.load(std::memory_order_acquire) == 1;
  210. }
  211. #ifdef SK_DEBUG
  212. const SkString& SkString::validate() const {
  213. // make sure know one has written over our global
  214. SkASSERT(0 == gEmptyRec.fLength);
  215. SkASSERT(0 == gEmptyRec.fRefCnt.load(std::memory_order_relaxed));
  216. SkASSERT(0 == gEmptyRec.data()[0]);
  217. if (fRec.get() != &gEmptyRec) {
  218. SkASSERT(fRec->fLength > 0);
  219. SkASSERT(fRec->fRefCnt.load(std::memory_order_relaxed) > 0);
  220. SkASSERT(0 == fRec->data()[fRec->fLength]);
  221. }
  222. return *this;
  223. }
  224. #endif
  225. ///////////////////////////////////////////////////////////////////////////////
  226. SkString::SkString() : fRec(const_cast<Rec*>(&gEmptyRec)) {
  227. }
  228. SkString::SkString(size_t len) {
  229. fRec = Rec::Make(nullptr, len);
  230. }
  231. SkString::SkString(const char text[]) {
  232. size_t len = text ? strlen(text) : 0;
  233. fRec = Rec::Make(text, len);
  234. }
  235. SkString::SkString(const char text[], size_t len) {
  236. fRec = Rec::Make(text, len);
  237. }
  238. SkString::SkString(const SkString& src) : fRec(src.validate().fRec) {}
  239. SkString::SkString(SkString&& src) : fRec(std::move(src.validate().fRec)) {
  240. src.fRec.reset(const_cast<Rec*>(&gEmptyRec));
  241. }
  242. SkString::~SkString() {
  243. this->validate();
  244. }
  245. bool SkString::equals(const SkString& src) const {
  246. return fRec == src.fRec || this->equals(src.c_str(), src.size());
  247. }
  248. bool SkString::equals(const char text[]) const {
  249. return this->equals(text, text ? strlen(text) : 0);
  250. }
  251. bool SkString::equals(const char text[], size_t len) const {
  252. SkASSERT(len == 0 || text != nullptr);
  253. return fRec->fLength == len && !memcmp(fRec->data(), text, len);
  254. }
  255. SkString& SkString::operator=(const SkString& src) {
  256. this->validate();
  257. fRec = src.fRec; // sk_sp<Rec>::operator=(const sk_sp<Ref>&) checks for self-assignment.
  258. return *this;
  259. }
  260. SkString& SkString::operator=(SkString&& src) {
  261. this->validate();
  262. if (fRec != src.fRec) {
  263. this->swap(src);
  264. }
  265. return *this;
  266. }
  267. SkString& SkString::operator=(const char text[]) {
  268. this->validate();
  269. return *this = SkString(text);
  270. }
  271. void SkString::reset() {
  272. this->validate();
  273. fRec.reset(const_cast<Rec*>(&gEmptyRec));
  274. }
  275. char* SkString::writable_str() {
  276. this->validate();
  277. if (fRec->fLength) {
  278. if (!fRec->unique()) {
  279. fRec = Rec::Make(fRec->data(), fRec->fLength);
  280. }
  281. }
  282. return fRec->data();
  283. }
  284. void SkString::set(const char text[]) {
  285. this->set(text, text ? strlen(text) : 0);
  286. }
  287. void SkString::set(const char text[], size_t len) {
  288. len = trim_size_t_to_u32(len);
  289. bool unique = fRec->unique();
  290. if (0 == len) {
  291. this->reset();
  292. } else if (unique && len <= fRec->fLength) {
  293. // should we resize if len <<<< fLength, to save RAM? (e.g. len < (fLength>>1))?
  294. // just use less of the buffer without allocating a smaller one
  295. char* p = this->writable_str();
  296. if (text) {
  297. memcpy(p, text, len);
  298. }
  299. p[len] = 0;
  300. fRec->fLength = SkToU32(len);
  301. } else if (unique && (fRec->fLength >> 2) == (len >> 2)) {
  302. // we have spare room in the current allocation, so don't alloc a larger one
  303. char* p = this->writable_str();
  304. if (text) {
  305. memcpy(p, text, len);
  306. }
  307. p[len] = 0;
  308. fRec->fLength = SkToU32(len);
  309. } else {
  310. SkString tmp(text, len);
  311. this->swap(tmp);
  312. }
  313. }
  314. void SkString::insert(size_t offset, const char text[]) {
  315. this->insert(offset, text, text ? strlen(text) : 0);
  316. }
  317. void SkString::insert(size_t offset, const char text[], size_t len) {
  318. if (len) {
  319. size_t length = fRec->fLength;
  320. if (offset > length) {
  321. offset = length;
  322. }
  323. // Check if length + len exceeds 32bits, we trim len
  324. len = check_add32(length, len);
  325. if (0 == len) {
  326. return;
  327. }
  328. /* If we're the only owner, and we have room in our allocation for the insert,
  329. do it in place, rather than allocating a new buffer.
  330. To know we have room, compare the allocated sizes
  331. beforeAlloc = SkAlign4(length + 1)
  332. afterAlloc = SkAligh4(length + 1 + len)
  333. but SkAlign4(x) is (x + 3) >> 2 << 2
  334. which is equivalent for testing to (length + 1 + 3) >> 2 == (length + 1 + 3 + len) >> 2
  335. and we can then eliminate the +1+3 since that doesn't affec the answer
  336. */
  337. if (fRec->unique() && (length >> 2) == ((length + len) >> 2)) {
  338. char* dst = this->writable_str();
  339. if (offset < length) {
  340. memmove(dst + offset + len, dst + offset, length - offset);
  341. }
  342. memcpy(dst + offset, text, len);
  343. dst[length + len] = 0;
  344. fRec->fLength = SkToU32(length + len);
  345. } else {
  346. /* Seems we should use realloc here, since that is safe if it fails
  347. (we have the original data), and might be faster than alloc/copy/free.
  348. */
  349. SkString tmp(fRec->fLength + len);
  350. char* dst = tmp.writable_str();
  351. if (offset > 0) {
  352. memcpy(dst, fRec->data(), offset);
  353. }
  354. memcpy(dst + offset, text, len);
  355. if (offset < fRec->fLength) {
  356. memcpy(dst + offset + len, fRec->data() + offset,
  357. fRec->fLength - offset);
  358. }
  359. this->swap(tmp);
  360. }
  361. }
  362. }
  363. void SkString::insertUnichar(size_t offset, SkUnichar uni) {
  364. char buffer[SkUTF::kMaxBytesInUTF8Sequence];
  365. size_t len = SkUTF::ToUTF8(uni, buffer);
  366. if (len) {
  367. this->insert(offset, buffer, len);
  368. }
  369. }
  370. void SkString::insertS32(size_t offset, int32_t dec) {
  371. char buffer[SkStrAppendS32_MaxSize];
  372. char* stop = SkStrAppendS32(buffer, dec);
  373. this->insert(offset, buffer, stop - buffer);
  374. }
  375. void SkString::insertS64(size_t offset, int64_t dec, int minDigits) {
  376. char buffer[SkStrAppendS64_MaxSize];
  377. char* stop = SkStrAppendS64(buffer, dec, minDigits);
  378. this->insert(offset, buffer, stop - buffer);
  379. }
  380. void SkString::insertU32(size_t offset, uint32_t dec) {
  381. char buffer[SkStrAppendU32_MaxSize];
  382. char* stop = SkStrAppendU32(buffer, dec);
  383. this->insert(offset, buffer, stop - buffer);
  384. }
  385. void SkString::insertU64(size_t offset, uint64_t dec, int minDigits) {
  386. char buffer[SkStrAppendU64_MaxSize];
  387. char* stop = SkStrAppendU64(buffer, dec, minDigits);
  388. this->insert(offset, buffer, stop - buffer);
  389. }
  390. void SkString::insertHex(size_t offset, uint32_t hex, int minDigits) {
  391. minDigits = SkTPin(minDigits, 0, 8);
  392. char buffer[8];
  393. char* p = buffer + sizeof(buffer);
  394. do {
  395. *--p = SkHexadecimalDigits::gUpper[hex & 0xF];
  396. hex >>= 4;
  397. minDigits -= 1;
  398. } while (hex != 0);
  399. while (--minDigits >= 0) {
  400. *--p = '0';
  401. }
  402. SkASSERT(p >= buffer);
  403. this->insert(offset, p, buffer + sizeof(buffer) - p);
  404. }
  405. void SkString::insertScalar(size_t offset, SkScalar value) {
  406. char buffer[SkStrAppendScalar_MaxSize];
  407. char* stop = SkStrAppendScalar(buffer, value);
  408. this->insert(offset, buffer, stop - buffer);
  409. }
  410. void SkString::printf(const char format[], ...) {
  411. V_SKSTRING_PRINTF((*this), format);
  412. }
  413. void SkString::appendf(const char format[], ...) {
  414. char buffer[kBufferSize];
  415. int length;
  416. const char* result;
  417. ARGS_TO_BUFFER(format, buffer, kBufferSize, length, result);
  418. this->append(result, length);
  419. }
  420. void SkString::appendVAList(const char format[], va_list args) {
  421. char buffer[kBufferSize];
  422. int length = vsnprintf(buffer, kBufferSize, format, args);
  423. SkASSERT(length >= 0 && length < SkToInt(kBufferSize));
  424. this->append(buffer, length);
  425. }
  426. void SkString::prependf(const char format[], ...) {
  427. char buffer[kBufferSize];
  428. int length;
  429. const char* result;
  430. ARGS_TO_BUFFER(format, buffer, kBufferSize, length, result);
  431. this->prepend(result, length);
  432. }
  433. void SkString::prependVAList(const char format[], va_list args) {
  434. char buffer[kBufferSize];
  435. int length = vsnprintf(buffer, kBufferSize, format, args);
  436. SkASSERT(length >= 0 && length < SkToInt(kBufferSize));
  437. this->prepend(buffer, length);
  438. }
  439. ///////////////////////////////////////////////////////////////////////////////
  440. void SkString::remove(size_t offset, size_t length) {
  441. size_t size = this->size();
  442. if (offset < size) {
  443. if (length > size - offset) {
  444. length = size - offset;
  445. }
  446. SkASSERT(length <= size);
  447. SkASSERT(offset <= size - length);
  448. if (length > 0) {
  449. SkString tmp(size - length);
  450. char* dst = tmp.writable_str();
  451. const char* src = this->c_str();
  452. if (offset) {
  453. memcpy(dst, src, offset);
  454. }
  455. size_t tail = size - (offset + length);
  456. if (tail) {
  457. memcpy(dst + offset, src + (offset + length), tail);
  458. }
  459. SkASSERT(dst[tmp.size()] == 0);
  460. this->swap(tmp);
  461. }
  462. }
  463. }
  464. void SkString::swap(SkString& other) {
  465. this->validate();
  466. other.validate();
  467. using std::swap;
  468. swap(fRec, other.fRec);
  469. }
  470. ///////////////////////////////////////////////////////////////////////////////
  471. SkString SkStringPrintf(const char* format, ...) {
  472. SkString formattedOutput;
  473. V_SKSTRING_PRINTF(formattedOutput, format);
  474. return formattedOutput;
  475. }
  476. void SkStrSplit(const char* str, const char* delimiters, SkStrSplitMode splitMode,
  477. SkTArray<SkString>* out) {
  478. if (splitMode == kCoalesce_SkStrSplitMode) {
  479. // Skip any delimiters.
  480. str += strspn(str, delimiters);
  481. }
  482. if (!*str) {
  483. return;
  484. }
  485. while (true) {
  486. // Find a token.
  487. const size_t len = strcspn(str, delimiters);
  488. if (splitMode == kStrict_SkStrSplitMode || len > 0) {
  489. out->push_back().set(str, len);
  490. str += len;
  491. }
  492. if (!*str) {
  493. return;
  494. }
  495. if (splitMode == kCoalesce_SkStrSplitMode) {
  496. // Skip any delimiters.
  497. str += strspn(str, delimiters);
  498. } else {
  499. // Skip one delimiter.
  500. str += 1;
  501. }
  502. }
  503. }