initial commit
This commit is contained in:
@@ -0,0 +1,364 @@
|
||||
#ifndef OPP_VECTOR_H
|
||||
#define OPP_VECTOR_H
|
||||
|
||||
#include <new>
|
||||
#include <stdlib.h>
|
||||
#include <opp/utility.h>
|
||||
|
||||
namespace opp {
|
||||
|
||||
template <class T>
|
||||
class vector
|
||||
{
|
||||
protected:
|
||||
T * _data;
|
||||
size_t _size, _capacity;
|
||||
public:
|
||||
typedef T element_type;
|
||||
|
||||
vector(void) : _data(nullptr), _size(0), _capacity(0) {}
|
||||
|
||||
vector(size_t n) : _data((T*)malloc(n * sizeof(T))), _size(n), _capacity(n)
|
||||
{
|
||||
for(size_t i=0; i<n; i++)
|
||||
new (_data + i) T();
|
||||
}
|
||||
|
||||
vector(const vector & v)
|
||||
: _data((T*)malloc(v._size * sizeof(T))), _size(v._size), _capacity(v._size)
|
||||
{
|
||||
size_t n = _size;
|
||||
for(size_t i=0; i<n; i++)
|
||||
new (_data + i)T(v._data[i]);
|
||||
}
|
||||
|
||||
vector(vector && v)
|
||||
: _data(v._data), _size(v._size), _capacity(v._capacity)
|
||||
{
|
||||
v._data = nullptr;
|
||||
v._size = 0;
|
||||
v._capacity = 0;
|
||||
}
|
||||
|
||||
~vector(void)
|
||||
{
|
||||
for(size_t i=0; i<_size; i++)
|
||||
_data[i].~T();
|
||||
free(_data);
|
||||
}
|
||||
|
||||
vector & operator=(const vector & v)
|
||||
{
|
||||
if (this != &v)
|
||||
{
|
||||
size_t n = _size;
|
||||
for(size_t i=0; i<n; i++)
|
||||
_data[i].~T();
|
||||
free(_data);
|
||||
|
||||
_data = (T*)malloc(v._size * sizeof(T));
|
||||
_size = v._size;
|
||||
_capacity = v._size;
|
||||
n = _size;
|
||||
for(size_t i=0; i<n; i++)
|
||||
new (_data + i)T(v._data[i]);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
vector & operator=(vector && v)
|
||||
{
|
||||
if (this != &v)
|
||||
{
|
||||
swap(_data, v._data);
|
||||
swap(_size, v._size);
|
||||
swap(_capacity, v._capacity);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
size_t size(void) const
|
||||
{
|
||||
return _size;
|
||||
}
|
||||
|
||||
size_t max_size(void) const
|
||||
{
|
||||
return 32767;
|
||||
}
|
||||
|
||||
bool empty(void) const
|
||||
{
|
||||
return _size == 0;
|
||||
}
|
||||
|
||||
size_t capacity(void) const
|
||||
{
|
||||
return _capacity;
|
||||
}
|
||||
|
||||
void clear(void);
|
||||
|
||||
void resize(size_t n);
|
||||
|
||||
void reserve(size_t n);
|
||||
|
||||
void shrink_to_fit(void);
|
||||
|
||||
T & at(size_t at)
|
||||
{
|
||||
return _data[at];
|
||||
}
|
||||
|
||||
const T & at(size_t at) const
|
||||
{
|
||||
return _data[at];
|
||||
}
|
||||
|
||||
T & operator[](size_t at)
|
||||
{
|
||||
return _data[at];
|
||||
}
|
||||
|
||||
const T & operator[](size_t at) const
|
||||
{
|
||||
return _data[at];
|
||||
}
|
||||
|
||||
T * begin(void)
|
||||
{
|
||||
return _data;
|
||||
}
|
||||
|
||||
const T * begin(void) const
|
||||
{
|
||||
return _data;
|
||||
}
|
||||
|
||||
const T * cbegin(void) const
|
||||
{
|
||||
return _data;
|
||||
}
|
||||
|
||||
T * end(void)
|
||||
{
|
||||
return _data + _size;
|
||||
}
|
||||
|
||||
const T * end(void) const
|
||||
{
|
||||
return _data + _size;
|
||||
}
|
||||
|
||||
const T * cend(void) const
|
||||
{
|
||||
return _data + _size;
|
||||
}
|
||||
|
||||
T & front(void)
|
||||
{
|
||||
return _data[0];
|
||||
}
|
||||
|
||||
const T & front(void) const
|
||||
{
|
||||
return _data[0];
|
||||
}
|
||||
|
||||
T & back(void)
|
||||
{
|
||||
return _data[_size - 1];
|
||||
}
|
||||
|
||||
const T & back(void) const
|
||||
{
|
||||
return _data[_size - 1];
|
||||
}
|
||||
|
||||
T * data(void)
|
||||
{
|
||||
return _data;
|
||||
}
|
||||
|
||||
const T * at(void) const
|
||||
{
|
||||
return _data;
|
||||
}
|
||||
|
||||
void push_back(const T & t);
|
||||
|
||||
void push_back(T && t);
|
||||
|
||||
void pop_back(void)
|
||||
{
|
||||
_size--;
|
||||
_data[_size].~T();
|
||||
}
|
||||
|
||||
void assign(size_t count, const T & t);
|
||||
|
||||
void insert(size_t at, const T & t);
|
||||
|
||||
void erase(size_t at, size_t n = 1);
|
||||
|
||||
T * insert(T * at, const T & t);
|
||||
|
||||
template <typename ...P>
|
||||
void emplace_back(const P&... p);
|
||||
protected:
|
||||
T * add_back(void);
|
||||
};
|
||||
|
||||
|
||||
template <class T>
|
||||
__noinline void vector<T>::reserve(size_t n)
|
||||
{
|
||||
if (n > _capacity)
|
||||
{
|
||||
_capacity = n;
|
||||
T * d = (T *)malloc(_capacity * sizeof(T));
|
||||
size_t s = _size;
|
||||
for(size_t i=0; i<s; i++)
|
||||
{
|
||||
new (d + i)T(move(_data[i]));
|
||||
_data[i].~T();
|
||||
}
|
||||
free(_data);
|
||||
_data = d;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void vector<T>::clear(void)
|
||||
{
|
||||
for(size_t i=0; i<_size; i++)
|
||||
_data[i].~T();
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
__noinline void vector<T>::resize(size_t n)
|
||||
{
|
||||
if (n < _size)
|
||||
{
|
||||
for(size_t i=n; i<_size; i++)
|
||||
_data[i].~T();
|
||||
_size = n;
|
||||
}
|
||||
else if (n < _capacity)
|
||||
{
|
||||
for(size_t i=_size; i<n; i++)
|
||||
new(_data + i)T();
|
||||
_size = n;
|
||||
}
|
||||
else
|
||||
{
|
||||
reserve(n);
|
||||
_size = n;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void vector<T>::shrink_to_fit(void)
|
||||
{
|
||||
if (_size < _capacity)
|
||||
{
|
||||
_capacity = _size;
|
||||
T * d = (T *)malloc(_capacity * sizeof(T));
|
||||
for(size_t i=0; i<_size; i++)
|
||||
{
|
||||
new (d + i)T(move(_data[i]));
|
||||
_data[i].~T();
|
||||
}
|
||||
free(_data);
|
||||
_data = d;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T * vector<T>::add_back(void)
|
||||
{
|
||||
if (_size == _capacity)
|
||||
reserve(_size + 1 + (_size >> 1));
|
||||
return _data + _size++;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void vector<T>::push_back(const T & t)
|
||||
{
|
||||
new (add_back())T(t);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void vector<T>::push_back(T && t)
|
||||
{
|
||||
new (add_back())T(t);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <typename ...P>
|
||||
void vector<T>::emplace_back(const P&... p)
|
||||
{
|
||||
new (add_back())T(p...);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void vector<T>::assign(size_t count, const T & t)
|
||||
{
|
||||
for(size_t i=0; i<_size; i++)
|
||||
_data[i].~T();
|
||||
if (count > _capacity)
|
||||
{
|
||||
_size = 0;
|
||||
reserve(count);
|
||||
}
|
||||
for(size_t i=0; i<count; i++)
|
||||
new (_data + i)T(t);
|
||||
_size = count;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void vector<T>::insert(size_t at, const T & t)
|
||||
{
|
||||
if (_size == _capacity)
|
||||
reserve(_size + 1 + (_size >> 1));
|
||||
new (_data + _size)T();
|
||||
for(size_t i=_size; i>at; i--)
|
||||
_data[i] = move(_data[i - 1]);
|
||||
_data[at] = t;
|
||||
_size++;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void vector<T>::erase(size_t at, size_t n)
|
||||
{
|
||||
_size -= n;
|
||||
for(size_t i=at; i<_size; i++)
|
||||
_data[i] = move(_data[i + n]);
|
||||
for(size_t i=0; i<n; i++)
|
||||
_data[_size + i].~T();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T * vector<T>::insert(T * at, const T & t)
|
||||
{
|
||||
if (_size == _capacity)
|
||||
{
|
||||
unsigned f = unsigned(at) - unsigned(_data);
|
||||
reserve(_size + 1 + (_size >> 1));
|
||||
at = (T *)(f + unsigned(_data));
|
||||
}
|
||||
T * dp = _data + _size;
|
||||
new (dp)T();
|
||||
while (dp != at)
|
||||
{
|
||||
dp--;
|
||||
dp[1] = move(dp[0]);
|
||||
}
|
||||
dp[0] = t;
|
||||
_size++;
|
||||
return dp + 1;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user