aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Catania <niko@google.com>2009-05-17 22:10:48 -0700
committerNicolas Catania <niko@google.com>2009-05-18 16:03:36 -0700
commit7618d7b9a011b1158ef868d6ae3ead242ddaccac (patch)
treea5d346eff47191bf86ba865c4212e812022d5d05
parentd738d268c8f915bde451bba52e0c3996113ba9f0 (diff)
downloadastl-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/string79
-rw-r--r--src/string.cpp105
-rw-r--r--tests/test_string.cpp5
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');
}