blob: bd6de3532ccfcd5df5d6735f74bf49b1d50944e5 [file] [log] [blame]
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001/*
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"
Ethan Nicholas0df1b042017-03-31 13:56:23 -040011#include <errno.h>
Ethan Nicholas0df1b042017-03-31 13:56:23 -040012#include <limits.h>
13#include <locale>
14#include <sstream>
15#include <string>
16
17namespace SkSL {
18
19String 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
Brian Osman93ba0a42017-08-14 14:48:10 -040027#ifdef SKSL_USE_STD_STRING
Ethan Nicholas0df1b042017-03-31 13:56:23 -040028void String::appendf(const char* fmt, ...) {
29 va_list args;
30 va_start(args, fmt);
31 this->vappendf(fmt, args);
32}
33#endif
34
35void 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];
Ethan Nicholas762466e2017-06-29 10:03:38 -040043 va_list reuse;
44 va_copy(reuse, args);
Ethan Nicholas0df1b042017-03-31 13:56:23 -040045 size_t size = VSNPRINTF(buffer, BUFFER_SIZE, fmt, args);
46 if (BUFFER_SIZE >= size) {
47 this->append(buffer, size);
48 } else {
Ethan Nicholas762466e2017-06-29 10:03:38 -040049 auto newBuffer = std::unique_ptr<char[]>(new char[size + 1]);
50 VSNPRINTF(newBuffer.get(), size + 1, fmt, reuse);
Ethan Nicholas0df1b042017-03-31 13:56:23 -040051 this->append(newBuffer.get(), size);
52 }
Ethan Nicholas0df1b042017-03-31 13:56:23 -040053}
54
55
56bool String::startsWith(const char* s) const {
Ethan Nicholas985febf2017-05-19 14:03:45 -040057 return !strncmp(c_str(), s, strlen(s));
Ethan Nicholas0df1b042017-03-31 13:56:23 -040058}
59
60bool String::endsWith(const char* s) const {
61 size_t len = strlen(s);
62 if (size() < len) {
63 return false;
64 }
Ethan Nicholas985febf2017-05-19 14:03:45 -040065 return !strncmp(c_str() + size() - len, s, len);
Ethan Nicholas0df1b042017-03-31 13:56:23 -040066}
67
68String String::operator+(const char* s) const {
69 String result(*this);
70 result.append(s);
71 return result;
72}
73
74String String::operator+(const String& s) const {
75 String result(*this);
76 result.append(s);
77 return result;
78}
79
Ethan Nicholas5b5f0962017-09-11 13:50:14 -070080String String::operator+(StringFragment s) const {
81 String result(*this);
82 result.append(s.fChars, s.fLength);
83 return result;
84}
85
86String& String::operator+=(char c) {
87 INHERITED::operator+=(c);
88 return *this;
89}
90
91String& String::operator+=(const char* s) {
92 INHERITED::operator+=(s);
93 return *this;
94}
95
96String& String::operator+=(const String& s) {
97 INHERITED::operator+=(s);
98 return *this;
99}
100
101String& String::operator+=(StringFragment s) {
102 this->append(s.fChars, s.fLength);
103 return *this;
104}
105
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400106bool String::operator==(const String& s) const {
107 return this->size() == s.size() && !memcmp(c_str(), s.c_str(), this->size());
108}
109
110bool String::operator!=(const String& s) const {
111 return !(*this == s);
112}
113
114bool String::operator==(const char* s) const {
115 return this->size() == strlen(s) && !memcmp(c_str(), s, this->size());
116}
117
118bool String::operator!=(const char* s) const {
119 return !(*this == s);
120}
121
122String operator+(const char* s1, const String& s2) {
123 String result(s1);
124 result.append(s2);
125 return result;
126}
127
128bool operator==(const char* s1, const String& s2) {
129 return s2 == s1;
130}
131
132bool operator!=(const char* s1, const String& s2) {
133 return s2 != s1;
134}
135
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700136bool StringFragment::operator==(StringFragment s) const {
137 if (fLength != s.fLength) {
138 return false;
139 }
140 return !memcmp(fChars, s.fChars, fLength);
141}
142
143bool StringFragment::operator!=(StringFragment s) const {
144 if (fLength != s.fLength) {
145 return true;
146 }
147 return memcmp(fChars, s.fChars, fLength);
148}
149
150bool StringFragment::operator==(const char* s) const {
151 return !strncmp(fChars, s, fLength);
152}
153
154bool StringFragment::operator!=(const char* s) const {
155 return strncmp(fChars, s, fLength);
156}
157
Ethan Nicholascc305772017-10-13 16:17:45 -0400158bool operator==(const char* s1, StringFragment s2) {
159 return s2 == s1;
160}
161
162bool operator!=(const char* s1, StringFragment s2) {
163 return s2 != s1;
164}
165
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400166String to_string(int32_t value) {
167 return SkSL::String::printf("%d", value);
168}
169
170String to_string(uint32_t value) {
171 return SkSL::String::printf("%u", value);
172}
173
174String to_string(int64_t value) {
Ethan Nicholasc8c17602017-03-31 18:53:05 -0400175 std::stringstream buffer;
176 buffer << value;
177 return String(buffer.str().c_str());
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400178}
179
180String to_string(uint64_t value) {
Ethan Nicholasc8c17602017-03-31 18:53:05 -0400181 std::stringstream buffer;
182 buffer << value;
183 return String(buffer.str().c_str());
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400184}
185
186String to_string(double value) {
187#ifdef SKSL_BUILD_FOR_WIN
188 #define SNPRINTF _snprintf
189#else
190 #define SNPRINTF snprintf
191#endif
192#define MAX_DOUBLE_CHARS 25
193 char buffer[MAX_DOUBLE_CHARS];
194 SKSL_DEBUGCODE(int len = )SNPRINTF(buffer, sizeof(buffer), "%.17g", value);
195 ASSERT(len < MAX_DOUBLE_CHARS);
196 String result(buffer);
197 if (!strchr(buffer, '.') && !strchr(buffer, 'e')) {
198 result += ".0";
199 }
200 return result;
201#undef SNPRINTF
202#undef MAX_DOUBLE_CHARS
203}
204
Brian Osman634624a2017-08-15 11:14:30 -0400205int stoi(const String& s) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400206 char* p;
207 SKSL_DEBUGCODE(errno = 0;)
208 long result = strtoul(s.c_str(), &p, 0);
209 ASSERT(*p == 0);
210 ASSERT(!errno);
211 return (int) result;
212}
213
Brian Osman634624a2017-08-15 11:14:30 -0400214double stod(const String& s) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400215 double result;
216 std::string str(s.c_str(), s.size());
217 std::stringstream buffer(str);
218 buffer.imbue(std::locale::classic());
219 buffer >> result;
220 ASSERT(!buffer.fail());
221 return result;
222}
223
Brian Osman634624a2017-08-15 11:14:30 -0400224long stol(const String& s) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400225 char* p;
226 SKSL_DEBUGCODE(errno = 0;)
227 long result = strtoul(s.c_str(), &p, 0);
228 ASSERT(*p == 0);
229 ASSERT(!errno);
230 return result;
231}
232
233} // namespace