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 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 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 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 56 bool String::startsWith(const char* s) const { 57 return !strncmp(c_str(), s, strlen(s)); 58 } 59 60 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 68 String String::operator+(const char* s) const { 69 String result(*this); 70 result.append(s); 71 return result; 72 } 73 74 String String::operator+(const String& s) const { 75 String result(*this); 76 result.append(s); 77 return result; 78 } 79 80 String String::operator+(StringFragment s) const { 81 String result(*this); 82 result.append(s.fChars, s.fLength); 83 return result; 84 } 85 86 String& String::operator+=(char c) { 87 INHERITED::operator+=(c); 88 return *this; 89 } 90 91 String& String::operator+=(const char* s) { 92 INHERITED::operator+=(s); 93 return *this; 94 } 95 96 String& String::operator+=(const String& s) { 97 INHERITED::operator+=(s); 98 return *this; 99 } 100 101 String& String::operator+=(StringFragment s) { 102 this->append(s.fChars, s.fLength); 103 return *this; 104 } 105 106 bool String::operator==(const String& s) const { 107 return this->size() == s.size() && !memcmp(c_str(), s.c_str(), this->size()); 108 } 109 110 bool String::operator!=(const String& s) const { 111 return !(*this == s); 112 } 113 114 bool String::operator==(const char* s) const { 115 return this->size() == strlen(s) && !memcmp(c_str(), s, this->size()); 116 } 117 118 bool String::operator!=(const char* s) const { 119 return !(*this == s); 120 } 121 122 String operator+(const char* s1, const String& s2) { 123 String result(s1); 124 result.append(s2); 125 return result; 126 } 127 128 bool operator==(const char* s1, const String& s2) { 129 return s2 == s1; 130 } 131 132 bool operator!=(const char* s1, const String& s2) { 133 return s2 != s1; 134 } 135 136 bool StringFragment::operator==(StringFragment s) const { 137 if (fLength != s.fLength) { 138 return false; 139 } 140 return !memcmp(fChars, s.fChars, fLength); 141 } 142 143 bool StringFragment::operator!=(StringFragment s) const { 144 if (fLength != s.fLength) { 145 return true; 146 } 147 return memcmp(fChars, s.fChars, fLength); 148 } 149 150 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 159 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 168 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 176 bool operator==(const char* s1, StringFragment s2) { 177 return s2 == s1; 178 } 179 180 bool operator!=(const char* s1, StringFragment s2) { 181 return s2 != s1; 182 } 183 184 String to_string(int32_t value) { 185 return SkSL::String::printf("%d", value); 186 } 187 188 String to_string(uint32_t value) { 189 return SkSL::String::printf("%u", value); 190 } 191 192 String to_string(int64_t value) { 193 std::stringstream buffer; 194 buffer << value; 195 return String(buffer.str().c_str()); 196 } 197 198 String to_string(uint64_t value) { 199 std::stringstream buffer; 200 buffer << value; 201 return String(buffer.str().c_str()); 202 } 203 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 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 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 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