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