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 <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