GCC Code Coverage Report


Directory: include/tts/
File: include/tts/tools/typename.hpp
Date: 2026-10-14 16:28:14
Exec Total Coverage
Lines: 7 7 100.0%
Functions: 89 131 67.9%
Branches: 0 0 -%

Line Branch Exec Source
1 //======================================================================================================================
2 //! @file
3 /*
4 TTS - Tiny Test System
5 Copyright : TTS Contributors & Maintainers
6 SPDX-License-Identifier: BSL-1.0
7 */
8 //======================================================================================================================
9 #pragma once
10
11 #include <tts/tools/concepts.hpp>
12 #include <tts/tools/text.hpp>
13
14 namespace tts::_
15 {
16 template<typename T> struct typename_impl
17 {
18 private:
19 using data_t = struct
20 {
21 char const* data;
22 int size;
23 };
24 data_t data_ = {};
25
26 public:
27 constexpr typename_impl()
28 {
29 data_ = typename_impl_value();
30 }
31 786 constexpr auto data() const
32 {
33 786 return data_.data;
34 }
35 786 constexpr auto size() const
36 {
37 786 return data_.size;
38 }
39
40 template<_::stream OS> friend OS& operator<<(OS& os, typename_impl t)
41 {
42 for(int i = 0; i < t.size(); ++i)
43 os << t.data()[ i ];
44 return os;
45 }
46
47 private:
48 //==================================================================================================================
49 // constexpr C-style string queries
50 //==================================================================================================================
51 constexpr static int length(char const* str)
52 {
53 int i = 0;
54 while(str[ i ] != '\0')
55 {
56 ++i;
57 }
58 return i;
59 }
60
61 constexpr static auto find(char const* str, char const* n)
62 {
63 auto compare = [](char const* lhs, char const* rhs, int count)
64 {
65 if(lhs == nullptr || rhs == nullptr)
66 {
67 return rhs != nullptr ? -1 : 1;
68 }
69 for(int i = 0; i < count; ++i)
70 {
71 if(lhs[ i ] != rhs[ i ])
72 {
73 return lhs[ i ] < rhs[ i ] ? -1 : 1;
74 }
75 else if(lhs[ i ] == '\0')
76 {
77 return 0;
78 }
79 }
80 return 0;
81 };
82
83 auto begin = str;
84 if(char c = *n++; c != '\0')
85 {
86 int len = length(n);
87 do
88 {
89 char sc = {};
90 do
91 {
92 if((sc = *str++) == '\0') return 0;
93 } while(sc != c);
94 } while(compare(str, n, len) != 0);
95 --str;
96 }
97
98 return static_cast<int>(str - begin);
99 }
100
101 // Helper to find the last occurrence of a character
102 constexpr static int find_last(char const* str, char c)
103 {
104 int last_pos = -1;
105 for(int i = 0; str[ i ] != '\0'; ++i)
106 {
107 if(str[ i ] == c)
108 {
109 last_pos = i;
110 }
111 }
112 return last_pos;
113 }
114
115 //==================================================================================================================
116 // extract type name from easy-to-parse function
117 //==================================================================================================================
118 constexpr static auto typename_impl_value()
119 {
120 data_t that = {};
121
122 #if defined(_MSC_VER)
123 that.data = __FUNCSIG__;
124 auto offset = find(that.data, "<") + 1;
125 that.size = find(that.data, ">::typename_impl_value(") - offset;
126 that.data += offset;
127 #else
128 that.data = __PRETTY_FUNCTION__;
129 auto i = find(that.data, "=") + 2;
130 that.size = find_last(that.data, ']') - i;
131 3 that.data += i;
132 #endif
133 return that;
134 }
135 };
136 }
137
138 namespace tts
139 {
140 //====================================================================================================================
141 /**
142 @defgroup tools-types Type Utilities
143 @{
144 **/
145 //====================================================================================================================
146
147 //====================================================================================================================
148 /**
149 @public
150 @brief Evaluates to an object containing the name of the type `T` in readable form.
151
152 `typename_<T>` is a `constexpr` object that can be used to retrieve the name of a type `T` as a
153 text-like object. It can be used in conjunction with `as_text` or stream output operators to
154 display type names.
155
156 @groupheader{Example}
157 @snippet doc/typename.cpp snippet1
158
159 @tparam T Type to query.
160 **/
161 //====================================================================================================================
162 template<typename T> inline auto constexpr typename_ = _::typename_impl<T> {};
163
164 //====================================================================================================================
165 /**
166 @public
167 @brief Returns the name of the type `T` in readable form.
168
169 This function is a convenience wrapper around @ref typename_.
170
171 @groupheader{Example}
172 @snippet doc/typename.cpp snippet2
173
174 @param t Value to retrieve the type name for.
175 @return A `typename_` instance representing the name of `T` as a string-like object.
176 **/
177 //====================================================================================================================
178 6 template<typename T> constexpr auto name([[maybe_unused]] T const& t)
179 {
180 6 return typename_<T>;
181 }
182
183 //====================================================================================================================
184 /// @}
185 //====================================================================================================================
186 }
187