xref: /third_party/skia/src/sksl/SkSLString.cpp (revision cb93a386)
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