blob: 9f9d14670220e150a9ed0fbbf96ec5be0b3f7ef3 [file] [log] [blame]
/* -*- 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__