DoorKeeper/include/doorkeeper/implem/typename.inl

115 lines
3.5 KiB
C++

/* Copyright 2015, Michele Santullo
* This file is part of DoorKeeper.
*
* DoorKeeper is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DoorKeeper is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DoorKeeper. If not, see <http://www.gnu.org/licenses/>.
*/
namespace dk {
#if defined(USE_MANUAL_TYPENAMES)
template <typename T>
inline constexpr const char* manual_type_name() {
static_assert(sizeof(T) == 0, "define an overload returning a const char* name for your type T");
return nullptr;
}
#endif
template <typename T>
#if defined(IS_PRETTY_FUNC_CONSTEXPR) || defined(USE_MANUAL_TYPENAMES)
constexpr
#endif
inline HashType type_name_hash() {
#if defined(IS_PRETTY_FUNC_CONSTEXPR) || defined(USE_MANUAL_TYPENAMES)
//static_assert(dk::tiger("a", 1, 0x01).a == 0xABF87E2EEFFBBE77ULL, "Bug in tiger hash");
//static_assert(dk::tiger("message digest", 14, 0x01).a == 0x951A2078CBF881D9ULL, "Bug in tiger hash");
// set padding to 0x80 for tiger V2
return dk::tiger(type_name<T>().data(), type_name<T>().size(), 0x01);
#else
const auto retstring = type_name<T>();
return implem::hash_string(retstring.data(), retstring.size());
#endif
}
template <typename T>
#if defined(IS_PRETTY_FUNC_CONSTEXPR) || defined(USE_MANUAL_TYPENAMES)
constexpr inline sprout::string<implem::type_name_len<T>()> type_name()
#else
inline std::string type_name()
#endif
{
#if defined(__GNUC__)
# if defined(IS_PRETTY_FUNC_CONSTEXPR) || defined(USE_MANUAL_TYPENAMES)
typedef sprout::string<implem::type_name_info<T>().len> sproutstring;
typedef sprout::string<implem::type_name_len<T>()> sproutstringret;
return sproutstringret(
implem::type_name_info<T>().str + sproutstring(implem::type_name_info<T>().str).find(
'=',
sproutstring(implem::type_name_info<T>().str).find('[')
) + 2,
implem::type_name_len<T>() - 1
);
# else
std::string pf(__PRETTY_FUNCTION__);
const auto read_start = pf.find('=', pf.find('[') + 1) + 2;
# if defined(__clang__)
const std::size_t typename_end = pf.size() - 1;
# else
const auto typename_end = pf.find(';', read_start);
#endif
return pf.substr(
read_start,
typename_end - read_start
);
# endif
#else
# error "not implemented"
const char* const pf = __PRETTY_FUNCTION__;
const std::size_t len = sizeof(__PRETTY_FUNCTION__) - 1;
#endif
}
namespace implem {
#if defined(IS_PRETTY_FUNC_CONSTEXPR) || defined(USE_MANUAL_TYPENAMES)
template <typename T>
constexpr type_name_info<T>::type_name_info() :
# if defined(__GNUC__)
# if defined(USE_MANUAL_TYPENAMES)
len(sprout::strlen(manual_type_name<T>())),
str(manual_type_name<T>())
# else
len(sizeof(__PRETTY_FUNCTION__)),
str(__PRETTY_FUNCTION__)
# endif
# else
# error "not implemented"
# endif
{
}
template <typename T>
constexpr std::size_t type_name_len() {
typedef sprout::string<implem::type_name_info<T>().len> sproutstring;
# if defined(__GNUC__)
return type_name_info<T>().len - sproutstring(
implem::type_name_info<T>().str).find('=', sproutstring(implem::type_name_info<T>().str).find('[')) - 3;
# else
# error "not implemented"
# endif
}
#endif
} //namespace implem
} //namespace dk