Radium Engine  1.7.2
Loading...
Searching...
No Matches
TypesUtils.hpp
1#pragma once
2#include <Core/RaCore.hpp>
3#include <Core/Utils/StringUtils.hpp>
4
5#ifndef _WIN32
6# include <cxxabi.h>
7# include <memory>
8#else
9# include <typeinfo>
10#endif
11
12#include <regex>
13#include <string>
14#include <typeindex>
15
16namespace Ra {
17namespace Core {
18namespace Utils {
19
21template <typename T>
22std::string demangleType() noexcept;
23
25template <typename T>
26std::string demangleType( const T& ) noexcept;
27
29RA_CORE_API std::string demangleType( const std::type_index& typeName ) noexcept;
30
32template <typename T>
33auto simplifiedDemangledType() noexcept -> std::string;
34
36template <typename T>
37auto simplifiedDemangledType( const T& ) noexcept -> std::string;
38
43RA_CORE_API auto simplifiedDemangledType( const std::type_index& typeName ) noexcept -> std::string;
44
45// Check if a type is a container with access to its element type and number
46// adapted from https://stackoverflow.com/questions/13830158/check-if-a-variable-type-is-iterable
47namespace detail {
48
49using std::begin;
50using std::end;
51
52template <typename T>
53auto is_container_impl( int )
54 -> decltype( begin( std::declval<T&>() ) !=
55 end( std::declval<T&>() ), // begin/end and operator !=
56 void(), // Handle evil operator ,
57 std::declval<T&>().empty(),
58 std::declval<T&>().size(),
59 ++std::declval<decltype( begin( std::declval<T&>() ) )&>(), // operator ++
60 void( *begin( std::declval<T&>() ) ), // operator*
61 std::true_type {} );
62
63template <typename T>
64std::false_type is_container_impl( ... );
65
66} // namespace detail
67
68template <typename T>
69using is_container = decltype( detail::is_container_impl<T>( 0 ) );
70
71// -----------------------------------------------------------------
72// ---------------------- inline methods ---------------------------
73
74namespace TypeInternal {
75RA_CORE_API auto makeTypeReadable( const std::string& ) -> std::string;
76}
77
78template <typename T>
79auto simplifiedDemangledType() noexcept -> std::string {
80 // don't get why we need a lambda here ?
81 // static auto demangled_name = []() {
82 // std::string demangledType =
83 // TypeInternal::makeTypeReadable( Ra::Core::Utils::demangleType<T>() );
84 // return demangledType;
85 // }();
86 static auto demangled_name =
87 TypeInternal::makeTypeReadable( Ra::Core::Utils::demangleType<T>() );
88
89 return demangled_name;
90}
91
92template <typename T>
93auto simplifiedDemangledType( const T& ) noexcept -> std::string {
94 return simplifiedDemangledType<T>();
95}
96
97inline auto simplifiedDemangledType( const std::type_index& typeName ) noexcept -> std::string {
98 return TypeInternal::makeTypeReadable( Ra::Core::Utils::demangleType( typeName ) );
99}
100
101// TypeList taken and adapted from
102// https://github.com/AcademySoftwareFoundation/openvdb/blob/master/openvdb/openvdb/TypeList.h
103// Only took small part of TypeList utilities
104
105// forward declarations
106template <typename... Ts>
107struct TypeList;
108
109namespace TypeListInternal {
110
115template <typename ListT, typename... Ts>
117
122template <typename... Ts, typename... OtherTs>
123struct TSAppendImpl<TypeList<Ts...>, OtherTs...> {
124 using type = TypeList<Ts..., OtherTs...>;
125};
126
131template <typename... Ts, typename... OtherTs>
132struct TSAppendImpl<TypeList<Ts...>, TypeList<OtherTs...>> {
133 using type = TypeList<Ts..., OtherTs...>;
134};
135
136} // namespace TypeListInternal
137
138template <typename... Ts>
139struct TypeList {
141 using Self = TypeList;
143 static constexpr size_t Size = sizeof...( Ts );
144
160 template <typename... TypesToAppend>
161 using Append = typename TypeListInternal::TSAppendImpl<Self, TypesToAppend...>::type;
162};
163
164inline std::string demangleType( const std::type_index& typeIndex ) noexcept {
165 std::string retval;
166
167 // On windows (since MSVC 2019), typeid( T ).name() (and then typeIndex.name() returns the
168 // demangled name
169#ifdef _WIN32
170 retval = typeIndex.name();
171 // On Linux/macos, use the C++ ABI demangler
172#else
173 int error = 0;
174 char* name = abi::__cxa_demangle( typeIndex.name(), 0, 0, &error );
175 if ( error == 0 ) { retval = name; }
176 else {
177 // error : -1 --> memory allocation failed
178 // error : -2 --> not a valid mangled name
179 // error : other --> __cxa_demangle
180 retval = std::string( "Type demangler error : " ) + std::to_string( error );
181 }
182 std::free( name );
183#endif
184 removeAllInString( retval, "class " );
185 removeAllInString( retval, "struct " );
186 removeAllInString( retval, "__cdecl" );
187 replaceAllInString( retval, "& __ptr64", "&" );
188 replaceAllInString( retval, ",", ", " );
189 replaceAllInString( retval, " >", ">" );
190 replaceAllInString( retval, "__int64", "long" );
191 replaceAllInString( retval, "const &", "const&" );
192 removeAllInString( retval, "__cxx11::" ); // windows<>gnu inconsistency
193 removeAllInString( retval, "__1::" ); // or "::__1" ?
194 replaceAllInString( retval, " >", ">" );
195
196 // " , , , ,," -> ,
197 retval = std::regex_replace( retval, std::regex( R"(\s*,(\s*,)+)" ), "," );
198 //" ," -> ,
199 retval = std::regex_replace( retval, std::regex( R"(\s*,)" ), "," );
200 // " , >" -> >
201 retval = std::regex_replace( retval, std::regex( R"(\s*,\s*>)" ), ">" );
202 // " " -> " "
203 retval = std::regex_replace( retval, std::regex( R"(\s+)" ), " " );
204
205 return retval;
206}
207
208template <typename T>
209std::string demangleType() noexcept {
210 // once per one type
211 static auto demangled_name = demangleType( std::type_index( typeid( T ) ) );
212 return demangled_name;
213}
214
215// calling with instances
216template <typename T>
217std::string demangleType( const T& ) noexcept {
218 return demangleType<T>();
219}
220
221} // namespace Utils
222} // namespace Core
223} // namespace Ra
T begin(T... args)
T declval(T... args)
T end(T... args)
T free(T... args)
hepler function to manage enum as underlying types in VariableSet
Definition Cage.cpp:4
STL namespace.
T regex_replace(T... args)
Append any number of types to a TypeList.
T to_string(T... args)