Lua function wrappers with typestring
This commit is contained in:
104
src/lua.cpp
104
src/lua.cpp
@@ -6,7 +6,7 @@
|
||||
|
||||
#include "gameobject.hh"
|
||||
|
||||
constexpr const char METATABLE_SCRIPT[] = R"(
|
||||
constexpr const char GAMEOBJECT_SCRIPT[] = R"(
|
||||
return function(metatable)
|
||||
local get_position = metatable.get_position
|
||||
local set_position = metatable.set_position
|
||||
@@ -36,16 +36,13 @@ end
|
||||
static int gameobjectSetPosition(psyqo::Lua L) {
|
||||
auto go = L.toUserdata<psxsplash::GameObject>(1);
|
||||
L.getField(2, "x");
|
||||
psyqo::FixedPoint<> x(L.toNumber(3), psyqo::FixedPoint<>::RAW);
|
||||
go->position.x = x;
|
||||
go->position.x = L.toFixedPoint(3);
|
||||
L.pop();
|
||||
L.getField(2, "y");
|
||||
psyqo::FixedPoint<> y(L.toNumber(3), psyqo::FixedPoint<>::RAW);
|
||||
go->position.y = y;
|
||||
go->position.y = L.toFixedPoint(3);
|
||||
L.pop();
|
||||
L.getField(2, "z");
|
||||
psyqo::FixedPoint<> z(L.toNumber(3), psyqo::FixedPoint<>::RAW);
|
||||
go->position.z = z;
|
||||
go->position.z = L.toFixedPoint(3);
|
||||
L.pop();
|
||||
return 0;
|
||||
}
|
||||
@@ -53,18 +50,19 @@ static int gameobjectSetPosition(psyqo::Lua L) {
|
||||
static int gameobjectGetPosition(psyqo::Lua L) {
|
||||
auto go = L.toUserdata<psxsplash::GameObject>(1);
|
||||
L.newTable();
|
||||
L.pushNumber(go->position.x.raw());
|
||||
L.push(go->position.x);
|
||||
L.setField(2, "x");
|
||||
L.pushNumber(go->position.y.raw());
|
||||
L.push(go->position.y);
|
||||
L.setField(2, "y");
|
||||
L.pushNumber(go->position.z.raw());
|
||||
L.push(go->position.z);
|
||||
L.setField(2, "z");
|
||||
return 1;
|
||||
}
|
||||
|
||||
void psxsplash::Lua::Init() {
|
||||
// Load and run the metatable script
|
||||
if (L.loadBuffer(METATABLE_SCRIPT, "buffer:metatableForAllGameObjects") == 0) {
|
||||
auto L = m_state;
|
||||
// Load and run the game objects script
|
||||
if (L.loadBuffer(GAMEOBJECT_SCRIPT, "buffer:gameObjects") == 0) {
|
||||
if (L.pcall(0, 1) == 0) {
|
||||
// This will be our metatable
|
||||
L.newTable();
|
||||
@@ -79,7 +77,7 @@ void psxsplash::Lua::Init() {
|
||||
m_metatableReference = L.ref();
|
||||
|
||||
if (L.pcall(1, 0) == 0) {
|
||||
printf("Lua script 'metatableForAllGameObjects' executed successfully");
|
||||
printf("Lua script 'gameObjects' executed successfully");
|
||||
} else {
|
||||
printf("Error registering Lua script: %s\n", L.optString(-1, "Unknown error"));
|
||||
L.clearStack();
|
||||
@@ -103,6 +101,7 @@ void psxsplash::Lua::Init() {
|
||||
}
|
||||
|
||||
void psxsplash::Lua::LoadLuaFile(const char* code, size_t len, int index) {
|
||||
auto L = m_state;
|
||||
char filename[32];
|
||||
snprintf(filename, sizeof(filename), "lua_asset:%d", index);
|
||||
if (L.loadBuffer(code, len, filename) != LUA_OK) {
|
||||
@@ -130,12 +129,37 @@ void psxsplash::Lua::LoadLuaFile(const char* code, size_t len, int index) {
|
||||
}
|
||||
}
|
||||
|
||||
void psxsplash::Lua::RegisterSceneScripts(int index) {
|
||||
if (index < 0) return;
|
||||
auto L = m_state;
|
||||
L.newTable();
|
||||
// (1) {}
|
||||
L.copy(1);
|
||||
// (1) {} (2) {}
|
||||
m_luaSceneScriptsReference = L.ref();
|
||||
// (1) {}
|
||||
L.rawGetI(LUA_REGISTRYINDEX, m_luascriptsReference);
|
||||
// (1) {} (2) scripts table
|
||||
L.pushNumber(index);
|
||||
// (1) {} (2) script environments table (2) index
|
||||
L.getTable(-2);
|
||||
// (1) {} (2) script environments table (3) script environment table for the scene
|
||||
onSceneCreationStartFunctionWrapper.resolveGlobal(L);
|
||||
onSceneCreationEndFunctionWrapper.resolveGlobal(L);
|
||||
L.pop(3);
|
||||
// empty stack
|
||||
}
|
||||
|
||||
// We're going to store the Lua table for the object at the address of the object,
|
||||
// and the table for its methods at the address of the object + 1 byte.
|
||||
void psxsplash::Lua::RegisterGameObject(GameObject* go) {
|
||||
L.push(go);
|
||||
uint8_t* ptr = reinterpret_cast<uint8_t*>(go);
|
||||
auto L = m_state;
|
||||
L.push(ptr);
|
||||
// (1) go
|
||||
L.newTable();
|
||||
// (1) go (2) {}
|
||||
L.push(go);
|
||||
L.push(ptr);
|
||||
// (1) go (2) {} (3) go
|
||||
L.setField(-2, "__cpp_ptr");
|
||||
// (1) go (2) { __cpp_ptr = go }
|
||||
@@ -150,35 +174,39 @@ void psxsplash::Lua::RegisterGameObject(GameObject* go) {
|
||||
// (1) go (2) { __cpp_ptr = go + metatable }
|
||||
L.rawSet(LUA_REGISTRYINDEX);
|
||||
// empty stack
|
||||
printf("GameObject registered in Lua registry: %p\n", go);
|
||||
L.newTable();
|
||||
// (1) {}
|
||||
L.push(ptr + 1);
|
||||
// (1) {} (2) go + 1
|
||||
L.copy(1);
|
||||
// (1) {} (2) go + 1 (3) {}
|
||||
L.rawSet(LUA_REGISTRYINDEX);
|
||||
// (1) {}
|
||||
if (go->luaFileIndex != -1) {
|
||||
L.rawGetI(LUA_REGISTRYINDEX, m_luascriptsReference);
|
||||
// (1) {} (2) script environments table
|
||||
L.rawGetI(-1, go->luaFileIndex);
|
||||
// (1) {} (2) script environments table (3) script environment table for this object
|
||||
onCollisionMethodWrapper.resolveGlobal(L);
|
||||
onInteractMethodWrapper.resolveGlobal(L);
|
||||
L.pop(2);
|
||||
// (1) {}
|
||||
}
|
||||
L.pop();
|
||||
// empty stack
|
||||
printf("GameObject registered in Lua registry: %p\n", ptr);
|
||||
}
|
||||
|
||||
void psxsplash::Lua::CallOnCollide(GameObject* self, GameObject* other) {
|
||||
if (self->luaFileIndex == -1) {
|
||||
return;
|
||||
}
|
||||
L.rawGetI(LUA_REGISTRYINDEX, m_luascriptsReference);
|
||||
// (1) scripts table
|
||||
L.rawGetI(-1, self->luaFileIndex);
|
||||
// (1) script table (2) script environment
|
||||
L.getField(-1, "onCollision");
|
||||
// (1) script table (2) script environment (3) onCollision
|
||||
if (!L.isFunction(-1)) {
|
||||
printf("Lua function 'onCollision' not found\n");
|
||||
L.clearStack();
|
||||
return;
|
||||
}
|
||||
void psxsplash::Lua::OnCollision(GameObject* self, GameObject* other) {
|
||||
onCollisionMethodWrapper.callMethod(*this, self, other);
|
||||
}
|
||||
|
||||
PushGameObject(self);
|
||||
PushGameObject(other);
|
||||
|
||||
if (L.pcall(2, 0) != LUA_OK) {
|
||||
printf("Lua error: %s\n", L.toString(-1));
|
||||
}
|
||||
L.clearStack();
|
||||
void psxsplash::Lua::OnInteract(GameObject* self) {
|
||||
onInteractMethodWrapper.callMethod(*this, self);
|
||||
}
|
||||
|
||||
void psxsplash::Lua::PushGameObject(GameObject* go) {
|
||||
auto L = m_state;
|
||||
L.push(go);
|
||||
L.rawGet(LUA_REGISTRYINDEX);
|
||||
|
||||
|
||||
85
src/lua.h
85
src/lua.h
@@ -1,8 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <psyqo-lua/lua.hh>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "gameobject.hh"
|
||||
#include "psyqo-lua/lua.hh"
|
||||
#include "psyqo/xprintf.h"
|
||||
#include "typestring.h"
|
||||
|
||||
namespace psxsplash {
|
||||
|
||||
@@ -19,14 +22,88 @@ class Lua {
|
||||
void Init();
|
||||
|
||||
void LoadLuaFile(const char* code, size_t len, int index);
|
||||
void RegisterSceneScripts(int index);
|
||||
void RegisterGameObject(GameObject* go);
|
||||
void CallOnCollide(GameObject* self, GameObject* other);
|
||||
|
||||
void OnSceneCreationStart() {
|
||||
onSceneCreationStartFunctionWrapper.callFunction(*this);
|
||||
}
|
||||
void OnSceneCreationEnd() {
|
||||
onSceneCreationEndFunctionWrapper.callFunction(*this);
|
||||
}
|
||||
void OnCollision(GameObject* self, GameObject* other);
|
||||
void OnInteract(GameObject* self);
|
||||
|
||||
private:
|
||||
template <int methodId, typename methodName>
|
||||
struct FunctionWrapper;
|
||||
template <int methodId, char... C>
|
||||
struct FunctionWrapper<methodId, irqus::typestring<C...>> {
|
||||
typedef irqus::typestring<C...> methodName;
|
||||
// Needs the methods table at index 1, and the script environment table at index 3
|
||||
static void resolveGlobal(psyqo::Lua L) {
|
||||
L.pushNumber(methodId);
|
||||
L.getTable(3);
|
||||
if (L.isFunction(-1)) {
|
||||
L.push(methodName::data(), methodName::size());
|
||||
L.setTable(1);
|
||||
} else {
|
||||
L.pop();
|
||||
}
|
||||
}
|
||||
template <typename... Args>
|
||||
static void pushArgs(psxsplash::Lua& lua, Args... args) {
|
||||
(push(lua, args), ...);
|
||||
}
|
||||
static void push(psxsplash::Lua& lua, GameObject* go) { lua.PushGameObject(go); }
|
||||
template <typename... Args>
|
||||
static void callMethod(psxsplash::Lua& lua, GameObject* go, Args... args) {
|
||||
auto L = lua.m_state;
|
||||
uint8_t* ptr = reinterpret_cast<uint8_t*>(go);
|
||||
L.push(ptr + 1);
|
||||
L.rawGet(LUA_REGISTRYINDEX);
|
||||
L.rawGetI(-1, methodId);
|
||||
if (!L.isFunction(-1)) {
|
||||
L.clearStack();
|
||||
return;
|
||||
}
|
||||
lua.PushGameObject(go);
|
||||
pushArgs(lua, args...);
|
||||
if (L.pcall(sizeof...(Args) + 1, 0) != LUA_OK) {
|
||||
printf("Lua error: %s\n", L.toString(-1));
|
||||
}
|
||||
L.clearStack();
|
||||
}
|
||||
template <typename... Args>
|
||||
static void callFunction(psxsplash::Lua& lua, Args... args) {
|
||||
auto L = lua.m_state;
|
||||
L.push(methodName::data(), methodName::size());
|
||||
L.rawGetI(LUA_REGISTRYINDEX, lua.m_metatableReference);
|
||||
if (!L.isFunction(-1)) {
|
||||
L.clearStack();
|
||||
return;
|
||||
}
|
||||
pushArgs(lua, args...);
|
||||
if (L.pcall(sizeof...(Args), 0) != LUA_OK) {
|
||||
printf("Lua error: %s\n", L.toString(-1));
|
||||
}
|
||||
L.clearStack();
|
||||
}
|
||||
};
|
||||
|
||||
[[no_unique_address]] FunctionWrapper<1, typestring_is("onSceneCreationStart")> onSceneCreationStartFunctionWrapper;
|
||||
[[no_unique_address]] FunctionWrapper<2, typestring_is("onSceneCreationEnd")> onSceneCreationEndFunctionWrapper;
|
||||
[[no_unique_address]] FunctionWrapper<1, typestring_is("onCreate")> onCreateMethodWrapper;
|
||||
[[no_unique_address]] FunctionWrapper<2, typestring_is("onCollision")> onCollisionMethodWrapper;
|
||||
[[no_unique_address]] FunctionWrapper<3, typestring_is("onInteract")> onInteractMethodWrapper;
|
||||
void PushGameObject(GameObject* go);
|
||||
psyqo::Lua L;
|
||||
psyqo::Lua m_state;
|
||||
|
||||
int m_metatableReference;
|
||||
int m_luascriptsReference;
|
||||
int m_luaSceneScriptsReference;
|
||||
|
||||
template <int methodId, typename methodName>
|
||||
friend struct FunctionWrapper;
|
||||
};
|
||||
} // namespace psxsplash
|
||||
} // namespace psxsplash
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include "renderer.hh"
|
||||
#include "splashpack.hh"
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
using namespace psyqo::trig_literals;
|
||||
|
||||
void psxsplash::SceneManager::InitializeScene(uint8_t* splashpackData) {
|
||||
@@ -26,12 +28,18 @@ void psxsplash::SceneManager::InitializeScene(uint8_t* splashpackData) {
|
||||
|
||||
m_playerHeight = sceneSetup.playerHeight;
|
||||
|
||||
// Load Lua files
|
||||
// Load Lua files - order is important here. We need
|
||||
// to load the Lua files before we register the game objects,
|
||||
// as the game objects may reference Lua files by index.
|
||||
for (int i = 0; i < m_luaFiles.size(); i++) {
|
||||
auto luaFile = m_luaFiles[i];
|
||||
L.LoadLuaFile(luaFile->luaCode, luaFile->length, i);
|
||||
}
|
||||
|
||||
L.RegisterSceneScripts(sceneSetup.sceneLuaFileIndex);
|
||||
|
||||
L.OnSceneCreationStart();
|
||||
|
||||
// Register game objects
|
||||
for (auto object : m_gameObjects) {
|
||||
L.RegisterGameObject(object);
|
||||
@@ -39,6 +47,8 @@ void psxsplash::SceneManager::InitializeScene(uint8_t* splashpackData) {
|
||||
|
||||
m_controls.Init();
|
||||
Renderer::GetInstance().SetCamera(m_currentCamera);
|
||||
|
||||
L.OnSceneCreationEnd();
|
||||
}
|
||||
|
||||
void psxsplash::SceneManager::GameTick() {
|
||||
@@ -56,4 +66,6 @@ void psxsplash::SceneManager::GameTick() {
|
||||
static_cast<psyqo::FixedPoint<12>>(m_playerPosition.y),
|
||||
static_cast<psyqo::FixedPoint<12>>(m_playerPosition.z));
|
||||
m_currentCamera.SetRotation(playerRotationX, playerRotationY, playerRotationZ);
|
||||
|
||||
L.OnCollision(m_gameObjects[0], m_gameObjects[1]); // Example call, replace with actual logic
|
||||
}
|
||||
@@ -65,7 +65,7 @@ void SplashPackLoader::LoadSplashpack(uint8_t *data, SplashpackSceneSetup &setup
|
||||
curentPointer += sizeof(psxsplash::LuaFile);
|
||||
}
|
||||
|
||||
setup.sceneLuaFile = setup.luaFiles[header->sceneLuaFileIndex];
|
||||
setup.sceneLuaFileIndex = header->sceneLuaFileIndex;
|
||||
|
||||
for (uint16_t i = 0; i < header->gameObjectCount; i++) {
|
||||
psxsplash::GameObject *go = reinterpret_cast<psxsplash::GameObject *>(curentPointer);
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace psxsplash {
|
||||
|
||||
struct SplashpackSceneSetup {
|
||||
LuaFile* sceneLuaFile;
|
||||
int sceneLuaFileIndex;
|
||||
eastl::vector<LuaFile *> luaFiles;
|
||||
eastl::vector<GameObject *> objects;
|
||||
eastl::vector<Navmesh *> navmeshes;
|
||||
|
||||
275
src/typestring.h
Normal file
275
src/typestring.h
Normal file
@@ -0,0 +1,275 @@
|
||||
/*~
|
||||
* Copyright (C) 2015, 2016 George Makrydakis <george@irrequietus.eu>
|
||||
*
|
||||
* The 'typestring' header is a single header C++ library for creating types
|
||||
* to use as type parameters in template instantiations, repository available
|
||||
* at https://github.com/irrequietus/typestring. Conceptually stemming from
|
||||
* own implementation of the same thing (but in a more complicated manner to
|
||||
* be revised) in 'clause': https://github.com/irrequietus/clause.
|
||||
*
|
||||
* File subject to the terms and conditions of the Mozilla Public License v 2.0.
|
||||
* If a copy of the MPLv2 license text was not distributed with this file, you
|
||||
* can obtain it at: http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#ifndef IRQUS_TYPESTRING_HH_
|
||||
#define IRQUS_TYPESTRING_HH_
|
||||
|
||||
namespace irqus {
|
||||
|
||||
/*~
|
||||
* @desc A class 'storing' strings into distinct, reusable compile-time types that
|
||||
* can be used as type parameters in a template parameter list.
|
||||
* @tprm C... : char non-type parameter pack whose ordered sequence results
|
||||
* into a specific string.
|
||||
* @note Could have wrapped up everything in a single class, eventually will,
|
||||
* once some compilers fix their class scope lookups! I have added some
|
||||
* utility functions because asides being a fun little project, it is of
|
||||
* use in certain constructs related to template metaprogramming
|
||||
* nonetheless.
|
||||
*/
|
||||
template<char... C>
|
||||
struct typestring final {
|
||||
private:
|
||||
static constexpr char const vals[sizeof...(C)+1] = { C...,'\0' };
|
||||
static constexpr unsigned int sval = sizeof...(C);
|
||||
public:
|
||||
|
||||
static constexpr char const * data() noexcept
|
||||
{ return &vals[0]; }
|
||||
|
||||
static constexpr unsigned int size() noexcept
|
||||
{ return sval; };
|
||||
|
||||
static constexpr char const * cbegin() noexcept
|
||||
{ return &vals[0]; }
|
||||
|
||||
static constexpr char const * cend() noexcept
|
||||
{ return &vals[sval]; }
|
||||
};
|
||||
|
||||
template<char... C>
|
||||
constexpr char const typestring<C...>::vals[sizeof...(C)+1];
|
||||
|
||||
//*~ part 1: preparing the ground, because function templates are awesome.
|
||||
|
||||
/*~
|
||||
* @note While it is easy to resort to constexpr strings for use in constexpr
|
||||
* metaprogramming, what we want is to convert compile time string in situ
|
||||
* definitions into reusable, distinct types, for use in advanced template
|
||||
* metaprogramming techniques. We want such features because this kind of
|
||||
* metaprogramming constitutes a pure, non-strict, untyped functional
|
||||
* programming language with pattern matching where declarative semantics
|
||||
* can really shine.
|
||||
*
|
||||
* Currently, there is no feature in C++ that offers the opportunity to
|
||||
* use strings as type parameter types themselves, despite there are
|
||||
* several, different library implementations. This implementation is a
|
||||
* fast, short, single-header, stupid-proof solution that works with any
|
||||
* C++11 compliant compiler and up, with the resulting type being easily
|
||||
* reusable throughout the code.
|
||||
*
|
||||
* @usge Just include the header and enable -std=c++11 or -std=c++14 etc, use
|
||||
* like in the following example:
|
||||
*
|
||||
* typestring_is("Hello!")
|
||||
*
|
||||
* is essentially identical to the following template instantiation:
|
||||
*
|
||||
* irqus::typestring<'H', 'e', 'l', 'l', 'o', '!'>
|
||||
*
|
||||
* By passing -DUSE_TYPESTRING=<power of 2> during compilation, you can
|
||||
* set the maximum length of the 'typestring' from 1 to 1024 (2^0 to 2^10).
|
||||
* Although all preprocessor implementations tested are capable of far
|
||||
* more with this method, exceeding this limit may cause internal compiler
|
||||
* errors in most, with at times rather hilarious results.
|
||||
*/
|
||||
|
||||
template<int N, int M>
|
||||
constexpr char tygrab(char const(&c)[M]) noexcept
|
||||
{ return c[N < M ? N : M-1]; }
|
||||
|
||||
//*~ part2: Function template type signatures for type deduction purposes. In
|
||||
// other words, exploiting the functorial nature of parameter packs
|
||||
// while mixing them with an obvious catamorphism through pattern
|
||||
// matching galore (partial ordering in this case in C++ "parlance").
|
||||
|
||||
template<char... X>
|
||||
auto typoke(typestring<X...>) // as is...
|
||||
-> typestring<X...>;
|
||||
|
||||
template<char... X, char... Y>
|
||||
auto typoke(typestring<X...>, typestring<'\0'>, typestring<Y>...)
|
||||
-> typestring<X...>;
|
||||
|
||||
template<char A, char... X, char... Y>
|
||||
auto typoke(typestring<X...>, typestring<A>, typestring<Y>...)
|
||||
-> decltype(typoke(typestring<X...,A>(), typestring<Y>()...));
|
||||
|
||||
template<char... C>
|
||||
auto typeek(typestring<C...>)
|
||||
-> decltype(typoke(typestring<C>()...));
|
||||
|
||||
template<char... A, char... B, typename... X>
|
||||
auto tycat_(typestring<A...>, typestring<B...>, X... x)
|
||||
-> decltype(tycat_(typestring<A..., B...>(), x...));
|
||||
|
||||
template<char... X>
|
||||
auto tycat_(typestring<X...>)
|
||||
-> typestring<X...>;
|
||||
|
||||
/*
|
||||
* Some people actually using this header as is asked me to include
|
||||
* a typestring "cat" utility given that it is easy enough to implement.
|
||||
* I have added this functionality through the template alias below. For
|
||||
* the obvious implementation, nothing more to say. All T... must be
|
||||
* of course, "typestrings".
|
||||
*/
|
||||
template<typename... T>
|
||||
using tycat
|
||||
= decltype(tycat_(T()...));
|
||||
|
||||
} /* irqus */
|
||||
|
||||
|
||||
//*~ part3: some necessary code generation using preprocessor metaprogramming!
|
||||
// There is functional nature in preprocessor metaprogramming as well.
|
||||
|
||||
/*~
|
||||
* @note Code generation block. Undoubtedly, the preprocessor implementations
|
||||
* of both clang++ and g++ are relatively competent in producing a
|
||||
* relatively adequate amount of boilerplate for implementing features
|
||||
* that the language itself will probably be having as features in a few
|
||||
* years. At times, like herein, the preprocessor is able to generate
|
||||
* boilerplate *extremely* fast, but over a certain limit the compiler is
|
||||
* incapable of compiling it. For the record, only certain versions of
|
||||
* g++ where capable of going beyond 4K, so I thought of going from base
|
||||
* 16 to base 2 for USE_TYPESTRING power base. For the record, it takes
|
||||
* a few milliseconds to generate boilerplate for several thousands worth
|
||||
* of "string" length through such an 'fmap' like procedure.
|
||||
*/
|
||||
|
||||
/* 2^0 = 1 */
|
||||
#define TYPESTRING1(n,x) irqus::tygrab<0x##n##0>(x)
|
||||
|
||||
/* 2^1 = 2 */
|
||||
#define TYPESTRING2(n,x) irqus::tygrab<0x##n##0>(x), irqus::tygrab<0x##n##1>(x)
|
||||
|
||||
/* 2^2 = 2 */
|
||||
#define TYPESTRING4(n,x) \
|
||||
irqus::tygrab<0x##n##0>(x), irqus::tygrab<0x##n##1>(x) \
|
||||
, irqus::tygrab<0x##n##2>(x), irqus::tygrab<0x##n##3>(x)
|
||||
|
||||
/* 2^3 = 8 */
|
||||
#define TYPESTRING8(n,x) \
|
||||
irqus::tygrab<0x##n##0>(x), irqus::tygrab<0x##n##1>(x) \
|
||||
, irqus::tygrab<0x##n##2>(x), irqus::tygrab<0x##n##3>(x) \
|
||||
, irqus::tygrab<0x##n##4>(x), irqus::tygrab<0x##n##5>(x) \
|
||||
, irqus::tygrab<0x##n##6>(x), irqus::tygrab<0x##n##7>(x)
|
||||
|
||||
/* 2^4 = 16 */
|
||||
#define TYPESTRING16(n,x) \
|
||||
irqus::tygrab<0x##n##0>(x), irqus::tygrab<0x##n##1>(x) \
|
||||
, irqus::tygrab<0x##n##2>(x), irqus::tygrab<0x##n##3>(x) \
|
||||
, irqus::tygrab<0x##n##4>(x), irqus::tygrab<0x##n##5>(x) \
|
||||
, irqus::tygrab<0x##n##6>(x), irqus::tygrab<0x##n##7>(x) \
|
||||
, irqus::tygrab<0x##n##8>(x), irqus::tygrab<0x##n##9>(x) \
|
||||
, irqus::tygrab<0x##n##A>(x), irqus::tygrab<0x##n##B>(x) \
|
||||
, irqus::tygrab<0x##n##C>(x), irqus::tygrab<0x##n##D>(x) \
|
||||
, irqus::tygrab<0x##n##E>(x), irqus::tygrab<0x##n##F>(x)
|
||||
|
||||
/* 2^5 = 32 */
|
||||
#define TYPESTRING32(n,x) \
|
||||
TYPESTRING16(n##0,x),TYPESTRING16(n##1,x)
|
||||
|
||||
/* 2^6 = 64 */
|
||||
#define TYPESTRING64(n,x) \
|
||||
TYPESTRING16(n##0,x), TYPESTRING16(n##1,x), TYPESTRING16(n##2,x) \
|
||||
, TYPESTRING16(n##3,x)
|
||||
|
||||
/* 2^7 = 128 */
|
||||
#define TYPESTRING128(n,x) \
|
||||
TYPESTRING16(n##0,x), TYPESTRING16(n##1,x), TYPESTRING16(n##2,x) \
|
||||
, TYPESTRING16(n##3,x), TYPESTRING16(n##4,x), TYPESTRING16(n##5,x) \
|
||||
, TYPESTRING16(n##6,x), TYPESTRING16(n##7,x)
|
||||
|
||||
/* 2^8 = 256 */
|
||||
#define TYPESTRING256(n,x) \
|
||||
TYPESTRING16(n##0,x), TYPESTRING16(n##1,x), TYPESTRING16(n##2,x) \
|
||||
, TYPESTRING16(n##3,x), TYPESTRING16(n##4,x), TYPESTRING16(n##5,x) \
|
||||
, TYPESTRING16(n##6,x), TYPESTRING16(n##7,x), TYPESTRING16(n##8,x) \
|
||||
, TYPESTRING16(n##9,x), TYPESTRING16(n##A,x), TYPESTRING16(n##B,x) \
|
||||
, TYPESTRING16(n##C,x), TYPESTRING16(n##D,x), TYPESTRING16(n##E,x) \
|
||||
, TYPESTRING16(n##F,x)
|
||||
|
||||
/* 2^9 = 512 */
|
||||
#define TYPESTRING512(n,x) \
|
||||
TYPESTRING256(n##0,x), TYPESTRING256(n##1,x)
|
||||
|
||||
/* 2^10 = 1024 */
|
||||
#define TYPESTRING1024(n,x) \
|
||||
TYPESTRING256(n##0,x), TYPESTRING256(n##1,x), TYPESTRING256(n##2,x) \
|
||||
, TYPESTRING128(n##3,x), TYPESTRING16(n##38,x), TYPESTRING16(n##39,x) \
|
||||
, TYPESTRING16(n##3A,x), TYPESTRING16(n##3B,x), TYPESTRING16(n##3C,x) \
|
||||
, TYPESTRING16(n##3D,x), TYPESTRING16(n##3E,x), TYPESTRING16(n##3F,x)
|
||||
|
||||
//*~ part4 : Let's give some logic with a -DUSE_TYPESTRING flag!
|
||||
|
||||
#ifdef USE_TYPESTRING
|
||||
#if USE_TYPESTRING == 0
|
||||
#define typestring_is(x) \
|
||||
decltype(irqus::typeek(irqus::typestring<TYPESTRING1(,x)>()))
|
||||
#elif USE_TYPESTRING == 1
|
||||
#define typestring_is(x) \
|
||||
decltype(irqus::typeek(irqus::typestring<TYPESTRING2(,x)>()))
|
||||
#elif USE_TYPESTRING == 2
|
||||
#define typestring_is(x) \
|
||||
decltype(irqus::typeek(irqus::typestring<TYPESTRING4(,x)>()))
|
||||
#elif USE_TYPESTRING == 3
|
||||
#define typestring_is(x) \
|
||||
decltype(irqus::typeek(irqus::typestring<TYPESTRING8(,x)>()))
|
||||
#elif USE_TYPESTRING == 4
|
||||
#define typestring_is(x) \
|
||||
decltype(irqus::typeek(irqus::typestring<TYPESTRING16(,x)>()))
|
||||
#elif USE_TYPESTRING == 5
|
||||
#define typestring_is(x) \
|
||||
decltype(irqus::typeek(irqus::typestring<TYPESTRING32(,x)>()))
|
||||
#elif USE_TYPESTRING == 6
|
||||
#define typestring_is(x) \
|
||||
decltype(irqus::typeek(irqus::typestring<TYPESTRING64(,x)>()))
|
||||
#elif USE_TYPESTRING == 7
|
||||
#define typestring_is(x) \
|
||||
decltype(irqus::typeek(irqus::typestring<TYPESTRING128(,x)>()))
|
||||
#elif USE_TYPESTRING == 8
|
||||
#define typestring_is(x) \
|
||||
decltype(irqus::typeek(irqus::typestring<TYPESTRING256(,x)>()))
|
||||
#elif USE_TYPESTRING == 9
|
||||
#define typestring_is(x) \
|
||||
decltype(irqus::typeek(irqus::typestring<TYPESTRING512(,x)>()))
|
||||
#elif USE_TYPESTRING == 10
|
||||
#define typestring_is(x) \
|
||||
decltype(irqus::typeek(irqus::typestring<TYPESTRING1024(,x)>()))
|
||||
#elif USE_TYPESTRING > 10
|
||||
|
||||
#warning !!!: custom typestring length exceeded allowed (1024) !!!
|
||||
#warning !!!: all typestrings to default maximum typestring length of 64 !!!
|
||||
#warning !!!: you can use -DUSE_TYPESTRING=<power of two> to set length !!!
|
||||
|
||||
#define typestring_is(x) \
|
||||
decltype(irqus::typeek(irqus::typestring<TYPESTRING64(,x)>()))
|
||||
|
||||
#elif USE_TYPESTRING < 0
|
||||
|
||||
#warning !!!: You used USE_TYPESTRING with a negative size specified !!!
|
||||
#warning !!!: all typestrings to default maximum typestring length of 64 !!!
|
||||
#warning !!!: you can use -DUSE_TYPESTRING=<power of two> to set length !!!
|
||||
|
||||
#define typestring_is(x) \
|
||||
decltype(irqus::typeek(irqus::typestring<TYPESTRING64(,x)>()))
|
||||
|
||||
#endif
|
||||
#else
|
||||
#define typestring_is(x) \
|
||||
decltype(irqus::typeek(irqus::typestring<TYPESTRING64(,x)>()))
|
||||
#endif
|
||||
#endif /* IRQUS_TYPESTRING_HH_ */
|
||||
Reference in New Issue
Block a user