From cf252fa91a15403b78cd15f79f2a51ef4ceed432 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Thu, 17 Jul 2014 19:54:05 -0700 Subject: [PATCH] Add simple type -> type name string compile time reflection stuff This is needed for passing types to the LuaJIT ffi. --- build/libaegisub/libaegisub.vcxproj | 1 + build/libaegisub/libaegisub.vcxproj.filters | 5 +- build/tests/tests.vcxproj.filters | 3 + libaegisub/include/libaegisub/type_name.h | 73 +++++++++++++++++++++ tests/tests/type_name.cpp | 34 ++++++++++ 5 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 libaegisub/include/libaegisub/type_name.h create mode 100644 tests/tests/type_name.cpp diff --git a/build/libaegisub/libaegisub.vcxproj b/build/libaegisub/libaegisub.vcxproj index 9b46a2277..370c3177a 100644 --- a/build/libaegisub/libaegisub.vcxproj +++ b/build/libaegisub/libaegisub.vcxproj @@ -108,6 +108,7 @@ + diff --git a/build/libaegisub/libaegisub.vcxproj.filters b/build/libaegisub/libaegisub.vcxproj.filters index dd843fe13..7288ab0e1 100644 --- a/build/libaegisub/libaegisub.vcxproj.filters +++ b/build/libaegisub/libaegisub.vcxproj.filters @@ -80,6 +80,9 @@ Header Files + + Header Files + Header Files @@ -373,4 +376,4 @@ Header Files - \ No newline at end of file + diff --git a/build/tests/tests.vcxproj.filters b/build/tests/tests.vcxproj.filters index c25a592f9..ebc82f7d6 100644 --- a/build/tests/tests.vcxproj.filters +++ b/build/tests/tests.vcxproj.filters @@ -71,6 +71,9 @@ Tests + + Tests + Tests diff --git a/libaegisub/include/libaegisub/type_name.h b/libaegisub/include/libaegisub/type_name.h new file mode 100644 index 000000000..e777404bf --- /dev/null +++ b/libaegisub/include/libaegisub/type_name.h @@ -0,0 +1,73 @@ +// Copyright (c) 2014, Thomas Goyne +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// +// Aegisub Project http://www.aegisub.org/ + +#include + +namespace agi { +// Get the name of a type as a string in C syntax +// Currently supports primitives, pointers, references, const, and function pointers +template struct type_name; + +#define AGI_TYPE_NAME_PRIMITIVE(type) \ + template<> struct type_name { static const char *name() { return #type; }} + +AGI_TYPE_NAME_PRIMITIVE(bool); +AGI_TYPE_NAME_PRIMITIVE(char); +AGI_TYPE_NAME_PRIMITIVE(double); +AGI_TYPE_NAME_PRIMITIVE(float); +AGI_TYPE_NAME_PRIMITIVE(int); +AGI_TYPE_NAME_PRIMITIVE(void); + +#undef AGI_TYPE_NAME_PRIMITIVE + +#define AGI_TYPE_NAME_MODIFIER(pre, type) \ + template \ + struct type_name { \ + static std::string name() { \ + return std::string(type_name::name()) + pre #type; \ + } \ + } + +AGI_TYPE_NAME_MODIFIER("", *); +AGI_TYPE_NAME_MODIFIER("", &); +AGI_TYPE_NAME_MODIFIER(" ", const); + +#undef AGI_TYPE_NAME_MODIFIER + +template +std::string function_args(bool is_first) { + return std::string(is_first ? "" : ", ") + type_name::name() + ")"; +} + +template +std::string function_args(bool is_first) { + return std::string(is_first ? "" : ", ") + type_name::name() + function_args(false); +} + +template +struct type_name { + static std::string name() { + return std::string(type_name::name()) + " (*)(" + function_args(true); + } +}; + +template +struct type_name { + static std::string name() { + return std::string(type_name::name()) + " (*)()"; + } +}; +} diff --git a/tests/tests/type_name.cpp b/tests/tests/type_name.cpp new file mode 100644 index 000000000..d624c5c73 --- /dev/null +++ b/tests/tests/type_name.cpp @@ -0,0 +1,34 @@ +// Copyright (c) 2014, Thomas Goyne +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// +// Aegisub Project http://www.aegisub.org/ + +#include +#include + +#include + +TEST(lagi_type_name, type_name) { + EXPECT_STREQ("bool", agi::type_name::name()); + EXPECT_EQ("char const", agi::type_name::name()); + EXPECT_EQ("void*", agi::type_name::name()); + EXPECT_EQ("float const*", agi::type_name::name()); + EXPECT_EQ("int const&", agi::type_name::name()); + EXPECT_EQ("double&", agi::type_name::name()); + EXPECT_EQ("void (*)()", agi::type_name::name()); + EXPECT_EQ("int (*)(bool)", agi::type_name::name()); + EXPECT_EQ("char const* (*)(int, bool, int)", agi::type_name::name()); + EXPECT_EQ("char* (*)(int, int, void (*)())", agi::type_name::name()); +} +