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 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 27#ifdef SKSL_USE_STD_STRING 28void 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]; 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 56bool String::startsWith(const char* s) const { 57 return !strncmp(c_str(), s, strlen(s)); 58} 59 60bool 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 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 80String 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 106bool 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 136bool 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 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 159bool 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 168bool 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 176bool operator==(const char* s1, StringFragment s2) { 177 return s2 == s1; 178} 179 180bool operator!=(const char* s1, StringFragment s2) { 181 return s2 != s1; 182} 183 184String to_string(int32_t value) { 185 return SkSL::String::printf("%d", value); 186} 187 188String to_string(uint32_t value) { 189 return SkSL::String::printf("%u", value); 190} 191 192String to_string(int64_t value) { 193 std::stringstream buffer; 194 buffer << value; 195 return String(buffer.str().c_str()); 196} 197 198String to_string(uint64_t value) { 199 std::stringstream buffer; 200 buffer << value; 201 return String(buffer.str().c_str()); 202} 203 204String 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 223int 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 232double 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 242long 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