Add simple type -> type name string compile time reflection stuff
This is needed for passing types to the LuaJIT ffi.
This commit is contained in:
parent
77ecff1cba
commit
cf252fa91a
5 changed files with 115 additions and 1 deletions
build
libaegisub/include/libaegisub
tests/tests
|
@ -108,6 +108,7 @@
|
|||
<ClInclude Include="$(SrcDir)include\libaegisub\spellchecker.h" />
|
||||
<ClInclude Include="$(SrcDir)include\libaegisub\split.h" />
|
||||
<ClInclude Include="$(SrcDir)include\libaegisub\thesaurus.h" />
|
||||
<ClInclude Include="$(SrcDir)include\libaegisub\type_name.h" />
|
||||
<ClInclude Include="$(SrcDir)include\libaegisub\util.h" />
|
||||
<ClInclude Include="$(SrcDir)include\libaegisub\util_osx.h" />
|
||||
<ClInclude Include="$(SrcDir)include\libaegisub\vfr.h" />
|
||||
|
|
|
@ -80,6 +80,9 @@
|
|||
<ClInclude Include="$(SrcDir)include\libaegisub\thesaurus.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(SrcDir)include\libaegisub\type_name.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(SrcDir)include\libaegisub\util.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
@ -373,4 +376,4 @@
|
|||
<Filter>Header Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
@ -71,6 +71,9 @@
|
|||
<ClCompile Include="$(SrcDir)tests\thesaurus.cpp">
|
||||
<Filter>Tests</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)tests\type_name.cpp">
|
||||
<Filter>Tests</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)tests\util.cpp">
|
||||
<Filter>Tests</Filter>
|
||||
</ClCompile>
|
||||
|
|
73
libaegisub/include/libaegisub/type_name.h
Normal file
73
libaegisub/include/libaegisub/type_name.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
// Copyright (c) 2014, Thomas Goyne <plorkyeran@aegisub.org>
|
||||
//
|
||||
// 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 <string>
|
||||
|
||||
namespace agi {
|
||||
// Get the name of a type as a string in C syntax
|
||||
// Currently supports primitives, pointers, references, const, and function pointers
|
||||
template<typename T> struct type_name;
|
||||
|
||||
#define AGI_TYPE_NAME_PRIMITIVE(type) \
|
||||
template<> struct type_name<type> { 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<typename T> \
|
||||
struct type_name<T type> { \
|
||||
static std::string name() { \
|
||||
return std::string(type_name<T>::name()) + pre #type; \
|
||||
} \
|
||||
}
|
||||
|
||||
AGI_TYPE_NAME_MODIFIER("", *);
|
||||
AGI_TYPE_NAME_MODIFIER("", &);
|
||||
AGI_TYPE_NAME_MODIFIER(" ", const);
|
||||
|
||||
#undef AGI_TYPE_NAME_MODIFIER
|
||||
|
||||
template<typename First>
|
||||
std::string function_args(bool is_first) {
|
||||
return std::string(is_first ? "" : ", ") + type_name<First>::name() + ")";
|
||||
}
|
||||
|
||||
template<typename First, typename Second, typename... Rest>
|
||||
std::string function_args(bool is_first) {
|
||||
return std::string(is_first ? "" : ", ") + type_name<First>::name() + function_args<Second, Rest...>(false);
|
||||
}
|
||||
|
||||
template<typename Return, typename... Args>
|
||||
struct type_name<Return (*)(Args...)> {
|
||||
static std::string name() {
|
||||
return std::string(type_name<Return>::name()) + " (*)(" + function_args<Args...>(true);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Return>
|
||||
struct type_name<Return (*)()> {
|
||||
static std::string name() {
|
||||
return std::string(type_name<Return>::name()) + " (*)()";
|
||||
}
|
||||
};
|
||||
}
|
34
tests/tests/type_name.cpp
Normal file
34
tests/tests/type_name.cpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
// Copyright (c) 2014, Thomas Goyne <plorkyeran@aegisub.org>
|
||||
//
|
||||
// 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 <main.h>
|
||||
#include <util.h>
|
||||
|
||||
#include <libaegisub/type_name.h>
|
||||
|
||||
TEST(lagi_type_name, type_name) {
|
||||
EXPECT_STREQ("bool", agi::type_name<bool>::name());
|
||||
EXPECT_EQ("char const", agi::type_name<char const>::name());
|
||||
EXPECT_EQ("void*", agi::type_name<void *>::name());
|
||||
EXPECT_EQ("float const*", agi::type_name<float const*>::name());
|
||||
EXPECT_EQ("int const&", agi::type_name<int const&>::name());
|
||||
EXPECT_EQ("double&", agi::type_name<double &>::name());
|
||||
EXPECT_EQ("void (*)()", agi::type_name<void (*)()>::name());
|
||||
EXPECT_EQ("int (*)(bool)", agi::type_name<int (*)(bool)>::name());
|
||||
EXPECT_EQ("char const* (*)(int, bool, int)", agi::type_name<char const*(*)(int, bool, int)>::name());
|
||||
EXPECT_EQ("char* (*)(int, int, void (*)())", agi::type_name<char *(*)(int, int, void (*)())>::name());
|
||||
}
|
||||
|
Loading…
Reference in a new issue