|
1 |
|
2 /* |
|
3 * Copyright 2006 The Android Open Source Project |
|
4 * |
|
5 * Use of this source code is governed by a BSD-style license that can be |
|
6 * found in the LICENSE file. |
|
7 */ |
|
8 |
|
9 |
|
10 #ifndef SkString_DEFINED |
|
11 #define SkString_DEFINED |
|
12 |
|
13 #include "SkScalar.h" |
|
14 #include "SkTArray.h" |
|
15 |
|
16 #include <stdarg.h> |
|
17 |
|
18 /* Some helper functions for C strings |
|
19 */ |
|
20 |
|
21 static bool SkStrStartsWith(const char string[], const char prefixStr[]) { |
|
22 SkASSERT(string); |
|
23 SkASSERT(prefixStr); |
|
24 return !strncmp(string, prefixStr, strlen(prefixStr)); |
|
25 } |
|
26 static bool SkStrStartsWith(const char string[], const char prefixChar) { |
|
27 SkASSERT(string); |
|
28 return (prefixChar == *string); |
|
29 } |
|
30 |
|
31 bool SkStrEndsWith(const char string[], const char suffixStr[]); |
|
32 bool SkStrEndsWith(const char string[], const char suffixChar); |
|
33 |
|
34 int SkStrStartsWithOneOf(const char string[], const char prefixes[]); |
|
35 |
|
36 static int SkStrFind(const char string[], const char substring[]) { |
|
37 const char *first = strstr(string, substring); |
|
38 if (NULL == first) return -1; |
|
39 return SkToS32(first - &string[0]); |
|
40 } |
|
41 |
|
42 static bool SkStrContains(const char string[], const char substring[]) { |
|
43 SkASSERT(string); |
|
44 SkASSERT(substring); |
|
45 return (-1 != SkStrFind(string, substring)); |
|
46 } |
|
47 static bool SkStrContains(const char string[], const char subchar) { |
|
48 SkASSERT(string); |
|
49 char tmp[2]; |
|
50 tmp[0] = subchar; |
|
51 tmp[1] = '\0'; |
|
52 return (-1 != SkStrFind(string, tmp)); |
|
53 } |
|
54 |
|
55 static inline char *SkStrDup(const char string[]) { |
|
56 char *ret = (char *) sk_malloc_throw(strlen(string)+1); |
|
57 memcpy(ret,string,strlen(string)+1); |
|
58 return ret; |
|
59 } |
|
60 |
|
61 |
|
62 |
|
63 #define SkStrAppendU32_MaxSize 10 |
|
64 char* SkStrAppendU32(char buffer[], uint32_t); |
|
65 #define SkStrAppendU64_MaxSize 20 |
|
66 char* SkStrAppendU64(char buffer[], uint64_t, int minDigits); |
|
67 |
|
68 #define SkStrAppendS32_MaxSize (SkStrAppendU32_MaxSize + 1) |
|
69 char* SkStrAppendS32(char buffer[], int32_t); |
|
70 #define SkStrAppendS64_MaxSize (SkStrAppendU64_MaxSize + 1) |
|
71 char* SkStrAppendS64(char buffer[], int64_t, int minDigits); |
|
72 |
|
73 /** |
|
74 * Floats have at most 8 significant digits, so we limit our %g to that. |
|
75 * However, the total string could be 15 characters: -1.2345678e-005 |
|
76 * |
|
77 * In theory we should only expect up to 2 digits for the exponent, but on |
|
78 * some platforms we have seen 3 (as in the example above). |
|
79 */ |
|
80 #define SkStrAppendScalar_MaxSize 15 |
|
81 |
|
82 /** |
|
83 * Write the scaler in decimal format into buffer, and return a pointer to |
|
84 * the next char after the last one written. Note: a terminating 0 is not |
|
85 * written into buffer, which must be at least SkStrAppendScalar_MaxSize. |
|
86 * Thus if the caller wants to add a 0 at the end, buffer must be at least |
|
87 * SkStrAppendScalar_MaxSize + 1 bytes large. |
|
88 */ |
|
89 #define SkStrAppendScalar SkStrAppendFloat |
|
90 |
|
91 char* SkStrAppendFloat(char buffer[], float); |
|
92 char* SkStrAppendFixed(char buffer[], SkFixed); |
|
93 |
|
94 /** \class SkString |
|
95 |
|
96 Light weight class for managing strings. Uses reference |
|
97 counting to make string assignments and copies very fast |
|
98 with no extra RAM cost. Assumes UTF8 encoding. |
|
99 */ |
|
100 class SK_API SkString { |
|
101 public: |
|
102 SkString(); |
|
103 explicit SkString(size_t len); |
|
104 explicit SkString(const char text[]); |
|
105 SkString(const char text[], size_t len); |
|
106 SkString(const SkString&); |
|
107 ~SkString(); |
|
108 |
|
109 bool isEmpty() const { return 0 == fRec->fLength; } |
|
110 size_t size() const { return (size_t) fRec->fLength; } |
|
111 const char* c_str() const { return fRec->data(); } |
|
112 char operator[](size_t n) const { return this->c_str()[n]; } |
|
113 |
|
114 bool equals(const SkString&) const; |
|
115 bool equals(const char text[]) const; |
|
116 bool equals(const char text[], size_t len) const; |
|
117 |
|
118 bool startsWith(const char prefixStr[]) const { |
|
119 return SkStrStartsWith(fRec->data(), prefixStr); |
|
120 } |
|
121 bool startsWith(const char prefixChar) const { |
|
122 return SkStrStartsWith(fRec->data(), prefixChar); |
|
123 } |
|
124 bool endsWith(const char suffixStr[]) const { |
|
125 return SkStrEndsWith(fRec->data(), suffixStr); |
|
126 } |
|
127 bool endsWith(const char suffixChar) const { |
|
128 return SkStrEndsWith(fRec->data(), suffixChar); |
|
129 } |
|
130 bool contains(const char substring[]) const { |
|
131 return SkStrContains(fRec->data(), substring); |
|
132 } |
|
133 bool contains(const char subchar) const { |
|
134 return SkStrContains(fRec->data(), subchar); |
|
135 } |
|
136 int find(const char substring[]) const { |
|
137 return SkStrFind(fRec->data(), substring); |
|
138 } |
|
139 |
|
140 friend bool operator==(const SkString& a, const SkString& b) { |
|
141 return a.equals(b); |
|
142 } |
|
143 friend bool operator!=(const SkString& a, const SkString& b) { |
|
144 return !a.equals(b); |
|
145 } |
|
146 |
|
147 // these methods edit the string |
|
148 |
|
149 SkString& operator=(const SkString&); |
|
150 SkString& operator=(const char text[]); |
|
151 |
|
152 char* writable_str(); |
|
153 char& operator[](size_t n) { return this->writable_str()[n]; } |
|
154 |
|
155 void reset(); |
|
156 void resize(size_t len) { this->set(NULL, len); } |
|
157 void set(const SkString& src) { *this = src; } |
|
158 void set(const char text[]); |
|
159 void set(const char text[], size_t len); |
|
160 void setUTF16(const uint16_t[]); |
|
161 void setUTF16(const uint16_t[], size_t len); |
|
162 |
|
163 void insert(size_t offset, const SkString& src) { this->insert(offset, src.c_str(), src.size()); } |
|
164 void insert(size_t offset, const char text[]); |
|
165 void insert(size_t offset, const char text[], size_t len); |
|
166 void insertUnichar(size_t offset, SkUnichar); |
|
167 void insertS32(size_t offset, int32_t value); |
|
168 void insertS64(size_t offset, int64_t value, int minDigits = 0); |
|
169 void insertU32(size_t offset, uint32_t value); |
|
170 void insertU64(size_t offset, uint64_t value, int minDigits = 0); |
|
171 void insertHex(size_t offset, uint32_t value, int minDigits = 0); |
|
172 void insertScalar(size_t offset, SkScalar); |
|
173 |
|
174 void append(const SkString& str) { this->insert((size_t)-1, str); } |
|
175 void append(const char text[]) { this->insert((size_t)-1, text); } |
|
176 void append(const char text[], size_t len) { this->insert((size_t)-1, text, len); } |
|
177 void appendUnichar(SkUnichar uni) { this->insertUnichar((size_t)-1, uni); } |
|
178 void appendS32(int32_t value) { this->insertS32((size_t)-1, value); } |
|
179 void appendS64(int64_t value, int minDigits = 0) { this->insertS64((size_t)-1, value, minDigits); } |
|
180 void appendU32(uint32_t value) { this->insertU32((size_t)-1, value); } |
|
181 void appendU64(uint64_t value, int minDigits = 0) { this->insertU64((size_t)-1, value, minDigits); } |
|
182 void appendHex(uint32_t value, int minDigits = 0) { this->insertHex((size_t)-1, value, minDigits); } |
|
183 void appendScalar(SkScalar value) { this->insertScalar((size_t)-1, value); } |
|
184 |
|
185 void prepend(const SkString& str) { this->insert(0, str); } |
|
186 void prepend(const char text[]) { this->insert(0, text); } |
|
187 void prepend(const char text[], size_t len) { this->insert(0, text, len); } |
|
188 void prependUnichar(SkUnichar uni) { this->insertUnichar(0, uni); } |
|
189 void prependS32(int32_t value) { this->insertS32(0, value); } |
|
190 void prependS64(int32_t value, int minDigits = 0) { this->insertS64(0, value, minDigits); } |
|
191 void prependHex(uint32_t value, int minDigits = 0) { this->insertHex(0, value, minDigits); } |
|
192 void prependScalar(SkScalar value) { this->insertScalar((size_t)-1, value); } |
|
193 |
|
194 void printf(const char format[], ...) SK_PRINTF_LIKE(2, 3); |
|
195 void appendf(const char format[], ...) SK_PRINTF_LIKE(2, 3); |
|
196 void appendVAList(const char format[], va_list); |
|
197 void prependf(const char format[], ...) SK_PRINTF_LIKE(2, 3); |
|
198 |
|
199 void remove(size_t offset, size_t length); |
|
200 |
|
201 SkString& operator+=(const SkString& s) { this->append(s); return *this; } |
|
202 SkString& operator+=(const char text[]) { this->append(text); return *this; } |
|
203 SkString& operator+=(const char c) { this->append(&c, 1); return *this; } |
|
204 |
|
205 /** |
|
206 * Swap contents between this and other. This function is guaranteed |
|
207 * to never fail or throw. |
|
208 */ |
|
209 void swap(SkString& other); |
|
210 |
|
211 private: |
|
212 struct Rec { |
|
213 public: |
|
214 uint32_t fLength; // logically size_t, but we want it to stay 32bits |
|
215 int32_t fRefCnt; |
|
216 char fBeginningOfData; |
|
217 |
|
218 char* data() { return &fBeginningOfData; } |
|
219 const char* data() const { return &fBeginningOfData; } |
|
220 }; |
|
221 Rec* fRec; |
|
222 |
|
223 #ifdef SK_DEBUG |
|
224 const char* fStr; |
|
225 void validate() const; |
|
226 #else |
|
227 void validate() const {} |
|
228 #endif |
|
229 |
|
230 static const Rec gEmptyRec; |
|
231 static Rec* AllocRec(const char text[], size_t len); |
|
232 static Rec* RefRec(Rec*); |
|
233 }; |
|
234 |
|
235 /// Creates a new string and writes into it using a printf()-style format. |
|
236 SkString SkStringPrintf(const char* format, ...); |
|
237 |
|
238 // Specialized to take advantage of SkString's fast swap path. The unspecialized function is |
|
239 // declared in SkTypes.h and called by SkTSort. |
|
240 template <> inline void SkTSwap(SkString& a, SkString& b) { |
|
241 a.swap(b); |
|
242 } |
|
243 |
|
244 // Split str on any characters in delimiters into out. (Think, strtok with a sane API.) |
|
245 void SkStrSplit(const char* str, const char* delimiters, SkTArray<SkString>* out); |
|
246 |
|
247 #endif |