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