1 /*
2 * Copyright 2013 Google Inc.
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
8 #include "src/core/SkStringUtils.h"
9
10 #include "include/core/SkString.h"
11 #include "include/private/base/SkAssert.h"
12 #include "include/private/base/SkTArray.h"
13 #include "src/base/SkFloatBits.h"
14 #include "src/base/SkUTF.h"
15
16 #include <cstring>
17
18 using namespace skia_private;
19
SkAppendScalar(SkString * str,SkScalar value,SkScalarAsStringType asType)20 void SkAppendScalar(SkString* str, SkScalar value, SkScalarAsStringType asType) {
21 switch (asType) {
22 case kHex_SkScalarAsStringType:
23 str->appendf("SkBits2Float(0x%08x)", SkFloat2Bits(value));
24 break;
25 case kDec_SkScalarAsStringType: {
26 SkString tmp;
27 tmp.printf("%.9g", value);
28 if (tmp.contains('.')) {
29 tmp.appendUnichar('f');
30 }
31 str->append(tmp);
32 break;
33 }
34 }
35 }
36
SkTabString(const SkString & string,int tabCnt)37 SkString SkTabString(const SkString& string, int tabCnt) {
38 if (tabCnt <= 0) {
39 return string;
40 }
41 SkString tabs;
42 for (int i = 0; i < tabCnt; ++i) {
43 tabs.append("\t");
44 }
45 SkString result;
46 static const char newline[] = "\n";
47 const char* input = string.c_str();
48 int nextNL = SkStrFind(input, newline);
49 while (nextNL >= 0) {
50 if (nextNL > 0) {
51 result.append(tabs);
52 }
53 result.append(input, nextNL + 1);
54 input += nextNL + 1;
55 nextNL = SkStrFind(input, newline);
56 }
57 if (*input != '\0') {
58 result.append(tabs);
59 result.append(input);
60 }
61 return result;
62 }
63
SkStringFromUTF16(const uint16_t * src,size_t count)64 SkString SkStringFromUTF16(const uint16_t* src, size_t count) {
65 SkString ret;
66 const uint16_t* stop = src + count;
67 if (count > 0) {
68 SkASSERT(src);
69 size_t n = 0;
70 const uint16_t* end = src + count;
71 for (const uint16_t* ptr = src; ptr < end;) {
72 const uint16_t* last = ptr;
73 SkUnichar u = SkUTF::NextUTF16(&ptr, stop);
74 size_t s = SkUTF::ToUTF8(u);
75 if (n > UINT32_MAX - s) {
76 end = last; // truncate input string
77 break;
78 }
79 n += s;
80 }
81 ret = SkString(n);
82 char* out = ret.data();
83 for (const uint16_t* ptr = src; ptr < end;) {
84 out += SkUTF::ToUTF8(SkUTF::NextUTF16(&ptr, stop), out);
85 }
86 SkASSERT(out == ret.data() + n);
87 }
88 return ret;
89 }
90
SkStrSplit(const char * str,const char * delimiters,SkStrSplitMode splitMode,TArray<SkString> * out)91 void SkStrSplit(const char* str,
92 const char* delimiters,
93 SkStrSplitMode splitMode,
94 TArray<SkString>* out) {
95 if (splitMode == kCoalesce_SkStrSplitMode) {
96 // Skip any delimiters.
97 str += strspn(str, delimiters);
98 }
99 if (!*str) {
100 return;
101 }
102
103 while (true) {
104 // Find a token.
105 const size_t len = strcspn(str, delimiters);
106 if (splitMode == kStrict_SkStrSplitMode || len > 0) {
107 out->push_back().set(str, len);
108 str += len;
109 }
110
111 if (!*str) {
112 return;
113 }
114 if (splitMode == kCoalesce_SkStrSplitMode) {
115 // Skip any delimiters.
116 str += strspn(str, delimiters);
117 } else {
118 // Skip one delimiter.
119 str += 1;
120 }
121 }
122 }
123