diff options
author | Nicolas Catania <niko@google.com> | 2009-05-17 22:10:48 -0700 |
---|---|---|
committer | Nicolas Catania <niko@google.com> | 2009-05-18 16:03:36 -0700 |
commit | 7618d7b9a011b1158ef868d6ae3ead242ddaccac (patch) | |
tree | a5d346eff47191bf86ba865c4212e812022d5d05 | |
parent | d738d268c8f915bde451bba52e0c3996113ba9f0 (diff) | |
download | astl-7618d7b9a011b1158ef868d6ae3ead242ddaccac.tar.gz |
Use realloc to implement the reserve call.
Minor cleanup of the type used to identify size type and
the basic char type used:
- size_t is now string::size_type
- char is now string::value_type
-rw-r--r-- | include/string | 79 | ||||
-rw-r--r-- | src/string.cpp | 105 | ||||
-rw-r--r-- | tests/test_string.cpp | 5 |
3 files changed, 100 insertions, 89 deletions
diff --git a/include/string b/include/string index 16dadba..646f631 100644 --- a/include/string +++ b/include/string @@ -49,7 +49,6 @@ namespace std { // temporary instance may be expensive. // . Currently there is no support for iterators. // -// TODO: use size_type instead of size_t to be consistent. class string { @@ -57,7 +56,7 @@ class string typedef size_t size_type; typedef char value_type; - static const size_t npos = static_cast<size_t>(-1); + static const size_type npos = static_cast<size_type>(-1); // Constructors string(); @@ -69,19 +68,19 @@ class string // @param idx The index of the character to start the copy at. // @param num The number of characters to copy. Use string::npos for the // remainder. - string(const string& str, size_t idx, size_t num); + string(const string& str, size_t idx, size_type num); // Same as above but implicitely copy from idx to the end of the str. - string(const string& str, size_t idx); + string(const string& str, size_type idx); // Construct a string from a C string. // @param str The source string, must be '\0' terminated. - string(const char *str); + string(const value_type *str); // Construct a string from a char array. // @param str The source C string. '\0' are ignored. // @param num The number of characters to copy. - string(const char *str, size_t num); + string(const value_type *str, size_type num); // Construct a string from a repetition of a character. // @param num The number of characters. @@ -92,18 +91,18 @@ class string // @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 char *begin, const char *end); + string(const value_type *begin, const value_type *end); ~string(); // @return The number of characters in the string, not including any // null-termination. - const size_t length() const { return mLength; } - const size_t size() const { return mLength; } + size_type length() const { return mLength; } + size_type size() const { return mLength; } // @return A pointer to null-terminated contents. - const char *c_str() const { return mData; } - const char *data() const { return mData; } + const value_type *c_str() const { return mData; } + const value_type *data() const { return mData; } // Clear the string. Empty on return. void clear(); @@ -117,7 +116,7 @@ class string // @param str The C string to be append. // @return A reference to this string. - string& operator+=(const char *str) { return this->append(str); } + string& operator+=(const value_type *str) { return this->append(str); } // @param c A character to be append. // @return A reference to this string. @@ -127,33 +126,33 @@ class string void push_back(const char c); // no-op if str is NULL. - string& append(const char *str); + string& append(const value_type *str); // no-op if str is NULL. len must be >= 0. - string& append(const char *str, size_t len); + string& append(const value_type *str, size_type len); // no-op if str is NULL. idx and len must be >= 0. - string& append(const char *str, size_t idx, size_t len); + string& append(const value_type *str, size_type idx, size_type len); string& append(const string& str); // Comparaison. // @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 char *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 char *right); - friend bool operator==(const char *left, const string& right) { return right == left; } + 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 char *left, const string& 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_t capacity() const { return mCapacity; } + 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_t new_size = 0); + 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. @@ -162,10 +161,10 @@ class string // Accessors. // @param idx of the char. No boundary, signed checks are done. // @return a const reference to the char. - const char& operator[](const size_t idx) const; + const char& operator[](const size_type idx) const; // @param idx of the char. No boundary, signed checks are done. // @return a reference to the char. - char& operator[](const size_t idx); + char& operator[](const size_type idx); // Assignments. string& operator=(const string& str) { return assign(str); } @@ -177,22 +176,22 @@ class string // @param str Original string. // @param pos Index of the start of the copy. // @param len Number of character to be copied. - string& assign(const string& str, size_t pos, size_t len); - string& assign(const char *str); + string& assign(const string& str, size_type pos, size_type len); + string& assign(const value_type *str); // Assign a non terminated array of chars. // @param array Of chars non-null terminated. // @param len Length of the array. - string& assign(const char *array, size_t len); + string& assign(const value_type *array, size_type len); // Concat. Prefer using += or append. // Uses unamed 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 char *right) { + friend string operator+(const string& left, const value_type *right) { return string(left).append(right); } - friend string operator+(const char *left, const string& right) { + friend string operator+(const value_type *left, const string& right) { return string(left).append(right); } friend string operator+(const string& left, char right) { @@ -222,23 +221,23 @@ class string // @return Index of start of the first occurence of the // string. string::npos if no occurence of str was found from the // starting position. - size_type find(const char *str, size_type pos = 0) const; + size_type find(const value_type *str, size_type pos = 0) const; private: - bool SafeMalloc(size_t num); - void SafeRealloc(size_t num); - void SafeFree(char *str); - void ResetTo(char *str); + bool SafeMalloc(size_type num); + void SafeRealloc(size_type num); + void SafeFree(value_type *str); + void ResetTo(value_type *str); void ConstructEmptyString(); - void Constructor(const char *str, size_t num); - void Constructor(const char *str, size_t pos, size_t num); - void Constructor(size_t num, char c); + void Constructor(const value_type *str, size_type num); + void Constructor(const value_type *str, size_type pos, size_type num); + void Constructor(size_type num, char c); void DeleteSafe(); - void Append(const char *str, size_t len); + void Append(const value_type *str, size_type len); - char *mData; // pointer to the buffer - size_t mCapacity; // size of the buffer. - size_t mLength; // len of the string excl. null-terminator. + value_type *mData; // pointer to the buffer + size_type mCapacity; // size of the buffer. + size_type mLength; // len of the string excl. null-terminator. }; } // namespace std diff --git a/src/string.cpp b/src/string.cpp index b37e91f..cbe7892 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -64,14 +64,14 @@ namespace std { // @param num Number of bytes requested. String allocate num + 1 to hold // the terminating '\0'. // @return true if the buffer could be allocated, false otherwise. -bool string::SafeMalloc(size_t num) +bool string::SafeMalloc(size_type num) { // Not empty and no overflow if (num > 0 && num + 1 > num) { - char *oldData = mData; + value_type *oldData = mData; - mData = static_cast<char *>(::malloc(num + 1)); + mData = static_cast<value_type *>(::malloc(num + 1)); if (NULL != mData) { mCapacity = num; @@ -85,28 +85,36 @@ bool string::SafeMalloc(size_t num) // Resize the buffer pointed by mData if num >= mLength. // mData points to an allocated buffer or the empty string. // @param num The number of bytes for the internal buffer. -// Must be > mLength. -void string::SafeRealloc(size_t num) +// Must be > mLength and > 0. +void string::SafeRealloc(size_type num) { - // Different capacity, at least greater than mLength and no - // overflow - if (num != mCapacity && num >= mLength && num + 1 > num) - { - char *oldData = mData; + // truncation or nothing to do or num too big (overflow) + if (num < mLength || num == mCapacity || num + 1 < num) { + return; + } - if (SafeMalloc(num)) - { - if (mLength > 0) - { - memcpy(mData, oldData, mLength + 1); - } - mData[mLength] = '\0'; - SafeFree(oldData); + if (kEmptyString == mData) + { + if (SafeMalloc(num)) { + *mData = '\0'; } + return; + } + + value_type *oldData = mData; + + mData = static_cast<char*>(::realloc(mData, num + 1)); + if (NULL == mData) // realloc failed. + { + mData = oldData; + } + else + { + mCapacity = num; } } -void string::SafeFree(char *buffer) +void string::SafeFree(value_type *buffer) { if (buffer != kEmptyString) { @@ -116,7 +124,7 @@ void string::SafeFree(char *buffer) // If the memory is on the heap, release it. Do nothing we we point at the empty // string. On return mData points to str. -void string::ResetTo(char *str) +void string::ResetTo(value_type *str) { SafeFree(mData); mData = str; @@ -129,13 +137,13 @@ void string::ConstructEmptyString() mCapacity = 0; } -void string::Constructor(const char *str, size_t num) +void string::Constructor(const value_type *str, size_type num) { Constructor(str, 0, num); } -void string::Constructor(const char *str, size_t pos, size_t num) +void string::Constructor(const value_type *str, size_type pos, size_type num) { // Enough data and no overflow @@ -149,7 +157,7 @@ void string::Constructor(const char *str, size_t pos, size_t num) ConstructEmptyString(); } -void string::Constructor(size_t num, char c) +void string::Constructor(size_type num, char c) { // Enough data and no overflow @@ -173,7 +181,7 @@ string::string(const string& str) Constructor(str.mData, str.mLength); } -string::string(const string& str, size_t idx, size_t num) +string::string(const string& str, size_type idx, size_type num) { if (idx < str.mLength && num <= (str.mLength - idx)) { @@ -185,7 +193,7 @@ string::string(const string& str, size_t idx, size_t num) } } -string::string(const string& str, size_t idx) +string::string(const string& str, size_type idx) { if (idx < str.mLength) { @@ -197,7 +205,7 @@ string::string(const string& str, size_t idx) } } -string::string(const char *str) +string::string(const value_type *str) { if (NULL != str) { @@ -209,18 +217,18 @@ string::string(const char *str) } } -string::string(const char *str, size_t num) +string::string(const value_type *str, size_type num) { Constructor(str, num); } // Char repeat constructor. -string::string(size_t num, char c) +string::string(size_type num, char c) { Constructor(num, c); } -string::string(const char *begin, const char *end) +string::string(const value_type *begin, const value_type *end) { if (begin < end) { @@ -244,9 +252,9 @@ void string::clear() ResetTo(kEmptyString); } -void string::Append(const char *str, size_t len) +void string::Append(const value_type *str, size_type len) { - const size_t total_len = mLength + len; + const size_type total_len = mLength + len; // len > 0 and no overflow for the string length + terminating nul. if (len > 0 && (total_len + 1) > mLength) @@ -265,7 +273,7 @@ void string::Append(const char *str, size_t len) } } -string& string::append(const char *str) +string& string::append(const value_type *str) { if (NULL != str) { @@ -274,7 +282,7 @@ string& string::append(const char *str) return *this; } -string& string::append(const char *str, size_t len) +string& string::append(const value_type *str, size_type len) { if (NULL != str) { @@ -283,7 +291,7 @@ string& string::append(const char *str, size_t len) return *this; } -string& string::append(const char *str, size_t idx, size_t len) +string& string::append(const value_type *str, size_type idx, size_type len) { if (NULL != str) { @@ -303,7 +311,7 @@ void string::push_back(const char c) // Check we don't overflow. if (mLength + 2 > mLength) { - const size_t total_len = mLength + 1; + const size_type total_len = mLength + 1; if (total_len > mCapacity) { @@ -336,7 +344,7 @@ int string::compare(const string& other) const } } -int string::compare(const char *other) const +int string::compare(const value_type *other) const { if (NULL == other) { @@ -359,7 +367,7 @@ bool operator==(const string& left, const string& right) } } -bool operator==(const string& left, const char *right) +bool operator==(const string& left, const string::value_type *right) { if (NULL == right) { @@ -370,7 +378,7 @@ bool operator==(const string& left, const char *right) return std::strcmp(left.mData, right) == 0; } -void string::reserve(size_t size) +void string::reserve(size_type size) { if (0 == size) { @@ -388,7 +396,6 @@ void string::reserve(size_t size) SafeRealloc(mLength); } } - // There is no overflow. else if (size > mLength) { SafeRealloc(size); @@ -398,9 +405,9 @@ void string::reserve(size_t size) void string::swap(string& other) { if (this == &other) return; - char *const tmp_mData = mData; - const size_t tmp_mCapacity = mCapacity; - const size_t tmp_mLength = mLength; + value_type *const tmp_mData = mData; + const size_type tmp_mCapacity = mCapacity; + const size_type tmp_mLength = mLength; mData = other.mData; mCapacity = other.mCapacity; @@ -411,12 +418,12 @@ void string::swap(string& other) other.mLength = tmp_mLength; } -const char& string::operator[](const size_t idx) const +const char& string::operator[](const size_type idx) const { return mData[idx]; } -char& string::operator[](const size_t idx) +char& string::operator[](const size_type idx) { return mData[idx]; } @@ -428,7 +435,7 @@ string& string::assign(const string& str) return *this; } -string& string::assign(const string& str, size_t pos, size_t len) +string& string::assign(const string& str, size_type pos, size_type len) { if (pos >= str.mLength) { // pos is out of bound @@ -442,7 +449,7 @@ string& string::assign(const string& str, size_t pos, size_t len) return *this; } -string& string::assign(const char *str) +string& string::assign(const value_type *str) { if (NULL == str) { @@ -453,7 +460,7 @@ string& string::assign(const char *str) return *this; } -string& string::assign(const char *array, size_t len) +string& string::assign(const value_type *array, size_type len) { if (NULL == array || 0 == len) { @@ -471,7 +478,7 @@ string& string::operator=(char c) return *this; } -string::size_type string::find(const char *str, size_type pos) const +string::size_type string::find(const value_type *str, size_type pos) const { if (NULL == str) @@ -492,7 +499,7 @@ string::size_type string::find(const char *str, size_type pos) const return string::npos; } - char *idx = std::strstr(mData + pos, str); + value_type *idx = std::strstr(mData + pos, str); if (NULL == idx) { diff --git a/tests/test_string.cpp b/tests/test_string.cpp index b98e9b0..cebb040 100644 --- a/tests/test_string.cpp +++ b/tests/test_string.cpp @@ -162,7 +162,12 @@ bool testConstructorRepeatChar() { string str03(i, 'x'); + EXPECT_TRUE(str03[i] == '\0'); + EXPECT_TRUE(str03.length() == i); + str03.reserve(i + 20); + EXPECT_TRUE(str03.capacity() == i + 20); + EXPECT_TRUE(str03.length() == i); EXPECT_TRUE(str03[i] == '\0'); } |