Home | History | Annotate | Download | only in sksl
      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