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