xref: /aosp_15_r20/external/skia/src/core/SkStringUtils.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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