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 <cmath>
13 #include <errno.h>
14 #include <limits.h>
15 #include <locale>
16 #include <sstream>
17 #include <string>
18
to_string(float value)19 std::string skstd::to_string(float value) {
20 return skstd::to_string((double)value);
21 }
22
to_string(double value)23 std::string skstd::to_string(double value) {
24 std::stringstream buffer;
25 buffer.imbue(std::locale::classic());
26 buffer.precision(17);
27 buffer << value;
28 bool needsDotZero = true;
29 const std::string str = buffer.str();
30 for (int i = str.size() - 1; i >= 0; --i) {
31 char c = str[i];
32 if (c == '.' || c == 'e') {
33 needsDotZero = false;
34 break;
35 }
36 }
37 if (needsDotZero) {
38 buffer << ".0";
39 }
40 return buffer.str();
41 }
42
stod(std::string_view s,SKSL_FLOAT * value)43 bool SkSL::stod(std::string_view s, SKSL_FLOAT* value) {
44 std::string str(s.data(), s.size());
45 std::stringstream buffer(str);
46 buffer.imbue(std::locale::classic());
47 buffer >> *value;
48 return !buffer.fail() && std::isfinite(*value);
49 }
50
stoi(std::string_view s,SKSL_INT * value)51 bool SkSL::stoi(std::string_view s, SKSL_INT* value) {
52 if (s.empty()) {
53 return false;
54 }
55 char suffix = s.back();
56 if (suffix == 'u' || suffix == 'U') {
57 s.remove_suffix(1);
58 }
59 std::string str(s); // s is not null-terminated
60 const char* strEnd = str.data() + str.length();
61 char* p;
62 errno = 0;
63 unsigned long long result = strtoull(str.data(), &p, /*base=*/0);
64 *value = static_cast<SKSL_INT>(result);
65 return p == strEnd && errno == 0 && result <= 0xFFFFFFFF;
66 }
67
printf(const char * fmt,...)68 std::string SkSL::String::printf(const char* fmt, ...) {
69 va_list args;
70 va_start(args, fmt);
71 std::string result;
72 vappendf(&result, fmt, args);
73 va_end(args);
74 return result;
75 }
76
appendf(std::string * str,const char * fmt,...)77 void SkSL::String::appendf(std::string *str, const char* fmt, ...) {
78 va_list args;
79 va_start(args, fmt);
80 vappendf(str, fmt, args);
81 va_end(args);
82 }
83
vappendf(std::string * str,const char * fmt,va_list args)84 void SkSL::String::vappendf(std::string *str, const char* fmt, va_list args) {
85 #define BUFFER_SIZE 256
86 char buffer[BUFFER_SIZE];
87 va_list reuse;
88 va_copy(reuse, args);
89 size_t size = vsnprintf(buffer, BUFFER_SIZE, fmt, args);
90 if (BUFFER_SIZE >= size + 1) {
91 str->append(buffer, size);
92 } else {
93 auto newBuffer = std::unique_ptr<char[]>(new char[size + 1]);
94 vsnprintf(newBuffer.get(), size + 1, fmt, reuse);
95 str->append(newBuffer.get(), size);
96 }
97 va_end(reuse);
98 }
99