• 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 "SkSLString.h"
9 
10 #include "SkSLUtil.h"
11 #include <errno.h>
12 #include <limits.h>
13 #include <locale>
14 #include <sstream>
15 #include <string>
16 
17 namespace SkSL {
18 
printf(const char * fmt,...)19 String String::printf(const char* fmt, ...) {
20     va_list args;
21     va_start(args, fmt);
22     String result;
23     result.vappendf(fmt, args);
24     return result;
25 }
26 
27 #ifdef SKSL_USE_STD_STRING
appendf(const char * fmt,...)28 void String::appendf(const char* fmt, ...) {
29     va_list args;
30     va_start(args, fmt);
31     this->vappendf(fmt, args);
32 }
33 #endif
34 
vappendf(const char * fmt,va_list args)35 void String::vappendf(const char* fmt, va_list args) {
36 #ifdef SKSL_BUILD_FOR_WIN
37     #define VSNPRINTF    _vsnprintf
38 #else
39     #define VSNPRINTF    vsnprintf
40 #endif
41     #define BUFFER_SIZE 256
42     char buffer[BUFFER_SIZE];
43     va_list reuse;
44     va_copy(reuse, args);
45     size_t size = VSNPRINTF(buffer, BUFFER_SIZE, fmt, args);
46     if (BUFFER_SIZE >= size) {
47         this->append(buffer, size);
48     } else {
49         auto newBuffer = std::unique_ptr<char[]>(new char[size + 1]);
50         VSNPRINTF(newBuffer.get(), size + 1, fmt, reuse);
51         this->append(newBuffer.get(), size);
52     }
53 }
54 
55 
startsWith(const char * s) const56 bool String::startsWith(const char* s) const {
57     return !strncmp(c_str(), s, strlen(s));
58 }
59 
endsWith(const char * s) const60 bool String::endsWith(const char* s) const {
61     size_t len = strlen(s);
62     if (size() < len) {
63         return false;
64     }
65     return !strncmp(c_str() + size() - len, s, len);
66 }
67 
operator +(const char * s) const68 String String::operator+(const char* s) const {
69     String result(*this);
70     result.append(s);
71     return result;
72 }
73 
operator +(const String & s) const74 String String::operator+(const String& s) const {
75     String result(*this);
76     result.append(s);
77     return result;
78 }
79 
operator +(StringFragment s) const80 String String::operator+(StringFragment s) const {
81     String result(*this);
82     result.append(s.fChars, s.fLength);
83     return result;
84 }
85 
operator +=(char c)86 String& String::operator+=(char c) {
87     INHERITED::operator+=(c);
88     return *this;
89 }
90 
operator +=(const char * s)91 String& String::operator+=(const char* s) {
92     INHERITED::operator+=(s);
93     return *this;
94 }
95 
operator +=(const String & s)96 String& String::operator+=(const String& s) {
97     INHERITED::operator+=(s);
98     return *this;
99 }
100 
operator +=(StringFragment s)101 String& String::operator+=(StringFragment s) {
102     this->append(s.fChars, s.fLength);
103     return *this;
104 }
105 
operator ==(const String & s) const106 bool String::operator==(const String& s) const {
107     return this->size() == s.size() && !memcmp(c_str(), s.c_str(), this->size());
108 }
109 
operator !=(const String & s) const110 bool String::operator!=(const String& s) const {
111     return !(*this == s);
112 }
113 
operator ==(const char * s) const114 bool String::operator==(const char* s) const {
115     return this->size() == strlen(s) && !memcmp(c_str(), s, this->size());
116 }
117 
operator !=(const char * s) const118 bool String::operator!=(const char* s) const {
119     return !(*this == s);
120 }
121 
operator +(const char * s1,const String & s2)122 String operator+(const char* s1, const String& s2) {
123     String result(s1);
124     result.append(s2);
125     return result;
126 }
127 
operator ==(const char * s1,const String & s2)128 bool operator==(const char* s1, const String& s2) {
129     return s2 == s1;
130 }
131 
operator !=(const char * s1,const String & s2)132 bool operator!=(const char* s1, const String& s2) {
133     return s2 != s1;
134 }
135 
operator ==(StringFragment s) const136 bool StringFragment::operator==(StringFragment s) const {
137     if (fLength != s.fLength) {
138         return false;
139     }
140     return !memcmp(fChars, s.fChars, fLength);
141 }
142 
operator !=(StringFragment s) const143 bool StringFragment::operator!=(StringFragment s) const {
144     if (fLength != s.fLength) {
145         return true;
146     }
147     return memcmp(fChars, s.fChars, fLength);
148 }
149 
operator ==(const char * s) const150 bool StringFragment::operator==(const char* s) const {
151     for (size_t i = 0; i < fLength; ++i) {
152         if (fChars[i] != s[i]) {
153             return false;
154         }
155     }
156     return 0 == s[fLength];
157 }
158 
operator !=(const char * s) const159 bool StringFragment::operator!=(const char* s) const {
160     for (size_t i = 0; i < fLength; ++i) {
161         if (fChars[i] != s[i]) {
162             return true;
163         }
164     }
165     return 0 != s[fLength];
166 }
167 
operator <(StringFragment other) const168 bool StringFragment::operator<(StringFragment other) const {
169     int comparison = strncmp(fChars, other.fChars, std::min(fLength, other.fLength));
170     if (comparison) {
171         return comparison < 0;
172     }
173     return fLength < other.fLength;
174 }
175 
operator ==(const char * s1,StringFragment s2)176 bool operator==(const char* s1, StringFragment s2) {
177     return s2 == s1;
178 }
179 
operator !=(const char * s1,StringFragment s2)180 bool operator!=(const char* s1, StringFragment s2) {
181     return s2 != s1;
182 }
183 
to_string(int32_t value)184 String to_string(int32_t value) {
185     return SkSL::String::printf("%d", value);
186 }
187 
to_string(uint32_t value)188 String to_string(uint32_t value) {
189     return SkSL::String::printf("%u", value);
190 }
191 
to_string(int64_t value)192 String to_string(int64_t value) {
193     std::stringstream buffer;
194     buffer << value;
195     return String(buffer.str().c_str());
196 }
197 
to_string(uint64_t value)198 String to_string(uint64_t value) {
199     std::stringstream buffer;
200     buffer << value;
201     return String(buffer.str().c_str());
202 }
203 
to_string(double value)204 String to_string(double value) {
205 #ifdef SKSL_BUILD_FOR_WIN
206     #define SNPRINTF    _snprintf
207 #else
208     #define SNPRINTF    snprintf
209 #endif
210 #define MAX_DOUBLE_CHARS 25
211     char buffer[MAX_DOUBLE_CHARS];
212     SKSL_DEBUGCODE(int len = )SNPRINTF(buffer, sizeof(buffer), "%.17g", value);
213     ASSERT(len < MAX_DOUBLE_CHARS);
214     String result(buffer);
215     if (!strchr(buffer, '.') && !strchr(buffer, 'e')) {
216         result += ".0";
217     }
218     return result;
219 #undef SNPRINTF
220 #undef MAX_DOUBLE_CHARS
221 }
222 
stoi(const String & s)223 int stoi(const String& s) {
224     char* p;
225     SKSL_DEBUGCODE(errno = 0;)
226     long result = strtoul(s.c_str(), &p, 0);
227     ASSERT(*p == 0);
228     ASSERT(!errno);
229     return (int) result;
230 }
231 
stod(const String & s)232 double stod(const String& s) {
233     double result;
234     std::string str(s.c_str(), s.size());
235     std::stringstream buffer(str);
236     buffer.imbue(std::locale::classic());
237     buffer >> result;
238     ASSERT(!buffer.fail());
239     return result;
240 }
241 
stol(const String & s)242 long stol(const String& s) {
243     char* p;
244     SKSL_DEBUGCODE(errno = 0;)
245     long result = strtoul(s.c_str(), &p, 0);
246     ASSERT(*p == 0);
247     ASSERT(!errno);
248     return result;
249 }
250 
251 } // namespace
252