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_STANDALONE
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 ==(const String & s) const80 bool String::operator==(const String& s) const {
81 return this->size() == s.size() && !memcmp(c_str(), s.c_str(), this->size());
82 }
83
operator !=(const String & s) const84 bool String::operator!=(const String& s) const {
85 return !(*this == s);
86 }
87
operator ==(const char * s) const88 bool String::operator==(const char* s) const {
89 return this->size() == strlen(s) && !memcmp(c_str(), s, this->size());
90 }
91
operator !=(const char * s) const92 bool String::operator!=(const char* s) const {
93 return !(*this == s);
94 }
95
operator +(const char * s1,const String & s2)96 String operator+(const char* s1, const String& s2) {
97 String result(s1);
98 result.append(s2);
99 return result;
100 }
101
operator ==(const char * s1,const String & s2)102 bool operator==(const char* s1, const String& s2) {
103 return s2 == s1;
104 }
105
operator !=(const char * s1,const String & s2)106 bool operator!=(const char* s1, const String& s2) {
107 return s2 != s1;
108 }
109
to_string(int32_t value)110 String to_string(int32_t value) {
111 return SkSL::String::printf("%d", value);
112 }
113
to_string(uint32_t value)114 String to_string(uint32_t value) {
115 return SkSL::String::printf("%u", value);
116 }
117
to_string(int64_t value)118 String to_string(int64_t value) {
119 std::stringstream buffer;
120 buffer << value;
121 return String(buffer.str().c_str());
122 }
123
to_string(uint64_t value)124 String to_string(uint64_t value) {
125 std::stringstream buffer;
126 buffer << value;
127 return String(buffer.str().c_str());
128 }
129
to_string(double value)130 String to_string(double value) {
131 #ifdef SKSL_BUILD_FOR_WIN
132 #define SNPRINTF _snprintf
133 #else
134 #define SNPRINTF snprintf
135 #endif
136 #define MAX_DOUBLE_CHARS 25
137 char buffer[MAX_DOUBLE_CHARS];
138 SKSL_DEBUGCODE(int len = )SNPRINTF(buffer, sizeof(buffer), "%.17g", value);
139 ASSERT(len < MAX_DOUBLE_CHARS);
140 String result(buffer);
141 if (!strchr(buffer, '.') && !strchr(buffer, 'e')) {
142 result += ".0";
143 }
144 return result;
145 #undef SNPRINTF
146 #undef MAX_DOUBLE_CHARS
147 }
148
stoi(String s)149 int stoi(String s) {
150 char* p;
151 SKSL_DEBUGCODE(errno = 0;)
152 long result = strtoul(s.c_str(), &p, 0);
153 ASSERT(*p == 0);
154 ASSERT(!errno);
155 return (int) result;
156 }
157
stod(String s)158 double stod(String s) {
159 double result;
160 std::string str(s.c_str(), s.size());
161 std::stringstream buffer(str);
162 buffer.imbue(std::locale::classic());
163 buffer >> result;
164 ASSERT(!buffer.fail());
165 return result;
166 }
167
stol(String s)168 long stol(String s) {
169 char* p;
170 SKSL_DEBUGCODE(errno = 0;)
171 long result = strtoul(s.c_str(), &p, 0);
172 ASSERT(*p == 0);
173 ASSERT(!errno);
174 return result;
175 }
176
177 } // namespace
178