SkString.h revision ca5bb87a31b8cfde73dfd7c554127ee9b3e1ab58
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
21static bool SkStrStartsWith(const char string[], const char prefixStr[]) {
22    SkASSERT(string);
23    SkASSERT(prefixStr);
24    return !strncmp(string, prefixStr, strlen(prefixStr));
25}
26static bool SkStrStartsWith(const char string[], const char prefixChar) {
27    SkASSERT(string);
28    return (prefixChar == *string);
29}
30
31bool SkStrEndsWith(const char string[], const char suffixStr[]);
32bool SkStrEndsWith(const char string[], const char suffixChar);
33
34int SkStrStartsWithOneOf(const char string[], const char prefixes[]);
35
36static 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
42static bool SkStrContains(const char string[], const char substring[]) {
43    SkASSERT(string);
44    SkASSERT(substring);
45    return (-1 != SkStrFind(string, substring));
46}
47static 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
55static 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
64char*   SkStrAppendU32(char buffer[], uint32_t);
65#define SkStrAppendU64_MaxSize  20
66char*   SkStrAppendU64(char buffer[], uint64_t, int minDigits);
67
68#define SkStrAppendS32_MaxSize  (SkStrAppendU32_MaxSize + 1)
69char*   SkStrAppendS32(char buffer[], int32_t);
70#define SkStrAppendS64_MaxSize  (SkStrAppendU64_MaxSize + 1)
71char*   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#ifdef SK_SCALAR_IS_FLOAT
90    #define SkStrAppendScalar SkStrAppendFloat
91#else
92    #define SkStrAppendScalar SkStrAppendFixed
93#endif
94
95char* SkStrAppendFloat(char buffer[], float);
96char* SkStrAppendFixed(char buffer[], SkFixed);
97
98/** \class SkString
99
100    Light weight class for managing strings. Uses reference
101    counting to make string assignments and copies very fast
102    with no extra RAM cost. Assumes UTF8 encoding.
103*/
104class SK_API SkString {
105public:
106                SkString();
107    explicit    SkString(size_t len);
108    explicit    SkString(const char text[]);
109                SkString(const char text[], size_t len);
110                SkString(const SkString&);
111                ~SkString();
112
113    bool        isEmpty() const { return 0 == fRec->fLength; }
114    size_t      size() const { return (size_t) fRec->fLength; }
115    const char* c_str() const { return fRec->data(); }
116    char operator[](size_t n) const { return this->c_str()[n]; }
117
118    bool equals(const SkString&) const;
119    bool equals(const char text[]) const;
120    bool equals(const char text[], size_t len) const;
121
122    bool startsWith(const char prefixStr[]) const {
123        return SkStrStartsWith(fRec->data(), prefixStr);
124    }
125    bool startsWith(const char prefixChar) const {
126        return SkStrStartsWith(fRec->data(), prefixChar);
127    }
128    bool endsWith(const char suffixStr[]) const {
129        return SkStrEndsWith(fRec->data(), suffixStr);
130    }
131    bool endsWith(const char suffixChar) const {
132        return SkStrEndsWith(fRec->data(), suffixChar);
133    }
134    bool contains(const char substring[]) const {
135        return SkStrContains(fRec->data(), substring);
136    }
137    bool contains(const char subchar) const {
138        return SkStrContains(fRec->data(), subchar);
139    }
140    int find(const char substring[]) const {
141        return SkStrFind(fRec->data(), substring);
142    }
143
144    friend bool operator==(const SkString& a, const SkString& b) {
145        return a.equals(b);
146    }
147    friend bool operator!=(const SkString& a, const SkString& b) {
148        return !a.equals(b);
149    }
150
151    // these methods edit the string
152
153    SkString& operator=(const SkString&);
154    SkString& operator=(const char text[]);
155
156    char* writable_str();
157    char& operator[](size_t n) { return this->writable_str()[n]; }
158
159    void reset();
160    void resize(size_t len) { this->set(NULL, len); }
161    void set(const SkString& src) { *this = src; }
162    void set(const char text[]);
163    void set(const char text[], size_t len);
164    void setUTF16(const uint16_t[]);
165    void setUTF16(const uint16_t[], size_t len);
166
167    void insert(size_t offset, const SkString& src) { this->insert(offset, src.c_str(), src.size()); }
168    void insert(size_t offset, const char text[]);
169    void insert(size_t offset, const char text[], size_t len);
170    void insertUnichar(size_t offset, SkUnichar);
171    void insertS32(size_t offset, int32_t value);
172    void insertS64(size_t offset, int64_t value, int minDigits = 0);
173    void insertU32(size_t offset, uint32_t value);
174    void insertU64(size_t offset, uint64_t value, int minDigits = 0);
175    void insertHex(size_t offset, uint32_t value, int minDigits = 0);
176    void insertScalar(size_t offset, SkScalar);
177
178    void append(const SkString& str) { this->insert((size_t)-1, str); }
179    void append(const char text[]) { this->insert((size_t)-1, text); }
180    void append(const char text[], size_t len) { this->insert((size_t)-1, text, len); }
181    void appendUnichar(SkUnichar uni) { this->insertUnichar((size_t)-1, uni); }
182    void appendS32(int32_t value) { this->insertS32((size_t)-1, value); }
183    void appendS64(int64_t value, int minDigits = 0) { this->insertS64((size_t)-1, value, minDigits); }
184    void appendU32(uint32_t value) { this->insertU32((size_t)-1, value); }
185    void appendU64(uint64_t value, int minDigits = 0) { this->insertU64((size_t)-1, value, minDigits); }
186    void appendHex(uint32_t value, int minDigits = 0) { this->insertHex((size_t)-1, value, minDigits); }
187    void appendScalar(SkScalar value) { this->insertScalar((size_t)-1, value); }
188
189    void prepend(const SkString& str) { this->insert(0, str); }
190    void prepend(const char text[]) { this->insert(0, text); }
191    void prepend(const char text[], size_t len) { this->insert(0, text, len); }
192    void prependUnichar(SkUnichar uni) { this->insertUnichar(0, uni); }
193    void prependS32(int32_t value) { this->insertS32(0, value); }
194    void prependS64(int32_t value, int minDigits = 0) { this->insertS64(0, value, minDigits); }
195    void prependHex(uint32_t value, int minDigits = 0) { this->insertHex(0, value, minDigits); }
196    void prependScalar(SkScalar value) { this->insertScalar((size_t)-1, value); }
197
198    void printf(const char format[], ...) SK_PRINTF_LIKE(2, 3);
199    void appendf(const char format[], ...) SK_PRINTF_LIKE(2, 3);
200    void appendVAList(const char format[], va_list);
201    void prependf(const char format[], ...) SK_PRINTF_LIKE(2, 3);
202
203    void remove(size_t offset, size_t length);
204
205    SkString& operator+=(const SkString& s) { this->append(s); return *this; }
206    SkString& operator+=(const char text[]) { this->append(text); return *this; }
207    SkString& operator+=(const char c) { this->append(&c, 1); return *this; }
208
209    /**
210     *  Swap contents between this and other. This function is guaranteed
211     *  to never fail or throw.
212     */
213    void swap(SkString& other);
214
215private:
216    struct Rec {
217    public:
218        uint32_t    fLength; // logically size_t, but we want it to stay 32bits
219        int32_t     fRefCnt;
220        char        fBeginningOfData;
221
222        char* data() { return &fBeginningOfData; }
223        const char* data() const { return &fBeginningOfData; }
224    };
225    Rec* fRec;
226
227#ifdef SK_DEBUG
228    const char* fStr;
229    void validate() const;
230#else
231    void validate() const {}
232#endif
233
234    static const Rec gEmptyRec;
235    static Rec* AllocRec(const char text[], size_t len);
236    static Rec* RefRec(Rec*);
237};
238
239/// Creates a new string and writes into it using a printf()-style format.
240SkString SkStringPrintf(const char* format, ...);
241
242// Specialized to take advantage of SkString's fast swap path. The unspecialized function is
243// declared in SkTypes.h and called by SkTSort.
244template <> inline void SkTSwap(SkString& a, SkString& b) {
245    a.swap(b);
246}
247
248// Split str on any characters in delimiters into out.  (Think, strtok with a sane API.)
249void SkStrSplit(const char* str, const char* delimiters, SkTArray<SkString>* out);
250
251#endif
252