From 705c92ddc33b050fd982aab728ef3eb7303e0af3 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 22 Jul 2008 14:39:26 +0000 Subject: Added String::trim() method svn-id: r33203 --- common/str.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'common/str.cpp') diff --git a/common/str.cpp b/common/str.cpp index a2e6e0c66d..f7cb84aa05 100644 --- a/common/str.cpp +++ b/common/str.cpp @@ -363,6 +363,26 @@ void String::ensureCapacity(uint32 new_len, bool keep_old) { } } +void String::trim() { + if (_len == 0) + return; + + // Trim trailing whitespace + while (_len >= 1 && isspace(_str[_len-1])) + _len--; + _str[_len] = 0; + + // Trim leading whitespace + char *t = _str; + while (isspace(*t)) + t++; + + if (t != _str) { + _len -= t - _str; + memmove(_str, t, _len + 1); + } +} + uint String::hash() const { return hashit(c_str()); } -- cgit v1.2.3 From d5e2c6d4bf32d066948df8a8a2bd4730e473a1cc Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 23 Jul 2008 09:53:29 +0000 Subject: Fix String::trim to work right for shared strings; augemented test cases to cover this svn-id: r33234 --- common/str.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'common/str.cpp') diff --git a/common/str.cpp b/common/str.cpp index f7cb84aa05..1b857546a8 100644 --- a/common/str.cpp +++ b/common/str.cpp @@ -288,12 +288,14 @@ void String::insertChar(char c, uint32 p) { } void String::toLowercase() { + // Ensure that the string is not shared ensureCapacity(_len, true); for (uint32 i = 0; i < _len; ++i) _str[i] = tolower(_str[i]); } void String::toUppercase() { + // Ensure that the string is not shared ensureCapacity(_len, true); for (uint32 i = 0; i < _len; ++i) _str[i] = toupper(_str[i]); @@ -367,6 +369,9 @@ void String::trim() { if (_len == 0) return; + // Ensure that the string is not shared + ensureCapacity(_len, true); + // Trim trailing whitespace while (_len >= 1 && isspace(_str[_len-1])) _len--; -- cgit v1.2.3 From 15c610a069c4f86f921791584fa0248a9e26b9c2 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 23 Jul 2008 16:33:53 +0000 Subject: Added convenience method String::makeUnique(); simplified String::operator=(char c); extended String unit tests svn-id: r33246 --- common/str.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'common/str.cpp') diff --git a/common/str.cpp b/common/str.cpp index 1b857546a8..14ba5ec530 100644 --- a/common/str.cpp +++ b/common/str.cpp @@ -170,7 +170,8 @@ String &String::operator =(const String &str) { } String& String::operator =(char c) { - ensureCapacity(1, false); + decRefCount(_extern._refCount); + _str = _storage; _len = 1; _str[0] = c; _str[1] = 0; @@ -256,7 +257,7 @@ void String::deleteChar(uint32 p) { // Call ensureCapacity to make sure we actually *own* the storage // to which _str points to -- we wouldn't want to modify a storage // which other string objects are sharing, after all. - ensureCapacity(_len, true); + makeUnique(); while (p++ < _len) _str[p-1] = _str[p]; _len--; @@ -273,7 +274,7 @@ void String::clear() { void String::setChar(char c, uint32 p) { assert(p <= _len); - ensureCapacity(_len, true); + makeUnique(); _str[p] = c; } @@ -289,18 +290,22 @@ void String::insertChar(char c, uint32 p) { void String::toLowercase() { // Ensure that the string is not shared - ensureCapacity(_len, true); + makeUnique(); for (uint32 i = 0; i < _len; ++i) _str[i] = tolower(_str[i]); } void String::toUppercase() { // Ensure that the string is not shared - ensureCapacity(_len, true); + makeUnique(); for (uint32 i = 0; i < _len; ++i) _str[i] = toupper(_str[i]); } +void String::makeUnique() { + ensureCapacity(_len, true); +} + /** * Ensure that enough storage is available to store at least new_len * characters plus a null byte. In addition, if we currently share @@ -370,7 +375,7 @@ void String::trim() { return; // Ensure that the string is not shared - ensureCapacity(_len, true); + makeUnique(); // Trim trailing whitespace while (_len >= 1 && isspace(_str[_len-1])) -- cgit v1.2.3 From 918e0fe4738ce3de0c069ec0fd423ae0daa524f0 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 23 Jul 2008 16:49:45 +0000 Subject: Reorder stuff a little bit, moving private String methods together: cleanup svn-id: r33248 --- common/str.cpp | 142 +++++++++++++++++++++++++++------------------------------ 1 file changed, 68 insertions(+), 74 deletions(-) (limited to 'common/str.cpp') diff --git a/common/str.cpp b/common/str.cpp index 14ba5ec530..5f8d4ffb7e 100644 --- a/common/str.cpp +++ b/common/str.cpp @@ -111,6 +111,74 @@ String::~String() { decRefCount(_extern._refCount); } +void String::makeUnique() { + ensureCapacity(_len, true); +} + +/** + * Ensure that enough storage is available to store at least new_len + * characters plus a null byte. In addition, if we currently share + * the storage with another string, unshare it, so that we can safely + * write to the storage. + */ +void String::ensureCapacity(uint32 new_len, bool keep_old) { + bool isShared; + uint32 curCapacity, newCapacity; + char *newStorage; + int *oldRefCount = _extern._refCount; + + if (isStorageIntern()) { + isShared = false; + curCapacity = _builtinCapacity - 1; + } else { + isShared = (oldRefCount && *oldRefCount > 1); + curCapacity = _extern._capacity; + } + + // Special case: If there is enough space, and we do not share + // the storage, then there is nothing to do. + if (!isShared && new_len <= curCapacity) + return; + + if (isShared && new_len <= _builtinCapacity - 1) { + // We share the storage, but there is enough internal storage: Use that. + newStorage = _storage; + newCapacity = _builtinCapacity - 1; + } else { + // We need to allocate storage on the heap! + + // Compute a suitable new capacity limit + newCapacity = computeCapacity(new_len); + + // Allocate new storage + newStorage = (char *)malloc(newCapacity+1); + assert(newStorage); + } + + // Copy old data if needed, elsewise reset the new storage. + if (keep_old) { + assert(_len <= newCapacity); + memcpy(newStorage, _str, _len + 1); + } else { + _len = 0; + newStorage[0] = 0; + } + + // Release hold on the old storage ... + decRefCount(oldRefCount); + + // ... in favor of the new storage + _str = newStorage; + + if (!isStorageIntern()) { + // Set the ref count & capacity if we use an external storage. + // It is important to do this *after* copying any old content, + // else we would override data that has not yet been copied! + _extern._refCount = 0; + _extern._capacity = newCapacity; + } +} + void String::incRefCount() const { assert(!isStorageIntern()); if (_extern._refCount == 0) { @@ -254,9 +322,6 @@ void String::deleteLastChar() { void String::deleteChar(uint32 p) { assert(p < _len); - // Call ensureCapacity to make sure we actually *own* the storage - // to which _str points to -- we wouldn't want to modify a storage - // which other string objects are sharing, after all. makeUnique(); while (p++ < _len) _str[p-1] = _str[p]; @@ -289,92 +354,21 @@ void String::insertChar(char c, uint32 p) { } void String::toLowercase() { - // Ensure that the string is not shared makeUnique(); for (uint32 i = 0; i < _len; ++i) _str[i] = tolower(_str[i]); } void String::toUppercase() { - // Ensure that the string is not shared makeUnique(); for (uint32 i = 0; i < _len; ++i) _str[i] = toupper(_str[i]); } -void String::makeUnique() { - ensureCapacity(_len, true); -} - -/** - * Ensure that enough storage is available to store at least new_len - * characters plus a null byte. In addition, if we currently share - * the storage with another string, unshare it, so that we can safely - * write to the storage. - */ -void String::ensureCapacity(uint32 new_len, bool keep_old) { - bool isShared; - uint32 curCapacity, newCapacity; - char *newStorage; - int *oldRefCount = _extern._refCount; - - if (isStorageIntern()) { - isShared = false; - curCapacity = _builtinCapacity - 1; - } else { - isShared = (oldRefCount && *oldRefCount > 1); - curCapacity = _extern._capacity; - } - - // Special case: If there is enough space, and we do not share - // the storage, then there is nothing to do. - if (!isShared && new_len <= curCapacity) - return; - - if (isShared && new_len <= _builtinCapacity - 1) { - // We share the storage, but there is enough internal storage: Use that. - newStorage = _storage; - newCapacity = _builtinCapacity - 1; - } else { - // We need to allocate storage on the heap! - - // Compute a suitable new capacity limit - newCapacity = computeCapacity(new_len); - - // Allocate new storage - newStorage = (char *)malloc(newCapacity+1); - assert(newStorage); - } - - // Copy old data if needed, elsewise reset the new storage. - if (keep_old) { - assert(_len <= newCapacity); - memcpy(newStorage, _str, _len + 1); - } else { - _len = 0; - newStorage[0] = 0; - } - - // Release hold on the old storage ... - decRefCount(oldRefCount); - - // ... in favor of the new storage - _str = newStorage; - - if (!isStorageIntern()) { - // Set the ref count & capacity if we use an external storage. - // It is important to do this *after* copying any old content, - // else we would override data that has not yet been copied! - _extern._refCount = 0; - _extern._capacity = newCapacity; - } -} - void String::trim() { if (_len == 0) return; - // Ensure that the string is not shared makeUnique(); // Trim trailing whitespace -- cgit v1.2.3