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 #ifndef SKSL_STRING
9 #define SKSL_STRING
10 
11 #include "include/private/SkSLDefines.h"
12 #include <cstring>
13 #include <stdarg.h>
14 #include <string>
15 
16 #ifndef SKSL_STANDALONE
17 #include "include/core/SkString.h"
18 #endif
19 
20 namespace SkSL {
21 
22 class String;
23 
24 // Represents a (not necessarily null-terminated) slice of a string.
25 struct StringFragment {
StringFragmentStringFragment26     StringFragment()
27     : fChars("")
28     , fLength(0) {}
29 
StringFragmentStringFragment30     StringFragment(const char* chars)
31     : fChars(chars)
32     , fLength(strlen(chars)) {}
33 
StringFragmentStringFragment34     StringFragment(const char* chars, size_t length)
35     : fChars(chars)
36     , fLength(length) {}
37 
beginStringFragment38     const char* begin() const { return fChars; }
endStringFragment39     const char* end() const { return fChars + fLength; }
40 
dataStringFragment41     const char* data() const { return fChars; }
sizeStringFragment42     size_t size() const { return fLength; }
lengthStringFragment43     size_t length() const { return fLength; }
44     char operator[](size_t idx) const { return fChars[idx]; }
45 
46     bool startsWith(const char prefix[]) const;
47     bool endsWith(const char suffix[]) const;
48 
49     bool operator==(const char* s) const;
50     bool operator!=(const char* s) const;
51     bool operator==(StringFragment s) const;
52     bool operator!=(StringFragment s) const;
53     bool operator<(StringFragment s) const;
54     String operator+(const char* s) const;
55     String operator+(const StringFragment& s) const;
56     String operator+(const String& s) const;
57 
58 #ifndef SKSL_STANDALONE
SkStringStringFragment59     operator SkString() const { return SkString(fChars, fLength); }
60 #endif
61 
62     const char* fChars;
63     size_t fLength;
64 };
65 
66 bool operator==(const char* s1, StringFragment s2);
67 
68 bool operator!=(const char* s1, StringFragment s2);
69 
70 class SK_API String : public std::string {
71 public:
72     using std::string::string;
73 
String(std::string s)74     explicit String(std::string s) : INHERITED(std::move(s)) {}
String(StringFragment s)75     String(StringFragment s) : INHERITED(s.fChars, s.fLength) {}
76 
77     static String printf(const char* fmt, ...) SK_PRINTF_LIKE(1, 2);
78     void appendf(const char* fmt, ...) SK_PRINTF_LIKE(2, 3);
79     void vappendf(const char* fmt, va_list va);
80 
startsWith(const char prefix[])81     bool startsWith(const char prefix[]) const {
82         return StringFragment(data(), size()).startsWith(prefix);
83     }
endsWith(const char suffix[])84     bool endsWith(const char suffix[]) const {
85         return StringFragment(data(), size()).endsWith(suffix);
86     }
87 
88     bool consumeSuffix(const char suffix[]);
89 
90     String operator+(const char* s) const;
91     String operator+(const String& s) const;
92     String operator+(StringFragment s) const;
93     String& operator+=(char c);
94     String& operator+=(const char* s);
95     String& operator+=(const String& s);
96     String& operator+=(StringFragment s);
97     bool operator==(const char* s) const;
98     bool operator!=(const char* s) const;
99     bool operator==(const String& s) const;
100     bool operator!=(const String& s) const;
101     friend String operator+(const char* s1, const String& s2);
102     friend bool operator==(const char* s1, const String& s2);
103     friend bool operator!=(const char* s1, const String& s2);
104 
105 private:
106     using INHERITED = std::string;
107 };
108 
109 String operator+(const char* s1, const String& s2);
110 bool operator!=(const char* s1, const String& s2);
111 
112 String to_string(double value);
113 String to_string(int32_t value);
114 String to_string(uint32_t value);
115 String to_string(int64_t value);
116 String to_string(uint64_t value);
117 
118 bool stod(const StringFragment& s, SKSL_FLOAT* value);
119 bool stoi(const StringFragment& s, SKSL_INT* value);
120 
121 } // namespace SkSL
122 
123 namespace std {
124     template<> struct hash<SkSL::StringFragment> {
125         size_t operator()(const SkSL::StringFragment& s) const {
126             size_t result = 0;
127             for (size_t i = 0; i < s.fLength; ++i) {
128                 result = result * 101 + (size_t) s.fChars[i];
129             }
130             return result;
131         }
132     };
133 
134     template<> struct hash<SkSL::String> {
135         size_t operator()(const SkSL::String& s) const {
136             return hash<std::string>{}(s);
137         }
138     };
139 } // namespace std
140 
141 #endif
142