blob: 26d7f0cae9470859e1367bb4e580f20f33dc5378 [file] [log] [blame]
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001/*
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
Ethan Nicholasdaed2592021-03-04 14:30:25 -05008#include "include/private/SkSLString.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -05009#include "src/sksl/SkSLUtil.h"
Brian Osmande7220f2018-02-09 09:32:36 -050010#include <algorithm>
John Stiles70e51e62021-02-17 20:43:54 -050011#include <cinttypes>
Ethan Nicholas0df1b042017-03-31 13:56:23 -040012#include <errno.h>
Ethan Nicholas0df1b042017-03-31 13:56:23 -040013#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);
z102.zhangd74f2c82018-08-10 09:08:47 +080025 va_end(args);
Ethan Nicholas0df1b042017-03-31 13:56:23 -040026 return result;
27}
28
Ethan Nicholas0df1b042017-03-31 13:56:23 -040029void String::appendf(const char* fmt, ...) {
30 va_list args;
31 va_start(args, fmt);
32 this->vappendf(fmt, args);
z102.zhangd74f2c82018-08-10 09:08:47 +080033 va_end(args);
Ethan Nicholas0df1b042017-03-31 13:56:23 -040034}
Michael Ludwige84fb192018-08-21 16:32:20 -040035
Ethan Nicholas0df1b042017-03-31 13:56:23 -040036void String::vappendf(const char* fmt, va_list args) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -040037 #define BUFFER_SIZE 256
38 char buffer[BUFFER_SIZE];
Ethan Nicholas762466e2017-06-29 10:03:38 -040039 va_list reuse;
40 va_copy(reuse, args);
Brian Osman061a5cf2020-06-24 14:50:25 -040041 size_t size = vsnprintf(buffer, BUFFER_SIZE, fmt, args);
Ethan Nicholasc18bb512020-07-28 14:46:53 -040042 if (BUFFER_SIZE >= size + 1) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -040043 this->append(buffer, size);
44 } else {
Ethan Nicholas762466e2017-06-29 10:03:38 -040045 auto newBuffer = std::unique_ptr<char[]>(new char[size + 1]);
Brian Osman061a5cf2020-06-24 14:50:25 -040046 vsnprintf(newBuffer.get(), size + 1, fmt, reuse);
Ethan Nicholas0df1b042017-03-31 13:56:23 -040047 this->append(newBuffer.get(), size);
48 }
z102.zhangd74f2c82018-08-10 09:08:47 +080049 va_end(reuse);
Ethan Nicholas0df1b042017-03-31 13:56:23 -040050}
51
John Stiles72664be2020-09-16 17:43:11 -040052bool 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
Ethan Nicholas0df1b042017-03-31 13:56:23 -040064String 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
Ethan Nicholas962dec42021-06-10 13:06:39 -040076String String::operator+(skstd::string_view s) const {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -070077 String result(*this);
Ethan Nicholasd2e09602021-06-10 11:21:59 -040078 result.append(s.data(), s.length());
Ethan Nicholas5b5f0962017-09-11 13:50:14 -070079 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
Ethan Nicholas962dec42021-06-10 13:06:39 -040097String& String::operator+=(skstd::string_view s) {
Ethan Nicholasd2e09602021-06-10 11:21:59 -040098 this->append(s.data(), s.length());
Ethan Nicholas5b5f0962017-09-11 13:50:14 -070099 return *this;
100}
101
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400102String operator+(const char* s1, const String& s2) {
103 String result(s1);
104 result.append(s2);
105 return result;
106}
107
Ethan Nicholas962dec42021-06-10 13:06:39 -0400108String operator+(skstd::string_view left, skstd::string_view right) {
Ethan Nicholasd2e09602021-06-10 11:21:59 -0400109 return String(left) + right;
Ethan Nicholascc305772017-10-13 16:17:45 -0400110}
111
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400112String to_string(int32_t value) {
John Stilesc8bcef12021-03-18 12:45:15 -0400113 return SkSL::String(std::to_string(value));
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400114}
115
116String to_string(uint32_t value) {
John Stilesc8bcef12021-03-18 12:45:15 -0400117 return SkSL::String(std::to_string(value));
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400118}
119
120String to_string(int64_t value) {
John Stilesc8bcef12021-03-18 12:45:15 -0400121 return SkSL::String(std::to_string(value));
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400122}
123
124String to_string(uint64_t value) {
John Stilesc8bcef12021-03-18 12:45:15 -0400125 return SkSL::String(std::to_string(value));
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400126}
127
128String to_string(double value) {
Ethan Nicholas2f103f02019-02-25 10:58:48 -0500129 std::stringstream buffer;
130 buffer.imbue(std::locale::classic());
131 buffer.precision(17);
132 buffer << value;
Ethan Nicholas00543112018-07-31 09:44:36 -0400133 bool needsDotZero = true;
Ethan Nicholas2f103f02019-02-25 10:58:48 -0500134 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') {
Ethan Nicholas00543112018-07-31 09:44:36 -0400138 needsDotZero = false;
139 break;
140 }
141 }
Ethan Nicholas00543112018-07-31 09:44:36 -0400142 if (needsDotZero) {
Ethan Nicholas2f103f02019-02-25 10:58:48 -0500143 buffer << ".0";
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400144 }
Ethan Nicholas2f103f02019-02-25 10:58:48 -0500145 return String(buffer.str().c_str());
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400146}
147
Ethan Nicholas962dec42021-06-10 13:06:39 -0400148bool stod(const skstd::string_view& s, SKSL_FLOAT* value) {
John Stilesf94348f2020-12-23 18:58:43 -0500149 std::string str(s.data(), s.size());
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400150 std::stringstream buffer(str);
151 buffer.imbue(std::locale::classic());
John Stilesf94348f2020-12-23 18:58:43 -0500152 buffer >> *value;
153 return !buffer.fail();
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400154}
155
Ethan Nicholas962dec42021-06-10 13:06:39 -0400156bool stoi(const skstd::string_view& s, SKSL_INT* value) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400157 char* p;
John Stilesf94348f2020-12-23 18:58:43 -0500158 errno = 0;
159 unsigned long long result = strtoull(s.begin(), &p, /*base=*/0);
John Stilesf94348f2020-12-23 18:58:43 -0500160 *value = static_cast<SKSL_INT>(result);
161 return p == s.end() && errno == 0 && result <= 0xFFFFFFFF;
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400162}
163
John Stilesa6841be2020-08-06 14:11:56 -0400164} // namespace SkSL