|
|
@@ -5,147 +5,216 @@
|
|
|
|
|
|
namespace pkpy{
|
|
|
|
|
|
-template<typename T>
|
|
|
-struct pod_vector{
|
|
|
- static constexpr int SizeT = sizeof(T);
|
|
|
- static constexpr int N = 128 / SizeT;
|
|
|
- static constexpr int Growth = 2;
|
|
|
-
|
|
|
- // static_assert(128 % SizeT == 0);
|
|
|
- static_assert(is_pod_v<T>);
|
|
|
- static_assert(N >= 4);
|
|
|
+struct explicit_copy_t {
|
|
|
+ explicit explicit_copy_t() = default;
|
|
|
+};
|
|
|
|
|
|
- int _size;
|
|
|
- int _capacity;
|
|
|
+template<typename T>
|
|
|
+struct array{
|
|
|
T* _data;
|
|
|
+ int _size;
|
|
|
|
|
|
using size_type = int;
|
|
|
|
|
|
- pod_vector(): _size(0), _capacity(N) {
|
|
|
- _data = (T*)pool128_alloc(_capacity * SizeT);
|
|
|
+ array(): _data(nullptr), _size(0) {}
|
|
|
+ array(int size): _data((T*)malloc(sizeof(T) * size)), _size(size) {}
|
|
|
+ array(array&& other) noexcept: _data(other._data), _size(other._size) {
|
|
|
+ other._data = nullptr;
|
|
|
+ other._size = 0;
|
|
|
+ }
|
|
|
+ array(const array& other) = delete;
|
|
|
+ array(explicit_copy_t, const array& other) {
|
|
|
+ _data = (T*)malloc(sizeof(T) * other._size);
|
|
|
+ _size = other._size;
|
|
|
+ for(int i=0; i<_size; i++) _data[i] = other._data[i];
|
|
|
}
|
|
|
|
|
|
- // support initializer list
|
|
|
- pod_vector(std::initializer_list<T> il): _size(il.size()), _capacity(std::max(N, _size)) {
|
|
|
- _data = (T*)pool128_alloc(_capacity * SizeT);
|
|
|
- for(int i=0; i<_size; i++) _data[i] = *(il.begin() + i);
|
|
|
+ array& operator=(array&& other) noexcept{
|
|
|
+ if(_data){
|
|
|
+ std::destroy(begin(), end());
|
|
|
+ free(_data);
|
|
|
+ }
|
|
|
+ _data = other._data;
|
|
|
+ _size = other._size;
|
|
|
+ other._data = nullptr;
|
|
|
+ other._size = 0;
|
|
|
+ return *this;
|
|
|
}
|
|
|
|
|
|
- pod_vector(int size): _size(size), _capacity(std::max(N, size)) {
|
|
|
- _data = (T*)pool128_alloc(_capacity * SizeT);
|
|
|
+ array& operator=(const array& other) = delete;
|
|
|
+
|
|
|
+ T& operator[](int i) {
|
|
|
+ PK_DEBUG_ASSERT(i>=0 && i<_size);
|
|
|
+ return _data[i];
|
|
|
}
|
|
|
|
|
|
- pod_vector(const pod_vector& other): _size(other._size), _capacity(other._capacity) {
|
|
|
- _data = (T*)pool128_alloc(_capacity * SizeT);
|
|
|
- memcpy(_data, other._data, SizeT * _size);
|
|
|
+ const T& operator[](int i) const {
|
|
|
+ PK_DEBUG_ASSERT(i>=0 && i<_size);
|
|
|
+ return _data[i];
|
|
|
}
|
|
|
|
|
|
- pod_vector(pod_vector&& other) noexcept {
|
|
|
- _size = other._size;
|
|
|
- _capacity = other._capacity;
|
|
|
- _data = other._data;
|
|
|
- other._data = nullptr;
|
|
|
+ int size() const { return _size; }
|
|
|
+
|
|
|
+ T* begin() const{ return _data; }
|
|
|
+ T* end() const{ return _data + _size; }
|
|
|
+
|
|
|
+ std::pair<T*, int> detach() noexcept {
|
|
|
+ std::pair<T*, int> retval(_data, _size);
|
|
|
+ _data = nullptr;
|
|
|
+ _size = 0;
|
|
|
+ return retval;
|
|
|
}
|
|
|
|
|
|
- pod_vector& operator=(pod_vector&& other) noexcept {
|
|
|
- if(_data!=nullptr) pool128_dealloc(_data);
|
|
|
- _size = other._size;
|
|
|
- _capacity = other._capacity;
|
|
|
- _data = other._data;
|
|
|
- other._data = nullptr;
|
|
|
- return *this;
|
|
|
+ ~array() {
|
|
|
+ if(_data){
|
|
|
+ std::destroy(begin(), end());
|
|
|
+ free(_data);
|
|
|
+ }
|
|
|
}
|
|
|
+};
|
|
|
|
|
|
- // remove copy assignment
|
|
|
- pod_vector& operator=(const pod_vector& other) = delete;
|
|
|
|
|
|
- template<typename __ValueT>
|
|
|
- void push_back(__ValueT&& t) {
|
|
|
- if (_size == _capacity) reserve(_capacity*Growth);
|
|
|
- _data[_size++] = std::forward<__ValueT>(t);
|
|
|
+template<typename T>
|
|
|
+struct vector{
|
|
|
+ T* _data;
|
|
|
+ int _capacity;
|
|
|
+ int _size;
|
|
|
+
|
|
|
+ using size_type = int;
|
|
|
+
|
|
|
+ vector(): _data(nullptr), _capacity(0), _size(0) {}
|
|
|
+ vector(int size):
|
|
|
+ _data((T*)malloc(sizeof(T) * size)),
|
|
|
+ _capacity(size), _size(size) {}
|
|
|
+ vector(vector&& other) noexcept:
|
|
|
+ _data(other._data), _capacity(other._capacity), _size(other._size) {
|
|
|
+ other._data = nullptr;
|
|
|
+ other._capacity = 0;
|
|
|
+ other._size = 0;
|
|
|
+ }
|
|
|
+ vector(const vector& other) = delete;
|
|
|
+ vector(explicit_copy_t, const vector& other):
|
|
|
+ _data((T*)malloc(sizeof(T) * other._size)),
|
|
|
+ _capacity(other._size), _size(other._size) {
|
|
|
+ for(int i=0; i<_size; i++) _data[i] = other._data[i];
|
|
|
}
|
|
|
|
|
|
- template<typename... Args>
|
|
|
- void emplace_back(Args&&... args) {
|
|
|
- if (_size == _capacity) reserve(_capacity*Growth);
|
|
|
- new (&_data[_size++]) T(std::forward<Args>(args)...);
|
|
|
+ // allow move
|
|
|
+ vector& operator=(vector&& other) noexcept{
|
|
|
+ if(_data){
|
|
|
+ std::destroy(begin(), end());
|
|
|
+ free(_data);
|
|
|
+ }
|
|
|
+ new (this) vector(std::move(other));
|
|
|
+ return *this;
|
|
|
}
|
|
|
+ // disallow copy
|
|
|
+ vector& operator=(const vector& other) = delete;
|
|
|
+
|
|
|
+ bool empty() const { return _size == 0; }
|
|
|
+ int size() const { return _size; }
|
|
|
+ int capacity() const { return _capacity; }
|
|
|
+ T& back() { return _data[_size-1]; }
|
|
|
+
|
|
|
+ T* begin() const { return _data; }
|
|
|
+ T* end() const { return _data + _size; }
|
|
|
+ T* data() const { return _data; }
|
|
|
|
|
|
void reserve(int cap){
|
|
|
- if(cap <= _capacity) return;
|
|
|
- _capacity = cap;
|
|
|
- T* old_data = _data;
|
|
|
- _data = (T*)pool128_alloc(_capacity * SizeT);
|
|
|
- if(old_data != nullptr){
|
|
|
- memcpy(_data, old_data, SizeT * _size);
|
|
|
- pool128_dealloc(old_data);
|
|
|
+ if(cap < 4) cap = 4; // minimum capacity
|
|
|
+ if(cap <= capacity()) return;
|
|
|
+ T* new_data = (T*)malloc(sizeof(T) * cap);
|
|
|
+ if constexpr(std::is_trivially_copyable_v<T>){
|
|
|
+ memcpy(new_data, _data, sizeof(T) * _size);
|
|
|
+ }else{
|
|
|
+ for(int i=0; i<_size; i++){
|
|
|
+ new(&new_data[i]) T(std::move(_data[i]));
|
|
|
+ _data[i].~T();
|
|
|
+ }
|
|
|
}
|
|
|
+ if(_data) free(_data);
|
|
|
+ _data = new_data;
|
|
|
+ _capacity = cap;
|
|
|
+ }
|
|
|
+
|
|
|
+ void resize(int size){
|
|
|
+ reserve(size);
|
|
|
+ _size = size;
|
|
|
}
|
|
|
|
|
|
- void pop_back() { _size--; }
|
|
|
- T popx_back() { T t = std::move(_data[_size-1]); _size--; return t; }
|
|
|
-
|
|
|
- void extend(const pod_vector& other){
|
|
|
- for(int i=0; i<other.size(); i++) push_back(other[i]);
|
|
|
+ void push_back(const T& t){
|
|
|
+ if(_size == _capacity) reserve(_capacity * 2);
|
|
|
+ new (&_data[_size++]) T(t);
|
|
|
}
|
|
|
|
|
|
- void extend(const T* begin, const T* end){
|
|
|
- for(auto it=begin; it!=end; it++) push_back(*it);
|
|
|
+ void push_back(T&& t){
|
|
|
+ if(_size == _capacity) reserve(_capacity * 2);
|
|
|
+ new(&_data[_size++]) T(std::move(t));
|
|
|
}
|
|
|
|
|
|
- T& operator[](int index) { return _data[index]; }
|
|
|
- const T& operator[](int index) const { return _data[index]; }
|
|
|
+ template<typename... Args>
|
|
|
+ void emplace_back(Args&&... args){
|
|
|
+ if(_size == _capacity) reserve(_capacity * 2);
|
|
|
+ new(&_data[_size++]) T(std::forward<Args>(args)...);
|
|
|
+ }
|
|
|
|
|
|
- T* begin() { return _data; }
|
|
|
- T* end() { return _data + _size; }
|
|
|
- const T* begin() const { return _data; }
|
|
|
- const T* end() const { return _data + _size; }
|
|
|
- T& back() { return _data[_size - 1]; }
|
|
|
- const T& back() const { return _data[_size - 1]; }
|
|
|
+ T& operator[](int i) { return _data[i]; }
|
|
|
+ const T& operator[](int i) const { return _data[i]; }
|
|
|
|
|
|
- bool empty() const { return _size == 0; }
|
|
|
- int size() const { return _size; }
|
|
|
- T* data() { return _data; }
|
|
|
- const T* data() const { return _data; }
|
|
|
- void clear() { _size=0; }
|
|
|
-
|
|
|
- template<typename __ValueT>
|
|
|
- void insert(int i, __ValueT&& val){
|
|
|
- if (_size == _capacity) reserve(_capacity*Growth);
|
|
|
- for(int j=_size; j>i; j--) _data[j] = _data[j-1];
|
|
|
- _data[i] = std::forward<__ValueT>(val);
|
|
|
+ void extend(T* begin, T* end){
|
|
|
+ int n = end - begin;
|
|
|
+ reserve(_size + n);
|
|
|
+ for(int i=0; i<n; i++) new(&_data[_size++]) T(begin[i]);
|
|
|
+ }
|
|
|
+
|
|
|
+ void insert(int index, const T& t){
|
|
|
+ if(_size == _capacity) reserve(_capacity * 2);
|
|
|
+ for(int i=_size; i>index; i--) _data[i] = std::move(_data[i-1]);
|
|
|
+ _data[index] = t;
|
|
|
_size++;
|
|
|
}
|
|
|
|
|
|
- void erase(int i){
|
|
|
- for(int j=i; j<_size-1; j++) _data[j] = _data[j+1];
|
|
|
+ void erase(int index){
|
|
|
+ for(int i=index; i<_size-1; i++) _data[i] = std::move(_data[i+1]);
|
|
|
_size--;
|
|
|
}
|
|
|
|
|
|
- void reverse(){
|
|
|
- std::reverse(_data, _data+_size);
|
|
|
+ void pop_back(){
|
|
|
+ PK_DEBUG_ASSERT(_size > 0);
|
|
|
+ _size--;
|
|
|
+ if constexpr(!std::is_trivially_destructible_v<T>){
|
|
|
+ _data[_size].~T();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- void resize(int size){
|
|
|
- if(size > _capacity) reserve(size);
|
|
|
- _size = size;
|
|
|
+ void clear(){
|
|
|
+ std::destroy(begin(), end());
|
|
|
+ _size = 0;
|
|
|
}
|
|
|
|
|
|
std::pair<T*, int> detach() noexcept {
|
|
|
- T* p = _data;
|
|
|
- int size = _size;
|
|
|
+ std::pair<T*, int> retval(_data, _size);
|
|
|
_data = nullptr;
|
|
|
+ _capacity = 0;
|
|
|
_size = 0;
|
|
|
- return {p, size};
|
|
|
+ return retval;
|
|
|
}
|
|
|
|
|
|
- ~pod_vector() {
|
|
|
- if(_data != nullptr) pool128_dealloc(_data);
|
|
|
+ void swap(vector& other){
|
|
|
+ std::swap(_data, other._data);
|
|
|
+ std::swap(_capacity, other._capacity);
|
|
|
+ std::swap(_size, other._size);
|
|
|
}
|
|
|
-};
|
|
|
|
|
|
+ ~vector(){
|
|
|
+ if(_data){
|
|
|
+ std::destroy(begin(), end());
|
|
|
+ free(_data);
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
|
|
|
-template <typename T, typename Container=std::vector<T>>
|
|
|
+template <typename T, typename Container=vector<T>>
|
|
|
class stack{
|
|
|
Container vec;
|
|
|
public:
|
|
|
@@ -167,7 +236,7 @@ public:
|
|
|
const Container& container() const { return vec; }
|
|
|
};
|
|
|
|
|
|
-template <typename T, typename Container=std::vector<T>>
|
|
|
+template <typename T, typename Container=vector<T>>
|
|
|
class stack_no_copy: public stack<T, Container>{
|
|
|
public:
|
|
|
stack_no_copy() = default;
|