1 /* 2 * Copyright (C) 2005 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ANDROID_STRING8_H 18 #define ANDROID_STRING8_H 19 20 #include <utils/Errors.h> 21 #include <utils/SharedBuffer.h> 22 #include <utils/Unicode.h> 23 #include <utils/TypeHelpers.h> 24 25 #include <string.h> // for strcmp 26 #include <stdarg.h> 27 28 // --------------------------------------------------------------------------- 29 30 namespace android { 31 32 class String16; 33 class TextOutput; 34 35 //! This is a string holding UTF-8 characters. Does not allow the value more 36 // than 0x10FFFF, which is not valid unicode codepoint. 37 class String8 38 { 39 public: 40 /* use String8(StaticLinkage) if you're statically linking against 41 * libutils and declaring an empty static String8, e.g.: 42 * 43 * static String8 sAStaticEmptyString(String8::kEmptyString); 44 * static String8 sAnotherStaticEmptyString(sAStaticEmptyString); 45 */ 46 enum StaticLinkage { kEmptyString }; 47 48 String8(); 49 explicit String8(StaticLinkage); 50 String8(const String8& o); 51 explicit String8(const char* o); 52 explicit String8(const char* o, size_t numChars); 53 54 explicit String8(const String16& o); 55 explicit String8(const char16_t* o); 56 explicit String8(const char16_t* o, size_t numChars); 57 explicit String8(const char32_t* o); 58 explicit String8(const char32_t* o, size_t numChars); 59 ~String8(); 60 61 static inline const String8 empty(); 62 63 static String8 format(const char* fmt, ...) __attribute__((format (printf, 1, 2))); 64 static String8 formatV(const char* fmt, va_list args); 65 66 inline const char* string() const; 67 inline size_t size() const; 68 inline size_t length() const; 69 inline size_t bytes() const; 70 inline bool isEmpty() const; 71 72 inline const SharedBuffer* sharedBuffer() const; 73 74 void clear(); 75 76 void setTo(const String8& other); 77 status_t setTo(const char* other); 78 status_t setTo(const char* other, size_t numChars); 79 status_t setTo(const char16_t* other, size_t numChars); 80 status_t setTo(const char32_t* other, 81 size_t length); 82 83 status_t append(const String8& other); 84 status_t append(const char* other); 85 status_t append(const char* other, size_t numChars); 86 87 status_t appendFormat(const char* fmt, ...) 88 __attribute__((format (printf, 2, 3))); 89 status_t appendFormatV(const char* fmt, va_list args); 90 91 // Note that this function takes O(N) time to calculate the value. 92 // No cache value is stored. 93 size_t getUtf32Length() const; 94 int32_t getUtf32At(size_t index, 95 size_t *next_index) const; 96 void getUtf32(char32_t* dst) const; 97 98 inline String8& operator=(const String8& other); 99 inline String8& operator=(const char* other); 100 101 inline String8& operator+=(const String8& other); 102 inline String8 operator+(const String8& other) const; 103 104 inline String8& operator+=(const char* other); 105 inline String8 operator+(const char* other) const; 106 107 inline int compare(const String8& other) const; 108 109 inline bool operator<(const String8& other) const; 110 inline bool operator<=(const String8& other) const; 111 inline bool operator==(const String8& other) const; 112 inline bool operator!=(const String8& other) const; 113 inline bool operator>=(const String8& other) const; 114 inline bool operator>(const String8& other) const; 115 116 inline bool operator<(const char* other) const; 117 inline bool operator<=(const char* other) const; 118 inline bool operator==(const char* other) const; 119 inline bool operator!=(const char* other) const; 120 inline bool operator>=(const char* other) const; 121 inline bool operator>(const char* other) const; 122 123 inline operator const char*() const; 124 125 char* lockBuffer(size_t size); 126 void unlockBuffer(); 127 status_t unlockBuffer(size_t size); 128 129 // return the index of the first byte of other in this at or after 130 // start, or -1 if not found 131 ssize_t find(const char* other, size_t start = 0) const; 132 133 void toLower(); 134 void toLower(size_t start, size_t numChars); 135 void toUpper(); 136 void toUpper(size_t start, size_t numChars); 137 138 /* 139 * These methods operate on the string as if it were a path name. 140 */ 141 142 /* 143 * Set the filename field to a specific value. 144 * 145 * Normalizes the filename, removing a trailing '/' if present. 146 */ 147 void setPathName(const char* name); 148 void setPathName(const char* name, size_t numChars); 149 150 /* 151 * Get just the filename component. 152 * 153 * "/tmp/foo/bar.c" --> "bar.c" 154 */ 155 String8 getPathLeaf(void) const; 156 157 /* 158 * Remove the last (file name) component, leaving just the directory 159 * name. 160 * 161 * "/tmp/foo/bar.c" --> "/tmp/foo" 162 * "/tmp" --> "" // ????? shouldn't this be "/" ???? XXX 163 * "bar.c" --> "" 164 */ 165 String8 getPathDir(void) const; 166 167 /* 168 * Retrieve the front (root dir) component. Optionally also return the 169 * remaining components. 170 * 171 * "/tmp/foo/bar.c" --> "tmp" (remain = "foo/bar.c") 172 * "/tmp" --> "tmp" (remain = "") 173 * "bar.c" --> "bar.c" (remain = "") 174 */ 175 String8 walkPath(String8* outRemains = NULL) const; 176 177 /* 178 * Return the filename extension. This is the last '.' and any number 179 * of characters that follow it. The '.' is included in case we 180 * decide to expand our definition of what constitutes an extension. 181 * 182 * "/tmp/foo/bar.c" --> ".c" 183 * "/tmp" --> "" 184 * "/tmp/foo.bar/baz" --> "" 185 * "foo.jpeg" --> ".jpeg" 186 * "foo." --> "" 187 */ 188 String8 getPathExtension(void) const; 189 190 /* 191 * Return the path without the extension. Rules for what constitutes 192 * an extension are described in the comment for getPathExtension(). 193 * 194 * "/tmp/foo/bar.c" --> "/tmp/foo/bar" 195 */ 196 String8 getBasePath(void) const; 197 198 /* 199 * Add a component to the pathname. We guarantee that there is 200 * exactly one path separator between the old path and the new. 201 * If there is no existing name, we just copy the new name in. 202 * 203 * If leaf is a fully qualified path (i.e. starts with '/', it 204 * replaces whatever was there before. 205 */ 206 String8& appendPath(const char* leaf); 207 String8& appendPath(const String8& leaf) { return appendPath(leaf.string()); } 208 209 /* 210 * Like appendPath(), but does not affect this string. Returns a new one instead. 211 */ 212 String8 appendPathCopy(const char* leaf) const 213 { String8 p(*this); p.appendPath(leaf); return p; } 214 String8 appendPathCopy(const String8& leaf) const { return appendPathCopy(leaf.string()); } 215 216 /* 217 * Converts all separators in this string to /, the default path separator. 218 * 219 * If the default OS separator is backslash, this converts all 220 * backslashes to slashes, in-place. Otherwise it does nothing. 221 * Returns self. 222 */ 223 String8& convertToResPath(); 224 225 private: 226 status_t real_append(const char* other, size_t numChars); 227 char* find_extension(void) const; 228 229 const char* mString; 230 }; 231 232 // String8 can be trivially moved using memcpy() because moving does not 233 // require any change to the underlying SharedBuffer contents or reference count. 234 ANDROID_TRIVIAL_MOVE_TRAIT(String8) 235 236 // --------------------------------------------------------------------------- 237 // No user servicable parts below. 238 239 inline int compare_type(const String8& lhs, const String8& rhs) 240 { 241 return lhs.compare(rhs); 242 } 243 244 inline int strictly_order_type(const String8& lhs, const String8& rhs) 245 { 246 return compare_type(lhs, rhs) < 0; 247 } 248 249 inline const String8 String8::empty() { 250 return String8(); 251 } 252 253 inline const char* String8::string() const 254 { 255 return mString; 256 } 257 258 inline size_t String8::length() const 259 { 260 return SharedBuffer::sizeFromData(mString)-1; 261 } 262 263 inline size_t String8::size() const 264 { 265 return length(); 266 } 267 268 inline bool String8::isEmpty() const 269 { 270 return length() == 0; 271 } 272 273 inline size_t String8::bytes() const 274 { 275 return SharedBuffer::sizeFromData(mString)-1; 276 } 277 278 inline const SharedBuffer* String8::sharedBuffer() const 279 { 280 return SharedBuffer::bufferFromData(mString); 281 } 282 283 inline String8& String8::operator=(const String8& other) 284 { 285 setTo(other); 286 return *this; 287 } 288 289 inline String8& String8::operator=(const char* other) 290 { 291 setTo(other); 292 return *this; 293 } 294 295 inline String8& String8::operator+=(const String8& other) 296 { 297 append(other); 298 return *this; 299 } 300 301 inline String8 String8::operator+(const String8& other) const 302 { 303 String8 tmp(*this); 304 tmp += other; 305 return tmp; 306 } 307 308 inline String8& String8::operator+=(const char* other) 309 { 310 append(other); 311 return *this; 312 } 313 314 inline String8 String8::operator+(const char* other) const 315 { 316 String8 tmp(*this); 317 tmp += other; 318 return tmp; 319 } 320 321 inline int String8::compare(const String8& other) const 322 { 323 return strcmp(mString, other.mString); 324 } 325 326 inline bool String8::operator<(const String8& other) const 327 { 328 return strcmp(mString, other.mString) < 0; 329 } 330 331 inline bool String8::operator<=(const String8& other) const 332 { 333 return strcmp(mString, other.mString) <= 0; 334 } 335 336 inline bool String8::operator==(const String8& other) const 337 { 338 return strcmp(mString, other.mString) == 0; 339 } 340 341 inline bool String8::operator!=(const String8& other) const 342 { 343 return strcmp(mString, other.mString) != 0; 344 } 345 346 inline bool String8::operator>=(const String8& other) const 347 { 348 return strcmp(mString, other.mString) >= 0; 349 } 350 351 inline bool String8::operator>(const String8& other) const 352 { 353 return strcmp(mString, other.mString) > 0; 354 } 355 356 inline bool String8::operator<(const char* other) const 357 { 358 return strcmp(mString, other) < 0; 359 } 360 361 inline bool String8::operator<=(const char* other) const 362 { 363 return strcmp(mString, other) <= 0; 364 } 365 366 inline bool String8::operator==(const char* other) const 367 { 368 return strcmp(mString, other) == 0; 369 } 370 371 inline bool String8::operator!=(const char* other) const 372 { 373 return strcmp(mString, other) != 0; 374 } 375 376 inline bool String8::operator>=(const char* other) const 377 { 378 return strcmp(mString, other) >= 0; 379 } 380 381 inline bool String8::operator>(const char* other) const 382 { 383 return strcmp(mString, other) > 0; 384 } 385 386 inline String8::operator const char*() const 387 { 388 return mString; 389 } 390 391 } // namespace android 392 393 // --------------------------------------------------------------------------- 394 395 #endif // ANDROID_STRING8_H 396