Modified Common::Str to use exponential growth for its storage; also changed the meaning of 'capacity' from 'max length of string' to 'size of storage' (i.e. added one)
svn-id: r34313
This commit is contained in:
parent
e1918341af
commit
c3d7c908e8
1 changed files with 10 additions and 11 deletions
|
@ -34,13 +34,12 @@ const String String::emptyString;
|
||||||
const char *String::emptyString = "";
|
const char *String::emptyString = "";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int computeCapacity(int len) {
|
static uint32 computeCapacity(uint32 len) {
|
||||||
// By default, for the capacity we use the nearest multiple of 32
|
// By default, for the capacity we use the nearest multiple of 32
|
||||||
// that leaves at least 16 chars of extra space (in case the string
|
// that leaves at least 16 chars of extra space (in case the string
|
||||||
// grows a bit).
|
// grows a bit).
|
||||||
// Finally, we subtract 1 to compensate for the trailing zero byte.
|
|
||||||
len += 16;
|
len += 16;
|
||||||
return ((len + 32 - 1) & ~0x1F) - 1;
|
return ((len + 32 - 1) & ~0x1F);
|
||||||
}
|
}
|
||||||
|
|
||||||
String::String(const char *str) : _size(0), _str(_storage) {
|
String::String(const char *str) : _size(0), _str(_storage) {
|
||||||
|
@ -73,7 +72,7 @@ void String::initWithCStr(const char *str, uint32 len) {
|
||||||
// Not enough internal storage, so allocate more
|
// Not enough internal storage, so allocate more
|
||||||
_extern._capacity = computeCapacity(len);
|
_extern._capacity = computeCapacity(len);
|
||||||
_extern._refCount = 0;
|
_extern._refCount = 0;
|
||||||
_str = (char *)malloc(_extern._capacity+1);
|
_str = (char *)malloc(_extern._capacity);
|
||||||
assert(_str != 0);
|
assert(_str != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +85,7 @@ String::String(const String &str)
|
||||||
: _size(str._size), _str(str.isStorageIntern() ? _storage : str._str) {
|
: _size(str._size), _str(str.isStorageIntern() ? _storage : str._str) {
|
||||||
if (str.isStorageIntern()) {
|
if (str.isStorageIntern()) {
|
||||||
// String in internal storage: just copy it
|
// String in internal storage: just copy it
|
||||||
memcpy(_storage, str._storage, _builtinCapacity);
|
memcpy(_storage, str._storage, sizeof(_storage));
|
||||||
} else {
|
} else {
|
||||||
// String in external storage: use refcount mechanism
|
// String in external storage: use refcount mechanism
|
||||||
str.incRefCount();
|
str.incRefCount();
|
||||||
|
@ -129,7 +128,7 @@ void String::ensureCapacity(uint32 new_size, bool keep_old) {
|
||||||
|
|
||||||
if (isStorageIntern()) {
|
if (isStorageIntern()) {
|
||||||
isShared = false;
|
isShared = false;
|
||||||
curCapacity = _builtinCapacity - 1;
|
curCapacity = _builtinCapacity;
|
||||||
} else {
|
} else {
|
||||||
isShared = (oldRefCount && *oldRefCount > 1);
|
isShared = (oldRefCount && *oldRefCount > 1);
|
||||||
curCapacity = _extern._capacity;
|
curCapacity = _extern._capacity;
|
||||||
|
@ -140,24 +139,24 @@ void String::ensureCapacity(uint32 new_size, bool keep_old) {
|
||||||
if (!isShared && new_size <= curCapacity)
|
if (!isShared && new_size <= curCapacity)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (isShared && new_size <= _builtinCapacity - 1) {
|
if (isShared && new_size < _builtinCapacity) {
|
||||||
// We share the storage, but there is enough internal storage: Use that.
|
// We share the storage, but there is enough internal storage: Use that.
|
||||||
newStorage = _storage;
|
newStorage = _storage;
|
||||||
newCapacity = _builtinCapacity - 1;
|
newCapacity = _builtinCapacity;
|
||||||
} else {
|
} else {
|
||||||
// We need to allocate storage on the heap!
|
// We need to allocate storage on the heap!
|
||||||
|
|
||||||
// Compute a suitable new capacity limit
|
// Compute a suitable new capacity limit
|
||||||
newCapacity = computeCapacity(new_size);
|
newCapacity = MAX(curCapacity * 2, computeCapacity(new_size));
|
||||||
|
|
||||||
// Allocate new storage
|
// Allocate new storage
|
||||||
newStorage = (char *)malloc(newCapacity+1);
|
newStorage = (char *)malloc(newCapacity);
|
||||||
assert(newStorage);
|
assert(newStorage);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy old data if needed, elsewise reset the new storage.
|
// Copy old data if needed, elsewise reset the new storage.
|
||||||
if (keep_old) {
|
if (keep_old) {
|
||||||
assert(_size <= newCapacity);
|
assert(_size < newCapacity);
|
||||||
memcpy(newStorage, _str, _size + 1);
|
memcpy(newStorage, _str, _size + 1);
|
||||||
} else {
|
} else {
|
||||||
_size = 0;
|
_size = 0;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue