SkString.h revision ff436617d8f11297f0eff93ddd49fb9022d0843b
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
18static bool SkStrStartsWith(const char string[], const char prefixStr[]) {
19    SkASSERT(string);
20    SkASSERT(prefixStr);
21    return !strncmp(string, prefixStr, strlen(prefixStr));
22}
23static bool SkStrStartsWith(const char string[], const char prefixChar) {
24    SkASSERT(string);
25    return (prefixChar == *string);
26}
27
28bool SkStrEndsWith(const char string[], const char suffixStr[]);
29bool SkStrEndsWith(const char string[], const char suffixChar);
30
31int SkStrStartsWithOneOf(const char string[], const char prefixes[]);
32
33static int SkStrFind(const char string[], const char substring[]) {
34    const char *first = strstr(string, substring);
35    if (NULL == first) return -1;
36    return SkToS32(first - &string[0]);
37}
38
39static bool SkStrContains(const char string[], const char substring[]) {
40    SkASSERT(string);
41    SkASSERT(substring);
42    return (-1 != SkStrFind(string, substring));
43}
44static 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
52static 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
61char*   SkStrAppendS32(char buffer[], int32_t);
62#define SkStrAppendS64_MaxSize  20
63char*   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
87char* SkStrAppendFloat(char buffer[], float);
88char* 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*/
96class SK_API SkString {
97public:
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
105    bool        isEmpty() const { return 0 == fRec->fLength; }
106    size_t      size() const { return (size_t) fRec->fLength; }
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
114    bool startsWith(const char prefixStr[]) const {
115        return SkStrStartsWith(fRec->data(), prefixStr);
116    }
117    bool startsWith(const char prefixChar) const {
118        return SkStrStartsWith(fRec->data(), prefixChar);
119    }
120    bool endsWith(const char suffixStr[]) const {
121        return SkStrEndsWith(fRec->data(), suffixStr);
122    }
123    bool endsWith(const char suffixChar) const {
124        return SkStrEndsWith(fRec->data(), suffixChar);
125    }
126    bool contains(const char substring[]) const {
127        return SkStrContains(fRec->data(), substring);
128    }
129    bool contains(const char subchar) const {
130        return SkStrContains(fRec->data(), subchar);
131    }
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();
152    void resize(size_t len) { this->set(NULL, len); }
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
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
168    void append(const SkString& str) { this->insert((size_t)-1, str); }
169    void append(const char text[]) { this->insert((size_t)-1, text); }
170    void append(const char text[], size_t len) { this->insert((size_t)-1, text, len); }
171    void appendUnichar(SkUnichar uni) { this->insertUnichar((size_t)-1, uni); }
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); }
175    void appendScalar(SkScalar value) { this->insertScalar((size_t)-1, value); }
176
177    void prepend(const SkString& str) { this->insert(0, str); }
178    void prepend(const char text[]) { this->insert(0, text); }
179    void prepend(const char text[], size_t len) { this->insert(0, text, len); }
180    void prependUnichar(SkUnichar uni) { this->insertUnichar(0, uni); }
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); }
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
202private:
203    struct Rec {
204    public:
205        size_t      fLength;
206        int32_t     fRefCnt;
207        char        fBeginningOfData;
208
209        char* data() { return &fBeginningOfData; }
210        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
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
226class SkAutoUCS2 {
227public:
228    SkAutoUCS2(const char utf8[]);
229    ~SkAutoUCS2();
230
231    /** This returns the number of ucs2 characters
232    */
233    int count() const { return fCount; }
234
235    /** This returns a null terminated ucs2 string
236    */
237    const uint16_t* getUCS2() const { return fUCS2; }
238
239private:
240    int         fCount;
241    uint16_t*   fUCS2;
242};
243
244/// Creates a new string and writes into it using a printf()-style format.
245SkString SkStringPrintf(const char* format, ...);
246
247// Specialized to take advantage of SkString's fast swap path. The unspecialized function is
248// declared in SkTypes.h and called by SkTSort.
249template <> inline void SkTSwap(SkString& a, SkString& b) {
250    a.swap(b);
251}
252
253#endif
254