string revision 0cc3ee31c3cddd2bb5322398d17c388975e96d64
1/* -*- c++ -*- */
2/*
3 * Copyright (C) 2009 The Android Open Source Project
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *  * Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 *  * Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in
13 *    the documentation and/or other materials provided with the
14 *    distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
23 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#ifndef ANDROID_ASTL_STRING__
31#define ANDROID_ASTL_STRING__
32
33#include <algorithm>
34#include <cstddef>
35#include <iterator>
36#include <char_traits.h>
37
38namespace std {
39
40class ostream;
41
42// Simple string implementation. Its purpose is to be able to compile code that
43// uses the STL and requires std::string.
44//
45// IMPORTANT:
46// . This class it is not fully STL compliant. Some constructors/methods maybe
47// missing, they will be added on demand.
48// . We don't provide a std::basic_string template that std::string extends
49// because we use only char (wchar is not supported on Android).
50// . The memory allocation scheme uses the heap. Since Android has the concept
51// of SharedBuffer, we may, in the future, templatize this class and add an
52// allocation parameter.
53// . The implementation is not optimized in any way (no copy on write support),
54// temporary instance may be expensive.
55// . Currently there is limited support for iterators.
56//
57
58class string
59{
60  public:
61    typedef char_traits<char>      traits_type;
62    typedef traits_type::char_type value_type;
63    typedef size_t                 size_type;
64    typedef ptrdiff_t              difference_type;
65    typedef value_type&            reference;
66    typedef const value_type&      const_reference;
67    typedef value_type*            pointer;
68    typedef const value_type*      const_pointer;
69    typedef __wrapper_iterator<pointer,string>  iterator;
70    typedef __wrapper_iterator<const_pointer,string> const_iterator;
71
72    static const size_type npos = static_cast<size_type>(-1);
73
74    // Constructors
75    string();
76
77    string(const string& str);
78
79    // Construct a string from a source's substring.
80    // @param str The source string.
81    // @param pos The index of the character to start the copy at.
82    // @param n The number of characters to copy. Use string::npos for the
83    // remainder.
84    string(const string& str, size_t pos, size_type n);
85
86    // Same as above but implicitly copy from pos to the end of the str.
87    string(const string& str, size_type pos);
88
89    // Construct a string from a C string.
90    // @param str The source string, must be '\0' terminated.
91    string(const value_type *str);
92
93    // Construct a string from a char array.
94    // @param str The source C string. '\0' are ignored.
95    // @param n The number of characters to copy.
96    string(const value_type *str, size_type n);
97
98    // Construct a string from a repetition of a character.
99    // @param n The number of characters.
100    // @param c The character to use.
101    string(size_t n, char c);
102
103    // Construct a string from a char array.
104    // @param begin The start of the source C string. '\0' are ignored.
105    // @param end The end of source C string. Points just pass the last
106    // character.
107    string(const value_type *begin, const value_type *end);
108
109    ~string();
110
111    // @return The number of characters in the string, not including any
112    // null-termination.
113    size_type length() const { return mLength; }
114    size_type size() const { return mLength; }
115
116    // @return A pointer to null-terminated contents.
117    const value_type *c_str() const { return mData; }
118    const value_type *data() const { return mData; }
119
120    // Empty the string on return. Release the internal buffer. Length
121    // and capacity are both 0 on return. If you want to keep the
122    // internal buffer around for reuse, call 'erase' instead.
123    void clear();
124
125    // @return true if the string is empty.
126    bool empty() const { return this->size() == 0; }
127
128    // Remove 'len' characters from the string starting at 'pos'. The
129    // string length is reduced by 'len'. If len is greater or equal
130    // to the number of characters in the string, it is truncated at
131    // 'pos'. If 'pos' is beyond the end of the string, 'erase' does
132    // nothing. Note, regular STL implementations throw a out_of_range
133    // exception in this case.
134    // Internally, the capacity of the buffer remains unchanged. If
135    // you wanted to recover the deleted chars' memory you should call
136    // 'reserve' explicitly (see also 'clear').
137    // @param pos Index of the first character to remove (default to 0)
138    // @param n Number of characters to delete. (default to remainder)
139    // @return a reference to this string.
140    string& erase(size_type pos = 0, size_type n = npos);
141
142    // @param str The string to be append.
143    // @return A reference to this string.
144    string& operator+=(const string& str) { return this->append(str); }
145
146    // @param str The C string to be append.
147    // @return A reference to this string.
148    string& operator+=(const value_type *str) { return this->append(str); }
149
150    // @param c A character to be append.
151    // @return A reference to this string.
152    string& operator+=(const char c) { this->push_back(c); return *this; }
153
154    // @param c A character to be append.
155    void push_back(const char c);
156
157    // no-op if str is NULL.
158    string& append(const value_type *str);
159    // no-op if str is NULL. n must be >= 0.
160    string& append(const value_type *str, size_type n);
161    // no-op if str is NULL. pos and n must be >= 0.
162    string& append(const value_type *str, size_type pos, size_type n);
163    string& append(const string& str);
164
165    template<typename _InputIterator>
166    string& append(_InputIterator first, _InputIterator last);
167
168    // Comparison.
169    // @return 0 if this==other, < 0 if this < other and > 0 if this > other.
170    // Don't assume the values are -1, 0, 1
171    int compare(const string& other) const;
172    int compare(const value_type *other) const;
173
174    friend bool operator==(const string& left, const string& right);
175    friend bool operator==(const string& left, const value_type *right);
176    friend bool operator==(const value_type *left, const string& right) { return right == left; }
177    friend bool operator!=(const string& left, const string& right) { return !(left == right); }
178    friend bool operator!=(const string& left, const char* right) { return !(left == right); }
179    friend bool operator!=(const value_type *left, const string& right) { return !(left == right); }
180
181    // @return Number of elements for which memory has been allocated. capacity >= size().
182    size_type capacity() const { return mCapacity; }
183
184    // Change the capacity to new_size. No effect if new_size < size().
185    // 0 means Shrink to fit.
186    // @param new_size number of character to be allocated.
187    void reserve(size_type new_size = 0);
188
189    // Exchange the content of this with the content of other.
190    // @param other Instance to swap this one with.
191    void swap(string& other);
192
193    // Accessors.
194    // @param pos of the char. No boundary, signed checks are done.
195    // @return a const reference to the char.
196    const char& operator[](const size_type pos) const;
197
198    // @param pos of the char. No boundary, signed checks are done.
199    // @return a reference to the char.
200    char& operator[](const size_type pos);
201
202    // 'at' is similar to operator[] except that it does check bounds.
203    const char& at(const size_type pos) const;
204    char& at(const size_type pos);
205
206    // Assignments.
207    string& operator=(const string& str) { return assign(str); }
208    string& operator=(const char* str) { return assign(str); }
209    string& operator=(char c);
210
211    string& assign(const string& str);
212    // Assign a substring of the original.
213    // @param str Original string.
214    // @param pos Index of the start of the copy.
215    // @param n Number of character to be copied.
216    string& assign(const string& str, size_type pos, size_type n);
217    string& assign(const value_type *str);
218
219    // Assign a non-nul terminated array of chars.
220    // @param array Of chars non-nul terminated.
221    // @param len Length of the array.
222    string& assign(const value_type *array, size_type len);
223
224    // Concat. Prefer using += or append.
225    // Uses unnamed object for return value optimization.
226    friend string operator+(const string& left, const string& right) {
227        return string(left).append(right);
228    }
229    friend string operator+(const string& left, const value_type *right) {
230        return string(left).append(right);
231    }
232    friend string operator+(const value_type *left, const string& right) {
233        return string(left).append(right);
234    }
235    friend string operator+(const string& left, char right) {
236        return string(left).operator+=(right);
237    }
238    friend string operator+(char left, const string& right) {
239        return string(&left, 1).append(right);
240    }
241
242    // Insert a copy of c before the character referred to by pos.
243    // @param pos A valid iterator on *this.
244    // @return An iterator which refers to the copy of the inserted
245    // character. Because internally some reallocation may occur, the
246    // returned iterator may be different from 'pos'.
247    iterator insert(iterator pos, char c);
248
249    // Find the position of a sub-string. The empty string is always
250    // found at the requested position except when it's beyond the
251    // string's end.
252    // @param str String to locate.
253    // @param pos Index of the character to search from. Default to 0.
254    // @return Index of start of the first occurrence of the
255    // string. string::npos if no occurrence of str was found from the
256    // starting position.
257    size_type find(const string& str, size_type pos = 0) const {
258        return find(str.mData, pos);
259    }
260
261    // Find the position of a C sub-string. The empty string is always
262    // found at the requested position except when it's beyond the
263    // string's end.
264    // @param str C string to locate.
265    // @param pos Index of the character to search from. Default to 0.
266    // @return Index of start of the first occurrence of the
267    // string. string::npos if no occurrence of str was found from the
268    // starting position.
269    size_type find(const value_type *str, size_type pos = 0) const;
270
271    // Find the lowest position xpos, if possible, such that:
272    //   pos <= xpos && xpos < size()
273    //   at(xpos) == c
274    // @return xpos if it exists, npos otherwise.
275    size_type find(const value_type c, size_type pos = 0) const {
276        return find_first_of(c, pos);
277    }
278
279    // Find the highest position xpos, if possible, such that:
280    //   xpos <= pos && xpos < size()
281    //   at(xpos) == c
282    // @return xpos if it exists, npos otherwise.
283    size_type rfind(const value_type c, size_type pos = npos) const {
284        return find_last_of(c, pos);
285    }
286
287    // Iterators
288    iterator begin() {return iterator(mData);}
289    const_iterator begin() const {return const_iterator(mData);}
290    iterator end() {return iterator(mData + mLength);}
291    const_iterator end() const {return const_iterator(mData + mLength);}
292
293    // @return the substring [pos, pos + n].
294    // Requires pos <= size(). If n > size() - pos, size() - pos is used.
295    string substr(size_type pos = 0, size_type n = npos) const;
296
297    // Find char methods. Return the position or npos if the char was not found.
298    size_type find_first_of(value_type c, size_type pos = 0) const;
299    size_type find_last_of(value_type c, size_type pos = npos) const;
300    size_type find_first_not_of(value_type c, size_type pos = 0) const;
301    size_type find_last_not_of(value_type c, size_type pos = npos) const;
302
303  private:
304    bool SafeMalloc(size_type n);
305    void SafeRealloc(size_type n);
306    void SafeFree(value_type *str);
307    void ResetTo(value_type *str);
308    void ConstructEmptyString();
309    void Constructor(const value_type *str, size_type n);
310    void Constructor(const value_type *str, size_type pos, size_type n);
311    void Constructor(size_type num, char c);
312    void DeleteSafe();
313    void Append(const value_type *str, size_type len);
314
315    value_type *mData;  // pointer to the buffer
316    size_type mCapacity;  // size of the buffer.
317    size_type mLength;  // len of the string excl. null-terminator.
318};
319
320// Comparaison:
321bool operator<(const string& lhs, const string& rhs);
322bool operator<=(const string& lhs, const string& rhs);
323bool operator>(const string& lhs, const string& rhs);
324bool operator>=(const string& lhs, const string& rhs);
325
326// Swap
327void swap(string& lhs, string& rhs);
328
329// I/O
330ostream& operator<<(ostream& os, const string& str);
331
332
333// Specialization of append(iterator, iterator) using string iterators
334// (const and non const).
335template<>
336string& string::append<__wrapper_iterator<const char *,string> >(
337    __wrapper_iterator<const char *,string> first,
338    __wrapper_iterator<const char *,string> last);
339template<>
340string& string::append<__wrapper_iterator<char *,string> >(
341    __wrapper_iterator<char *,string> first,
342    __wrapper_iterator<char *,string> last);
343
344// append(iterator,iterator) default implementation.
345template<typename _InputIterator>
346string& string::append(_InputIterator first, _InputIterator last) {
347    size_type dist = std::distance(first, last);
348    size_type new_len = mLength + dist;
349    if (new_len <= mLength) {
350        return *this;  // 0 / overflow
351    }
352    reserve(new_len);
353    if (new_len > mCapacity) {
354        return *this;  // memory allocation failed.
355    }
356    std::copy(first, last, mData + mLength);
357    mLength = new_len;
358    mData[mLength] = '\0';
359    return *this;
360}
361
362
363}  // namespace std
364
365#endif  // ANDROID_ASTL_STRING__
366