| /* -*- c++ -*- */ |
| /* |
| * Copyright (C) 2009 The Android Open Source Project |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
| * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
| * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
| * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
| * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS |
| * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
| * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| */ |
| |
| #ifndef ANDROID_ASTL_STRING__ |
| #define ANDROID_ASTL_STRING__ |
| |
| #include <algorithm> |
| #include <cstddef> |
| #include <iterator> |
| #include <char_traits.h> |
| |
| namespace std { |
| |
| class ostream; |
| |
| // Simple string implementation. Its purpose is to be able to compile code that |
| // uses the STL and requires std::string. |
| // |
| // IMPORTANT: |
| // . This class it is not fully STL compliant. Some constructors/methods maybe |
| // missing, they will be added on demand. |
| // . We don't provide a std::basic_string template that std::string extends |
| // because we use only char (wchar is not supported on Android). |
| // . The memory allocation scheme uses the heap. Since Android has the concept |
| // of SharedBuffer, we may, in the future, templatize this class and add an |
| // allocation parameter. |
| // . The implementation is not optimized in any way (no copy on write support), |
| // temporary instance may be expensive. |
| // . Currently there is limited support for iterators. |
| // |
| |
| class string |
| { |
| public: |
| typedef char_traits<char> traits_type; |
| typedef traits_type::char_type value_type; |
| typedef size_t size_type; |
| typedef ptrdiff_t difference_type; |
| typedef value_type& reference; |
| typedef const value_type& const_reference; |
| typedef value_type* pointer; |
| typedef const value_type* const_pointer; |
| typedef __wrapper_iterator<pointer,string> iterator; |
| typedef __wrapper_iterator<const_pointer,string> const_iterator; |
| |
| static const size_type npos = static_cast<size_type>(-1); |
| |
| // Constructors |
| string(); |
| |
| string(const string& str); |
| |
| // Construct a string from a source's substring. |
| // @param str The source string. |
| // @param pos The index of the character to start the copy at. |
| // @param n The number of characters to copy. Use string::npos for the |
| // remainder. |
| string(const string& str, size_t pos, size_type n); |
| |
| // Same as above but implicitly copy from pos to the end of the str. |
| string(const string& str, size_type pos); |
| |
| // Construct a string from a C string. |
| // @param str The source string, must be '\0' terminated. |
| string(const value_type *str); |
| |
| // Construct a string from a char array. |
| // @param str The source C string. '\0' are ignored. |
| // @param n The number of characters to copy. |
| string(const value_type *str, size_type n); |
| |
| // Construct a string from a repetition of a character. |
| // @param n The number of characters. |
| // @param c The character to use. |
| string(size_t n, char c); |
| |
| // Construct a string from a char array. |
| // @param begin The start of the source C string. '\0' are ignored. |
| // @param end The end of source C string. Points just pass the last |
| // character. |
| string(const value_type *begin, const value_type *end); |
| |
| ~string(); |
| |
| // @return The number of characters in the string, not including any |
| // null-termination. |
| size_type length() const { return mLength; } |
| size_type size() const { return mLength; } |
| |
| // @return A pointer to null-terminated contents. |
| const value_type *c_str() const { return mData; } |
| const value_type *data() const { return mData; } |
| |
| // Empty the string on return. Release the internal buffer. Length |
| // and capacity are both 0 on return. If you want to keep the |
| // internal buffer around for reuse, call 'erase' instead. |
| void clear(); |
| |
| // @return true if the string is empty. |
| bool empty() const { return this->size() == 0; } |
| |
| // Remove 'len' characters from the string starting at 'pos'. The |
| // string length is reduced by 'len'. If len is greater or equal |
| // to the number of characters in the string, it is truncated at |
| // 'pos'. If 'pos' is beyond the end of the string, 'erase' does |
| // nothing. Note, regular STL implementations throw a out_of_range |
| // exception in this case. |
| // Internally, the capacity of the buffer remains unchanged. If |
| // you wanted to recover the deleted chars' memory you should call |
| // 'reserve' explicitly (see also 'clear'). |
| // @param pos Index of the first character to remove (default to 0) |
| // @param n Number of characters to delete. (default to remainder) |
| // @return a reference to this string. |
| string& erase(size_type pos = 0, size_type n = npos); |
| |
| // @param str The string to be append. |
| // @return A reference to this string. |
| string& operator+=(const string& str) { return this->append(str); } |
| |
| // @param str The C string to be append. |
| // @return A reference to this string. |
| string& operator+=(const value_type *str) { return this->append(str); } |
| |
| // @param c A character to be append. |
| // @return A reference to this string. |
| string& operator+=(const char c) { this->push_back(c); return *this; } |
| |
| // @param c A character to be append. |
| void push_back(const char c); |
| |
| // no-op if str is NULL. |
| string& append(const value_type *str); |
| // no-op if str is NULL. n must be >= 0. |
| string& append(const value_type *str, size_type n); |
| // no-op if str is NULL. pos and n must be >= 0. |
| string& append(const value_type *str, size_type pos, size_type n); |
| string& append(const string& str); |
| |
| template<typename _InputIterator> |
| string& append(_InputIterator first, _InputIterator last); |
| |
| // Comparison. |
| // @return 0 if this==other, < 0 if this < other and > 0 if this > other. |
| // Don't assume the values are -1, 0, 1 |
| int compare(const string& other) const; |
| int compare(const value_type *other) const; |
| |
| friend bool operator==(const string& left, const string& right); |
| friend bool operator==(const string& left, const value_type *right); |
| friend bool operator==(const value_type *left, const string& right) { return right == left; } |
| friend bool operator!=(const string& left, const string& right) { return !(left == right); } |
| friend bool operator!=(const string& left, const char* right) { return !(left == right); } |
| friend bool operator!=(const value_type *left, const string& right) { return !(left == right); } |
| |
| // @return Number of elements for which memory has been allocated. capacity >= size(). |
| size_type capacity() const { return mCapacity; } |
| |
| // Change the capacity to new_size. No effect if new_size < size(). |
| // 0 means Shrink to fit. |
| // @param new_size number of character to be allocated. |
| void reserve(size_type new_size = 0); |
| |
| // Exchange the content of this with the content of other. |
| // @param other Instance to swap this one with. |
| void swap(string& other); |
| |
| // Accessors. |
| // @param pos of the char. No boundary, signed checks are done. |
| // @return a const reference to the char. |
| const char& operator[](const size_type pos) const; |
| |
| // @param pos of the char. No boundary, signed checks are done. |
| // @return a reference to the char. |
| char& operator[](const size_type pos); |
| |
| // 'at' is similar to operator[] except that it does check bounds. |
| const char& at(const size_type pos) const; |
| char& at(const size_type pos); |
| |
| // Assignments. |
| string& operator=(const string& str) { return assign(str); } |
| string& operator=(const char* str) { return assign(str); } |
| string& operator=(char c); |
| |
| string& assign(const string& str); |
| // Assign a substring of the original. |
| // @param str Original string. |
| // @param pos Index of the start of the copy. |
| // @param n Number of character to be copied. |
| string& assign(const string& str, size_type pos, size_type n); |
| string& assign(const value_type *str); |
| |
| // Assign a non-nul terminated array of chars. |
| // @param array Of chars non-nul terminated. |
| // @param len Length of the array. |
| string& assign(const value_type *array, size_type len); |
| |
| // Concat. Prefer using += or append. |
| // Uses unnamed object for return value optimization. |
| friend string operator+(const string& left, const string& right) { |
| return string(left).append(right); |
| } |
| friend string operator+(const string& left, const value_type *right) { |
| return string(left).append(right); |
| } |
| friend string operator+(const value_type *left, const string& right) { |
| return string(left).append(right); |
| } |
| friend string operator+(const string& left, char right) { |
| return string(left).operator+=(right); |
| } |
| friend string operator+(char left, const string& right) { |
| return string(&left, 1).append(right); |
| } |
| |
| // Insert a copy of c before the character referred to by pos. |
| // @param pos A valid iterator on *this. |
| // @return An iterator which refers to the copy of the inserted |
| // character. Because internally some reallocation may occur, the |
| // returned iterator may be different from 'pos'. |
| iterator insert(iterator pos, char c); |
| |
| // Find the position of a sub-string. The empty string is always |
| // found at the requested position except when it's beyond the |
| // string's end. |
| // @param str String to locate. |
| // @param pos Index of the character to search from. Default to 0. |
| // @return Index of start of the first occurrence of the |
| // string. string::npos if no occurrence of str was found from the |
| // starting position. |
| size_type find(const string& str, size_type pos = 0) const { |
| return find(str.mData, pos); |
| } |
| |
| // Find the position of a C sub-string. The empty string is always |
| // found at the requested position except when it's beyond the |
| // string's end. |
| // @param str C string to locate. |
| // @param pos Index of the character to search from. Default to 0. |
| // @return Index of start of the first occurrence of the |
| // string. string::npos if no occurrence of str was found from the |
| // starting position. |
| size_type find(const value_type *str, size_type pos = 0) const; |
| |
| // Find the lowest position xpos, if possible, such that: |
| // pos <= xpos && xpos < size() |
| // at(xpos) == c |
| // @return xpos if it exists, npos otherwise. |
| size_type find(const value_type c, size_type pos = 0) const { |
| return find_first_of(c, pos); |
| } |
| |
| // Find the highest position xpos, if possible, such that: |
| // xpos <= pos && xpos < size() |
| // at(xpos) == c |
| // @return xpos if it exists, npos otherwise. |
| size_type rfind(const value_type c, size_type pos = npos) const { |
| return find_last_of(c, pos); |
| } |
| |
| // Iterators |
| iterator begin() {return iterator(mData);} |
| const_iterator begin() const {return const_iterator(mData);} |
| iterator end() {return iterator(mData + mLength);} |
| const_iterator end() const {return const_iterator(mData + mLength);} |
| |
| // @return the substring [pos, pos + n]. |
| // Requires pos <= size(). If n > size() - pos, size() - pos is used. |
| string substr(size_type pos = 0, size_type n = npos) const; |
| |
| // Find char methods. Return the position or npos if the char was not found. |
| size_type find_first_of(value_type c, size_type pos = 0) const; |
| size_type find_last_of(value_type c, size_type pos = npos) const; |
| size_type find_first_not_of(value_type c, size_type pos = 0) const; |
| size_type find_last_not_of(value_type c, size_type pos = npos) const; |
| |
| private: |
| bool SafeMalloc(size_type n); |
| void SafeRealloc(size_type n); |
| void SafeFree(value_type *str); |
| void ResetTo(value_type *str); |
| void ConstructEmptyString(); |
| void Constructor(const value_type *str, size_type n); |
| void Constructor(const value_type *str, size_type pos, size_type n); |
| void Constructor(size_type num, char c); |
| void DeleteSafe(); |
| void Append(const value_type *str, size_type len); |
| |
| value_type *mData; // pointer to the buffer |
| size_type mCapacity; // size of the buffer. |
| size_type mLength; // len of the string excl. null-terminator. |
| }; |
| |
| // Comparaison: |
| bool operator<(const string& lhs, const string& rhs); |
| bool operator<=(const string& lhs, const string& rhs); |
| bool operator>(const string& lhs, const string& rhs); |
| bool operator>=(const string& lhs, const string& rhs); |
| |
| // Swap |
| void swap(string& lhs, string& rhs); |
| |
| // I/O |
| ostream& operator<<(ostream& os, const string& str); |
| |
| |
| // Specialization of append(iterator, iterator) using string iterators |
| // (const and non const). |
| template<> |
| string& string::append<__wrapper_iterator<const char *,string> >( |
| __wrapper_iterator<const char *,string> first, |
| __wrapper_iterator<const char *,string> last); |
| template<> |
| string& string::append<__wrapper_iterator<char *,string> >( |
| __wrapper_iterator<char *,string> first, |
| __wrapper_iterator<char *,string> last); |
| |
| // append(iterator,iterator) default implementation. |
| template<typename _InputIterator> |
| string& string::append(_InputIterator first, _InputIterator last) { |
| size_type dist = std::distance(first, last); |
| size_type new_len = mLength + dist; |
| if (new_len <= mLength) { |
| return *this; // 0 / overflow |
| } |
| reserve(new_len); |
| if (new_len > mCapacity) { |
| return *this; // memory allocation failed. |
| } |
| std::copy(first, last, mData + mLength); |
| mLength = new_len; |
| mData[mLength] = '\0'; |
| return *this; |
| } |
| |
| |
| } // namespace std |
| |
| #endif // ANDROID_ASTL_STRING__ |