libcruft-util/introspection/name.hpp

125 lines
4.6 KiB
C++

/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright 2019-2020 Danny Robson <danny@nerdcruft.net>
*/
#pragma once
#include "../algo/search.hpp"
#include "../std.hpp"
#include <string_view>
#include <algorithm>
///////////////////////////////////////////////////////////////////////////////
namespace cruft::introspection::name {
template <typename T>
constexpr
std::string_view full (void)
{
std::string_view pretty_function (__PRETTY_FUNCTION__);
#ifdef __clang__
// PRETTY_FUNCTION = std::string_view cruft::type_name() [T = std::__1::vector<int, std::__1::allocator<int> >]
std::string_view const prefix = "[T = ";
#elif defined(__GNUC__)
// PRETTY_FUNCTION = "constexpr std::string_view cruft::type_name() [with T = std::__debug::vector<int>; std::string_view = std::basic_string_view<char>]"
std::string_view prefix = "[with T = ";
#else
#error "Unsupported compiler"
#endif
// Find the location where the type begins.
auto const type_begin = std::search (
pretty_function.begin (),
pretty_function.end (),
prefix.begin (),
prefix.end ()
) + prefix.size ();
// Find the point the type name ends. Both use ']', but gcc lists
// std::string_view in the function signature too and so requires the
// delimiting ';' as a suffix.
char const suffixes[] = ";]";
auto const type_end = std::find_first_of (
type_begin,
pretty_function.end (),
std::begin (suffixes),
std::end (suffixes)
);
// Find the start of the first template parameter so we can cut it out.
// If this isn't present we end up with a pointer to the end of the
// type string which is the end of the type anyway.
auto const template_start = std::find (type_begin, type_end, '<');
auto const template_end = cruft::search::balanced (template_start, type_end, '<', '>');
return std::string_view (
type_begin,
std::distance (type_begin, template_end)
);
}
template <typename T>
constexpr
std::string_view bare (void)
{
auto const fullname = full<T> ();
constexpr char const namespace_symbol[] = "::";
auto const last_namespace_pos = std::search (
std::rbegin (fullname),
std::rend (fullname),
namespace_symbol + 0,
namespace_symbol + 2
);
auto const length = std::distance (std::rbegin (fullname), last_namespace_pos);
auto const offset = fullname.size () - length;
return std::string_view (fullname.data () + offset, length);
}
template <> constexpr std::string_view bare<i08> (void) { return "i08"; }
template <> constexpr std::string_view bare<i16> (void) { return "i16"; }
template <> constexpr std::string_view bare<i32> (void) { return "i32"; }
template <> constexpr std::string_view bare<i64> (void) { return "i64"; }
template <> constexpr std::string_view bare<u08> (void) { return "u08"; }
template <> constexpr std::string_view bare<u16> (void) { return "u16"; }
template <> constexpr std::string_view bare<u32> (void) { return "u32"; }
template <> constexpr std::string_view bare<u64> (void) { return "u64"; }
template <> constexpr std::string_view bare<f32> (void) { return "f32"; }
template <> constexpr std::string_view bare<f64> (void) { return "f64"; }
///////////////////////////////////////////////////////////////////////////
template <typename T>
struct type_char;
template <> struct type_char<float > { static constexpr char value = 'f'; };
template <> struct type_char<double> { static constexpr char value = 'd'; };
template <> struct type_char< int8_t> { static constexpr char value = 'i'; };
template <> struct type_char< int16_t> { static constexpr char value = 'i'; };
template <> struct type_char< int32_t> { static constexpr char value = 'i'; };
template <> struct type_char< int64_t> { static constexpr char value = 'i'; };
template <> struct type_char< uint8_t> { static constexpr char value = 'u'; };
template <> struct type_char<uint16_t> { static constexpr char value = 'u'; };
template <> struct type_char<uint32_t> { static constexpr char value = 'u'; };
template <> struct type_char<uint64_t> { static constexpr char value = 'u'; };
template <typename T>
constexpr auto type_char_v = type_char<T>::value;
}