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 // return true if this string contains the specified substring 134 inline bool contains(const char* other) const; 135 136 // removes all occurrence of the specified substring 137 // returns true if any were found and removed 138 bool removeAll(const char* other); 139 140 void toLower(); 141 void toLower(size_t start, size_t numChars); 142 void toUpper(); 143 void toUpper(size_t start, size_t numChars); 144 145 146 /* 147 * These methods operate on the string as if it were a path name. 148 */ 149 150 /* 151 * Set the filename field to a specific value. 152 * 153 * Normalizes the filename, removing a trailing '/' if present. 154 */ 155 void setPathName(const char* name); 156 void setPathName(const char* name, size_t numChars); 157 158 /* 159 * Get just the filename component. 160 * 161 * "/tmp/foo/bar.c" --> "bar.c" 162 */ 163 String8 getPathLeaf(void) const; 164 165 /* 166 * Remove the last (file name) component, leaving just the directory 167 * name. 168 * 169 * "/tmp/foo/bar.c" --> "/tmp/foo" 170 * "/tmp" --> "" // ????? shouldn't this be "/" ???? XXX 171 * "bar.c" --> "" 172 */ 173 String8 getPathDir(void) const; 174 175 /* 176 * Retrieve the front (root dir) component. Optionally also return the 177 * remaining components. 178 * 179 * "/tmp/foo/bar.c" --> "tmp" (remain = "foo/bar.c") 180 * "/tmp" --> "tmp" (remain = "") 181 * "bar.c" --> "bar.c" (remain = "") 182 */ 183 String8 walkPath(String8* outRemains = NULL) const; 184 185 /* 186 * Return the filename extension. This is the last '.' and any number 187 * of characters that follow it. The '.' is included in case we 188 * decide to expand our definition of what constitutes an extension. 189 * 190 * "/tmp/foo/bar.c" --> ".c" 191 * "/tmp" --> "" 192 * "/tmp/foo.bar/baz" --> "" 193 * "foo.jpeg" --> ".jpeg" 194 * "foo." --> "" 195 */ 196 String8 getPathExtension(void) const; 197 198 /* 199 * Return the path without the extension. Rules for what constitutes 200 * an extension are described in the comment for getPathExtension(). 201 * 202 * "/tmp/foo/bar.c" --> "/tmp/foo/bar" 203 */ 204 String8 getBasePath(void) const; 205 206 /* 207 * Add a component to the pathname. We guarantee that there is 208 * exactly one path separator between the old path and the new. 209 * If there is no existing name, we just copy the new name in. 210 * 211 * If leaf is a fully qualified path (i.e. starts with '/', it 212 * replaces whatever was there before. 213 */ 214 String8& appendPath(const char* leaf); 215 String8& appendPath(const String8& leaf) { return appendPath(leaf.string()); } 216 217 /* 218 * Like appendPath(), but does not affect this string. Returns a new one instead. 219 */ 220 String8 appendPathCopy(const char* leaf) const 221 { String8 p(*this); p.appendPath(leaf); return p; } 222 String8 appendPathCopy(const String8& leaf) const { return appendPathCopy(leaf.string()); } 223 224 /* 225 * Converts all separators in this string to /, the default path separator. 226 * 227 * If the default OS separator is backslash, this converts all 228 * backslashes to slashes, in-place. Otherwise it does nothing. 229 * Returns self. 230 */ 231 String8& convertToResPath(); 232 233 private: 234 status_t real_append(const char* other, size_t numChars); 235 char* find_extension(void) const; 236 237 const char* mString; 238 }; 239 240 // String8 can be trivially moved using memcpy() because moving does not 241 // require any change to the underlying SharedBuffer contents or reference count. 242 ANDROID_TRIVIAL_MOVE_TRAIT(String8) 243 244 // --------------------------------------------------------------------------- 245 // No user servicable parts below. 246 247 inline int compare_type(const String8& lhs, const String8& rhs) 248 { 249 return lhs.compare(rhs); 250 } 251 252 inline int strictly_order_type(const String8& lhs, const String8& rhs) 253 { 254 return compare_type(lhs, rhs) < 0; 255 } 256 257 inline const String8 String8::empty() { 258 return String8(); 259 } 260 261 inline const char* String8::string() const 262 { 263 return mString; 264 } 265 266 inline size_t String8::length() const 267 { 268 return SharedBuffer::sizeFromData(mString)-1; 269 } 270 271 inline size_t String8::size() const 272 { 273 return length(); 274 } 275 276 inline bool String8::isEmpty() const 277 { 278 return length() == 0; 279 } 280 281 inline size_t String8::bytes() const 282 { 283 return SharedBuffer::sizeFromData(mString)-1; 284 } 285 286 inline const SharedBuffer* String8::sharedBuffer() const 287 { 288 return SharedBuffer::bufferFromData(mString); 289 } 290 291 inline bool String8::contains(const char* other) const 292 { 293 return find(other) >= 0; 294 } 295 296 inline String8& String8::operator=(const String8& other) 297 { 298 setTo(other); 299 return *this; 300 } 301 302 inline String8& String8::operator=(const char* other) 303 { 304 setTo(other); 305 return *this; 306 } 307 308 inline String8& String8::operator+=(const String8& other) 309 { 310 append(other); 311 return *this; 312 } 313 314 inline String8 String8::operator+(const String8& other) const 315 { 316 String8 tmp(*this); 317 tmp += other; 318 return tmp; 319 } 320 321 inline String8& String8::operator+=(const char* other) 322 { 323 append(other); 324 return *this; 325 } 326 327 inline String8 String8::operator+(const char* other) const 328 { 329 String8 tmp(*this); 330 tmp += other; 331 return tmp; 332 } 333 334 inline int String8::compare(const String8& other) const 335 { 336 return strcmp(mString, other.mString); 337 } 338 339 inline bool String8::operator<(const String8& other) const 340 { 341 return strcmp(mString, other.mString) < 0; 342 } 343 344 inline bool String8::operator<=(const String8& other) const 345 { 346 return strcmp(mString, other.mString) <= 0; 347 } 348 349 inline bool String8::operator==(const String8& other) const 350 { 351 return strcmp(mString, other.mString) == 0; 352 } 353 354 inline bool String8::operator!=(const String8& other) const 355 { 356 return strcmp(mString, other.mString) != 0; 357 } 358 359 inline bool String8::operator>=(const String8& other) const 360 { 361 return strcmp(mString, other.mString) >= 0; 362 } 363 364 inline bool String8::operator>(const String8& other) const 365 { 366 return strcmp(mString, other.mString) > 0; 367 } 368 369 inline bool String8::operator<(const char* other) const 370 { 371 return strcmp(mString, other) < 0; 372 } 373 374 inline bool String8::operator<=(const char* other) const 375 { 376 return strcmp(mString, other) <= 0; 377 } 378 379 inline bool String8::operator==(const char* other) const 380 { 381 return strcmp(mString, other) == 0; 382 } 383 384 inline bool String8::operator!=(const char* other) const 385 { 386 return strcmp(mString, other) != 0; 387 } 388 389 inline bool String8::operator>=(const char* other) const 390 { 391 return strcmp(mString, other) >= 0; 392 } 393 394 inline bool String8::operator>(const char* other) const 395 { 396 return strcmp(mString, other) > 0; 397 } 398 399 inline String8::operator const char*() const 400 { 401 return mString; 402 } 403 404 } // namespace android 405 406 // --------------------------------------------------------------------------- 407 408 #endif // ANDROID_STRING8_H 409