Menu/60_Utils/02_Bean/beans/std/vector.bean
2019-07-02 03:32:09 +00:00

208 lines
5.0 KiB
Plaintext
Executable File

class std+, vector<T> {
import rt::c;
struct vector {
ptr void;
page size_t;
capacity size_t;
used size_t;
}
func constructor() {
this.ptr = null;
this.page = sizeof(T, 32);
this.capacity = 0;
this.used = 0;
}
func destructor() {
this->clear(true);
}
inline size() size_t {
return this.used;
}
inline resize(count size_t) {
if count {
this->adjust_size(this.used = sizeof(T, count));
else
this.used = 0;
}
}
inline count() size_t {
return this.used / sizeof(T);
}
inline capacity() size_t {
return this.capacity;
}
inline empty() bool {
return !this.used;
}
inline reserve(count size_t) {
if count;
this->adjust_size(sizeof(T, count));
}
func shrink_to_fit() {
// ...
}
inline at(pos size_t) .T {
var offset size_t = sizeof(T, pos);
if offset < this.used;
return this.ptr + offset;
return null;
}
inline front() .T {
if this.used;
return this.ptr;
return null;
}
inline back() .T {
if this.used;
return this.ptr + this.used - sizeof(T);
return null;
}
inline data() .T {
return this.ptr;
}
inline alloc() .T {
var used size_t = this.used;
this->adjust_size(this.used += sizeof(T));
return this.ptr + used;
}
inline new() .T {
func = this->alloc();
#if objectid(T).is_class;
#if objectid(T).func.constructor;
func->constructor();
#endif
#elseif objectid(T).is_struct;
constructor(func);
#endif
}
inline push_back(value T) {
.this->alloc() = value;
}
inline push_back_ref(value. T) {
.this->alloc() = .value;
}
func pop_back(count size_t = 1) {
var size size_t = sizeof(T, count);
#if objectid(T).is_struct;
if this.used <= size {
this->clear();
else
for ; count; count-- {
var t. T = this.ptr + (this.used -= sizeof(T));
#if objectid(T).is_class;
#if objectid(T).func.destructor;
t->destructor();
#endif
#elseif objectid(T).is_struct;
destructor(t);
#endif
}
}
#else
if this.used <= size {
this.used = 0;
else
this.used -= size;
}
#endif
}
func insert(pos size_t, value T) {
// ...
}
func insert_ref(pos size_t, value. T) {
// ...
}
func erase(pos size_t) bool {
var count size_t = this->count();
if !count or count <= pos;
return false;
if (count - 1) == pos {
this->pop_back();
else
var offset size_t = pos * sizeof(T);
var move size_t = offset + sizeof(T);
var t. T = this.ptr + offset;
#if objectid(T).is_class;
#if objectid(T).func.destructor;
t->destructor();
#endif
#elseif objectid(T).is_struct;
destructor(t);
#endif
memmove(t, this.ptr + move, this.used - move);
this.used -= sizeof(T);
}
return true;
}
func erases(start size_t, end size_t) bool {
// ...
}
inline swap(other. vector) {
var tmp $vector = .this;
.this = .other;
.other = tmp;
}
func clear(free_mem bool = false) {
#if objectid(T).is_class;
#if objectid(T).func.destructor;
forvar count size_t = this->count(); count;;
this->at(--count)->destructor();
#endif
#elseif objectid(T).is_struct;
forvar count size_t = this->count(); count;;
destructor(this->at(--count));
#endif
this.used = 0;
if free_mem {
if this.ptr ~= null {
free(this.ptr);
this.ptr = null;
this.capacity = 0;
}
}
}
private func adjust_size(size size_t) {
var capacity size_t = this.capacity;
if !capacity;
capacity = this.page;
while capacity < size {
if capacity & 0x80000000 {
printf("vector: out of memory\n");
exit(1);
}
capacity <<= 1;
}
if capacity ~= this.capacity;
this.ptr = realloc(this.ptr, this.capacity = capacity);
}
}