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