1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2017 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "include/private/SkSLString.h"
9cb93a386Sopenharmony_ci#include "src/sksl/SkSLUtil.h"
10cb93a386Sopenharmony_ci#include <algorithm>
11cb93a386Sopenharmony_ci#include <cinttypes>
12cb93a386Sopenharmony_ci#include <errno.h>
13cb93a386Sopenharmony_ci#include <limits.h>
14cb93a386Sopenharmony_ci#include <locale>
15cb93a386Sopenharmony_ci#include <sstream>
16cb93a386Sopenharmony_ci#include <string>
17cb93a386Sopenharmony_ci
18cb93a386Sopenharmony_cinamespace SkSL {
19cb93a386Sopenharmony_ci
20cb93a386Sopenharmony_ciString String::printf(const char* fmt, ...) {
21cb93a386Sopenharmony_ci    va_list args;
22cb93a386Sopenharmony_ci    va_start(args, fmt);
23cb93a386Sopenharmony_ci    String result;
24cb93a386Sopenharmony_ci    result.vappendf(fmt, args);
25cb93a386Sopenharmony_ci    va_end(args);
26cb93a386Sopenharmony_ci    return result;
27cb93a386Sopenharmony_ci}
28cb93a386Sopenharmony_ci
29cb93a386Sopenharmony_civoid String::appendf(const char* fmt, ...) {
30cb93a386Sopenharmony_ci    va_list args;
31cb93a386Sopenharmony_ci    va_start(args, fmt);
32cb93a386Sopenharmony_ci    this->vappendf(fmt, args);
33cb93a386Sopenharmony_ci    va_end(args);
34cb93a386Sopenharmony_ci}
35cb93a386Sopenharmony_ci
36cb93a386Sopenharmony_civoid String::vappendf(const char* fmt, va_list args) {
37cb93a386Sopenharmony_ci    #define BUFFER_SIZE 256
38cb93a386Sopenharmony_ci    char buffer[BUFFER_SIZE];
39cb93a386Sopenharmony_ci    va_list reuse;
40cb93a386Sopenharmony_ci    va_copy(reuse, args);
41cb93a386Sopenharmony_ci    size_t size = vsnprintf(buffer, BUFFER_SIZE, fmt, args);
42cb93a386Sopenharmony_ci    if (BUFFER_SIZE >= size + 1) {
43cb93a386Sopenharmony_ci        this->append(buffer, size);
44cb93a386Sopenharmony_ci    } else {
45cb93a386Sopenharmony_ci        auto newBuffer = std::unique_ptr<char[]>(new char[size + 1]);
46cb93a386Sopenharmony_ci        vsnprintf(newBuffer.get(), size + 1, fmt, reuse);
47cb93a386Sopenharmony_ci        this->append(newBuffer.get(), size);
48cb93a386Sopenharmony_ci    }
49cb93a386Sopenharmony_ci    va_end(reuse);
50cb93a386Sopenharmony_ci}
51cb93a386Sopenharmony_ci
52cb93a386Sopenharmony_cibool String::consumeSuffix(const char suffix[]) {
53cb93a386Sopenharmony_ci    size_t suffixLength = strlen(suffix);
54cb93a386Sopenharmony_ci    if (this->length() < suffixLength) {
55cb93a386Sopenharmony_ci        return false;
56cb93a386Sopenharmony_ci    }
57cb93a386Sopenharmony_ci    if (0 != strncmp(this->data() + this->size() - suffixLength, suffix, suffixLength)) {
58cb93a386Sopenharmony_ci        return false;
59cb93a386Sopenharmony_ci    }
60cb93a386Sopenharmony_ci    this->resize(this->length() - suffixLength);
61cb93a386Sopenharmony_ci    return true;
62cb93a386Sopenharmony_ci}
63cb93a386Sopenharmony_ci
64cb93a386Sopenharmony_ciString String::operator+(const char* s) const {
65cb93a386Sopenharmony_ci    String result(*this);
66cb93a386Sopenharmony_ci    result.append(s);
67cb93a386Sopenharmony_ci    return result;
68cb93a386Sopenharmony_ci}
69cb93a386Sopenharmony_ci
70cb93a386Sopenharmony_ciString String::operator+(const String& s) const {
71cb93a386Sopenharmony_ci    String result(*this);
72cb93a386Sopenharmony_ci    result.append(s);
73cb93a386Sopenharmony_ci    return result;
74cb93a386Sopenharmony_ci}
75cb93a386Sopenharmony_ci
76cb93a386Sopenharmony_ciString String::operator+(skstd::string_view s) const {
77cb93a386Sopenharmony_ci    String result(*this);
78cb93a386Sopenharmony_ci    result.append(s.data(), s.length());
79cb93a386Sopenharmony_ci    return result;
80cb93a386Sopenharmony_ci}
81cb93a386Sopenharmony_ci
82cb93a386Sopenharmony_ciString& String::operator+=(char c) {
83cb93a386Sopenharmony_ci    INHERITED::operator+=(c);
84cb93a386Sopenharmony_ci    return *this;
85cb93a386Sopenharmony_ci}
86cb93a386Sopenharmony_ci
87cb93a386Sopenharmony_ciString& String::operator+=(const char* s) {
88cb93a386Sopenharmony_ci    INHERITED::operator+=(s);
89cb93a386Sopenharmony_ci    return *this;
90cb93a386Sopenharmony_ci}
91cb93a386Sopenharmony_ci
92cb93a386Sopenharmony_ciString& String::operator+=(const String& s) {
93cb93a386Sopenharmony_ci    INHERITED::operator+=(s);
94cb93a386Sopenharmony_ci    return *this;
95cb93a386Sopenharmony_ci}
96cb93a386Sopenharmony_ci
97cb93a386Sopenharmony_ciString& String::operator+=(skstd::string_view s) {
98cb93a386Sopenharmony_ci    this->append(s.data(), s.length());
99cb93a386Sopenharmony_ci    return *this;
100cb93a386Sopenharmony_ci}
101cb93a386Sopenharmony_ci
102cb93a386Sopenharmony_ciString operator+(const char* s1, const String& s2) {
103cb93a386Sopenharmony_ci    String result(s1);
104cb93a386Sopenharmony_ci    result.append(s2);
105cb93a386Sopenharmony_ci    return result;
106cb93a386Sopenharmony_ci}
107cb93a386Sopenharmony_ci
108cb93a386Sopenharmony_ciString operator+(skstd::string_view left, skstd::string_view right) {
109cb93a386Sopenharmony_ci    return String(left) + right;
110cb93a386Sopenharmony_ci}
111cb93a386Sopenharmony_ci
112cb93a386Sopenharmony_ciString to_string(int32_t value) {
113cb93a386Sopenharmony_ci    return SkSL::String(std::to_string(value));
114cb93a386Sopenharmony_ci}
115cb93a386Sopenharmony_ci
116cb93a386Sopenharmony_ciString to_string(uint32_t value) {
117cb93a386Sopenharmony_ci    return SkSL::String(std::to_string(value));
118cb93a386Sopenharmony_ci}
119cb93a386Sopenharmony_ci
120cb93a386Sopenharmony_ciString to_string(int64_t value) {
121cb93a386Sopenharmony_ci    return SkSL::String(std::to_string(value));
122cb93a386Sopenharmony_ci}
123cb93a386Sopenharmony_ci
124cb93a386Sopenharmony_ciString to_string(uint64_t value) {
125cb93a386Sopenharmony_ci    return SkSL::String(std::to_string(value));
126cb93a386Sopenharmony_ci}
127cb93a386Sopenharmony_ci
128cb93a386Sopenharmony_ciString to_string(double value) {
129cb93a386Sopenharmony_ci    std::stringstream buffer;
130cb93a386Sopenharmony_ci    buffer.imbue(std::locale::classic());
131cb93a386Sopenharmony_ci    buffer.precision(17);
132cb93a386Sopenharmony_ci    buffer << value;
133cb93a386Sopenharmony_ci    bool needsDotZero = true;
134cb93a386Sopenharmony_ci    const std::string str = buffer.str();
135cb93a386Sopenharmony_ci    for (int i = str.size() - 1; i >= 0; --i) {
136cb93a386Sopenharmony_ci        char c = str[i];
137cb93a386Sopenharmony_ci        if (c == '.' || c == 'e') {
138cb93a386Sopenharmony_ci            needsDotZero = false;
139cb93a386Sopenharmony_ci            break;
140cb93a386Sopenharmony_ci        }
141cb93a386Sopenharmony_ci    }
142cb93a386Sopenharmony_ci    if (needsDotZero) {
143cb93a386Sopenharmony_ci        buffer << ".0";
144cb93a386Sopenharmony_ci    }
145cb93a386Sopenharmony_ci    return String(buffer.str().c_str());
146cb93a386Sopenharmony_ci}
147cb93a386Sopenharmony_ci
148cb93a386Sopenharmony_cibool stod(const skstd::string_view& s, SKSL_FLOAT* value) {
149cb93a386Sopenharmony_ci    std::string str(s.data(), s.size());
150cb93a386Sopenharmony_ci    std::stringstream buffer(str);
151cb93a386Sopenharmony_ci    buffer.imbue(std::locale::classic());
152cb93a386Sopenharmony_ci    buffer >> *value;
153cb93a386Sopenharmony_ci    return !buffer.fail();
154cb93a386Sopenharmony_ci}
155cb93a386Sopenharmony_ci
156cb93a386Sopenharmony_cibool stoi(const skstd::string_view& s, SKSL_INT* value) {
157cb93a386Sopenharmony_ci    char* p;
158cb93a386Sopenharmony_ci    errno = 0;
159cb93a386Sopenharmony_ci    unsigned long long result = strtoull(s.begin(), &p, /*base=*/0);
160cb93a386Sopenharmony_ci    *value = static_cast<SKSL_INT>(result);
161cb93a386Sopenharmony_ci    return p == s.end() && errno == 0 && result <= 0xFFFFFFFF;
162cb93a386Sopenharmony_ci}
163cb93a386Sopenharmony_ci
164cb93a386Sopenharmony_ci}  // namespace SkSL
165