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
consumeSuffix(const char suffix[])52 bool String::consumeSuffix(const char suffix[]) {
53 size_t suffixLength = strlen(suffix);
54 if (this->length() < suffixLength) {
55 return false;
56 }
57 if (0 != strncmp(this->data() + this->size() - suffixLength, suffix, suffixLength)) {
58 return false;
59 }
60 this->resize(this->length() - suffixLength);
61 return true;
62 }
63
operator +(const char * s) const64 String String::operator+(const char* s) const {
65 String result(*this);
66 result.append(s);
67 return result;
68 }
69
operator +(const String & s) const70 String String::operator+(const String& s) const {
71 String result(*this);
72 result.append(s);
73 return result;
74 }
75
operator +(skstd::string_view s) const76 String String::operator+(skstd::string_view s) const {
77 String result(*this);
78 result.append(s.data(), s.length());
79 return result;
80 }
81
operator +=(char c)82 String& String::operator+=(char c) {
83 INHERITED::operator+=(c);
84 return *this;
85 }
86
operator +=(const char * s)87 String& String::operator+=(const char* s) {
88 INHERITED::operator+=(s);
89 return *this;
90 }
91
operator +=(const String & s)92 String& String::operator+=(const String& s) {
93 INHERITED::operator+=(s);
94 return *this;
95 }
96
operator +=(skstd::string_view s)97 String& String::operator+=(skstd::string_view s) {
98 this->append(s.data(), s.length());
99 return *this;
100 }
101
operator +(const char * s1,const String & s2)102 String operator+(const char* s1, const String& s2) {
103 String result(s1);
104 result.append(s2);
105 return result;
106 }
107
operator +(skstd::string_view left,skstd::string_view right)108 String operator+(skstd::string_view left, skstd::string_view right) {
109 return String(left) + right;
110 }
111
to_string(int32_t value)112 String to_string(int32_t value) {
113 return SkSL::String(std::to_string(value));
114 }
115
to_string(uint32_t value)116 String to_string(uint32_t value) {
117 return SkSL::String(std::to_string(value));
118 }
119
to_string(int64_t value)120 String to_string(int64_t value) {
121 return SkSL::String(std::to_string(value));
122 }
123
to_string(uint64_t value)124 String to_string(uint64_t value) {
125 return SkSL::String(std::to_string(value));
126 }
127
to_string(double value)128 String to_string(double value) {
129 std::stringstream buffer;
130 buffer.imbue(std::locale::classic());
131 buffer.precision(17);
132 buffer << value;
133 bool needsDotZero = true;
134 const std::string str = buffer.str();
135 for (int i = str.size() - 1; i >= 0; --i) {
136 char c = str[i];
137 if (c == '.' || c == 'e') {
138 needsDotZero = false;
139 break;
140 }
141 }
142 if (needsDotZero) {
143 buffer << ".0";
144 }
145 return String(buffer.str().c_str());
146 }
147
stod(const skstd::string_view & s,SKSL_FLOAT * value)148 bool stod(const skstd::string_view& s, SKSL_FLOAT* value) {
149 std::string str(s.data(), s.size());
150 std::stringstream buffer(str);
151 buffer.imbue(std::locale::classic());
152 buffer >> *value;
153 return !buffer.fail();
154 }
155
stoi(const skstd::string_view & s,SKSL_INT * value)156 bool stoi(const skstd::string_view& s, SKSL_INT* value) {
157 char* p;
158 errno = 0;
159 unsigned long long result = strtoull(s.begin(), &p, /*base=*/0);
160 *value = static_cast<SKSL_INT>(result);
161 return p == s.end() && errno == 0 && result <= 0xFFFFFFFF;
162 }
163
164 } // namespace SkSL
165