• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2017 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 "include/private/SkSLString.h"
9 #include "src/sksl/SkSLUtil.h"
10 #include <algorithm>
11 #include <cinttypes>
12 #include <errno.h>
13 #include <limits.h>
14 #include <locale>
15 #include <sstream>
16 #include <string>
17 
18 namespace SkSL {
19 
printf(const char * fmt,...)20 String String::printf(const char* fmt, ...) {
21     va_list args;
22     va_start(args, fmt);
23     String result;
24     result.vappendf(fmt, args);
25     va_end(args);
26     return result;
27 }
28 
appendf(const char * fmt,...)29 void String::appendf(const char* fmt, ...) {
30     va_list args;
31     va_start(args, fmt);
32     this->vappendf(fmt, args);
33     va_end(args);
34 }
35 
vappendf(const char * fmt,va_list args)36 void String::vappendf(const char* fmt, va_list args) {
37     #define BUFFER_SIZE 256
38     char buffer[BUFFER_SIZE];
39     va_list reuse;
40     va_copy(reuse, args);
41     size_t size = vsnprintf(buffer, BUFFER_SIZE, fmt, args);
42     if (BUFFER_SIZE >= size + 1) {
43         this->append(buffer, size);
44     } else {
45         auto newBuffer = std::unique_ptr<char[]>(new char[size + 1]);
46         vsnprintf(newBuffer.get(), size + 1, fmt, reuse);
47         this->append(newBuffer.get(), size);
48     }
49     va_end(reuse);
50 }
51 
startsWith(const char prefix[]) const52 bool StringFragment::startsWith(const char prefix[]) const {
53     return !strncmp(fChars, prefix, strlen(prefix));
54 }
55 
endsWith(const char suffix[]) const56 bool StringFragment::endsWith(const char suffix[]) const {
57     size_t suffixLength = strlen(suffix);
58     if (fLength < suffixLength) {
59         return false;
60     }
61     return !strncmp(fChars + fLength - suffixLength, suffix, suffixLength);
62 }
63 
consumeSuffix(const char suffix[])64 bool String::consumeSuffix(const char suffix[]) {
65     size_t suffixLength = strlen(suffix);
66     if (this->length() < suffixLength) {
67         return false;
68     }
69     if (0 != strncmp(this->data() + this->size() - suffixLength, suffix, suffixLength)) {
70         return false;
71     }
72     this->resize(this->length() - suffixLength);
73     return true;
74 }
75 
operator +(const char * s) const76 String String::operator+(const char* s) const {
77     String result(*this);
78     result.append(s);
79     return result;
80 }
81 
operator +(const String & s) const82 String String::operator+(const String& s) const {
83     String result(*this);
84     result.append(s);
85     return result;
86 }
87 
operator +(StringFragment s) const88 String String::operator+(StringFragment s) const {
89     String result(*this);
90     result.append(s.fChars, s.fLength);
91     return result;
92 }
93 
operator +=(char c)94 String& String::operator+=(char c) {
95     INHERITED::operator+=(c);
96     return *this;
97 }
98 
operator +=(const char * s)99 String& String::operator+=(const char* s) {
100     INHERITED::operator+=(s);
101     return *this;
102 }
103 
operator +=(const String & s)104 String& String::operator+=(const String& s) {
105     INHERITED::operator+=(s);
106     return *this;
107 }
108 
operator +=(StringFragment s)109 String& String::operator+=(StringFragment s) {
110     this->append(s.fChars, s.fLength);
111     return *this;
112 }
113 
operator ==(const String & s) const114 bool String::operator==(const String& s) const {
115     return this->size() == s.size() && !memcmp(c_str(), s.c_str(), this->size());
116 }
117 
operator !=(const String & s) const118 bool String::operator!=(const String& s) const {
119     return !(*this == s);
120 }
121 
operator ==(const char * s) const122 bool String::operator==(const char* s) const {
123     return this->size() == strlen(s) && !memcmp(c_str(), s, this->size());
124 }
125 
operator !=(const char * s) const126 bool String::operator!=(const char* s) const {
127     return !(*this == s);
128 }
129 
operator +(const char * s1,const String & s2)130 String operator+(const char* s1, const String& s2) {
131     String result(s1);
132     result.append(s2);
133     return result;
134 }
135 
operator ==(const char * s1,const String & s2)136 bool operator==(const char* s1, const String& s2) {
137     return s2 == s1;
138 }
139 
operator !=(const char * s1,const String & s2)140 bool operator!=(const char* s1, const String& s2) {
141     return s2 != s1;
142 }
143 
operator ==(StringFragment s) const144 bool StringFragment::operator==(StringFragment s) const {
145     if (fLength != s.fLength) {
146         return false;
147     }
148     return !memcmp(fChars, s.fChars, fLength);
149 }
150 
operator !=(StringFragment s) const151 bool StringFragment::operator!=(StringFragment s) const {
152     if (fLength != s.fLength) {
153         return true;
154     }
155     return memcmp(fChars, s.fChars, fLength);
156 }
157 
operator ==(const char * s) const158 bool StringFragment::operator==(const char* s) const {
159     for (size_t i = 0; i < fLength; ++i) {
160         if (fChars[i] != s[i]) {
161             return false;
162         }
163     }
164     return 0 == s[fLength];
165 }
166 
operator !=(const char * s) const167 bool StringFragment::operator!=(const char* s) const {
168     for (size_t i = 0; i < fLength; ++i) {
169         if (fChars[i] != s[i]) {
170             return true;
171         }
172     }
173     return 0 != s[fLength];
174 }
175 
operator <(StringFragment other) const176 bool StringFragment::operator<(StringFragment other) const {
177     int comparison = strncmp(fChars, other.fChars, std::min(fLength, other.fLength));
178     if (comparison) {
179         return comparison < 0;
180     }
181     return fLength < other.fLength;
182 }
183 
operator +(const char * other) const184 String StringFragment::operator+(const char* other) const {
185     return String(*this) + other;
186 }
187 
operator +(const StringFragment & other) const188 String StringFragment::operator+(const StringFragment& other) const {
189     return String(*this) + other;
190 }
191 
operator +(const String & other) const192 String StringFragment::operator+(const String& other) const {
193     return String(*this) + other;
194 }
195 
operator ==(const char * s1,StringFragment s2)196 bool operator==(const char* s1, StringFragment s2) {
197     return s2 == s1;
198 }
199 
operator !=(const char * s1,StringFragment s2)200 bool operator!=(const char* s1, StringFragment s2) {
201     return s2 != s1;
202 }
203 
to_string(int32_t value)204 String to_string(int32_t value) {
205     return SkSL::String(std::to_string(value));
206 }
207 
to_string(uint32_t value)208 String to_string(uint32_t value) {
209     return SkSL::String(std::to_string(value));
210 }
211 
to_string(int64_t value)212 String to_string(int64_t value) {
213     return SkSL::String(std::to_string(value));
214 }
215 
to_string(uint64_t value)216 String to_string(uint64_t value) {
217     return SkSL::String(std::to_string(value));
218 }
219 
to_string(double value)220 String to_string(double value) {
221     std::stringstream buffer;
222     buffer.imbue(std::locale::classic());
223     buffer.precision(17);
224     buffer << value;
225     bool needsDotZero = true;
226     const std::string str = buffer.str();
227     for (int i = str.size() - 1; i >= 0; --i) {
228         char c = str[i];
229         if (c == '.' || c == 'e') {
230             needsDotZero = false;
231             break;
232         }
233     }
234     if (needsDotZero) {
235         buffer << ".0";
236     }
237     return String(buffer.str().c_str());
238 }
239 
stod(const StringFragment & s,SKSL_FLOAT * value)240 bool stod(const StringFragment& s, SKSL_FLOAT* value) {
241     std::string str(s.data(), s.size());
242     std::stringstream buffer(str);
243     buffer.imbue(std::locale::classic());
244     buffer >> *value;
245     return !buffer.fail();
246 }
247 
stoi(const StringFragment & s,SKSL_INT * value)248 bool stoi(const StringFragment& s, SKSL_INT* value) {
249     char* p;
250     errno = 0;
251     unsigned long long result = strtoull(s.begin(), &p, /*base=*/0);
252     *value = static_cast<SKSL_INT>(result);
253     return p == s.end() && errno == 0 && result <= 0xFFFFFFFF;
254 }
255 
256 }  // namespace SkSL
257