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