2014-07-18 04:54:05 +02:00
|
|
|
// 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;
|
|
|
|
|
2014-07-18 19:33:57 +02:00
|
|
|
#define AGI_DEFINE_TYPE_NAME(type) \
|
2014-07-18 04:54:05 +02:00
|
|
|
template<> struct type_name<type> { static const char *name() { return #type; }}
|
|
|
|
|
2014-07-18 19:33:57 +02:00
|
|
|
AGI_DEFINE_TYPE_NAME(bool);
|
|
|
|
AGI_DEFINE_TYPE_NAME(char);
|
|
|
|
AGI_DEFINE_TYPE_NAME(float);
|
2015-02-07 23:35:17 +01:00
|
|
|
AGI_DEFINE_TYPE_NAME(double);
|
|
|
|
AGI_DEFINE_TYPE_NAME(int);
|
|
|
|
AGI_DEFINE_TYPE_NAME(long);
|
|
|
|
AGI_DEFINE_TYPE_NAME(long long);
|
|
|
|
AGI_DEFINE_TYPE_NAME(unsigned int);
|
|
|
|
AGI_DEFINE_TYPE_NAME(unsigned long);
|
|
|
|
AGI_DEFINE_TYPE_NAME(unsigned long long);
|
2014-07-18 19:33:57 +02:00
|
|
|
AGI_DEFINE_TYPE_NAME(void);
|
2014-07-18 04:54:05 +02:00
|
|
|
|
|
|
|
#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()) + " (*)()";
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|