Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *  * Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  *  * Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in
     12  *    the documentation and/or other materials provided with the
     13  *    distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
     22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include <string>
     30 #include <algorithm>
     31 #include <climits>
     32 #include <cstddef>
     33 #include <cstring>
     34 #include <malloc.h>
     35 #include <ostream>
     36 
     37 #ifndef MAX_SIZE_T
     38 #define MAX_SIZE_T           (~(size_t)0)
     39 #endif
     40 
     41 namespace {
     42 char kEmptyString[1] = { '\0' };
     43 // Dummy char used in the 'at' accessor when the index is out of
     44 // range.
     45 char sDummy;
     46 }
     47 
     48 namespace std {
     49 // Implementation of the std::string class.
     50 //
     51 // mData points either to a heap allocated array of bytes or the constant
     52 // kEmptyString when empty and reserve has not been called.
     53 //
     54 // The size of the buffer pointed by mData is mCapacity + 1.
     55 // The extra byte is need to store the '\0'.
     56 //
     57 // mCapacity is either mLength or the number of bytes reserved using
     58 // reserve(int)).
     59 //
     60 // mLength is the number of char in the string, excluding the terminating '\0'.
     61 //
     62 // TODO: replace the overflow checks with some better named macros.
     63 //
     64 // Allocate n + 1 number of bytes for the string. Update mCapacity.
     65 // Ensure that mCapacity + 1 and mLength + 1 is accessible.
     66 // In case of error the original state of the string is restored.
     67 // @param n Number of bytes requested. String allocate n + 1 to hold
     68 //            the terminating '\0'.
     69 // @return true if the buffer could be allocated, false otherwise.
     70 bool string::SafeMalloc(size_type n)
     71 {
     72     // Not empty and no overflow
     73     if (n > 0 && n + 1 > n)
     74     {
     75         value_type *oldData = mData;
     76 
     77         mData = static_cast<value_type *>(::malloc(n + 1));
     78         if (NULL != mData)
     79         {
     80             mCapacity = n;
     81             return true;
     82         }
     83         mData = oldData;  // roll back
     84     }
     85     return false;
     86 }
     87 
     88 // Resize the buffer pointed by mData if n >= mLength.
     89 // mData points to an allocated buffer or the empty string.
     90 // @param n The number of bytes for the internal buffer.
     91 //            Must be > mLength and > 0.
     92 void string::SafeRealloc(size_type n)
     93 {
     94     // truncation or nothing to do or n too big (overflow)
     95     if (n < mLength || n == mCapacity || n + 1 < n) {
     96         return;
     97     }
     98 
     99     if (kEmptyString == mData)
    100     {
    101         if (SafeMalloc(n)) {
    102             *mData = '\0';
    103         }
    104         return;
    105     }
    106 
    107     value_type *oldData = mData;
    108 
    109     mData = static_cast<char*>(::realloc(mData, n + 1));
    110     if (NULL == mData) // reallocate failed.
    111     {
    112         mData = oldData;
    113     }
    114     else
    115     {
    116         mCapacity = n;
    117     }
    118 }
    119 
    120 void string::SafeFree(value_type *buffer)
    121 {
    122     if (buffer != kEmptyString)
    123     {
    124         ::free(buffer);
    125     }
    126 }
    127 
    128 // If the memory is on the heap, release it. Do nothing we we point at the empty
    129 // string. On return mData points to str.
    130 void string::ResetTo(value_type *str)
    131 {
    132     SafeFree(mData);
    133     mData = str;
    134 }
    135 
    136 void string::ConstructEmptyString()
    137 {
    138     mData = kEmptyString;
    139     mLength = 0;
    140     mCapacity = 0;
    141 }
    142 
    143 void string::Constructor(const value_type *str, size_type n)
    144 {
    145     Constructor(str, 0, n);
    146 }
    147 
    148 
    149 void string::Constructor(const value_type *str, size_type pos, size_type n)
    150 {
    151     // Enough data and no overflow
    152     if (SafeMalloc(n))
    153     {
    154         memcpy(mData, str + pos, n);
    155         mLength = n;
    156         mData[mLength] = '\0';
    157         return;  // Success
    158     }
    159     ConstructEmptyString();
    160 }
    161 
    162 void string::Constructor(size_type n, char c)
    163 {
    164     // Enough data and no overflow
    165 
    166     if (SafeMalloc(n))
    167     {
    168         memset(mData, c, n);
    169         mLength = n;
    170         mData[mLength] = '\0';
    171         return;  // Success
    172     }
    173     ConstructEmptyString();
    174 }
    175 
    176 string::string()
    177 {
    178     ConstructEmptyString();
    179 }
    180 
    181 string::string(const string& str)
    182 {
    183     Constructor(str.mData, str.mLength);
    184 }
    185 
    186 string::string(const string& str, size_type pos, size_type n)
    187 {
    188     if (pos < str.mLength)
    189     {
    190         if (n > (str.mLength - pos)) {
    191             n = str.mLength - pos;
    192         }
    193         Constructor(str.mData + pos , n);
    194     }
    195     else
    196     {
    197         ConstructEmptyString();
    198     }
    199 }
    200 
    201 string::string(const string& str, size_type pos)
    202 {
    203     if (pos < str.mLength)
    204     {
    205         Constructor(str.mData, pos, str.mLength - pos);
    206     }
    207     else
    208     {
    209         ConstructEmptyString();
    210     }
    211 }
    212 
    213 string::string(const value_type *str)
    214 {
    215     if (NULL != str)
    216     {
    217         Constructor(str, traits_type::length(str));
    218     }
    219     else
    220     {
    221         ConstructEmptyString();
    222     }
    223 }
    224 
    225 string::string(const value_type *str, size_type n)
    226 {
    227     Constructor(str, n);
    228 }
    229 
    230 // Char repeat constructor.
    231 string::string(size_type n, char c)
    232 {
    233     Constructor(n, c);
    234 }
    235 
    236 string::string(const value_type *begin, const value_type *end)
    237 {
    238     if (begin < end)
    239     {
    240         Constructor(begin, end - begin);
    241     }
    242     else
    243     {
    244         ConstructEmptyString();
    245     }
    246 }
    247 
    248 string::~string()
    249 {
    250     clear();  // non virtual, ok to call.
    251 }
    252 
    253 void string::clear()
    254 {
    255     mCapacity = 0;
    256     mLength = 0;
    257     ResetTo(kEmptyString);
    258 }
    259 
    260 string& string::erase(size_type pos, size_type n)
    261 {
    262     if (pos >= mLength || 0 == n)
    263     {
    264         return *this;
    265     }
    266     // start of the characters left which need to be moved down.
    267     const size_t remainder = pos + n;
    268 
    269     // Truncate, even if there is an overflow.
    270     if (remainder >= mLength || remainder < pos)
    271     {
    272         *(mData + pos) = '\0';
    273         mLength = pos;
    274         return *this;
    275     }
    276     // remainder < mLength and allocation guarantees to be at least
    277     // mLength + 1
    278     size_t left = mLength - remainder + 1;
    279     value_type *d = mData + pos;
    280     value_type *s = mData + remainder;
    281     memmove(d, s, left);
    282     mLength -= n;
    283     return *this;
    284 }
    285 
    286 void string::Append(const value_type *str, size_type n)
    287 {
    288     const size_type total_len = mLength + n;
    289 
    290     // n > 0 and no overflow for the string length + terminating null.
    291     if (n > 0 && (total_len + 1) > mLength)
    292     {
    293         if (total_len > mCapacity)
    294         {
    295             reserve(total_len);
    296             if (total_len > mCapacity)
    297             {  // something went wrong in the reserve call.
    298                 return;
    299             }
    300         }
    301         memcpy(mData + mLength, str, n);
    302         mLength = total_len;
    303         mData[mLength] = '\0';
    304     }
    305 }
    306 
    307 string& string::append(const value_type *str)
    308 {
    309     if (NULL != str)
    310     {
    311         Append(str, traits_type::length(str));
    312     }
    313     return *this;
    314 }
    315 
    316 string& string::append(const value_type *str, size_type n)
    317 {
    318     if (NULL != str)
    319     {
    320         Append(str, n);
    321     }
    322     return *this;
    323 }
    324 
    325 string& string::append(const value_type *str, size_type pos, size_type n)
    326 {
    327     if (NULL != str)
    328     {
    329         Append(str + pos, n);
    330     }
    331     return *this;
    332 }
    333 
    334 string& string::append(const string& str)
    335 {
    336     Append(str.mData, str.mLength);
    337     return *this;
    338 }
    339 
    340 // Specialization to append from other strings' iterators.
    341 template<>
    342 string& string::append<__wrapper_iterator<const char *,string> >(
    343     __wrapper_iterator<const char *,string> first,
    344     __wrapper_iterator<const char *,string> last) {
    345     Append(&*first, std::distance(first, last));
    346     return *this;
    347 }
    348 template<>
    349 string& string::append<__wrapper_iterator<char *,string> >(
    350     __wrapper_iterator<char *,string> first,
    351     __wrapper_iterator<char *,string> last) {
    352     Append(&*first, std::distance(first, last));
    353     return *this;
    354 }
    355 
    356 void string::push_back(const char c)
    357 {
    358     // Check we don't overflow.
    359     if (mLength + 2 > mLength)
    360     {
    361         const size_type total_len = mLength + 1;
    362 
    363         if (total_len > mCapacity)
    364         {
    365             reserve(total_len);
    366             if (total_len > mCapacity)
    367             {  // something went wrong in the reserve call.
    368                 return;
    369             }
    370         }
    371         *(mData + mLength) = c;
    372         ++mLength;
    373         mData[mLength] = '\0';
    374     }
    375 }
    376 
    377 
    378 int string::compare(const string& other) const
    379 {
    380     if (this == &other)
    381     {
    382         return 0;
    383     }
    384     else if (mLength == other.mLength)
    385     {
    386         return memcmp(mData, other.mData, mLength);
    387     }
    388     else
    389     {
    390         return mLength < other.mLength ? -1 : 1;
    391     }
    392 }
    393 
    394 int string::compare(const value_type *other) const
    395 {
    396     if (NULL == other)
    397     {
    398         return 1;
    399     }
    400     return strcmp(mData, other);
    401 }
    402 
    403 bool operator==(const string& left, const string& right)
    404 {
    405     if (&left == &right) {
    406         return true;
    407     }
    408     return (left.size() == right.size() &&
    409             !char_traits<char>::compare(left.mData, right.mData, left.size()));
    410 }
    411 
    412 bool operator==(const string& left, const string::value_type *right)
    413 {
    414     if (NULL == right) {
    415         return false;
    416     }
    417     // We can use strcmp here because even when the string is build from an
    418     // array of char we insert the terminating '\0'.
    419     return std::strcmp(left.mData, right) == 0;
    420 }
    421 
    422 void string::reserve(size_type size)
    423 {
    424     if (0 == size)
    425     {
    426         if (0 == mCapacity)
    427         {
    428             return;
    429         }
    430         else if (0 == mLength)
    431         {  // Shrink to fit an empty string.
    432             mCapacity = 0;
    433             ResetTo(kEmptyString);
    434         }
    435         else
    436         {  // Shrink to fit a non empty string
    437             SafeRealloc(mLength);
    438         }
    439     }
    440     else if (size > mLength)
    441     {
    442         SafeRealloc(size);
    443     }
    444 }
    445 
    446 void string::swap(string& other)
    447 {
    448     if (this == &other) return;
    449     value_type *const tmp_mData = mData;
    450     const size_type tmp_mCapacity = mCapacity;
    451     const size_type tmp_mLength = mLength;
    452 
    453     mData = other.mData;
    454     mCapacity = other.mCapacity;
    455     mLength = other.mLength;
    456 
    457     other.mData = tmp_mData;
    458     other.mCapacity = tmp_mCapacity;
    459     other.mLength = tmp_mLength;
    460 }
    461 
    462 const char& string::operator[](const size_type pos) const
    463 {
    464     return mData[pos];
    465 }
    466 
    467 char& string::operator[](const size_type pos)
    468 {
    469     return mData[pos];
    470 }
    471 
    472 const char& string::at(const size_type pos) const
    473 {
    474     if (pos < mLength) {
    475         return mData[pos];
    476     } else {
    477         sDummy = 'X';
    478         return sDummy;
    479     }
    480 }
    481 
    482 char& string::at(const size_type pos)
    483 {
    484     if (pos < mLength) {
    485         return mData[pos];
    486     } else {
    487         sDummy = 'X';
    488         return sDummy;
    489     }
    490 }
    491 
    492 string& string::assign(const string& str)
    493 {
    494     clear();
    495     Constructor(str.mData, str.mLength);
    496     return *this;
    497 }
    498 
    499 string& string::assign(const string& str, size_type pos, size_type n)
    500 {
    501     if (pos >= str.mLength)
    502     {  // pos is out of bound
    503         return *this;
    504     }
    505     if (n <= str.mLength - pos)
    506     {
    507         clear();
    508         Constructor(str.mData, pos, n);
    509     }
    510     return *this;
    511 }
    512 
    513 string& string::assign(const value_type *str)
    514 {
    515     if (NULL == str)
    516     {
    517         return *this;
    518     }
    519     clear();
    520     Constructor(str, traits_type::length(str));
    521     return *this;
    522 }
    523 
    524 string& string::assign(const value_type *array, size_type n)
    525 {
    526     if (NULL == array || 0 == n)
    527     {
    528         return *this;
    529     }
    530     clear();
    531     Constructor(array, n);
    532     return *this;
    533 }
    534 
    535 string::iterator string::insert(iterator iter, char c) {
    536     const size_type new_len = mLength + 1;
    537     char *base = iter.base();
    538 
    539     if (base < mData || base > mData + mLength || new_len < mLength) {
    540         return iterator(&sDummy);  // out of bound || overflow
    541     }
    542 
    543     const size_type pos = base - mData;
    544     if (new_len > mCapacity) {
    545         reserve(new_len);
    546         if (new_len > mCapacity) {
    547             return iterator(&sDummy);  // not enough memory?
    548         }
    549     }
    550     // At this point 'iter' and 'base' are not valid anymore since
    551     // realloc could have taken place.
    552     base = mData + pos;
    553     std::memmove(base + 1, base, mLength - pos);
    554     *base = c;
    555     mLength = new_len;
    556     mData[mLength] = 0;
    557     return iterator(base);
    558 }
    559 
    560 string& string::operator=(char c)
    561 {
    562     clear();
    563     Constructor(1, c);
    564     return *this;
    565 }
    566 
    567 string::size_type string::find(const value_type *str, size_type pos) const
    568 {
    569 
    570     if (NULL == str)
    571     {
    572         return string::npos;
    573     }
    574 
    575     // Empty string is found everywhere except beyond the end. It is
    576     // possible to find the empty string right after the last char,
    577     // hence we used mLength and not mLength - 1 in the comparison.
    578     if (*str == '\0')
    579     {
    580         return pos > mLength ? string::npos : pos;
    581     }
    582 
    583     if (mLength == 0 || pos > mLength - 1)
    584     {
    585         return string::npos;
    586     }
    587 
    588     value_type *idx = std::strstr(mData + pos, str);
    589 
    590     if (NULL == idx)
    591     {
    592         return string::npos;
    593     }
    594 
    595     const std::ptrdiff_t delta = idx - mData;
    596 
    597     return static_cast<size_type>(delta);
    598 }
    599 
    600 string string::substr(size_type pos, size_type n) const {
    601     return string(*this, pos, n);
    602 }
    603 
    604 string::size_type string::find_first_of(value_type c, size_type pos) const {
    605     if (pos >= mLength) {
    606         return npos;
    607     }
    608     const char *res;
    609     // The last parameter represents a number of chars, not a index.
    610     res = static_cast<const char *>(std::memchr(mData + pos, c, mLength - pos));
    611     return res != NULL ? res - mData : npos;
    612 }
    613 
    614 string::size_type string::find_last_of(value_type c, size_type pos) const {
    615     if (mLength == 0) {
    616         return npos;
    617     } else if (pos >= mLength) {
    618         pos = mLength - 1;  // >= 0
    619     }
    620 
    621     const char *res;
    622     // Note:memrchr is not in the std namepace.
    623     // The last parameter represents a number of chars, not a index.
    624     res = static_cast<const char *>(memrchr(mData, c, pos + 1));
    625     return res != NULL ? res - mData : npos;
    626 }
    627 
    628 string::size_type string::find_first_not_of(value_type c, size_type pos) const {
    629     char *curr = mData + pos;
    630     for (size_type i = pos; i < mLength; ++i, ++curr) {
    631         if (c != *curr) {
    632             return i;
    633         }
    634     }
    635     return npos;
    636 }
    637 
    638 string::size_type string::find_last_not_of(value_type c, size_type pos) const {
    639     if (mLength == 0) {
    640         return npos;
    641     } else if (pos >= mLength) {
    642         pos = mLength - 1;  // >= 0
    643     }
    644 
    645     char *curr = mData + pos;
    646     size_type i = pos;
    647 
    648     for (;; --i, --curr) {
    649         if (c != *curr) {
    650             return i;
    651         } else if (i == 0) {
    652             return npos;
    653         }
    654     }
    655 }
    656 
    657 bool operator<(const string& lhs, const string& rhs) {
    658     return lhs.compare(rhs) < 0;
    659 }
    660 
    661 bool operator<=(const string& lhs, const string& rhs) {
    662     return lhs.compare(rhs) <= 0;
    663 }
    664 
    665 bool operator>(const string& lhs, const string& rhs) {
    666     return lhs.compare(rhs) > 0;
    667 }
    668 
    669 bool operator>=(const string& lhs, const string& rhs) {
    670     return lhs.compare(rhs) >= 0;
    671 }
    672 
    673 void swap(string& lhs, string& rhs) {
    674     lhs.swap(rhs);
    675 }
    676 
    677 ostream& operator<<(ostream& os, const string& str) {
    678     return os.write_formatted(str.data(), str.size());
    679 }
    680 
    681 }  // namespace std
    682