• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/SkSLDefines.h"
9 #include "include/private/SkSLString.h"
10 #include "include/private/base/SkAssert.h"
11 #include "src/base/SkStringView.h"
12 
13 #include <cerrno>
14 #include <cmath>
15 #include <cstdarg>
16 #include <cstdio>
17 #include <cstdlib>
18 #include <locale>
19 #include <memory>
20 #include <sstream>
21 #include <string>
22 #include <string_view>
23 
24 template <typename RoundtripType, int kFullPrecision>
to_string_impl(RoundtripType value)25 static std::string to_string_impl(RoundtripType value) {
26     std::stringstream buffer;
27     buffer.imbue(std::locale::classic());
28     buffer.precision(7);
29     buffer << value;
30     std::string text = buffer.str();
31 
32     double roundtripped;
33     buffer >> roundtripped;
34     if (value != (RoundtripType)roundtripped && std::isfinite(value)) {
35         buffer.str({});
36         buffer.clear();
37         buffer.precision(kFullPrecision);
38         buffer << value;
39         text = buffer.str();
40         SkASSERTF((buffer >> roundtripped, value == (RoundtripType)roundtripped),
41                   "%.17g -> %s -> %.17g", value, text.c_str(), roundtripped);
42     }
43 
44     // We need to emit a decimal point to distinguish floats from ints.
45     if (!skstd::contains(text, '.') && !skstd::contains(text, 'e')) {
46         text += ".0";
47     }
48 
49     return text;
50 }
51 
to_string(float value)52 std::string skstd::to_string(float value) {
53     return to_string_impl<float, 9>(value);
54 }
55 
to_string(double value)56 std::string skstd::to_string(double value) {
57     return to_string_impl<double, 17>(value);
58 }
59 
stod(std::string_view s,SKSL_FLOAT * value)60 bool SkSL::stod(std::string_view s, SKSL_FLOAT* value) {
61     std::string str(s.data(), s.size());
62     std::stringstream buffer(str);
63     buffer.imbue(std::locale::classic());
64     buffer >> *value;
65     return !buffer.fail() && std::isfinite(*value);
66 }
67 
stoi(std::string_view s,SKSL_INT * value)68 bool SkSL::stoi(std::string_view s, SKSL_INT* value) {
69     if (s.empty()) {
70         return false;
71     }
72     char suffix = s.back();
73     if (suffix == 'u' || suffix == 'U') {
74         s.remove_suffix(1);
75     }
76     std::string str(s);  // s is not null-terminated
77     const char* strEnd = str.data() + str.length();
78     char* p;
79     errno = 0;
80     unsigned long long result = strtoull(str.data(), &p, /*base=*/0);
81     *value = static_cast<SKSL_INT>(result);
82     return p == strEnd && errno == 0 && result <= 0xFFFFFFFF;
83 }
84 
printf(const char * fmt,...)85 std::string SkSL::String::printf(const char* fmt, ...) {
86     va_list args;
87     va_start(args, fmt);
88     std::string result;
89     vappendf(&result, fmt, args);
90     va_end(args);
91     return result;
92 }
93 
appendf(std::string * str,const char * fmt,...)94 void SkSL::String::appendf(std::string *str, const char* fmt, ...) {
95     va_list args;
96     va_start(args, fmt);
97     vappendf(str, fmt, args);
98     va_end(args);
99 }
100 
vappendf(std::string * str,const char * fmt,va_list args)101 void SkSL::String::vappendf(std::string *str, const char* fmt, va_list args) {
102     #define BUFFER_SIZE 256
103     char buffer[BUFFER_SIZE];
104     va_list reuse;
105     va_copy(reuse, args);
106     size_t size = vsnprintf(buffer, BUFFER_SIZE, fmt, args);
107     if (BUFFER_SIZE >= size + 1) {
108         str->append(buffer, size);
109     } else {
110         auto newBuffer = std::unique_ptr<char[]>(new char[size + 1]);
111         vsnprintf(newBuffer.get(), size + 1, fmt, reuse);
112         str->append(newBuffer.get(), size);
113     }
114     va_end(reuse);
115 }
116