2024-02-18 18:08:11 +08:00

173 lines
4.9 KiB
C++

#pragma once
#include "common.h"
#include "memory.h"
namespace pkpy{
template<typename T>
struct pod_vector{
static_assert(64 % sizeof(T) == 0);
static_assert(is_pod<T>::value);
static constexpr int N = 64 / sizeof(T);
static_assert(N >= 4);
int _size;
int _capacity;
T* _data;
pod_vector(): _size(0), _capacity(N) {
_data = (T*)pool64_alloc(_capacity * sizeof(T));
}
// support initializer list
pod_vector(std::initializer_list<T> il): _size(il.size()), _capacity(std::max(N, _size)) {
_data = (T*)pool64_alloc(_capacity * sizeof(T));
for(int i=0; i<_size; i++) _data[i] = *(il.begin() + i);
}
pod_vector(int size): _size(size), _capacity(std::max(N, size)) {
_data = (T*)pool64_alloc(_capacity * sizeof(T));
}
pod_vector(const pod_vector& other): _size(other._size), _capacity(other._capacity) {
_data = (T*)pool64_alloc(_capacity * sizeof(T));
memcpy(_data, other._data, sizeof(T) * _size);
}
pod_vector(pod_vector&& other) noexcept {
_size = other._size;
_capacity = other._capacity;
_data = other._data;
other._data = nullptr;
}
pod_vector& operator=(pod_vector&& other) noexcept {
if(_data!=nullptr) pool64_dealloc(_data);
_size = other._size;
_capacity = other._capacity;
_data = other._data;
other._data = nullptr;
return *this;
}
// remove copy assignment
pod_vector& operator=(const pod_vector& other) = delete;
template<typename __ValueT>
void push_back(__ValueT&& t) {
if (_size == _capacity) reserve(_capacity*2);
_data[_size++] = std::forward<__ValueT>(t);
}
template<typename... Args>
void emplace_back(Args&&... args) {
if (_size == _capacity) reserve(_capacity*2);
new (&_data[_size++]) T(std::forward<Args>(args)...);
}
void reserve(int cap){
if(cap <= _capacity) return;
_capacity = cap;
T* old_data = _data;
_data = (T*)pool64_alloc(_capacity * sizeof(T));
if(old_data != nullptr){
memcpy(_data, old_data, sizeof(T) * _size);
pool64_dealloc(old_data);
}
}
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 extend(const T* begin, const T* end){
for(auto it=begin; it!=end; it++) push_back(*it);
}
T& operator[](int index) { return _data[index]; }
const T& operator[](int index) const { return _data[index]; }
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]; }
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*2);
for(int j=_size; j>i; j--) _data[j] = _data[j-1];
_data[i] = std::forward<__ValueT>(val);
_size++;
}
void erase(int i){
for(int j=i; j<_size-1; j++) _data[j] = _data[j+1];
_size--;
}
void reverse(){
std::reverse(_data, _data+_size);
}
void resize(int size){
if(size > _capacity) reserve(size);
_size = size;
}
std::pair<T*, int> detach() noexcept {
T* p = _data;
int size = _size;
_data = nullptr;
_size = 0;
return {p, size};
}
~pod_vector() {
if(_data != nullptr) pool64_dealloc(_data);
}
};
template <typename T, typename Container=std::vector<T>>
class stack{
Container vec;
public:
void push(const T& t){ vec.push_back(t); }
void push(T&& t){ vec.push_back(std::move(t)); }
template<typename... Args>
void emplace(Args&&... args){
vec.emplace_back(std::forward<Args>(args)...);
}
void pop(){ vec.pop_back(); }
void clear(){ vec.clear(); }
bool empty() const { return vec.empty(); }
size_t size() const { return vec.size(); }
T& top(){ return vec.back(); }
const T& top() const { return vec.back(); }
T popx(){ T t = std::move(vec.back()); vec.pop_back(); return t; }
void reserve(int n){ vec.reserve(n); }
Container& data() { return vec; }
};
template <typename T, typename Container=std::vector<T>>
class stack_no_copy: public stack<T, Container>{
public:
stack_no_copy() = default;
stack_no_copy(const stack_no_copy& other) = delete;
stack_no_copy& operator=(const stack_no_copy& other) = delete;
stack_no_copy(stack_no_copy&& other) noexcept = default;
stack_no_copy& operator=(stack_no_copy&& other) noexcept = default;
};
} // namespace pkpy