From 5b761ab5bc8df6a5196f9b2e219e9f07486d13c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20R=C3=A1=C4=8Dek?= Date: Wed, 20 Aug 2025 01:53:35 +0200 Subject: [PATCH] Lua function wrappers with typestring --- output.bin | Bin 408332 -> 433084 bytes src/lua.cpp | 104 ++++++++++------ src/lua.h | 85 ++++++++++++- src/scenemanager.cpp | 14 ++- src/splashpack.cpp | 2 +- src/splashpack.hh | 2 +- src/typestring.h | 275 +++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 437 insertions(+), 45 deletions(-) create mode 100644 src/typestring.h diff --git a/output.bin b/output.bin index 6dc40e71e2d7d2d32a181eba1644f749c97271c2..066fa29f4d0e48deab2dff53e07c9928a7fb27b0 100644 GIT binary patch delta 102602 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 delta 77776 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 diff --git a/src/lua.cpp b/src/lua.cpp index 5c17d80..c923543 100644 --- a/src/lua.cpp +++ b/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(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(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(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); diff --git a/src/lua.h b/src/lua.h index f0d714f..38a5960 100644 --- a/src/lua.h +++ b/src/lua.h @@ -1,8 +1,11 @@ #pragma once -#include +#include #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 + struct FunctionWrapper; + template + struct FunctionWrapper> { + typedef irqus::typestring 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 + static void pushArgs(psxsplash::Lua& lua, Args... args) { + (push(lua, args), ...); + } + static void push(psxsplash::Lua& lua, GameObject* go) { lua.PushGameObject(go); } + template + static void callMethod(psxsplash::Lua& lua, GameObject* go, Args... args) { + auto L = lua.m_state; + uint8_t* ptr = reinterpret_cast(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 + 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 + friend struct FunctionWrapper; }; -} // namespace psxsplash \ No newline at end of file +} // namespace psxsplash diff --git a/src/scenemanager.cpp b/src/scenemanager.cpp index 2742e7c..52bce6e 100644 --- a/src/scenemanager.cpp +++ b/src/scenemanager.cpp @@ -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>(m_playerPosition.y), static_cast>(m_playerPosition.z)); m_currentCamera.SetRotation(playerRotationX, playerRotationY, playerRotationZ); + + L.OnCollision(m_gameObjects[0], m_gameObjects[1]); // Example call, replace with actual logic } \ No newline at end of file diff --git a/src/splashpack.cpp b/src/splashpack.cpp index 593f60a..c157a54 100644 --- a/src/splashpack.cpp +++ b/src/splashpack.cpp @@ -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(curentPointer); diff --git a/src/splashpack.hh b/src/splashpack.hh index 0a8c360..d32936c 100644 --- a/src/splashpack.hh +++ b/src/splashpack.hh @@ -11,7 +11,7 @@ namespace psxsplash { struct SplashpackSceneSetup { - LuaFile* sceneLuaFile; + int sceneLuaFileIndex; eastl::vector luaFiles; eastl::vector objects; eastl::vector navmeshes; diff --git a/src/typestring.h b/src/typestring.h new file mode 100644 index 0000000..694c2f9 --- /dev/null +++ b/src/typestring.h @@ -0,0 +1,275 @@ +/*~ + * Copyright (C) 2015, 2016 George Makrydakis + * + * 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 +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 +constexpr char const typestring::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= 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 +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 +auto typoke(typestring) // as is... + -> typestring; + +template +auto typoke(typestring, typestring<'\0'>, typestring...) + -> typestring; + +template +auto typoke(typestring, typestring, typestring...) + -> decltype(typoke(typestring(), typestring()...)); + +template +auto typeek(typestring) + -> decltype(typoke(typestring()...)); + +template +auto tycat_(typestring, typestring, X... x) + -> decltype(tycat_(typestring(), x...)); + +template +auto tycat_(typestring) + -> typestring; + +/* + * 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 +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())) +#elif USE_TYPESTRING == 1 +#define typestring_is(x) \ + decltype(irqus::typeek(irqus::typestring())) +#elif USE_TYPESTRING == 2 +#define typestring_is(x) \ + decltype(irqus::typeek(irqus::typestring())) +#elif USE_TYPESTRING == 3 +#define typestring_is(x) \ + decltype(irqus::typeek(irqus::typestring())) +#elif USE_TYPESTRING == 4 +#define typestring_is(x) \ + decltype(irqus::typeek(irqus::typestring())) +#elif USE_TYPESTRING == 5 +#define typestring_is(x) \ + decltype(irqus::typeek(irqus::typestring())) +#elif USE_TYPESTRING == 6 +#define typestring_is(x) \ + decltype(irqus::typeek(irqus::typestring())) +#elif USE_TYPESTRING == 7 +#define typestring_is(x) \ + decltype(irqus::typeek(irqus::typestring())) +#elif USE_TYPESTRING == 8 +#define typestring_is(x) \ + decltype(irqus::typeek(irqus::typestring())) +#elif USE_TYPESTRING == 9 +#define typestring_is(x) \ + decltype(irqus::typeek(irqus::typestring())) +#elif USE_TYPESTRING == 10 +#define typestring_is(x) \ + decltype(irqus::typeek(irqus::typestring())) +#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= to set length !!! + +#define typestring_is(x) \ + decltype(irqus::typeek(irqus::typestring())) + +#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= to set length !!! + +#define typestring_is(x) \ + decltype(irqus::typeek(irqus::typestring())) + +#endif +#else +#define typestring_is(x) \ + decltype(irqus::typeek(irqus::typestring())) +#endif +#endif /* IRQUS_TYPESTRING_HH_ */