wrote mote code for Array
This commit is contained in:
parent
0c0f0df7d8
commit
bdf3e2652d
@ -38,6 +38,8 @@ struct ArrayResizer
|
|||||||
{
|
{
|
||||||
qse_size_t operator() (qse_size_t current) const
|
qse_size_t operator() (qse_size_t current) const
|
||||||
{
|
{
|
||||||
|
if (current <= 0) current = 1;
|
||||||
|
|
||||||
return (current < 5000)? (current + current):
|
return (current < 5000)? (current + current):
|
||||||
(current < 50000)? (current + (current / 2)):
|
(current < 50000)? (current + (current / 2)):
|
||||||
(current < 100000)? (current + (current / 4)):
|
(current < 100000)? (current + (current / 4)):
|
||||||
@ -46,11 +48,24 @@ struct ArrayResizer
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename RESIZER = ArrayResizer>
|
template<typename T>
|
||||||
|
struct ArrayAssigner
|
||||||
|
{
|
||||||
|
// The assignment proxy is used to get the value informed of its position
|
||||||
|
// within the heap. This default implmentation, however, doesn't utilize
|
||||||
|
// the position (index).
|
||||||
|
T& operator() (T& v1, const T& v2, qse_size_t index) const
|
||||||
|
{
|
||||||
|
v1 = v2;
|
||||||
|
return v1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename ASSIGNER = ArrayAssigner<T>, typename RESIZER = ArrayResizer >
|
||||||
class Array: public Mmged
|
class Array: public Mmged
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef Array<T,RESIZER> SelfType;
|
typedef Array<T,ASSIGNER,RESIZER> SelfType;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
@ -59,8 +74,8 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
Array (Mmgr* mmgr = QSE_NULL,
|
Array (Mmgr* mmgr = QSE_NULL,
|
||||||
qse_size_t capacity = DEFAULT_CAPACITY,
|
qse_size_t capacity = DEFAULT_CAPACITY,
|
||||||
qse_size_t mpb_size = 0):
|
qse_size_t mpb_size = 0):
|
||||||
Mmged (mmgr),
|
Mmged (mmgr),
|
||||||
mp (mmgr, QSE_SIZEOF(T), mpb_size)
|
mp (mmgr, QSE_SIZEOF(T), mpb_size)
|
||||||
{
|
{
|
||||||
@ -79,82 +94,89 @@ public:
|
|||||||
this->count = 0;
|
this->count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
Array (const SelfType& array):
|
||||||
Array (const SelfType& array)
|
Mmged (array.getMmgr()),
|
||||||
|
mp (array.getMmgr(), array.mp.getDatumSize(), array.mp.getBlockSize()),
|
||||||
|
count (0), capacity (0), buffer (QSE_NULL)
|
||||||
{
|
{
|
||||||
if (array.buffer == QSE_NULL)
|
if (array.buffer)
|
||||||
{
|
{
|
||||||
this->buffer = QSE_NULL;
|
this->buffer = this->clone_buffer (array, array.capacity, array.count);
|
||||||
this->capacity = 0;
|
this->count = array.count;
|
||||||
this->grow_factor = array.grow_factor;
|
|
||||||
this->count = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
T* tmp = QSE_NULL;
|
|
||||||
QSE_ASSERT (array.capacity > 0 && array.grow_factor > 0);
|
|
||||||
|
|
||||||
try {
|
|
||||||
tmp = new T[array.capacity];
|
|
||||||
for (qse_size_t i = 0; i < array.this->count; i++) {
|
|
||||||
tmp[i] = array.buffer[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (...) {
|
|
||||||
// just in case where the assignment throws an
|
|
||||||
// exception. when T is a class type, the operator =
|
|
||||||
// for the class may throw an exception.
|
|
||||||
if (tmp != QSE_NULL) delete[] tmp;
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->buffer = tmp;
|
|
||||||
this->capacity = array.capacity;
|
this->capacity = array.capacity;
|
||||||
this->grow_factor = array.grow_factor;
|
|
||||||
this->count = array.this->count;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
~Array ()
|
~Array ()
|
||||||
{
|
{
|
||||||
if (this->buffer)
|
this->clear (true);
|
||||||
{
|
|
||||||
for (qse_size_t i = this->count; i > 0; )
|
|
||||||
{
|
|
||||||
--i;
|
|
||||||
this->buffer[i].~T ();
|
|
||||||
}
|
|
||||||
|
|
||||||
::operator delete (this->buffer, &this->mp);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
SelfType& operator= (const SelfType& array)
|
SelfType& operator= (const SelfType& array)
|
||||||
{
|
{
|
||||||
setSize (array.this->count);
|
this->clear (true);
|
||||||
for (qse_size_t i = 0; i < array.this->count; i++) {
|
if (array.buffer)
|
||||||
this->buffer[i] = array.buffer[i];
|
{
|
||||||
|
this->buffer = this->clone_buffer (array, array.capacity, array.count);
|
||||||
|
this->count = array.count;
|
||||||
|
this->capacity = array.capacity;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
protected:
|
||||||
Array<T>& operator+= (const T& value)
|
T* clone_buffer (const T* srcbuf, qse_size_t capa, qse_size_t count)
|
||||||
{
|
{
|
||||||
addDatum (value);
|
QSE_ASSERT (capa > 0);
|
||||||
return *this;
|
QSE_ASSERT (count <= capa);
|
||||||
}
|
|
||||||
Array<T>& operator+ (const T& value) const
|
|
||||||
{
|
|
||||||
Array<T> array (*this);
|
|
||||||
array.addDatum (value);
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
qse_size_t index;
|
||||||
|
|
||||||
|
//T* tmp = new T[capa];
|
||||||
|
T* tmp = (T*)::operator new (capa * QSE_SIZEOF(*tmp), &this->mp);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for (index = 0; index < count; index++)
|
||||||
|
{
|
||||||
|
//tmp[index] = srcbuf[index];
|
||||||
|
// copy-construct each element.
|
||||||
|
new((QSE::Mpool*)QSE_NULL, &tmp[index]) T(srcbuf[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
// in case copy-constructor raises an exception.
|
||||||
|
QSE_ASSERT (tmp != QSE_NULL);
|
||||||
|
while (index > 0)
|
||||||
|
{
|
||||||
|
--index;
|
||||||
|
tmp[index].~T ();
|
||||||
|
}
|
||||||
|
::operator delete (tmp, &this->mp);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void put_item (qse_size_t index, const T& value)
|
||||||
|
{
|
||||||
|
if (index >= this->count)
|
||||||
|
{
|
||||||
|
// no value exists in the given position.
|
||||||
|
// i can copy-construct the value.
|
||||||
|
new((QSE::Mpool*)QSE_NULL, &this->buffer[index]) T(value);
|
||||||
|
//this->notify_position (this->buffer[index], index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// there is an old value in the position.
|
||||||
|
this->assigner (this->buffer[index], value, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
bool isEmpty () const
|
bool isEmpty () const
|
||||||
{
|
{
|
||||||
return this->count == 0;
|
return this->count == 0;
|
||||||
@ -190,6 +212,19 @@ public:
|
|||||||
return this->buffer;
|
return this->buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The getBufferIndex() function returns the index of the
|
||||||
|
/// given value \a v if it is one of the values of the array.
|
||||||
|
/// It returns #INVALID_INDEX if not.
|
||||||
|
qse_size_t getIndex (const T& v)
|
||||||
|
{
|
||||||
|
if (&v >= &this->buffer[0] && &v < &this->buffer[this->count])
|
||||||
|
{
|
||||||
|
return &v - &this->buffer[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return INVALID_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
T& operator[] (qse_size_t index)
|
T& operator[] (qse_size_t index)
|
||||||
{
|
{
|
||||||
QSE_ASSERT (index < this->count);
|
QSE_ASSERT (index < this->count);
|
||||||
@ -217,23 +252,15 @@ public:
|
|||||||
void set (qse_size_t index, const T& value)
|
void set (qse_size_t index, const T& value)
|
||||||
{
|
{
|
||||||
QSE_ASSERT (index < this->count);
|
QSE_ASSERT (index < this->count);
|
||||||
this->buffer[index] = value;
|
this->insert (index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
|
||||||
void set_item (qse_size_t index, const T& value)
|
|
||||||
{
|
|
||||||
if (index >= this->count)
|
|
||||||
new((QSE::Mpool*)QSE_NULL, &this->buffer[index]) T(value);
|
|
||||||
else
|
|
||||||
this->buffer[index] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
qse_size_t insert (qse_size_t index, const T& value)
|
qse_size_t insert (qse_size_t index, const T& value)
|
||||||
{
|
{
|
||||||
if (index >= this->capacity)
|
if (index >= this->capacity)
|
||||||
{
|
{
|
||||||
|
// the position to add the element is beyond the
|
||||||
|
// capacity. resize the buffer.
|
||||||
qse_size_t new_capa = this->resizer (this->capacity);
|
qse_size_t new_capa = this->resizer (this->capacity);
|
||||||
|
|
||||||
if (index < new_capa)
|
if (index < new_capa)
|
||||||
@ -243,18 +270,33 @@ public:
|
|||||||
}
|
}
|
||||||
else if (this->count >= this->capacity)
|
else if (this->count >= this->capacity)
|
||||||
{
|
{
|
||||||
|
// the array is already full.
|
||||||
|
// insertion requires at least one more slot
|
||||||
qse_size_t new_capa = this->resizer (this->capacity);
|
qse_size_t new_capa = this->resizer (this->capacity);
|
||||||
this->setCapacity (new_capa);
|
this->setCapacity (new_capa);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (qse_size_t i = this->count; i > index; i--)
|
if (index < this->count)
|
||||||
{
|
{
|
||||||
//this->buffer[i] = this->buffer[i - 1];
|
// shift the existing elements to the back by one slot.
|
||||||
this->set_item (i, this->buffer[i - 1]);
|
for (qse_size_t i = this->count; i > index; i--)
|
||||||
|
{
|
||||||
|
//this->buffer[i] = this->buffer[i - 1];
|
||||||
|
this->put_item (i, this->buffer[i - 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (index > this->count)
|
||||||
|
{
|
||||||
|
// the insertion position leaves some gaps in between.
|
||||||
|
// fill the gap with a default value.
|
||||||
|
for (qse_size_t i = this->count; i < index; i++)
|
||||||
|
{
|
||||||
|
new((QSE::Mpool*)QSE_NULL, &this->buffer[i]) T();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//this->buffer[index] = value;
|
//this->buffer[index] = value;
|
||||||
this->set_item (index, value);
|
this->put_item (index, value);
|
||||||
if (index > this->count) this->count = index + 1;
|
if (index > this->count) this->count = index + 1;
|
||||||
else this->count++;
|
else this->count++;
|
||||||
|
|
||||||
@ -273,150 +315,171 @@ public:
|
|||||||
|
|
||||||
qse_size_t j = from_index;
|
qse_size_t j = from_index;
|
||||||
qse_size_t i = to_index + 1;
|
qse_size_t i = to_index + 1;
|
||||||
|
|
||||||
|
// replace deleted elements by surviving elements at the back
|
||||||
while (i < this->count)
|
while (i < this->count)
|
||||||
{
|
{
|
||||||
this->buffer[j++] = this->buffer[i++];
|
//this->buffer[j++] = this->buffer[i++];
|
||||||
|
this->assigner (this->buffer[j], this->buffer[i], j);
|
||||||
|
j++; i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// call the destructor of deleted elements.
|
||||||
|
while (j < this->count)
|
||||||
|
{
|
||||||
|
this->buffer[j].~T ();
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// recalculate the number of elements
|
||||||
this->count -= to_index - from_index + 1;
|
this->count -= to_index - from_index + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
protected:
|
||||||
qse_size_t addDatum (const T& value)
|
void clear_all_items ()
|
||||||
{
|
{
|
||||||
return insert (this->count, value);
|
QSE_ASSERT (this->count <= 0 || (this->count >= 1 && this->buffer));
|
||||||
|
|
||||||
|
for (qse_size_t i = this->count; i > 0; )
|
||||||
|
{
|
||||||
|
--i;
|
||||||
|
this->buffer[i].~T ();
|
||||||
|
}
|
||||||
|
|
||||||
|
this->count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
qse_size_t removeDatum (const T& value)
|
public:
|
||||||
|
void clear (bool clear_mpool = false)
|
||||||
{
|
{
|
||||||
qse_size_t i = 0, sz = this->size();
|
this->clear_all_items ();
|
||||||
while (i < this->count)
|
|
||||||
|
if (clear_mpool)
|
||||||
{
|
{
|
||||||
if (value == this->buffer[i])
|
if (this->buffer)
|
||||||
{
|
{
|
||||||
remove (i);
|
// the buffer has been allocated using the memory pool.
|
||||||
break;
|
// if the memory pool should be cleared, the buffer must
|
||||||
|
// not be left over either.
|
||||||
|
QSE_ASSERT (this->capacity > 0);
|
||||||
|
::operator delete (this->buffer, &this->mp);
|
||||||
|
this->capacity = 0;
|
||||||
|
this->buffer = QSE_NULL;
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
|
QSE_ASSERT (this->capacity == 0);
|
||||||
|
this->mp.dispose ();
|
||||||
}
|
}
|
||||||
|
|
||||||
return sz - this->size();
|
|
||||||
}
|
|
||||||
|
|
||||||
qse_size_t removeDatums (const T& value)
|
|
||||||
{
|
|
||||||
qse_size_t i = 0, sz = this->size();
|
|
||||||
|
|
||||||
while (i < this->count)
|
|
||||||
{
|
|
||||||
if (value == this->buffer[i]) remove (i);
|
|
||||||
else i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return sz - this->size();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
void clear ()
|
|
||||||
{
|
|
||||||
setSize (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void trimToSize ()
|
|
||||||
{
|
|
||||||
setCapacity (this->size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSize (qse_size_t size)
|
void setSize (qse_size_t size)
|
||||||
{
|
{
|
||||||
if (size > this->capacity) this->setCapacity (size);
|
if (size < this->count)
|
||||||
QSE_ASSERT (size <= this->capacity);
|
{
|
||||||
this->count = size;
|
for (qse_size_t i = size; i < this->count; ++i)
|
||||||
|
{
|
||||||
|
// call the destructor of the items
|
||||||
|
this->buffer[i].~T ();
|
||||||
|
}
|
||||||
|
|
||||||
|
this->count = size;
|
||||||
|
}
|
||||||
|
else if (size > this->count)
|
||||||
|
{
|
||||||
|
if (size > this->capacity) this->setCapacity (size);
|
||||||
|
for (qse_size_t i = this->count; i < size; ++i)
|
||||||
|
{
|
||||||
|
// use the default contructor to set the value.
|
||||||
|
new((QSE::Mpool*)QSE_NULL, &this->buffer[i]) T();
|
||||||
|
}
|
||||||
|
|
||||||
|
this->count = size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setCapacity (qse_size_t capacity)
|
void setCapacity (qse_size_t capacity)
|
||||||
{
|
{
|
||||||
if (capacity <= 0)
|
if (capacity <= 0)
|
||||||
{
|
{
|
||||||
if (this->buffer != QSE_NULL)
|
this->clear (true);
|
||||||
delete[] this->buffer;
|
|
||||||
this->buffer = QSE_NULL;
|
|
||||||
this->capacity = 0;
|
|
||||||
this->count = 0;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
T* tmp = QSE_NULL;
|
|
||||||
qse_size_t cnt = this->count;
|
qse_size_t cnt = this->count;
|
||||||
|
if (cnt > capacity) cnt = capacity;
|
||||||
|
|
||||||
try
|
T* tmp = clone_buffer (*this, capacity, cnt);
|
||||||
|
|
||||||
|
if (this->buffer)
|
||||||
{
|
{
|
||||||
tmp = new T[capacity];
|
// don't call this->clear (true) here. clear items only.
|
||||||
if (cnt > capacity) cnt = capacity;
|
// the memory pool may destory the cloned buffer as well.
|
||||||
for (qse_size_t i = 0; i < cnt; i++)
|
this->clear_all_items ();
|
||||||
{
|
|
||||||
tmp[i] = this->buffer[i];
|
// deallocate the current buffer;
|
||||||
}
|
::operator delete (this->buffer, &this->mp);
|
||||||
}
|
this->capacity = 0;
|
||||||
catch (...)
|
this->buffer = QSE_NULL;
|
||||||
{
|
|
||||||
if (tmp != QSE_NULL) delete[] tmp;
|
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->buffer != QSE_NULL)
|
|
||||||
delete[] this->buffer;
|
|
||||||
this->buffer = tmp;
|
this->buffer = tmp;
|
||||||
this->capacity = capacity;
|
this->capacity = capacity;
|
||||||
this->count = cnt;
|
this->count = cnt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void trimToSize ()
|
||||||
|
{
|
||||||
|
this->setCapacity (this->size);
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
qse_size_t indexOf (const T& value) const
|
qse_size_t findFirstIndex (const T& value) const
|
||||||
{
|
{
|
||||||
for (qse_size_t i = 0; i < this->count; i++)
|
for (qse_size_t i = 0; i < this->count; i++)
|
||||||
{
|
{
|
||||||
if (this->buffer[i] == value) return i;
|
if (this->is_equal (this->buffer[i], value)) return i;
|
||||||
}
|
}
|
||||||
return INVALID_INDEX;
|
return INVALID_INDEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
qse_size_t indexOf (const T& value, qse_size_t index) const
|
qse_size_t findFirstIndex (const T& value, qse_size_t index) const
|
||||||
{
|
{
|
||||||
for (qse_size_t i = index; i < this->count; i++)
|
for (qse_size_t i = index; i < this->count; i++)
|
||||||
{
|
{
|
||||||
if (this->buffer[i] == value) return i;
|
if (this->is_equal (this->buffer[i], value)) return i;
|
||||||
|
}
|
||||||
|
return INVALID_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_size_t findLastIndex (const T& value) const
|
||||||
|
{
|
||||||
|
for (qse_size_t i = this->count; i > 0; )
|
||||||
|
{
|
||||||
|
if (this->is_equal (this->buffer[--i], value)) return i;
|
||||||
}
|
}
|
||||||
return INVALID_INDEX;
|
return INVALID_INDEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
qse_size_t lastIndexOf (const T& value) const
|
qse_size_t findLastIndex (const T& value, qse_size_t index) const
|
||||||
{
|
|
||||||
for (qse_size_t i = this->count; i > 0; )
|
|
||||||
{
|
|
||||||
if (this->buffer[--i] == value) return i;
|
|
||||||
}
|
|
||||||
return INVALID_INDEX;
|
|
||||||
}
|
|
||||||
|
|
||||||
qse_size_t lastIndexOf (const T& value, qse_size_t index) const
|
|
||||||
{
|
{
|
||||||
for (qse_size_t i = index + 1; i > 0; )
|
for (qse_size_t i = index + 1; i > 0; )
|
||||||
{
|
{
|
||||||
if (this->buffer[--i] == value) return i;
|
if (this->is_equal (this->buffer[--i], value)) return i;
|
||||||
}
|
}
|
||||||
return INVALID_INDEX;
|
return INVALID_INDEX;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void rotate (int dir, qse_size_t n)
|
void rotate (int dir, qse_size_t n)
|
||||||
{
|
{
|
||||||
qse_size_t first, last, cnt, index, nk;
|
qse_size_t first, last, cnt, index, nk;
|
||||||
T c;
|
T c;
|
||||||
|
|
||||||
if (dir == 0) return this->count;
|
if (dir == 0) return;
|
||||||
if ((n %= this->count) == 0) return this->count;
|
if ((n %= this->count) == 0) return;
|
||||||
|
|
||||||
if (dir > 0) n = this->count - n;
|
if (dir > 0) n = this->count - n;
|
||||||
first = 0; nk = this->count - n; cnt = 0;
|
first = 0; nk = this->count - n; cnt = 0;
|
||||||
@ -425,30 +488,36 @@ public:
|
|||||||
{
|
{
|
||||||
last = first + nk;
|
last = first + nk;
|
||||||
index = first;
|
index = first;
|
||||||
c = this->buffer[first];
|
//c = this->buffer[first];
|
||||||
|
this->assigner (c, this->buffer[first], INVALID_INDEX);
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
cnt++;
|
cnt++;
|
||||||
while (index < nk)
|
while (index < nk)
|
||||||
{
|
{
|
||||||
this->buffer[index] = this->buffer[index + n];
|
//this->buffer[index] = this->buffer[index + n];
|
||||||
|
this->assigner (this->buffer[index], this->buffer[index + n], index);
|
||||||
index += n;
|
index += n;
|
||||||
}
|
}
|
||||||
if (index == last) break;
|
if (index == last) break;
|
||||||
this->buffer[index] = this->buffer[index - nk];
|
//this->buffer[index] = this->buffer[index - nk];
|
||||||
|
this->assigner (this->buffer[index], this->buffer[index - nk], index);
|
||||||
index -= nk;
|
index -= nk;
|
||||||
}
|
}
|
||||||
this->buffer[last] = c; first++;
|
//this->buffer[last] = c;
|
||||||
|
this->assigner (this->buffer[last], c, last);
|
||||||
|
first++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Mpool mp;
|
Mpool mp;
|
||||||
|
ASSIGNER assigner;
|
||||||
RESIZER resizer;
|
RESIZER resizer;
|
||||||
|
|
||||||
qse_size_t count;
|
qse_size_t count;
|
||||||
qse_size_t capacity;
|
qse_size_t capacity;
|
||||||
T* buffer;
|
T* buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
|
@ -92,7 +92,7 @@ struct BinaryHeapAssigner
|
|||||||
// The assignment proxy is used to get the value informed of its position
|
// The assignment proxy is used to get the value informed of its position
|
||||||
// within the heap. This default implmentation, however, doesn't utilize
|
// within the heap. This default implmentation, however, doesn't utilize
|
||||||
// the position (index).
|
// the position (index).
|
||||||
T& operator() (T& v1, const T& v2, xp_size_t index) const
|
T& operator() (T& v1, const T& v2, qse_size_t index) const
|
||||||
{
|
{
|
||||||
v1 = v2;
|
v1 = v2;
|
||||||
return v1;
|
return v1;
|
||||||
|
@ -220,7 +220,7 @@ public:
|
|||||||
|
|
||||||
SelfType& operator= (const SelfType& list)
|
SelfType& operator= (const SelfType& list)
|
||||||
{
|
{
|
||||||
this->clear ();
|
this->clear (false);
|
||||||
|
|
||||||
// note that the memory pool itself is not copied.
|
// note that the memory pool itself is not copied.
|
||||||
|
|
||||||
@ -620,6 +620,7 @@ protected:
|
|||||||
mutable DatumList* datum_list;
|
mutable DatumList* datum_list;
|
||||||
mutable qse_size_t threshold;
|
mutable qse_size_t threshold;
|
||||||
qse_size_t load_factor;
|
qse_size_t load_factor;
|
||||||
|
|
||||||
HASHER hasher;
|
HASHER hasher;
|
||||||
EQUALER equaler;
|
EQUALER equaler;
|
||||||
RESIZER resizer;
|
RESIZER resizer;
|
||||||
|
@ -211,14 +211,16 @@ public:
|
|||||||
this->clear (true);
|
this->clear (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
LinkedList (Mmgr* mmgr = QSE_NULL, qse_size_t mpb_size = 0): Mmged(mmgr), mp (mmgr, QSE_SIZEOF(Node), mpb_size)
|
LinkedList (Mmgr* mmgr = QSE_NULL, qse_size_t mpb_size = 0):
|
||||||
|
Mmged(mmgr), mp (mmgr, QSE_SIZEOF(Node), mpb_size)
|
||||||
{
|
{
|
||||||
this->node_count = 0;
|
this->node_count = 0;
|
||||||
this->head_node = QSE_NULL;
|
this->head_node = QSE_NULL;
|
||||||
this->tail_node = QSE_NULL;
|
this->tail_node = QSE_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
LinkedList (const SelfType& ll): Mmged(ll.getMmgr()), mp (ll.getMmgr(), ll.mp.getDatumSize(), ll.mp.getBlockSize())
|
LinkedList (const SelfType& ll):
|
||||||
|
Mmged(ll.getMmgr()), mp (ll.getMmgr(), ll.mp.getDatumSize(), ll.mp.getBlockSize())
|
||||||
{
|
{
|
||||||
this->node_count = 0;
|
this->node_count = 0;
|
||||||
this->head_node = QSE_NULL;
|
this->head_node = QSE_NULL;
|
||||||
|
@ -324,8 +324,15 @@ public:
|
|||||||
mp (mmgr, QSE_SIZEOF(Node), mpb_size),
|
mp (mmgr, QSE_SIZEOF(Node), mpb_size),
|
||||||
node_count (0)
|
node_count (0)
|
||||||
{
|
{
|
||||||
// create a nil object
|
#if defined(QSE_REDBLACKTREE_ALLOCATE_NIL)
|
||||||
this->nil = new(&this->mp) Node();
|
// create a nil object. note it doesn't go into the memory pool.
|
||||||
|
// the nil node allocated inside the memory pool makes implementation
|
||||||
|
// of this->clear (true) difficult as disposal of memory pool
|
||||||
|
// also deallocates the nil node.
|
||||||
|
this->nil = new(this->getMmgr()) Node();
|
||||||
|
#else
|
||||||
|
this->nil = &this->xnil;
|
||||||
|
#endif
|
||||||
|
|
||||||
// set root to nil
|
// set root to nil
|
||||||
this->root = this->nil;
|
this->root = this->nil;
|
||||||
@ -336,14 +343,20 @@ public:
|
|||||||
mp (rbt.getMmgr(), rbt.mp.getDatumSize(), rbt.mp.getBlockSize()),
|
mp (rbt.getMmgr(), rbt.mp.getDatumSize(), rbt.mp.getBlockSize()),
|
||||||
node_count (0)
|
node_count (0)
|
||||||
{
|
{
|
||||||
|
#if defined(QSE_REDBLACKTREE_ALLOCATE_NIL)
|
||||||
// create a nil object
|
// create a nil object. note it doesn't go into the memory pool.
|
||||||
this->nil = new(&this->mp) Node();
|
// the nil node allocated inside the memory pool makes implementation
|
||||||
|
// of this->clear (true) difficult as disposal of memory pool
|
||||||
|
// also deallocates the nil node.
|
||||||
|
this->nil = new(this->getMmgr()) Node();
|
||||||
|
#else
|
||||||
|
this->nil = &this->xnil;
|
||||||
|
#endif
|
||||||
|
|
||||||
// set root to nil
|
// set root to nil
|
||||||
this->root = this->nil;
|
this->root = this->nil;
|
||||||
|
|
||||||
// TODO: do the level-order traversal to minize rebalancing.
|
// TODO: do the level-order traversal to minimize rebalancing.
|
||||||
Iterator it = rbt.getIterator();
|
Iterator it = rbt.getIterator();
|
||||||
while (it.isLegit())
|
while (it.isLegit())
|
||||||
{
|
{
|
||||||
@ -354,15 +367,22 @@ public:
|
|||||||
|
|
||||||
~RedBlackTree ()
|
~RedBlackTree ()
|
||||||
{
|
{
|
||||||
this->clear ();
|
this->clear (true);
|
||||||
this->dispose_node (this->nil);
|
|
||||||
|
#if defined(QSE_REDBLACKTREE_ALLOCATE_NIL)
|
||||||
|
// destroy the nil node.
|
||||||
|
this->nil->~Node ();
|
||||||
|
::operator delete (this->nil, this->getMmgr());
|
||||||
|
#else
|
||||||
|
// do nothing
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SelfType& operator= (const SelfType& rbt)
|
SelfType& operator= (const SelfType& rbt)
|
||||||
{
|
{
|
||||||
this->clear ();
|
this->clear (false);
|
||||||
|
|
||||||
// TODO: do the level-order traversal to minize rebalancing.
|
// TODO: do the level-order traversal to minimize rebalancing.
|
||||||
Iterator it = rbt.getIterator();
|
Iterator it = rbt.getIterator();
|
||||||
while (it.isLegit())
|
while (it.isLegit())
|
||||||
{
|
{
|
||||||
@ -946,6 +966,8 @@ public:
|
|||||||
while (this->root->notNil()) this->remove_node (this->root);
|
while (this->root->notNil()) this->remove_node (this->root);
|
||||||
QSE_ASSERT (this->root = this->nil);
|
QSE_ASSERT (this->root = this->nil);
|
||||||
QSE_ASSERT (this->node_count == 0);
|
QSE_ASSERT (this->node_count == 0);
|
||||||
|
|
||||||
|
if (clear_mpool) this->mp.dispose ();
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator getIterator (typename Iterator::Mode mode = Iterator::ASCENDING) const
|
Iterator getIterator (typename Iterator::Mode mode = Iterator::ASCENDING) const
|
||||||
@ -963,6 +985,13 @@ protected:
|
|||||||
COMPARATOR comparator;
|
COMPARATOR comparator;
|
||||||
|
|
||||||
qse_size_t node_count;
|
qse_size_t node_count;
|
||||||
|
#if defined(QSE_REDBLACKTREE_ALLOCATE_NIL)
|
||||||
|
// nothing. let the constructor allocate it to this->nil.
|
||||||
|
#else
|
||||||
|
// use a statically declared nil object.
|
||||||
|
Node xnil;
|
||||||
|
#endif
|
||||||
|
|
||||||
Node* nil; // internal node to present nil
|
Node* nil; // internal node to present nil
|
||||||
Node* root; // root node.
|
Node* root; // root node.
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user