File args.hpp
File List > include > simplesquirrel > args.hpp
Go to the documentation of this file.
#pragma once
#ifndef SSQ_ARGS_HEADER_H
#define SSQ_ARGS_HEADER_H
#include "exceptions.hpp"
#include <squirrel.h>
#include <iostream>
#include <typeinfo>
#include <vector>
namespace ssq {
class Array;
class Enum;
class VM;
class SqWeakRef;
#ifndef DOXYGEN_SHOULD_SKIP_THIS
namespace detail {
SSQ_API void addClassObj(HSQUIRRELVM vm, size_t hashCode, const HSQOBJECT& obj);
SSQ_API const HSQOBJECT& getClassObj(HSQUIRRELVM vm, size_t hashCode);
template<class T>
static SQInteger classDestructor(SQUserPointer ptr, SQInteger size) {
T* p = static_cast<T*>(ptr);
delete p;
return 0;
}
template<class T>
static SQInteger classPtrDestructor(SQUserPointer ptr, SQInteger size) {
T** p = static_cast<T**>(ptr);
delete *p;
return 0;
}
inline void checkType(HSQUIRRELVM vm, SQInteger index, SQObjectType expected){
auto type = sq_gettype(vm, index);
if (expected == OT_CLOSURE) {
if (type != OT_CLOSURE && type != OT_NATIVECLOSURE) throw TypeException("bad cast", typeToStr(Type(expected)), typeToStr(Type(type)));
return;
}
if (type != expected) throw TypeException("bad cast", typeToStr(Type(expected)), typeToStr(Type(type)));
}
template<typename T>
inline T popValue(HSQUIRRELVM vm, SQInteger index){
SQObjectType type = sq_gettype(vm, index);
SQUserPointer ptr;
SQUserPointer typetag;
if(type == OT_USERDATA) {
sq_getuserdata(vm, index, &ptr, &typetag);
if(reinterpret_cast<size_t>(typetag) != typeid(T).hash_code()) {
throw TypeException("bad cast", typeid(T).name(), "UNKNOWN");
}
T** p = reinterpret_cast<T**>(ptr);
return T(**p);
}
else if(type == OT_INSTANCE) {
sq_getinstanceup(vm, index, &ptr, &typetag);
sq_gettypetag(vm, index, &typetag);
if(reinterpret_cast<size_t>(typetag) != typeid(T*).hash_code()) {
throw TypeException("bad cast", typeid(T).name(), "UNKNOWN");
}
T* p = reinterpret_cast<T*>(ptr);
return T(*p);
}
else {
throw TypeException("bad cast", "INSTANCE", typeToStr(Type(type)));
}
}
template<typename T>
inline T popPointer(HSQUIRRELVM vm, SQInteger index) {
auto type = sq_gettype(vm, index);
if(type == OT_USERPOINTER) {
SQUserPointer val;
if (SQ_FAILED(sq_getuserpointer(vm, index, &val))) {
throw TypeException("Could not get instance from squirrel stack");
}
return reinterpret_cast<T>(val);
}
else {
if (type != OT_INSTANCE) throw TypeException("bad cast", typeToStr(Type(OT_INSTANCE)), typeToStr(Type(type)));
SQUserPointer val;
/*sq_gettypetag(vm, index, &val);
if (reinterpret_cast<size_t>(val) != typeid(T).hash_code()) {
throw TypeException("bad cast", typeid(T).name(), "UNKNOWN");
}*/
if (SQ_FAILED(sq_getinstanceup(vm, index, &val, nullptr))) {
throw TypeException("Could not get instance from squirrel stack");
}
return reinterpret_cast<T>(val);
}
}
template<>
inline Object popValue(HSQUIRRELVM vm, SQInteger index){
Object val(vm);
if (SQ_FAILED(sq_getstackobj(vm, index, &val.getRaw()))) throw TypeException("Could not get Object from squirrel stack");
sq_addref(vm, &val.getRaw());
return val;
}
template<>
inline char popValue(HSQUIRRELVM vm, SQInteger index){
checkType(vm, index, OT_INTEGER);
SQInteger val;
if (SQ_FAILED(sq_getinteger(vm, index, &val))) throw TypeException("Could not get char from squirrel stack");
return static_cast<char>(val);
}
template<>
inline signed char popValue(HSQUIRRELVM vm, SQInteger index){
checkType(vm, index, OT_INTEGER);
SQInteger val;
if (SQ_FAILED(sq_getinteger(vm, index, &val))) throw TypeException("Could not get signed char from squirrel stack");
return static_cast<signed char>(val);
}
template<>
inline short popValue(HSQUIRRELVM vm, SQInteger index){
checkType(vm, index, OT_INTEGER);
SQInteger val;
if (SQ_FAILED(sq_getinteger(vm, index, &val))) throw TypeException("Could not get short from squirrel stack");
return static_cast<short>(val);
}
template<>
inline int popValue(HSQUIRRELVM vm, SQInteger index){
checkType(vm, index, OT_INTEGER);
SQInteger val;
if (SQ_FAILED(sq_getinteger(vm, index, &val))) throw TypeException("Could not get int from squirrel stack");
return static_cast<int>(val);
}
template<>
inline long popValue(HSQUIRRELVM vm, SQInteger index){
checkType(vm, index, OT_INTEGER);
SQInteger val;
if (SQ_FAILED(sq_getinteger(vm, index, &val))) throw TypeException("Could not get long from squirrel stack");
return static_cast<long>(val);
}
template<>
inline unsigned char popValue(HSQUIRRELVM vm, SQInteger index){
checkType(vm, index, OT_INTEGER);
SQInteger val;
if (SQ_FAILED(sq_getinteger(vm, index, &val))) throw TypeException("Could not get unsigned char from squirrel stack");
return static_cast<unsigned char>(val);
}
template<>
inline unsigned short popValue(HSQUIRRELVM vm, SQInteger index){
checkType(vm, index, OT_INTEGER);
SQInteger val;
if (SQ_FAILED(sq_getinteger(vm, index, &val))) throw TypeException("Could not get unsigned short from squirrel stack");
return static_cast<unsigned short>(val);
}
template<>
inline unsigned int popValue(HSQUIRRELVM vm, SQInteger index){
checkType(vm, index, OT_INTEGER);
SQInteger val;
if (SQ_FAILED(sq_getinteger(vm, index, &val))) throw TypeException("Could not get unsigned int from squirrel stack");
return static_cast<unsigned int>(val);
}
template<>
inline unsigned long popValue(HSQUIRRELVM vm, SQInteger index){
checkType(vm, index, OT_INTEGER);
SQInteger val;
if (SQ_FAILED(sq_getinteger(vm, index, &val))) throw TypeException("Could not get unsigned long from squirrel stack");
return static_cast<unsigned long>(val);
}
#ifdef _SQ64
template<>
inline long long popValue(HSQUIRRELVM vm, SQInteger index){
checkType(vm, index, OT_INTEGER);
SQInteger val;
if (SQ_FAILED(sq_getinteger(vm, index, &val))) throw TypeException("Could not get long long from squirrel stack");
return static_cast<long long>(val);
}
template<>
inline unsigned long long popValue(HSQUIRRELVM vm, SQInteger index){
checkType(vm, index, OT_INTEGER);
SQInteger val;
if (SQ_FAILED(sq_getinteger(vm, index, &val))) throw TypeException("Could not get unsigned long long from squirrel stack");
return static_cast<unsigned long long>(val);
}
#endif
#ifdef SQUSEDOUBLE
template<>
inline double popValue(HSQUIRRELVM vm, SQInteger index){
checkType(vm, index, OT_INTEGER);
SQFloat val;
if (SQ_FAILED(sq_getfloat(vm, index, &val))) throw TypeException("Could not get double from squirrel stack");
return static_cast<double>(val);
}
#endif
template<>
inline float popValue(HSQUIRRELVM vm, SQInteger index){
checkType(vm, index, OT_FLOAT);
SQFloat val;
if (SQ_FAILED(sq_getfloat(vm, index, &val))) throw TypeException("Could not get float from squirrel stack");
return static_cast<float>(val);
}
template<>
inline bool popValue(HSQUIRRELVM vm, SQInteger index){
checkType(vm, index, OT_BOOL);
SQBool val;
if (SQ_FAILED(sq_getbool(vm, index, &val))) throw TypeException("Could not get bool from squirrel stack");
return val == 1;
}
#ifdef SQUNICODE
template<>
inline std::wstring popValue(HSQUIRRELVM vm, SQInteger index){
checkType(vm, index, OT_STRING);
const SQChar* val;
if (SQ_FAILED(sq_getstring(vm, index, &val))) throw TypeException("Could not get string from squirrel stack");
if(val == nullptr)
{
return std::wstring(L"");
}
SQInteger len = sq_getsize(vm,index);
return std::wstring(val,len);
}
#else
template<>
inline std::string popValue(HSQUIRRELVM vm, SQInteger index){
checkType(vm, index, OT_STRING);
const SQChar* val;
if (SQ_FAILED(sq_getstring(vm, index, &val))) throw TypeException("Could not get string from squirrel stack");
if(val == nullptr)
{
return std::string("");
}
SQInteger len = sq_getsize(vm,index);
return std::string(val,len);
}
#endif
template <typename T> inline typename std::enable_if<!std::is_pointer<T>::value, T>::type
pop(HSQUIRRELVM vm, SQInteger index) {
return popValue<typename std::remove_cv<T>::type>(vm, index);
}
template <typename T> inline typename std::enable_if<std::is_pointer<T>::value, T>::type
pop(HSQUIRRELVM vm, SQInteger index) {
return popPointer<T>(vm, index);
}
template<typename T>
inline void pushByCopy(HSQUIRRELVM vm, const T& value) {
static const auto hashCode = typeid(T*).hash_code();
try {
sq_pushobject(vm, getClassObj(vm, hashCode));
sq_createinstance(vm, -1);
sq_remove(vm, -2);
sq_setinstanceup(vm, -1, reinterpret_cast<SQUserPointer>(new T(value)));
sq_settypetag(vm, -1, reinterpret_cast<SQUserPointer>(hashCode));
sq_setreleasehook(vm, -1, classDestructor<T>);
} catch (std::out_of_range& e) {
(void)e;
T** data = reinterpret_cast<T**>(sq_newuserdata(vm, sizeof(T*)));
*data = new T(value);
sq_setreleasehook(vm, -1, classPtrDestructor<T>);
sq_settypetag(vm, -1, reinterpret_cast<SQUserPointer>(typeid(T).hash_code()));
}
}
template<typename T>
inline void pushValue(HSQUIRRELVM vm, const T& value){
pushByCopy<T>(vm, value);
}
SSQ_API void pushRaw(HSQUIRRELVM vm, const Object& value);
SSQ_API void pushRaw(HSQUIRRELVM vm, const Class& value);
SSQ_API void pushRaw(HSQUIRRELVM vm, const Instance& value);
SSQ_API void pushRaw(HSQUIRRELVM vm, const Table& value);
SSQ_API void pushRaw(HSQUIRRELVM vm, const Function& value);
SSQ_API void pushRaw(HSQUIRRELVM vm, const Enum& value);
SSQ_API void pushRaw(HSQUIRRELVM vm, const Array& value);
SSQ_API void pushRaw(HSQUIRRELVM vm, const SqWeakRef& value);
template<>
inline void pushValue(HSQUIRRELVM vm, const std::nullptr_t& value){
(void)value;
sq_pushnull(vm);
}
template<>
inline void pushValue(HSQUIRRELVM vm, const HSQOBJECT& value){
sq_pushobject(vm, value);
}
template<>
inline void pushValue(HSQUIRRELVM vm, const Object& value){
pushRaw(vm, value);
}
template<>
inline void pushValue(HSQUIRRELVM vm, const Class& value){
pushRaw(vm, value);
}
template<>
inline void pushValue(HSQUIRRELVM vm, const Instance& value){
pushRaw(vm, value);
}
template<>
inline void pushValue(HSQUIRRELVM vm, const SqWeakRef& value) {
pushRaw(vm, value);
}
template<>
inline void pushValue(HSQUIRRELVM vm, const Table& value){
pushRaw(vm, value);
}
template<>
inline void pushValue(HSQUIRRELVM vm, const Function& value){
pushRaw(vm, value);
}
template<>
inline void pushValue(HSQUIRRELVM vm, const Enum& value){
pushRaw(vm, value);
}
template<>
inline void pushValue(HSQUIRRELVM vm, const Array& value){
pushRaw(vm, value);
}
template<>
inline void pushValue(HSQUIRRELVM vm, const bool& value) {
sq_pushbool(vm, value);
}
template<>
inline void pushValue(HSQUIRRELVM vm, const int& value) {
sq_pushinteger(vm, value);
}
template<>
inline void pushValue(HSQUIRRELVM vm, const short& value) {
sq_pushinteger(vm, value);
}
template<>
inline void pushValue(HSQUIRRELVM vm, const long& value) {
sq_pushinteger(vm, value);
}
template<>
inline void pushValue(HSQUIRRELVM vm, const char& value) {
sq_pushinteger(vm, value);
}
template<>
inline void pushValue(HSQUIRRELVM vm, const signed char& value) {
sq_pushinteger(vm, value);
}
template<>
inline void pushValue(HSQUIRRELVM vm, const unsigned int& value) {
sq_pushinteger(vm, *reinterpret_cast<const int*>(&value));
}
template<>
inline void pushValue(HSQUIRRELVM vm, const unsigned short& value) {
sq_pushinteger(vm, *reinterpret_cast<const short*>(&value));
}
template<>
inline void pushValue(HSQUIRRELVM vm, const unsigned long& value) {
sq_pushinteger(vm, *reinterpret_cast<const long*>(&value));
}
template<>
inline void pushValue(HSQUIRRELVM vm, const unsigned char& value) {
sq_pushinteger(vm, *reinterpret_cast<const char*>(&value));
}
#ifdef _SQ64
template<>
inline void pushValue(HSQUIRRELVM vm, const unsigned long long& value) {
sq_pushinteger(vm, *reinterpret_cast<const long long*>(&value));
}
template<>
inline void pushValue(HSQUIRRELVM vm, const long long& value) {
sq_pushinteger(vm, *reinterpret_cast<const long long*>(&value));
}
#endif
#ifdef SQUSEDOUBLE
template<>
inline void pushValue(HSQUIRRELVM vm, const double& value) {
sq_pushfloat(vm, value);
}
#endif
template<>
inline void pushValue(HSQUIRRELVM vm, const float& value) {
sq_pushfloat(vm, value);
}
#ifdef SQUNICODE
template<>
inline void pushValue(HSQUIRRELVM vm, const std::wstring& value) {
sq_pushstring(vm, value.c_str(), value.size());
}
#else
template<>
inline void pushValue(HSQUIRRELVM vm, const std::string& value) {
sq_pushstring(vm, value.c_str(), value.size());
}
#endif
template<typename T>
inline void pushByPtr(HSQUIRRELVM vm, T* value) {
static const auto hashCode = typeid(T*).hash_code();
if (value == nullptr) {
sq_pushnull(vm);
}
else {
try {
sq_pushobject(vm, getClassObj(vm, hashCode));
sq_createinstance(vm, -1);
sq_remove(vm, -2);
sq_setinstanceup(vm, -1, (SQUserPointer)(value));
sq_settypetag(vm, -1, reinterpret_cast<SQUserPointer>(hashCode));
}
catch (std::out_of_range& e) {
(void)e;
sq_pushuserpointer(vm, (SQUserPointer)(value));
}
}
}
template <typename T, typename std::enable_if<!std::is_pointer<T>::value, T>::type* = nullptr>
inline void push(HSQUIRRELVM vm, const T& value) {
pushValue<typename std::remove_pointer<typename std::remove_cv<T>::type>::type>(vm, value);
}
template <typename T, typename std::enable_if<std::is_pointer<T>::value, T>::type* = nullptr>
inline void push(HSQUIRRELVM vm, const T& value) {
pushByPtr<typename std::remove_pointer<typename std::remove_cv<T>::type>::type>(vm, value);
}
}
#endif
}
#endif