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