mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
173 lines
4.9 KiB
C++
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
|