210 lines
4.4 KiB
C++
210 lines
4.4 KiB
C++
|
|
#ifndef CLASS_LIST
|
|
#define CLASS_LIST
|
|
|
|
#include <stddef.h>
|
|
#include <assert.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <valgrind/memcheck.h>
|
|
|
|
#include <type_traits>
|
|
#include <new>
|
|
#include <utility>
|
|
|
|
template<typename T> class list
|
|
{
|
|
public:
|
|
class iterable
|
|
{
|
|
private:
|
|
list* owner;
|
|
size_t index;
|
|
|
|
public:
|
|
iterable(
|
|
list* _owner, size_t _index):
|
|
owner(_owner), index(_index)
|
|
{
|
|
;
|
|
}
|
|
|
|
T operator *()
|
|
{
|
|
assert(index <= owner->n);
|
|
|
|
VALGRIND_CHECK_VALUE_IS_DEFINED(owner->data[index]);
|
|
|
|
T retval = owner->data[index];
|
|
|
|
return retval;
|
|
}
|
|
|
|
void operator ++()
|
|
{
|
|
index++;
|
|
}
|
|
|
|
bool operator != (const iterable& other)
|
|
{
|
|
bool retval = false
|
|
|| this->owner != other.owner
|
|
|| this->index != other.index;
|
|
|
|
return retval;
|
|
}
|
|
};
|
|
|
|
class const_iterable
|
|
{
|
|
private:
|
|
const list* owner;
|
|
size_t index;
|
|
|
|
public:
|
|
const_iterable(
|
|
const list* _owner, size_t _index):
|
|
owner(_owner), index(_index)
|
|
{
|
|
;
|
|
}
|
|
|
|
const T operator *()
|
|
{
|
|
assert(index <= owner->n);
|
|
|
|
VALGRIND_CHECK_VALUE_IS_DEFINED(owner->data[index]);
|
|
|
|
const T retval = owner->data[index];
|
|
|
|
return retval;
|
|
}
|
|
|
|
void operator ++()
|
|
{
|
|
index++;
|
|
}
|
|
|
|
bool operator != (const const_iterable& other)
|
|
{
|
|
bool retval = false
|
|
|| this->owner != other.owner
|
|
|| this->index != other.index;
|
|
|
|
return retval;
|
|
}
|
|
};
|
|
|
|
public:
|
|
T* data;
|
|
size_t n, cap;
|
|
|
|
public:
|
|
list(): data(NULL), n(0), cap(0)
|
|
{
|
|
;
|
|
}
|
|
|
|
iterable begin()
|
|
{
|
|
return iterable(this, 0);
|
|
}
|
|
|
|
iterable end()
|
|
{
|
|
return iterable(this, n);
|
|
}
|
|
|
|
const_iterable begin() const
|
|
{
|
|
return const_iterable(this, 0);
|
|
}
|
|
|
|
const_iterable end() const
|
|
{
|
|
return const_iterable(this, n);
|
|
}
|
|
|
|
void append(T appendme)
|
|
{
|
|
if constexpr (std::is_trivially_copyable_v<T>)
|
|
{
|
|
if (n == cap)
|
|
{
|
|
cap = cap << 1 ?: 1;
|
|
|
|
data = (T*) realloc((void*) data, sizeof(*data) * cap);
|
|
}
|
|
|
|
data[n++] = appendme;
|
|
}
|
|
else
|
|
{
|
|
if (n == cap)
|
|
{
|
|
cap = cap << 1 ?: 1;
|
|
|
|
T* new_data = new T[cap]();
|
|
|
|
for (size_t i = 0; i < n; i++)
|
|
{
|
|
new_data[i] = std::move(data[i]);
|
|
}
|
|
|
|
delete[] data;
|
|
|
|
data = new_data;
|
|
}
|
|
|
|
new (&data[n]) T(appendme);
|
|
|
|
VALGRIND_CHECK_VALUE_IS_DEFINED(data[n]);
|
|
|
|
n++;
|
|
}
|
|
}
|
|
|
|
~list()
|
|
{
|
|
if constexpr (std::is_trivially_copyable_v<T>)
|
|
{
|
|
free(data);
|
|
}
|
|
else
|
|
{
|
|
delete[] data;
|
|
}
|
|
}
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|