Skia
2D Graphics Library
SkString.h
Go to the documentation of this file.
1 /*
2  * Copyright 2006 The Android Open Source Project
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 SkString_DEFINED
9 #define SkString_DEFINED
10 
11 #include "include/core/SkRefCnt.h"
12 #include "include/core/SkScalar.h"
13 #include "include/core/SkTypes.h"
14 #include "include/private/base/SkTo.h"
15 #include "include/private/base/SkTypeTraits.h"
16 
17 #include <atomic>
18 #include <cstdarg>
19 #include <cstdint>
20 #include <cstring>
21 #include <string>
22 #include <string_view>
23 #include <type_traits>
24 
25 /* Some helper functions for C strings */
26 static inline bool SkStrStartsWith(const char string[], const char prefixStr[]) {
27  SkASSERT(string);
28  SkASSERT(prefixStr);
29  return !strncmp(string, prefixStr, strlen(prefixStr));
30 }
31 static inline bool SkStrStartsWith(const char string[], const char prefixChar) {
32  SkASSERT(string);
33  return (prefixChar == *string);
34 }
35 
36 bool SkStrEndsWith(const char string[], const char suffixStr[]);
37 bool SkStrEndsWith(const char string[], const char suffixChar);
38 
39 int SkStrStartsWithOneOf(const char string[], const char prefixes[]);
40 
41 static inline int SkStrFind(const char string[], const char substring[]) {
42  const char *first = strstr(string, substring);
43  if (nullptr == first) return -1;
44  return SkToInt(first - &string[0]);
45 }
46 
47 static inline int SkStrFindLastOf(const char string[], const char subchar) {
48  const char* last = strrchr(string, subchar);
49  if (nullptr == last) return -1;
50  return SkToInt(last - &string[0]);
51 }
52 
53 static inline bool SkStrContains(const char string[], const char substring[]) {
54  SkASSERT(string);
55  SkASSERT(substring);
56  return (-1 != SkStrFind(string, substring));
57 }
58 static inline bool SkStrContains(const char string[], const char subchar) {
59  SkASSERT(string);
60  char tmp[2];
61  tmp[0] = subchar;
62  tmp[1] = '\0';
63  return (-1 != SkStrFind(string, tmp));
64 }
65 
66 /*
67  * The SkStrAppend... methods will write into the provided buffer, assuming it is large enough.
68  * Each method has an associated const (e.g. kSkStrAppendU32_MaxSize) which will be the largest
69  * value needed for that method's buffer.
70  *
71  * char storage[kSkStrAppendU32_MaxSize];
72  * SkStrAppendU32(storage, value);
73  *
74  * Note : none of the SkStrAppend... methods write a terminating 0 to their buffers. Instead,
75  * the methods return the ptr to the end of the written part of the buffer. This can be used
76  * to compute the length, and/or know where to write a 0 if that is desired.
77  *
78  * char storage[kSkStrAppendU32_MaxSize + 1];
79  * char* stop = SkStrAppendU32(storage, value);
80  * size_t len = stop - storage;
81  * *stop = 0; // valid, since storage was 1 byte larger than the max.
82  */
83 
84 static constexpr int kSkStrAppendU32_MaxSize = 10;
85 char* SkStrAppendU32(char buffer[], uint32_t);
86 static constexpr int kSkStrAppendU64_MaxSize = 20;
87 char* SkStrAppendU64(char buffer[], uint64_t, int minDigits);
88 
90 char* SkStrAppendS32(char buffer[], int32_t);
92 char* SkStrAppendS64(char buffer[], int64_t, int minDigits);
93 
101 static constexpr int kSkStrAppendScalar_MaxSize = 15;
102 
110 char* SkStrAppendScalar(char buffer[], SkScalar);
111 
118 class SK_API SkString {
119 public:
121  explicit SkString(size_t len);
122  explicit SkString(const char text[]);
123  SkString(const char text[], size_t len);
126  explicit SkString(const std::string&);
127  explicit SkString(std::string_view);
129 
130  bool isEmpty() const { return 0 == fRec->fLength; }
131  size_t size() const { return (size_t) fRec->fLength; }
132  const char* data() const { return fRec->data(); }
133  const char* c_str() const { return fRec->data(); }
134  char operator[](size_t n) const { return this->c_str()[n]; }
135 
136  bool equals(const SkString&) const;
137  bool equals(const char text[]) const;
138  bool equals(const char text[], size_t len) const;
139 
140  bool startsWith(const char prefixStr[]) const {
141  return SkStrStartsWith(fRec->data(), prefixStr);
142  }
143  bool startsWith(const char prefixChar) const {
144  return SkStrStartsWith(fRec->data(), prefixChar);
145  }
146  bool endsWith(const char suffixStr[]) const {
147  return SkStrEndsWith(fRec->data(), suffixStr);
148  }
149  bool endsWith(const char suffixChar) const {
150  return SkStrEndsWith(fRec->data(), suffixChar);
151  }
152  bool contains(const char substring[]) const {
153  return SkStrContains(fRec->data(), substring);
154  }
155  bool contains(const char subchar) const {
156  return SkStrContains(fRec->data(), subchar);
157  }
158  int find(const char substring[]) const {
159  return SkStrFind(fRec->data(), substring);
160  }
161  int findLastOf(const char subchar) const {
162  return SkStrFindLastOf(fRec->data(), subchar);
163  }
164 
165  friend bool operator==(const SkString& a, const SkString& b) {
166  return a.equals(b);
167  }
168  friend bool operator!=(const SkString& a, const SkString& b) {
169  return !a.equals(b);
170  }
171 
172  // these methods edit the string
173 
176  SkString& operator=(const char text[]);
177 
178  char* data();
179  char& operator[](size_t n) { return this->data()[n]; }
180 
181  void reset();
185  void resize(size_t len);
186  void set(const SkString& src) { *this = src; }
187  void set(const char text[]);
188  void set(const char text[], size_t len);
189  void set(std::string_view str) { this->set(str.data(), str.size()); }
190 
191  void insert(size_t offset, const char text[]);
192  void insert(size_t offset, const char text[], size_t len);
193  void insert(size_t offset, const SkString& str) { this->insert(offset, str.c_str(), str.size()); }
194  void insert(size_t offset, std::string_view str) { this->insert(offset, str.data(), str.size()); }
195  void insertUnichar(size_t offset, SkUnichar);
196  void insertS32(size_t offset, int32_t value);
197  void insertS64(size_t offset, int64_t value, int minDigits = 0);
198  void insertU32(size_t offset, uint32_t value);
199  void insertU64(size_t offset, uint64_t value, int minDigits = 0);
200  void insertHex(size_t offset, uint32_t value, int minDigits = 0);
201  void insertScalar(size_t offset, SkScalar);
202 
203  void append(const char text[]) { this->insert((size_t)-1, text); }
204  void append(const char text[], size_t len) { this->insert((size_t)-1, text, len); }
205  void append(const SkString& str) { this->insert((size_t)-1, str.c_str(), str.size()); }
206  void append(std::string_view str) { this->insert((size_t)-1, str.data(), str.size()); }
207  void appendUnichar(SkUnichar uni) { this->insertUnichar((size_t)-1, uni); }
208  void appendS32(int32_t value) { this->insertS32((size_t)-1, value); }
209  void appendS64(int64_t value, int minDigits = 0) { this->insertS64((size_t)-1, value, minDigits); }
210  void appendU32(uint32_t value) { this->insertU32((size_t)-1, value); }
211  void appendU64(uint64_t value, int minDigits = 0) { this->insertU64((size_t)-1, value, minDigits); }
212  void appendHex(uint32_t value, int minDigits = 0) { this->insertHex((size_t)-1, value, minDigits); }
213  void appendScalar(SkScalar value) { this->insertScalar((size_t)-1, value); }
214 
215  void prepend(const char text[]) { this->insert(0, text); }
216  void prepend(const char text[], size_t len) { this->insert(0, text, len); }
217  void prepend(const SkString& str) { this->insert(0, str.c_str(), str.size()); }
218  void prepend(std::string_view str) { this->insert(0, str.data(), str.size()); }
219  void prependUnichar(SkUnichar uni) { this->insertUnichar(0, uni); }
220  void prependS32(int32_t value) { this->insertS32(0, value); }
221  void prependS64(int32_t value, int minDigits = 0) { this->insertS64(0, value, minDigits); }
222  void prependHex(uint32_t value, int minDigits = 0) { this->insertHex(0, value, minDigits); }
223  void prependScalar(SkScalar value) { this->insertScalar((size_t)-1, value); }
224 
225  void printf(const char format[], ...) SK_PRINTF_LIKE(2, 3);
226  void printVAList(const char format[], va_list) SK_PRINTF_LIKE(2, 0);
227  void appendf(const char format[], ...) SK_PRINTF_LIKE(2, 3);
228  void appendVAList(const char format[], va_list) SK_PRINTF_LIKE(2, 0);
229  void prependf(const char format[], ...) SK_PRINTF_LIKE(2, 3);
230  void prependVAList(const char format[], va_list) SK_PRINTF_LIKE(2, 0);
231 
232  void remove(size_t offset, size_t length);
233 
234  SkString& operator+=(const SkString& s) { this->append(s); return *this; }
235  SkString& operator+=(const char text[]) { this->append(text); return *this; }
236  SkString& operator+=(const char c) { this->append(&c, 1); return *this; }
237 
242  void swap(SkString& other);
243 
244  using sk_is_trivially_relocatable = std::true_type;
245 
246 private:
247  struct Rec {
248  public:
249  constexpr Rec(uint32_t len, int32_t refCnt) : fLength(len), fRefCnt(refCnt) {}
250  static sk_sp<Rec> Make(const char text[], size_t len);
251  char* data() { return fBeginningOfData; }
252  const char* data() const { return fBeginningOfData; }
253  void ref() const;
254  void unref() const;
255  bool unique() const;
256 #ifdef SK_DEBUG
257  int32_t getRefCnt() const;
258 #endif
259  uint32_t fLength; // logically size_t, but we want it to stay 32 bits
260 
261  private:
262  mutable std::atomic<int32_t> fRefCnt;
263  char fBeginningOfData[1] = {'\0'};
264 
265  // Ensure the unsized delete is called.
266  void operator delete(void* p) { ::operator delete(p); }
267  };
268  sk_sp<Rec> fRec;
269 
270  static_assert(::sk_is_trivially_relocatable<decltype(fRec)>::value);
271 
272 #ifdef SK_DEBUG
273  SkString& validate();
274  const SkString& validate() const;
275 #else
276  SkString& validate() { return *this; }
277  const SkString& validate() const { return *this; }
278 #endif
279 
280  static const Rec gEmptyRec;
281 };
282 
284 SkString SkStringPrintf(const char* format, ...) SK_PRINTF_LIKE(1, 2);
287 static inline SkString SkStringPrintf() { return SkString(); }
288 
289 static inline void swap(SkString& a, SkString& b) {
290  a.swap(b);
291 }
292 
293 #endif
float SkScalar
Definition: SkScalar.h:14
SkString SkStringPrintf(const char *format,...) SK_PRINTF_LIKE(1
Creates a new string and writes into it using a printf()-style format.
static constexpr int kSkStrAppendS32_MaxSize
Definition: SkString.h:89
static constexpr int kSkStrAppendS64_MaxSize
Definition: SkString.h:91
static constexpr int kSkStrAppendU32_MaxSize
Definition: SkString.h:84
static void swap(SkString &a, SkString &b)
Definition: SkString.h:289
static int SkStrFindLastOf(const char string[], const char subchar)
Definition: SkString.h:47
char * SkStrAppendU64(char buffer[], uint64_t, int minDigits)
static constexpr int kSkStrAppendScalar_MaxSize
Floats have at most 8 significant digits, so we limit our g to that.
Definition: SkString.h:101
bool SkStrEndsWith(const char string[], const char suffixStr[])
static bool SkStrStartsWith(const char string[], const char prefixStr[])
Definition: SkString.h:26
char * SkStrAppendS64(char buffer[], int64_t, int minDigits)
static int SkStrFind(const char string[], const char substring[])
Definition: SkString.h:41
static constexpr int kSkStrAppendU64_MaxSize
Definition: SkString.h:86
char * SkStrAppendScalar(char buffer[], SkScalar)
Write the scalar in decimal format into buffer, and return a pointer to the next char after the last ...
char * SkStrAppendS32(char buffer[], int32_t)
static bool SkStrContains(const char string[], const char substring[])
Definition: SkString.h:53
char * SkStrAppendU32(char buffer[], uint32_t)
int SkStrStartsWithOneOf(const char string[], const char prefixes[])
int32_t SkUnichar
32 bit integer to hold a unicode value
Definition: SkTypes.h:167
Light weight class for managing strings.
Definition: SkString.h:118
void insertScalar(size_t offset, SkScalar)
void appendUnichar(SkUnichar uni)
Definition: SkString.h:207
void insertUnichar(size_t offset, SkUnichar)
void set(const char text[], size_t len)
void append(const char text[], size_t len)
Definition: SkString.h:204
bool endsWith(const char suffixChar) const
Definition: SkString.h:149
SkString & operator=(SkString &&)
SkString(size_t len)
bool startsWith(const char prefixStr[]) const
Definition: SkString.h:140
friend bool operator==(const SkString &a, const SkString &b)
Definition: SkString.h:165
bool equals(const char text[]) const
char * data()
bool startsWith(const char prefixChar) const
Definition: SkString.h:143
void prependS64(int32_t value, int minDigits=0)
Definition: SkString.h:221
const char * data() const
Definition: SkString.h:132
void append(const SkString &str)
Definition: SkString.h:205
void printf(const char format[],...) SK_PRINTF_LIKE(2
void prepend(const char text[], size_t len)
Definition: SkString.h:216
SkString(const SkString &)
void insertU64(size_t offset, uint64_t value, int minDigits=0)
void prependS32(int32_t value)
Definition: SkString.h:220
bool equals(const char text[], size_t len) const
SkString(SkString &&)
void appendS64(int64_t value, int minDigits=0)
Definition: SkString.h:209
void insert(size_t offset, const SkString &str)
Definition: SkString.h:193
SkString(const std::string &)
size_t size() const
Definition: SkString.h:131
void prependScalar(SkScalar value)
Definition: SkString.h:223
void insertU32(size_t offset, uint32_t value)
SkString & operator+=(const char c)
Definition: SkString.h:236
void appendU64(uint64_t value, int minDigits=0)
Definition: SkString.h:211
void insertS32(size_t offset, int32_t value)
void set(const SkString &src)
Definition: SkString.h:186
bool equals(const SkString &) const
void prependUnichar(SkUnichar uni)
Definition: SkString.h:219
bool isEmpty() const
Definition: SkString.h:130
int find(const char substring[]) const
Definition: SkString.h:158
void append(const char text[])
Definition: SkString.h:203
void swap(SkString &other)
Swap contents between this and other.
void prepend(const SkString &str)
Definition: SkString.h:217
void set(std::string_view str)
Definition: SkString.h:189
void appendHex(uint32_t value, int minDigits=0)
Definition: SkString.h:212
void appendS32(int32_t value)
Definition: SkString.h:208
bool contains(const char substring[]) const
Definition: SkString.h:152
SkString(const char text[], size_t len)
void append(std::string_view str)
Definition: SkString.h:206
void resize(size_t len)
String contents are preserved on resize.
void appendScalar(SkScalar value)
Definition: SkString.h:213
char & operator[](size_t n)
Definition: SkString.h:179
void insert(size_t offset, const char text[])
void appendU32(uint32_t value)
Definition: SkString.h:210
SkString & operator=(const char text[])
void insert(size_t offset, const char text[], size_t len)
SkString & operator+=(const char text[])
Definition: SkString.h:235
bool endsWith(const char suffixStr[]) const
Definition: SkString.h:146
void prepend(std::string_view str)
Definition: SkString.h:218
void reset()
bool contains(const char subchar) const
Definition: SkString.h:155
void prependHex(uint32_t value, int minDigits=0)
Definition: SkString.h:222
std::true_type sk_is_trivially_relocatable
Definition: SkString.h:244
SkString & operator=(const SkString &)
char operator[](size_t n) const
Definition: SkString.h:134
void set(const char text[])
friend bool operator!=(const SkString &a, const SkString &b)
Definition: SkString.h:168
SkString(std::string_view)
SkString(const char text[])
void prepend(const char text[])
Definition: SkString.h:215
void insert(size_t offset, std::string_view str)
Definition: SkString.h:194
const char * c_str() const
Definition: SkString.h:133
void insertS64(size_t offset, int64_t value, int minDigits=0)
int findLastOf(const char subchar) const
Definition: SkString.h:161
void insertHex(size_t offset, uint32_t value, int minDigits=0)
sk_sp< SkDrawLooper > SK_API Make(SkColor4f color, SkColorSpace *cs, SkScalar sigma, SkScalar dx, SkScalar dy)