File array.hpp
File List > include > simplesquirrel > array.hpp
Go to the documentation of this file.
#pragma once
#ifndef SSQ_ARRAY_HEADER_H
#define SSQ_ARRAY_HEADER_H
#include "object.hpp"
#include "args.hpp"
#include <squirrel.h>
#include <vector>
namespace ssq {
class SSQ_API Array: public Object {
public:
Array(HSQUIRRELVM vm, size_t len = 0);
virtual ~Array() = default;
template<typename T>
Array(HSQUIRRELVM vm, const std::vector<T>& vector):Object(vm) {
sq_newarray(vm, 0);
sq_getstackobj(vm, -1, &obj);
sq_addref(vm, &obj);
for(const auto& val : vector) {
detail::push(vm, val);
if(SQ_FAILED(sq_arrayappend(vm, -2))) {
sq_pop(vm, 2);
throw TypeException("Failed to push value to back of the array");
}
}
sq_pop(vm, 1); // Pop array
}
explicit Array(const Object& object);
Array(const Array& other);
Array(Array&& other) NOEXCEPT;
size_t size();
template<typename T>
void push(const T& value) {
sq_pushobject(vm, obj);
detail::push(vm, value);
if(SQ_FAILED(sq_arrayappend(vm, -2))) {
sq_pop(vm, 2);
throw TypeException("Failed to push value to back of the array");
}
sq_pop(vm, 1);
}
template<typename T>
T popAndGet() {
sq_pushobject(vm, obj);
auto s = sq_getsize(vm, -1);
if(s == 0) {
sq_pop(vm, 1);
throw TypeException("Out of bounds");
}
try {
if(SQ_FAILED(sq_arraypop(vm, -1, true))) {
sq_pop(vm, 1);
throw TypeException("Failed to pop value from back of the array");
}
T ret(detail::pop<T>(vm, -1));
sq_pop(vm, 1);
return std::move(ret);
} catch (...) {
sq_pop(vm, 1);
std::rethrow_exception(std::current_exception());
}
}
void pop();
template<typename T>
T get(size_t index) {
sq_pushobject(vm, obj);
auto s = static_cast<size_t>(sq_getsize(vm, -1));
if(index >= s) {
sq_pop(vm, 1);
throw TypeException("Out of bounds");
}
detail::push(vm, index);
if(SQ_FAILED(sq_get(vm, -2))) {
sq_pop(vm, 1);
throw TypeException("Failed to get value from the array");
}
try {
T ret(detail::pop<T>(vm, -1));
sq_pop(vm, 2);
return std::move(ret);
} catch (...) {
sq_pop(vm, 2);
std::rethrow_exception(std::current_exception());
}
}
template<typename T>
T begin() {
return get<T>(0);
}
template<typename T>
T back() {
auto s = size();
if (s == 0) throw TypeException("Out of bounds");
return get<T>(s - 1);
}
template<typename T>
void set(size_t index, const T& value) {
sq_pushobject(vm, obj);
auto s = static_cast<size_t>(sq_getsize(vm, -1));
if(index >= s) {
sq_pop(vm, 1);
throw TypeException("Out of bounds");
}
detail::push(vm, index);
detail::push(vm, value);
if(SQ_FAILED(sq_set(vm, -3))) {
sq_pop(vm, 1);
throw TypeException("Failed to set value in the array");
}
sq_pop(vm, 1);
}
std::vector<Object> convertRaw();
template<typename T>
std::vector<T> convert() {
sq_pushobject(vm, obj);
auto s = static_cast<size_t>(sq_getsize(vm, -1));
std::vector<T> ret;
ret.reserve(s);
while(s--) {
sq_arraypop(vm, -1, true);
ret.push_back(detail::pop<T>(vm, -1));
}
sq_pop(vm, 1);
return ret;
}
Array& operator = (const Array& other);
Array& operator = (Array&& other) NOEXCEPT;
};
#ifndef DOXYGEN_SHOULD_SKIP_THIS
namespace detail {
template<>
inline Array popValue(HSQUIRRELVM vm, SQInteger index){
checkType(vm, index, OT_ARRAY);
Array val(vm);
if (SQ_FAILED(sq_getstackobj(vm, index, &val.getRaw()))) throw TypeException("Could not get Array from squirrel stack");
sq_addref(vm, &val.getRaw());
return val;
}
}
#endif
}
#endif