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 18namespace SkSL { 19 20String 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 29void 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 36void 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 52bool 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 64String String::operator+(const char* s) const { 65 String result(*this); 66 result.append(s); 67 return result; 68} 69 70String String::operator+(const String& s) const { 71 String result(*this); 72 result.append(s); 73 return result; 74} 75 76String String::operator+(skstd::string_view s) const { 77 String result(*this); 78 result.append(s.data(), s.length()); 79 return result; 80} 81 82String& String::operator+=(char c) { 83 INHERITED::operator+=(c); 84 return *this; 85} 86 87String& String::operator+=(const char* s) { 88 INHERITED::operator+=(s); 89 return *this; 90} 91 92String& String::operator+=(const String& s) { 93 INHERITED::operator+=(s); 94 return *this; 95} 96 97String& String::operator+=(skstd::string_view s) { 98 this->append(s.data(), s.length()); 99 return *this; 100} 101 102String operator+(const char* s1, const String& s2) { 103 String result(s1); 104 result.append(s2); 105 return result; 106} 107 108String operator+(skstd::string_view left, skstd::string_view right) { 109 return String(left) + right; 110} 111 112String to_string(int32_t value) { 113 return SkSL::String(std::to_string(value)); 114} 115 116String to_string(uint32_t value) { 117 return SkSL::String(std::to_string(value)); 118} 119 120String to_string(int64_t value) { 121 return SkSL::String(std::to_string(value)); 122} 123 124String to_string(uint64_t value) { 125 return SkSL::String(std::to_string(value)); 126} 127 128String 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 148bool 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 156bool 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