160 lines
4.2 KiB
C++
160 lines
4.2 KiB
C++
/*
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <cstddef>
|
|
#include <type_traits>
|
|
|
|
#include <folly/Portability.h>
|
|
|
|
namespace folly {
|
|
|
|
namespace detail {
|
|
|
|
template <std::size_t S>
|
|
struct pretty_carray {
|
|
char data[S];
|
|
};
|
|
|
|
template <std::size_t S>
|
|
static constexpr pretty_carray<S> pretty_carray_from(char const (&in)[S]) {
|
|
pretty_carray<S> out{};
|
|
for (std::size_t i = 0; i < S; ++i) {
|
|
out.data[i] = in[i];
|
|
}
|
|
return out;
|
|
}
|
|
|
|
struct pretty_info {
|
|
std::size_t b;
|
|
std::size_t e;
|
|
};
|
|
|
|
template <typename To, std::size_t S>
|
|
static constexpr To pretty_info_to(pretty_info info, char const (&name)[S]) {
|
|
return To(name + info.b, info.e - info.b);
|
|
}
|
|
|
|
template <std::size_t S>
|
|
static constexpr std::size_t pretty_lfind(
|
|
char const (&haystack)[S],
|
|
char const needle) {
|
|
for (std::size_t i = 0; i < S - 1; ++i) {
|
|
if (haystack[i] == needle) {
|
|
return i;
|
|
}
|
|
}
|
|
return ~std::size_t(0);
|
|
}
|
|
|
|
template <std::size_t S>
|
|
static constexpr std::size_t pretty_rfind(
|
|
char const (&haystack)[S],
|
|
char const needle) {
|
|
for (std::size_t i = S; i != 0; --i) {
|
|
if (haystack[i - 1] == needle) {
|
|
return i - 1;
|
|
}
|
|
}
|
|
return ~std::size_t(0);
|
|
}
|
|
|
|
struct pretty_tag_msc {};
|
|
struct pretty_tag_gcc {};
|
|
|
|
using pretty_default_tag = std::conditional_t< //
|
|
kMscVer && !kIsClang,
|
|
pretty_tag_msc,
|
|
pretty_tag_gcc>;
|
|
|
|
template <typename T>
|
|
static constexpr auto pretty_raw(pretty_tag_msc) {
|
|
#if defined(_MSC_VER)
|
|
return pretty_carray_from(__FUNCSIG__);
|
|
#endif
|
|
}
|
|
|
|
template <typename T>
|
|
static constexpr auto pretty_raw(pretty_tag_gcc) {
|
|
#if defined(__GNUC__) || defined(__clang__)
|
|
return pretty_carray_from(__PRETTY_FUNCTION__);
|
|
#endif
|
|
}
|
|
|
|
template <std::size_t S>
|
|
static constexpr pretty_info pretty_parse(
|
|
pretty_tag_msc,
|
|
char const (&name)[S]) {
|
|
// void __cdecl folly::detail::pretty_raw<{...}>(
|
|
// folly::detail::pretty_tag_msc)
|
|
auto const la = pretty_lfind(name, '<');
|
|
auto const rp = pretty_rfind(name, '>');
|
|
return pretty_info{la + 1, rp};
|
|
}
|
|
|
|
template <std::size_t S>
|
|
static constexpr pretty_info pretty_parse(
|
|
pretty_tag_gcc,
|
|
char const (&name)[S]) {
|
|
// void folly::detail::pretty_raw(
|
|
// folly::detail::pretty_tag_gcc) [T = {...}]
|
|
auto const eq = pretty_lfind(name, '=');
|
|
auto const br = pretty_rfind(name, ']');
|
|
return pretty_info{eq + 2, br};
|
|
}
|
|
|
|
template <typename T, typename Tag>
|
|
struct pretty_name_zarray {
|
|
static constexpr auto raw_() {
|
|
constexpr auto const raw_ = pretty_raw<T>(Tag{});
|
|
return raw_;
|
|
}
|
|
static constexpr auto raw = raw_(); // indirection b/c of gcc-5.3 ice, gh#1105
|
|
static constexpr auto info = pretty_parse(Tag{}, raw.data);
|
|
static constexpr auto size = info.e - info.b;
|
|
static constexpr auto zarray_() {
|
|
pretty_carray<size + 1> data{};
|
|
for (std::size_t i = 0; i < size; ++i) {
|
|
data.data[i] = raw.data[info.b + i];
|
|
}
|
|
data.data[size] = 0;
|
|
return data;
|
|
}
|
|
static constexpr pretty_carray<size + 1> zarray = zarray_();
|
|
};
|
|
|
|
template <typename T, typename Tag>
|
|
constexpr pretty_carray<pretty_name_zarray<T, Tag>::size + 1>
|
|
pretty_name_zarray<T, Tag>::zarray;
|
|
|
|
} // namespace detail
|
|
|
|
// pretty_name
|
|
//
|
|
// Returns a statically-allocated C string containing the pretty name of T.
|
|
//
|
|
// The pretty name of a type varies by compiler, may include tokens which
|
|
// would not be present in the type name as it is spelled in the source code
|
|
// or as it would be symbolized, and may not include tokens which would be
|
|
// present in the type name as it would be symbolized.
|
|
template <typename T>
|
|
constexpr char const* pretty_name() {
|
|
return detail::pretty_name_zarray<T, detail::pretty_default_tag>::zarray.data;
|
|
}
|
|
|
|
} // namespace folly
|