michael@0: /* michael@0: * Copyright (C) 2005 The Android Open Source Project michael@0: * michael@0: * Licensed under the Apache License, Version 2.0 (the "License"); michael@0: * you may not use this file except in compliance with the License. michael@0: * You may obtain a copy of the License at michael@0: * michael@0: * http://www.apache.org/licenses/LICENSE-2.0 michael@0: * michael@0: * Unless required by applicable law or agreed to in writing, software michael@0: * distributed under the License is distributed on an "AS IS" BASIS, michael@0: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. michael@0: * See the License for the specific language governing permissions and michael@0: * limitations under the License. michael@0: */ michael@0: michael@0: #ifndef ANDROID_STRING8_H michael@0: #define ANDROID_STRING8_H michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: #include // for strcmp michael@0: #include michael@0: michael@0: // --------------------------------------------------------------------------- michael@0: michael@0: namespace android { michael@0: michael@0: class String16; michael@0: class TextOutput; michael@0: michael@0: //! This is a string holding UTF-8 characters. Does not allow the value more michael@0: // than 0x10FFFF, which is not valid unicode codepoint. michael@0: class String8 michael@0: { michael@0: public: michael@0: String8(); michael@0: String8(const String8& o); michael@0: explicit String8(const char* o); michael@0: explicit String8(const char* o, size_t numChars); michael@0: michael@0: explicit String8(const String16& o); michael@0: explicit String8(const char16_t* o); michael@0: explicit String8(const char16_t* o, size_t numChars); michael@0: explicit String8(const char32_t* o); michael@0: explicit String8(const char32_t* o, size_t numChars); michael@0: ~String8(); michael@0: michael@0: static inline const String8 empty(); michael@0: michael@0: static String8 format(const char* fmt, ...) __attribute__((format (printf, 1, 2))); michael@0: static String8 formatV(const char* fmt, va_list args); michael@0: michael@0: inline const char* string() const; michael@0: inline size_t size() const; michael@0: inline size_t length() const; michael@0: inline size_t bytes() const; michael@0: inline bool isEmpty() const; michael@0: michael@0: inline const SharedBuffer* sharedBuffer() const; michael@0: michael@0: void clear(); michael@0: michael@0: void setTo(const String8& other); michael@0: status_t setTo(const char* other); michael@0: status_t setTo(const char* other, size_t numChars); michael@0: status_t setTo(const char16_t* other, size_t numChars); michael@0: status_t setTo(const char32_t* other, michael@0: size_t length); michael@0: michael@0: status_t append(const String8& other); michael@0: status_t append(const char* other); michael@0: status_t append(const char* other, size_t numChars); michael@0: michael@0: status_t appendFormat(const char* fmt, ...) michael@0: __attribute__((format (printf, 2, 3))); michael@0: status_t appendFormatV(const char* fmt, va_list args); michael@0: michael@0: // Note that this function takes O(N) time to calculate the value. michael@0: // No cache value is stored. michael@0: size_t getUtf32Length() const; michael@0: int32_t getUtf32At(size_t index, michael@0: size_t *next_index) const; michael@0: void getUtf32(char32_t* dst) const; michael@0: michael@0: inline String8& operator=(const String8& other); michael@0: inline String8& operator=(const char* other); michael@0: michael@0: inline String8& operator+=(const String8& other); michael@0: inline String8 operator+(const String8& other) const; michael@0: michael@0: inline String8& operator+=(const char* other); michael@0: inline String8 operator+(const char* other) const; michael@0: michael@0: inline int compare(const String8& other) const; michael@0: michael@0: inline bool operator<(const String8& other) const; michael@0: inline bool operator<=(const String8& other) const; michael@0: inline bool operator==(const String8& other) const; michael@0: inline bool operator!=(const String8& other) const; michael@0: inline bool operator>=(const String8& other) const; michael@0: inline bool operator>(const String8& other) const; michael@0: michael@0: inline bool operator<(const char* other) const; michael@0: inline bool operator<=(const char* other) const; michael@0: inline bool operator==(const char* other) const; michael@0: inline bool operator!=(const char* other) const; michael@0: inline bool operator>=(const char* other) const; michael@0: inline bool operator>(const char* other) const; michael@0: michael@0: inline operator const char*() const; michael@0: michael@0: char* lockBuffer(size_t size); michael@0: void unlockBuffer(); michael@0: status_t unlockBuffer(size_t size); michael@0: michael@0: // return the index of the first byte of other in this at or after michael@0: // start, or -1 if not found michael@0: ssize_t find(const char* other, size_t start = 0) const; michael@0: michael@0: void toLower(); michael@0: void toLower(size_t start, size_t numChars); michael@0: void toUpper(); michael@0: void toUpper(size_t start, size_t numChars); michael@0: michael@0: /* michael@0: * These methods operate on the string as if it were a path name. michael@0: */ michael@0: michael@0: /* michael@0: * Set the filename field to a specific value. michael@0: * michael@0: * Normalizes the filename, removing a trailing '/' if present. michael@0: */ michael@0: void setPathName(const char* name); michael@0: void setPathName(const char* name, size_t numChars); michael@0: michael@0: /* michael@0: * Get just the filename component. michael@0: * michael@0: * "/tmp/foo/bar.c" --> "bar.c" michael@0: */ michael@0: String8 getPathLeaf(void) const; michael@0: michael@0: /* michael@0: * Remove the last (file name) component, leaving just the directory michael@0: * name. michael@0: * michael@0: * "/tmp/foo/bar.c" --> "/tmp/foo" michael@0: * "/tmp" --> "" // ????? shouldn't this be "/" ???? XXX michael@0: * "bar.c" --> "" michael@0: */ michael@0: String8 getPathDir(void) const; michael@0: michael@0: /* michael@0: * Retrieve the front (root dir) component. Optionally also return the michael@0: * remaining components. michael@0: * michael@0: * "/tmp/foo/bar.c" --> "tmp" (remain = "foo/bar.c") michael@0: * "/tmp" --> "tmp" (remain = "") michael@0: * "bar.c" --> "bar.c" (remain = "") michael@0: */ michael@0: String8 walkPath(String8* outRemains = NULL) const; michael@0: michael@0: /* michael@0: * Return the filename extension. This is the last '.' and any number michael@0: * of characters that follow it. The '.' is included in case we michael@0: * decide to expand our definition of what constitutes an extension. michael@0: * michael@0: * "/tmp/foo/bar.c" --> ".c" michael@0: * "/tmp" --> "" michael@0: * "/tmp/foo.bar/baz" --> "" michael@0: * "foo.jpeg" --> ".jpeg" michael@0: * "foo." --> "" michael@0: */ michael@0: String8 getPathExtension(void) const; michael@0: michael@0: /* michael@0: * Return the path without the extension. Rules for what constitutes michael@0: * an extension are described in the comment for getPathExtension(). michael@0: * michael@0: * "/tmp/foo/bar.c" --> "/tmp/foo/bar" michael@0: */ michael@0: String8 getBasePath(void) const; michael@0: michael@0: /* michael@0: * Add a component to the pathname. We guarantee that there is michael@0: * exactly one path separator between the old path and the new. michael@0: * If there is no existing name, we just copy the new name in. michael@0: * michael@0: * If leaf is a fully qualified path (i.e. starts with '/', it michael@0: * replaces whatever was there before. michael@0: */ michael@0: String8& appendPath(const char* leaf); michael@0: String8& appendPath(const String8& leaf) { return appendPath(leaf.string()); } michael@0: michael@0: /* michael@0: * Like appendPath(), but does not affect this string. Returns a new one instead. michael@0: */ michael@0: String8 appendPathCopy(const char* leaf) const michael@0: { String8 p(*this); p.appendPath(leaf); return p; } michael@0: String8 appendPathCopy(const String8& leaf) const { return appendPathCopy(leaf.string()); } michael@0: michael@0: /* michael@0: * Converts all separators in this string to /, the default path separator. michael@0: * michael@0: * If the default OS separator is backslash, this converts all michael@0: * backslashes to slashes, in-place. Otherwise it does nothing. michael@0: * Returns self. michael@0: */ michael@0: String8& convertToResPath(); michael@0: michael@0: private: michael@0: status_t real_append(const char* other, size_t numChars); michael@0: char* find_extension(void) const; michael@0: michael@0: const char* mString; michael@0: }; michael@0: michael@0: TextOutput& operator<<(TextOutput& to, const String16& val); michael@0: michael@0: // --------------------------------------------------------------------------- michael@0: // No user servicable parts below. michael@0: michael@0: inline int compare_type(const String8& lhs, const String8& rhs) michael@0: { michael@0: return lhs.compare(rhs); michael@0: } michael@0: michael@0: inline int strictly_order_type(const String8& lhs, const String8& rhs) michael@0: { michael@0: return compare_type(lhs, rhs) < 0; michael@0: } michael@0: michael@0: inline const String8 String8::empty() { michael@0: return String8(); michael@0: } michael@0: michael@0: inline const char* String8::string() const michael@0: { michael@0: return mString; michael@0: } michael@0: michael@0: inline size_t String8::length() const michael@0: { michael@0: return SharedBuffer::sizeFromData(mString)-1; michael@0: } michael@0: michael@0: inline size_t String8::size() const michael@0: { michael@0: return length(); michael@0: } michael@0: michael@0: inline bool String8::isEmpty() const michael@0: { michael@0: return length() == 0; michael@0: } michael@0: michael@0: inline size_t String8::bytes() const michael@0: { michael@0: return SharedBuffer::sizeFromData(mString)-1; michael@0: } michael@0: michael@0: inline const SharedBuffer* String8::sharedBuffer() const michael@0: { michael@0: return SharedBuffer::bufferFromData(mString); michael@0: } michael@0: michael@0: inline String8& String8::operator=(const String8& other) michael@0: { michael@0: setTo(other); michael@0: return *this; michael@0: } michael@0: michael@0: inline String8& String8::operator=(const char* other) michael@0: { michael@0: setTo(other); michael@0: return *this; michael@0: } michael@0: michael@0: inline String8& String8::operator+=(const String8& other) michael@0: { michael@0: append(other); michael@0: return *this; michael@0: } michael@0: michael@0: inline String8 String8::operator+(const String8& other) const michael@0: { michael@0: String8 tmp(*this); michael@0: tmp += other; michael@0: return tmp; michael@0: } michael@0: michael@0: inline String8& String8::operator+=(const char* other) michael@0: { michael@0: append(other); michael@0: return *this; michael@0: } michael@0: michael@0: inline String8 String8::operator+(const char* other) const michael@0: { michael@0: String8 tmp(*this); michael@0: tmp += other; michael@0: return tmp; michael@0: } michael@0: michael@0: inline int String8::compare(const String8& other) const michael@0: { michael@0: return strcmp(mString, other.mString); michael@0: } michael@0: michael@0: inline bool String8::operator<(const String8& other) const michael@0: { michael@0: return strcmp(mString, other.mString) < 0; michael@0: } michael@0: michael@0: inline bool String8::operator<=(const String8& other) const michael@0: { michael@0: return strcmp(mString, other.mString) <= 0; michael@0: } michael@0: michael@0: inline bool String8::operator==(const String8& other) const michael@0: { michael@0: return strcmp(mString, other.mString) == 0; michael@0: } michael@0: michael@0: inline bool String8::operator!=(const String8& other) const michael@0: { michael@0: return strcmp(mString, other.mString) != 0; michael@0: } michael@0: michael@0: inline bool String8::operator>=(const String8& other) const michael@0: { michael@0: return strcmp(mString, other.mString) >= 0; michael@0: } michael@0: michael@0: inline bool String8::operator>(const String8& other) const michael@0: { michael@0: return strcmp(mString, other.mString) > 0; michael@0: } michael@0: michael@0: inline bool String8::operator<(const char* other) const michael@0: { michael@0: return strcmp(mString, other) < 0; michael@0: } michael@0: michael@0: inline bool String8::operator<=(const char* other) const michael@0: { michael@0: return strcmp(mString, other) <= 0; michael@0: } michael@0: michael@0: inline bool String8::operator==(const char* other) const michael@0: { michael@0: return strcmp(mString, other) == 0; michael@0: } michael@0: michael@0: inline bool String8::operator!=(const char* other) const michael@0: { michael@0: return strcmp(mString, other) != 0; michael@0: } michael@0: michael@0: inline bool String8::operator>=(const char* other) const michael@0: { michael@0: return strcmp(mString, other) >= 0; michael@0: } michael@0: michael@0: inline bool String8::operator>(const char* other) const michael@0: { michael@0: return strcmp(mString, other) > 0; michael@0: } michael@0: michael@0: inline String8::operator const char*() const michael@0: { michael@0: return mString; michael@0: } michael@0: michael@0: } // namespace android michael@0: michael@0: // --------------------------------------------------------------------------- michael@0: michael@0: #endif // ANDROID_STRING8_H