blob: ac6d7f85c148c69dc102e744823ad14bac4e150a [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
8#include "SkSLString.h"
9
10#include "SkSLUtil.h"
Ethan Nicholas0df1b042017-03-31 13:56:23 -040011#include <errno.h>
Ethan Nicholas0df1b042017-03-31 13:56:23 -040012#include <limits.h>
13#include <locale>
14#include <sstream>
15#include <string>
16
17namespace SkSL {
18
19String 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
Brian Osman93ba0a42017-08-14 14:48:10 -040027#ifdef SKSL_USE_STD_STRING
Ethan Nicholas0df1b042017-03-31 13:56:23 -040028void String::appendf(const char* fmt, ...) {
29 va_list args;
30 va_start(args, fmt);
31 this->vappendf(fmt, args);
32}
33#endif
34
35void 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];
Ethan Nicholas762466e2017-06-29 10:03:38 -040043 va_list reuse;
44 va_copy(reuse, args);
Ethan Nicholas0df1b042017-03-31 13:56:23 -040045 size_t size = VSNPRINTF(buffer, BUFFER_SIZE, fmt, args);
46 if (BUFFER_SIZE >= size) {
47 this->append(buffer, size);
48 } else {
Ethan Nicholas762466e2017-06-29 10:03:38 -040049 auto newBuffer = std::unique_ptr<char[]>(new char[size + 1]);
50 VSNPRINTF(newBuffer.get(), size + 1, fmt, reuse);
Ethan Nicholas0df1b042017-03-31 13:56:23 -040051 this->append(newBuffer.get(), size);
52 }
Ethan Nicholas0df1b042017-03-31 13:56:23 -040053}
54
55
56bool String::startsWith(const char* s) const {
Ethan Nicholas985febf2017-05-19 14:03:45 -040057 return !strncmp(c_str(), s, strlen(s));
Ethan Nicholas0df1b042017-03-31 13:56:23 -040058}
59
60bool String::endsWith(const char* s) const {
61 size_t len = strlen(s);
62 if (size() < len) {
63 return false;
64 }
Ethan Nicholas985febf2017-05-19 14:03:45 -040065 return !strncmp(c_str() + size() - len, s, len);
Ethan Nicholas0df1b042017-03-31 13:56:23 -040066}
67
68String String::operator+(const char* s) const {
69 String result(*this);
70 result.append(s);
71 return result;
72}
73
74String String::operator+(const String& s) const {
75 String result(*this);
76 result.append(s);
77 return result;
78}
79
80bool String::operator==(const String& s) const {
81 return this->size() == s.size() && !memcmp(c_str(), s.c_str(), this->size());
82}
83
84bool String::operator!=(const String& s) const {
85 return !(*this == s);
86}
87
88bool String::operator==(const char* s) const {
89 return this->size() == strlen(s) && !memcmp(c_str(), s, this->size());
90}
91
92bool String::operator!=(const char* s) const {
93 return !(*this == s);
94}
95
96String operator+(const char* s1, const String& s2) {
97 String result(s1);
98 result.append(s2);
99 return result;
100}
101
102bool operator==(const char* s1, const String& s2) {
103 return s2 == s1;
104}
105
106bool operator!=(const char* s1, const String& s2) {
107 return s2 != s1;
108}
109
110String to_string(int32_t value) {
111 return SkSL::String::printf("%d", value);
112}
113
114String to_string(uint32_t value) {
115 return SkSL::String::printf("%u", value);
116}
117
118String to_string(int64_t value) {
Ethan Nicholasc8c17602017-03-31 18:53:05 -0400119 std::stringstream buffer;
120 buffer << value;
121 return String(buffer.str().c_str());
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400122}
123
124String to_string(uint64_t value) {
Ethan Nicholasc8c17602017-03-31 18:53:05 -0400125 std::stringstream buffer;
126 buffer << value;
127 return String(buffer.str().c_str());
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400128}
129
130String to_string(double value) {
131#ifdef SKSL_BUILD_FOR_WIN
132 #define SNPRINTF _snprintf
133#else
134 #define SNPRINTF snprintf
135#endif
136#define MAX_DOUBLE_CHARS 25
137 char buffer[MAX_DOUBLE_CHARS];
138 SKSL_DEBUGCODE(int len = )SNPRINTF(buffer, sizeof(buffer), "%.17g", value);
139 ASSERT(len < MAX_DOUBLE_CHARS);
140 String result(buffer);
141 if (!strchr(buffer, '.') && !strchr(buffer, 'e')) {
142 result += ".0";
143 }
144 return result;
145#undef SNPRINTF
146#undef MAX_DOUBLE_CHARS
147}
148
Brian Osman634624a2017-08-15 11:14:30 -0400149int stoi(const String& s) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400150 char* p;
151 SKSL_DEBUGCODE(errno = 0;)
152 long result = strtoul(s.c_str(), &p, 0);
153 ASSERT(*p == 0);
154 ASSERT(!errno);
155 return (int) result;
156}
157
Brian Osman634624a2017-08-15 11:14:30 -0400158double stod(const String& s) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400159 double result;
160 std::string str(s.c_str(), s.size());
161 std::stringstream buffer(str);
162 buffer.imbue(std::locale::classic());
163 buffer >> result;
164 ASSERT(!buffer.fail());
165 return result;
166}
167
Brian Osman634624a2017-08-15 11:14:30 -0400168long stol(const String& s) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400169 char* p;
170 SKSL_DEBUGCODE(errno = 0;)
171 long result = strtoul(s.c_str(), &p, 0);
172 ASSERT(*p == 0);
173 ASSERT(!errno);
174 return result;
175}
176
177} // namespace