Unified member names in container/storage classes Array, HashMap and String: _storage, _size, _capacity

svn-id: r34052
This commit is contained in:
Max Horn 2008-08-20 11:07:16 +00:00
parent 47429f2197
commit a79e9385a1
5 changed files with 195 additions and 196 deletions

View file

@ -35,7 +35,7 @@ class Array {
protected:
uint _capacity;
uint _size;
T *_data;
T *_storage;
public:
typedef T *iterator;
@ -44,41 +44,41 @@ public:
typedef T value_type;
public:
Array() : _capacity(0), _size(0), _data(0) {}
Array(const Array<T> &array) : _capacity(0), _size(0), _data(0) {
Array() : _capacity(0), _size(0), _storage(0) {}
Array(const Array<T> &array) : _capacity(0), _size(0), _storage(0) {
_size = array._size;
_capacity = _size + 32;
_data = new T[_capacity];
copy(array._data, array._data + _size, _data);
_storage = new T[_capacity];
copy(array._storage, array._storage + _size, _storage);
}
~Array() {
delete[] _data;
delete[] _storage;
}
void push_back(const T &element) {
ensureCapacity(_size + 1);
_data[_size++] = element;
_storage[_size++] = element;
}
void push_back(const Array<T> &array) {
ensureCapacity(_size + array._size);
copy(array._data, array._data + array._size, _data + _size);
copy(array._storage, array._storage + array._size, _storage + _size);
_size += array._size;
}
void insert_at(int idx, const T &element) {
assert(idx >= 0 && (uint)idx <= _size);
ensureCapacity(_size + 1);
copy_backward(_data + idx, _data + _size, _data + _size + 1);
_data[idx] = element;
copy_backward(_storage + idx, _storage + _size, _storage + _size + 1);
_storage[idx] = element;
_size++;
}
T remove_at(int idx) {
assert(idx >= 0 && (uint)idx < _size);
T tmp = _data[idx];
copy(_data + idx + 1, _data + _size, _data + idx);
T tmp = _storage[idx];
copy(_storage + idx + 1, _storage + _size, _storage + idx);
_size--;
return tmp;
}
@ -87,23 +87,23 @@ public:
T& operator[](int idx) {
assert(idx >= 0 && (uint)idx < _size);
return _data[idx];
return _storage[idx];
}
const T& operator[](int idx) const {
assert(idx >= 0 && (uint)idx < _size);
return _data[idx];
return _storage[idx];
}
Array<T>& operator=(const Array<T> &array) {
if (this == &array)
return *this;
delete[] _data;
delete[] _storage;
_size = array._size;
_capacity = _size + 32;
_data = new T[_capacity];
copy(array._data, array._data + _size, _data);
_storage = new T[_capacity];
copy(array._storage, array._storage + _size, _storage);
return *this;
}
@ -113,8 +113,8 @@ public:
}
void clear() {
delete[] _data;
_data = 0;
delete[] _storage;
_storage = 0;
_size = 0;
_capacity = 0;
}
@ -125,33 +125,33 @@ public:
iterator begin() {
return _data;
return _storage;
}
iterator end() {
return _data + _size;
return _storage + _size;
}
const_iterator begin() const {
return _data;
return _storage;
}
const_iterator end() const {
return _data + _size;
return _storage + _size;
}
void reserve(uint newCapacity) {
if (newCapacity <= _capacity)
return;
T *old_data = _data;
T *old_storage = _storage;
_capacity = newCapacity;
_data = new T[newCapacity];
_storage = new T[newCapacity];
if (old_data) {
if (old_storage) {
// Copy old data
copy(old_data, old_data + _size, _data);
delete[] old_data;
copy(old_storage, old_storage + _size, _storage);
delete[] old_storage;
}
}
@ -159,14 +159,14 @@ public:
if (newSize == _size)
return;
T *old_data = _data;
T *old_storage = _storage;
_capacity = newSize;
_data = new T[newSize];
if (old_data) {
_storage = new T[newSize];
if (old_storage) {
// Copy old data
int cnt = (_size < newSize ? _size : newSize);
copy(old_data, old_data + cnt, _data);
delete[] old_data;
copy(old_storage, old_storage + cnt, _storage);
delete[] old_storage;
}
_size = newSize;
}

View file

@ -94,9 +94,9 @@ static double
g_collisions = 0,
g_lookups = 0,
g_collPerLook = 0,
g_arrsize = 0,
g_nele = 0;
static int g_max_arrsize = 0, g_max_nele = 0;
g_capacity = 0,
g_size = 0;
static int g_max_capacity = 0, g_max_size = 0;
static int g_totalHashmaps = 0;
void updateHashCollisionStats(int collisions, int lookups, int arrsize, int nele) {
@ -104,20 +104,20 @@ void updateHashCollisionStats(int collisions, int lookups, int arrsize, int nele
g_lookups += lookups;
if (lookups)
g_collPerLook += (double)collisions / (double)lookups;
g_arrsize += arrsize;
g_nele += nele;
g_capacity += arrsize;
g_size += nele;
g_totalHashmaps++;
g_max_arrsize = MAX(g_max_arrsize, arrsize);
g_max_nele = MAX(g_max_nele, nele);
g_max_capacity = MAX(g_max_capacity, arrsize);
g_max_size = MAX(g_max_size, nele);
fprintf(stdout, "%d hashmaps: colls %.1f; lookups %.1f; ratio %.3f%%; size %f (max: %d); capacity %f (max: %d)\n",
g_totalHashmaps,
g_collisions / g_totalHashmaps,
g_lookups / g_totalHashmaps,
100 * g_collPerLook / g_totalHashmaps,
g_nele / g_totalHashmaps, g_max_nele,
g_arrsize / g_totalHashmaps, g_max_arrsize);
g_size / g_totalHashmaps, g_max_size,
g_capacity / g_totalHashmaps, g_max_capacity);
}
#endif

View file

@ -136,8 +136,9 @@ public:
}
#endif
Node **_arr; // hashtable of size arrsize.
uint _arrsize, _nele;
Node **_storage; // hashtable of size arrsize.
uint _capacity;
uint _size;
HashFunc _hash;
EqualFunc _equal;
@ -174,8 +175,8 @@ public:
NodeType *deref() const {
assert(_hashmap != 0);
assert(_idx < _hashmap->_arrsize);
Node *node = _hashmap->_arr[_idx];
assert(_idx < _hashmap->_capacity);
Node *node = _hashmap->_storage[_idx];
assert(node != 0);
return node;
}
@ -195,8 +196,8 @@ public:
assert(_hashmap);
do {
_idx++;
} while (_idx < _hashmap->_arrsize && _hashmap->_arr[_idx] == 0);
if (_idx >= _hashmap->_arrsize)
} while (_idx < _hashmap->_capacity && _hashmap->_storage[_idx] == 0);
if (_idx >= _hashmap->_capacity)
_idx = (uint)-1;
return *this;
@ -223,7 +224,7 @@ public:
// Remove the previous content and ...
clear();
delete[] _arr;
delete[] _storage;
// ... copy the new stuff.
assign(map);
return *this;
@ -242,12 +243,12 @@ public:
void erase(const Key &key);
uint size() const { return _nele; }
uint size() const { return _size; }
iterator begin() {
// Find and return the _key non-empty entry
for (uint ctr = 0; ctr < _arrsize; ++ctr) {
if (_arr[ctr])
for (uint ctr = 0; ctr < _capacity; ++ctr) {
if (_storage[ctr])
return iterator(ctr, this);
}
return end();
@ -258,8 +259,8 @@ public:
const_iterator begin() const {
// Find and return the first non-empty entry
for (uint ctr = 0; ctr < _arrsize; ++ctr) {
if (_arr[ctr])
for (uint ctr = 0; ctr < _capacity; ++ctr) {
if (_storage[ctr])
return const_iterator(ctr, this);
}
return end();
@ -270,14 +271,14 @@ public:
iterator find(const Key &key) {
uint ctr = lookup(key);
if (_arr[ctr])
if (_storage[ctr])
return iterator(ctr, this);
return end();
}
const_iterator find(const Key &key) const {
uint ctr = lookup(key);
if (_arr[ctr])
if (_storage[ctr])
return const_iterator(ctr, this);
return end();
}
@ -285,7 +286,7 @@ public:
// TODO: insert() method?
bool empty() const {
return (_nele == 0);
return (_size == 0);
}
};
@ -301,12 +302,12 @@ HashMap<Key, Val, HashFunc, EqualFunc>::HashMap() :
_nodePool(sizeof(Node)),
#endif
_defaultVal() {
_arrsize = nextTableSize(0);
_arr = new Node *[_arrsize];
assert(_arr != NULL);
memset(_arr, 0, _arrsize * sizeof(Node *));
_capacity = nextTableSize(0);
_storage = new Node *[_capacity];
assert(_storage != NULL);
memset(_storage, 0, _capacity * sizeof(Node *));
_nele = 0;
_size = 0;
#ifdef DEBUG_HASH_COLLISIONS
_collisions = 0;
@ -333,14 +334,14 @@ HashMap<Key, Val, HashFunc, EqualFunc>::HashMap(const HM_t &map) :
*/
template<class Key, class Val, class HashFunc, class EqualFunc>
HashMap<Key, Val, HashFunc, EqualFunc>::~HashMap() {
for (uint ctr = 0; ctr < _arrsize; ++ctr)
if (_arr[ctr] != NULL)
freeNode(_arr[ctr]);
for (uint ctr = 0; ctr < _capacity; ++ctr)
if (_storage[ctr] != NULL)
freeNode(_storage[ctr]);
delete[] _arr;
delete[] _storage;
#ifdef DEBUG_HASH_COLLISIONS
extern void updateHashCollisionStats(int, int, int, int);
updateHashCollisionStats(_collisions, _lookups, _arrsize, _nele);
updateHashCollisionStats(_collisions, _lookups, _capacity, _size);
#endif
}
@ -353,95 +354,95 @@ HashMap<Key, Val, HashFunc, EqualFunc>::~HashMap() {
*/
template<class Key, class Val, class HashFunc, class EqualFunc>
void HashMap<Key, Val, HashFunc, EqualFunc>::assign(const HM_t &map) {
_arrsize = map._arrsize;
_arr = new Node *[_arrsize];
assert(_arr != NULL);
memset(_arr, 0, _arrsize * sizeof(Node *));
_capacity = map._capacity;
_storage = new Node *[_capacity];
assert(_storage != NULL);
memset(_storage, 0, _capacity * sizeof(Node *));
// Simply clone the map given to us, one by one.
_nele = 0;
for (uint ctr = 0; ctr < _arrsize; ++ctr) {
if (map._arr[ctr] != NULL) {
_arr[ctr] = allocNode(map._arr[ctr]->_key);
_arr[ctr]->_value = map._arr[ctr]->_value;
_nele++;
_size = 0;
for (uint ctr = 0; ctr < _capacity; ++ctr) {
if (map._storage[ctr] != NULL) {
_storage[ctr] = allocNode(map._storage[ctr]->_key);
_storage[ctr]->_value = map._storage[ctr]->_value;
_size++;
}
}
// Perform a sanity check (to help track down hashmap corruption)
assert(_nele == map._nele);
assert(_size == map._size);
}
template<class Key, class Val, class HashFunc, class EqualFunc>
void HashMap<Key, Val, HashFunc, EqualFunc>::clear(bool shrinkArray) {
for (uint ctr = 0; ctr < _arrsize; ++ctr) {
if (_arr[ctr] != NULL) {
freeNode(_arr[ctr]);
_arr[ctr] = NULL;
for (uint ctr = 0; ctr < _capacity; ++ctr) {
if (_storage[ctr] != NULL) {
freeNode(_storage[ctr]);
_storage[ctr] = NULL;
}
}
if (shrinkArray && _arrsize > nextTableSize(0)) {
delete[] _arr;
if (shrinkArray && _capacity > nextTableSize(0)) {
delete[] _storage;
_arrsize = nextTableSize(0);
_arr = new Node *[_arrsize];
assert(_arr != NULL);
memset(_arr, 0, _arrsize * sizeof(Node *));
_capacity = nextTableSize(0);
_storage = new Node *[_capacity];
assert(_storage != NULL);
memset(_storage, 0, _capacity * sizeof(Node *));
}
_nele = 0;
_size = 0;
}
template<class Key, class Val, class HashFunc, class EqualFunc>
void HashMap<Key, Val, HashFunc, EqualFunc>::expand_array(uint newsize) {
assert(newsize > _arrsize);
assert(newsize > _capacity);
uint ctr, dex;
const uint old_nele = _nele;
const uint old_arrsize = _arrsize;
Node **old_arr = _arr;
const uint old_size = _size;
const uint old_capacity = _capacity;
Node **old_storage = _storage;
// allocate a new array
_nele = 0;
_arrsize = newsize;
_arr = new Node *[_arrsize];
assert(_arr != NULL);
memset(_arr, 0, _arrsize * sizeof(Node *));
_size = 0;
_capacity = newsize;
_storage = new Node *[_capacity];
assert(_storage != NULL);
memset(_storage, 0, _capacity * sizeof(Node *));
// rehash all the old elements
for (ctr = 0; ctr < old_arrsize; ++ctr) {
if (old_arr[ctr] == NULL)
for (ctr = 0; ctr < old_capacity; ++ctr) {
if (old_storage[ctr] == NULL)
continue;
// Insert the element from the old table into the new table.
// Since we know that no key exists twice in the old table, we
// can do this slightly better than by calling lookup, since we
// don't have to call _equal().
dex = _hash(old_arr[ctr]->_key) % _arrsize;
while (_arr[dex] != NULL) {
dex = (dex + 1) % _arrsize;
dex = _hash(old_storage[ctr]->_key) % _capacity;
while (_storage[dex] != NULL) {
dex = (dex + 1) % _capacity;
}
_arr[dex] = old_arr[ctr];
_nele++;
_storage[dex] = old_storage[ctr];
_size++;
}
// Perform a sanity check: Old number of elements should match the new one!
// This check will fail if some previous operation corrupted this hashmap.
assert(_nele == old_nele);
assert(_size == old_size);
delete[] old_arr;
delete[] old_storage;
return;
}
template<class Key, class Val, class HashFunc, class EqualFunc>
int HashMap<Key, Val, HashFunc, EqualFunc>::lookup(const Key &key) const {
uint ctr = _hash(key) % _arrsize;
uint ctr = _hash(key) % _capacity;
while (_arr[ctr] != NULL && !_equal(_arr[ctr]->_key, key)) {
ctr = (ctr + 1) % _arrsize;
while (_storage[ctr] != NULL && !_equal(_storage[ctr]->_key, key)) {
ctr = (ctr + 1) % _capacity;
#ifdef DEBUG_HASH_COLLISIONS
_collisions++;
@ -452,7 +453,7 @@ int HashMap<Key, Val, HashFunc, EqualFunc>::lookup(const Key &key) const {
_lookups++;
fprintf(stderr, "collisions %d, lookups %d, ratio %f in HashMap %p; size %d num elements %d\n",
_collisions, _lookups, ((double) _collisions / (double)_lookups),
(const void *)this, _arrsize, _nele);
(const void *)this, _capacity, _size);
#endif
return ctr;
@ -462,13 +463,13 @@ template<class Key, class Val, class HashFunc, class EqualFunc>
int HashMap<Key, Val, HashFunc, EqualFunc>::lookupAndCreateIfMissing(const Key &key) {
uint ctr = lookup(key);
if (_arr[ctr] == NULL) {
_arr[ctr] = allocNode(key);
_nele++;
if (_storage[ctr] == NULL) {
_storage[ctr] = allocNode(key);
_size++;
// Keep the load factor below 75%.
if (_nele > _arrsize * 75 / 100) {
expand_array(nextTableSize(_arrsize));
if (_size > _capacity * 75 / 100) {
expand_array(nextTableSize(_capacity));
ctr = lookup(key);
}
}
@ -480,7 +481,7 @@ int HashMap<Key, Val, HashFunc, EqualFunc>::lookupAndCreateIfMissing(const Key &
template<class Key, class Val, class HashFunc, class EqualFunc>
bool HashMap<Key, Val, HashFunc, EqualFunc>::contains(const Key &key) const {
uint ctr = lookup(key);
return (_arr[ctr] != NULL);
return (_storage[ctr] != NULL);
}
template<class Key, class Val, class HashFunc, class EqualFunc>
@ -496,15 +497,15 @@ const Val &HashMap<Key, Val, HashFunc, EqualFunc>::operator[](const Key &key) co
template<class Key, class Val, class HashFunc, class EqualFunc>
Val &HashMap<Key, Val, HashFunc, EqualFunc>::getVal(const Key &key) {
uint ctr = lookupAndCreateIfMissing(key);
assert(_arr[ctr] != NULL);
return _arr[ctr]->_value;
assert(_storage[ctr] != NULL);
return _storage[ctr]->_value;
}
template<class Key, class Val, class HashFunc, class EqualFunc>
const Val &HashMap<Key, Val, HashFunc, EqualFunc>::getVal(const Key &key) const {
uint ctr = lookup(key);
if (_arr[ctr] != NULL)
return _arr[ctr]->_value;
if (_storage[ctr] != NULL)
return _storage[ctr]->_value;
else
return _defaultVal;
}
@ -512,38 +513,38 @@ const Val &HashMap<Key, Val, HashFunc, EqualFunc>::getVal(const Key &key) const
template<class Key, class Val, class HashFunc, class EqualFunc>
void HashMap<Key, Val, HashFunc, EqualFunc>::setVal(const Key &key, const Val &val) {
uint ctr = lookupAndCreateIfMissing(key);
assert(_arr[ctr] != NULL);
_arr[ctr]->_value = val;
assert(_storage[ctr] != NULL);
_storage[ctr]->_value = val;
}
template<class Key, class Val, class HashFunc, class EqualFunc>
void HashMap<Key, Val, HashFunc, EqualFunc>::erase(const Key &key) {
// This is based on code in the Wikipedia article on Hash tables.
uint i = lookup(key);
if (_arr[i] == NULL)
if (_storage[i] == NULL)
return; // key wasn't present, so no work has to be done
// If we remove a key, we must check all subsequent keys and possibly
// reinsert them.
uint j = i;
freeNode(_arr[i]);
_arr[i] = NULL;
freeNode(_storage[i]);
_storage[i] = NULL;
while (true) {
// Look at the next table slot
j = (j + 1) % _arrsize;
j = (j + 1) % _capacity;
// If the next slot is empty, we are done
if (_arr[j] == NULL)
if (_storage[j] == NULL)
break;
// Compute the slot where the content of the next slot should normally be,
// assuming an empty table, and check whether we have to move it.
uint k = _hash(_arr[j]->_key) % _arrsize;
uint k = _hash(_storage[j]->_key) % _capacity;
if ((j > i && (k <= i || k > j)) ||
(j < i && (k <= i && k > j)) ) {
_arr[i] = _arr[j];
_storage[i] = _storage[j];
i = j;
}
}
_arr[i] = NULL;
_nele--;
_storage[i] = NULL;
_size--;
return;
}

View file

@ -43,19 +43,19 @@ static int computeCapacity(int len) {
return ((len + 32 - 1) & ~0x1F) - 1;
}
String::String(const char *str) : _len(0), _str(_storage) {
String::String(const char *str) : _size(0), _str(_storage) {
if (str == 0) {
_storage[0] = 0;
_len = 0;
_size = 0;
} else
initWithCStr(str, strlen(str));
}
String::String(const char *str, uint32 len) : _len(0), _str(_storage) {
String::String(const char *str, uint32 len) : _size(0), _str(_storage) {
initWithCStr(str, len);
}
String::String(const char *beginP, const char *endP) : _len(0), _str(_storage) {
String::String(const char *beginP, const char *endP) : _size(0), _str(_storage) {
assert(endP >= beginP);
initWithCStr(beginP, endP - beginP);
}
@ -67,7 +67,7 @@ void String::initWithCStr(const char *str, uint32 len) {
// for GCC 2.95.x compatibility (see also tracker item #1602879).
_storage[0] = 0;
_len = len;
_size = len;
if (len >= _builtinCapacity) {
// Not enough internal storage, so allocate more
@ -83,7 +83,7 @@ void String::initWithCStr(const char *str, uint32 len) {
}
String::String(const String &str)
: _len(str._len), _str(str.isStorageIntern() ? _storage : str._str) {
: _size(str._size), _str(str.isStorageIntern() ? _storage : str._str) {
if (str.isStorageIntern()) {
// String in internal storage: just copy it
memcpy(_storage, str._storage, _builtinCapacity);
@ -97,14 +97,14 @@ String::String(const String &str)
}
String::String(char c)
: _len(0), _str(_storage) {
: _size(0), _str(_storage) {
_storage[0] = c;
_storage[1] = 0;
// TODO/FIXME: There is no reason for the following check -- we *do*
// allow strings to contain 0 bytes!
_len = (c == 0) ? 0 : 1;
_size = (c == 0) ? 0 : 1;
}
String::~String() {
@ -112,16 +112,16 @@ String::~String() {
}
void String::makeUnique() {
ensureCapacity(_len, true);
ensureCapacity(_size, true);
}
/**
* Ensure that enough storage is available to store at least new_len
* Ensure that enough storage is available to store at least new_size
* 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) {
void String::ensureCapacity(uint32 new_size, bool keep_old) {
bool isShared;
uint32 curCapacity, newCapacity;
char *newStorage;
@ -137,10 +137,10 @@ void String::ensureCapacity(uint32 new_len, bool keep_old) {
// 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)
if (!isShared && new_size <= curCapacity)
return;
if (isShared && new_len <= _builtinCapacity - 1) {
if (isShared && new_size <= _builtinCapacity - 1) {
// We share the storage, but there is enough internal storage: Use that.
newStorage = _storage;
newCapacity = _builtinCapacity - 1;
@ -148,7 +148,7 @@ void String::ensureCapacity(uint32 new_len, bool keep_old) {
// We need to allocate storage on the heap!
// Compute a suitable new capacity limit
newCapacity = computeCapacity(new_len);
newCapacity = computeCapacity(new_size);
// Allocate new storage
newStorage = (char *)malloc(newCapacity+1);
@ -157,10 +157,10 @@ void String::ensureCapacity(uint32 new_len, bool keep_old) {
// Copy old data if needed, elsewise reset the new storage.
if (keep_old) {
assert(_len <= newCapacity);
memcpy(newStorage, _str, _len + 1);
assert(_size <= newCapacity);
memcpy(newStorage, _str, _size + 1);
} else {
_len = 0;
_size = 0;
newStorage[0] = 0;
}
@ -210,7 +210,7 @@ void String::decRefCount(int *oldRefCount) {
String& String::operator =(const char *str) {
uint32 len = strlen(str);
ensureCapacity(len, false);
_len = len;
_size = len;
memmove(_str, str, len + 1);
return *this;
}
@ -221,16 +221,16 @@ String &String::operator =(const String &str) {
if (str.isStorageIntern()) {
decRefCount(_extern._refCount);
_len = str._len;
_size = str._size;
_str = _storage;
memcpy(_str, str._str, _len + 1);
memcpy(_str, str._str, _size + 1);
} else {
str.incRefCount();
decRefCount(_extern._refCount);
_extern._refCount = str._extern._refCount;
_extern._capacity = str._extern._capacity;
_len = str._len;
_size = str._size;
_str = str._str;
}
@ -240,7 +240,7 @@ String &String::operator =(const String &str) {
String& String::operator =(char c) {
decRefCount(_extern._refCount);
_str = _storage;
_len = 1;
_size = 1;
_str[0] = c;
_str[1] = 0;
return *this;
@ -249,30 +249,30 @@ String& String::operator =(char c) {
String &String::operator +=(const char *str) {
int len = strlen(str);
if (len > 0) {
ensureCapacity(_len + len, true);
ensureCapacity(_size + len, true);
memcpy(_str + _len, str, len + 1);
_len += len;
memcpy(_str + _size, str, len + 1);
_size += len;
}
return *this;
}
String &String::operator +=(const String &str) {
int len = str._len;
int len = str._size;
if (len > 0) {
ensureCapacity(_len + len, true);
ensureCapacity(_size + len, true);
memcpy(_str + _len, str._str, len + 1);
_len += len;
memcpy(_str + _size, str._str, len + 1);
_size += len;
}
return *this;
}
String &String::operator +=(char c) {
ensureCapacity(_len + 1, true);
ensureCapacity(_size + 1, true);
_str[_len++] = c;
_str[_len] = 0;
_str[_size++] = c;
_str[_size] = 0;
return *this;
}
@ -293,10 +293,10 @@ bool String::hasPrefix(const char *x) const {
bool String::hasSuffix(const char *x) const {
assert(x != 0);
// Compare x with the end of _str.
const uint32 x_len = strlen(x);
if (x_len > _len)
const uint32 x_size = strlen(x);
if (x_size > _size)
return false;
const char *y = c_str() + _len - x_len;
const char *y = c_str() + _size - x_size;
while (*x && *x == *y) {
++x;
++y;
@ -316,65 +316,65 @@ bool String::contains(char x) const {
}
void String::deleteLastChar() {
deleteChar(_len - 1);
deleteChar(_size - 1);
}
void String::deleteChar(uint32 p) {
assert(p < _len);
assert(p < _size);
makeUnique();
while (p++ < _len)
while (p++ < _size)
_str[p-1] = _str[p];
_len--;
_size--;
}
void String::clear() {
decRefCount(_extern._refCount);
_len = 0;
_size = 0;
_str = _storage;
_storage[0] = 0;
}
void String::setChar(char c, uint32 p) {
assert(p <= _len);
assert(p <= _size);
makeUnique();
_str[p] = c;
}
void String::insertChar(char c, uint32 p) {
assert(p <= _len);
assert(p <= _size);
ensureCapacity(_len + 1, true);
_len++;
for (uint32 i = _len; i > p; --i)
ensureCapacity(_size + 1, true);
_size++;
for (uint32 i = _size; i > p; --i)
_str[i] = _str[i-1];
_str[p] = c;
}
void String::toLowercase() {
makeUnique();
for (uint32 i = 0; i < _len; ++i)
for (uint32 i = 0; i < _size; ++i)
_str[i] = tolower(_str[i]);
}
void String::toUppercase() {
makeUnique();
for (uint32 i = 0; i < _len; ++i)
for (uint32 i = 0; i < _size; ++i)
_str[i] = toupper(_str[i]);
}
void String::trim() {
if (_len == 0)
if (_size == 0)
return;
makeUnique();
// Trim trailing whitespace
while (_len >= 1 && isspace(_str[_len-1]))
_len--;
_str[_len] = 0;
while (_size >= 1 && isspace(_str[_size-1]))
_size--;
_str[_size] = 0;
// Trim leading whitespace
char *t = _str;
@ -382,8 +382,8 @@ void String::trim() {
t++;
if (t != _str) {
_len -= t - _str;
memmove(_str, t, _len + 1);
_size -= t - _str;
memmove(_str, t, _size + 1);
}
}

View file

@ -61,7 +61,7 @@ protected:
* a lot. Yes, we limit ourselves to strings shorter than 4GB --
* on purpose :-).
*/
uint32 _len;
uint32 _size;
/**
* Pointer to the actual string storage. Either points to _storage,
@ -97,7 +97,7 @@ public:
#endif
/** Construct a new empty string. */
String() : _len(0), _str(_storage) { _storage[0] = 0; }
String() : _size(0), _str(_storage) { _storage[0] = 0; }
/** Construct a new string from the given NULL-terminated C string. */
String(const char *str);
@ -150,13 +150,13 @@ public:
bool contains(char x) const;
inline const char *c_str() const { return _str; }
inline uint size() const { return _len; }
inline uint size() const { return _size; }
inline bool empty() const { return (_len == 0); }
char lastChar() const { return (_len > 0) ? _str[_len-1] : 0; }
inline bool empty() const { return (_size == 0); }
char lastChar() const { return (_size > 0) ? _str[_size-1] : 0; }
char operator [](int idx) const {
assert(_str && idx >= 0 && idx < (int)_len);
assert(_str && idx >= 0 && idx < (int)_size);
return _str[idx];
}
@ -203,7 +203,7 @@ public:
protected:
void makeUnique();
void ensureCapacity(uint32 new_len, bool keep_old);
void ensureCapacity(uint32 new_size, bool keep_old);
void incRefCount() const;
void decRefCount(int *oldRefCount);
void initWithCStr(const char *str, uint32 len);
@ -230,13 +230,11 @@ extern char *trim(char *t);
class StringList : public Array<String> {
public:
void push_back(const char *str) {
ensureCapacity(_size + 1);
_data[_size++] = str;
Array<String>::push_back(str);
}
void push_back(const String &str) {
ensureCapacity(_size + 1);
_data[_size++] = str;
Array<String>::push_back(str);
}
};