/* see copyright notice in squirrel.h */ #ifndef _SQUTILS_H_ #define _SQUTILS_H_ #include "../../fmt/format.h" #include "../../../script/script_fatalerror.hpp" #include void *sq_vm_malloc(SQUnsignedInteger size); void *sq_vm_realloc(void *p,SQUnsignedInteger oldsize,SQUnsignedInteger size); void sq_vm_free(void *p,SQUnsignedInteger size); #define sq_new(__ptr,__type) {__ptr=(__type *)sq_vm_malloc(sizeof(__type));new (__ptr) __type;} #define sq_delete(__ptr,__type) {__ptr->~__type();sq_vm_free(__ptr,sizeof(__type));static_assert(!std::is_base_of());} #define sq_delete_refcounted(__ptr,__type) {__ptr->~__type();__ptr->SQDeallocate(__ptr);} #define SQ_MALLOC(__size) sq_vm_malloc((__size)); #define SQ_FREE(__ptr,__size) {sq_vm_free((__ptr),(__size));static_assert(!std::is_base_of>());} #define SQ_REALLOC(__ptr,__oldsize,__size) sq_vm_realloc((__ptr),(__oldsize),(__size)); //sqvector mini vector class, supports objects by value template class sqvector { public: sqvector() { _vals = nullptr; _size = 0; _allocated = 0; } sqvector(const sqvector& v) { copy(v); } void copy(const sqvector& v) { resize(v._size); for(SQUnsignedInteger i = 0; i < v._size; i++) { new ((void *)&_vals[i]) T(v._vals[i]); } _size = v._size; } ~sqvector() { if(_allocated) { /* Break freeing loops, if this vector (indirectly) links to itself. */ size_t allocated_size = _allocated * sizeof(T); _allocated = 0; for(size_t i = 0; i < _size; i++) _vals[i].~T(); SQ_FREE(_vals, allocated_size); } } void reserve(SQUnsignedInteger newsize) { _realloc(newsize); } void resize(SQUnsignedInteger newsize, const T& fill = T()) { if(newsize > _allocated) _realloc(newsize); if(newsize > _size) { while(_size < newsize) { new ((void *)&_vals[_size]) T(fill); _size++; } } else{ for(SQUnsignedInteger i = newsize; i < _size; i++) { _vals[i].~T(); } _size = (size_t)newsize; } } void shrinktofit() { if(_size > 4) { _realloc(_size); } } T& top() const { return _vals[_size - 1]; } inline SQUnsignedInteger size() const { return _size; } bool empty() const { return (_size <= 0); } inline T &push_back(const T& val = T()) { if(_allocated <= _size) _realloc(_size * 2); return *(new ((void *)&_vals[_size++]) T(val)); } inline void pop_back() { _size--; _vals[_size].~T(); } void insert(SQUnsignedInteger idx, const T& val) { resize(_size + 1); for(SQUnsignedInteger i = _size - 1; i > idx; i--) { _vals[i] = _vals[i - 1]; } _vals[idx] = val; } void remove(SQUnsignedInteger idx) { _vals[idx].~T(); if(idx < (_size - 1)) { memmove(static_cast(&_vals[idx]), &_vals[idx+1], sizeof(T) * (_size - (size_t)idx - 1)); } _size--; } SQUnsignedInteger capacity() { return _allocated; } inline T &back() const { return _vals[_size - 1]; } inline T& operator[](SQUnsignedInteger pos) const{ assert(pos < _allocated); return _vals[pos]; } T* _vals; private: void _realloc(SQUnsignedInteger newsize) { newsize = (newsize > 0)?newsize:4; if (newsize > SIZE_MAX / sizeof(T)) { std::string msg = fmt::format("cannot resize to {}", newsize); throw Script_FatalError(msg); } _vals = (T*)SQ_REALLOC(_vals, _allocated * sizeof(T), newsize * sizeof(T)); _allocated = (size_t)newsize; } size_t _size; size_t _allocated; }; #endif //_SQUTILS_H_