qxLib
type_strings.inl
Go to the documentation of this file.
1 /**
2 
3  @file type_strings.inl
4  @author Khrapov
5  @date 24.09.2022
6  @copyright © Nick Khrapov, 2022. All right reserved.
7 
8 **/
9 
10 namespace qx
11 {
12 
13 namespace details
14 {
15 
16 template<class char_t, size_t N>
17 constexpr std::array<char_t, N> to_char_array(std::span<const char, N> svChar)
18 {
19  std::array<char_t, N> result;
20  for (size_t i = 0; i < N; ++i)
21  result[i] = svChar[i];
22  return result;
23 }
24 
25 template<class char_t, string_literal array>
27 {
28  static constexpr auto char_array =
29  to_char_array<char_t>(std::span<const char, array.size()>(array.data(), array.data() + array.size()));
30 };
31 
32 } // namespace details
33 
34 template<class T, class char_t>
35 constexpr typename type_strings<T, char_t>::string_view_type type_strings<T, char_t>::create_full_signature()
36 {
37 #if QX_MSVC
38  return QX_STR_PREFIX(char_t, __FUNCSIG__);
39 #elif QX_CLANG || QX_GNU
40  if constexpr (std::is_same_v<char_t, char>)
41  {
42  return __PRETTY_FUNCTION__;
43  }
44  else
45  {
46  return string_view_type(details::char_array_helper<char_t, __PRETTY_FUNCTION__>::char_array.data());
47  }
48 #endif
49 }
50 
51 template<class T, class char_t>
52 constexpr typename type_strings<T, char_t>::string_view_type type_strings<T, char_t>::create_signature()
53 {
54  constexpr string_view_type svFunctionSignature = create_full_signature();
55 
56 #if QX_MSVC
57  constexpr string_view_type svStartMarker = QX_STR_PREFIX(char_t, "type_strings<");
58  constexpr string_view_type svEndMarker = QX_STR_PREFIX(char_t, ">::create_full_signature(");
59 #elif QX_CLANG
60  constexpr string_view_type svStartMarker = QX_STR_PREFIX(char_t, "T = ");
61  constexpr string_view_type svEndMarker = QX_STR_PREFIX(char_t, ", char_t = ");
62 #elif QX_GNU
63  constexpr string_view_type svStartMarker = QX_STR_PREFIX(char_t, "T = ");
64  constexpr string_view_type svEndMarker = QX_STR_PREFIX(char_t, ";");
65 #endif
66 
67  size_t nStartMarker = svFunctionSignature.find(svStartMarker);
68  size_t nStart = nStartMarker != string_view_type::npos ? (nStartMarker + svStartMarker.size()) : 0;
69 
70  constexpr string_view_type classMarker = QX_STR_PREFIX(char_t, "class ");
71  size_t nClassMarker = svFunctionSignature.find(classMarker, nStart);
72  if (nClassMarker != string_view_type::npos)
73  nStart = nClassMarker + classMarker.size();
74 
75  size_t nEndMarker = svFunctionSignature.find(svEndMarker, nStart);
76  size_t nEnd = nEndMarker != string_view_type::npos ? nEndMarker : svFunctionSignature.size();
77 
78 #if QX_MSVC
79  size_t nCharCommaMarker = svFunctionSignature.rfind(QX_CHAR_PREFIX(char_t, ','), nEnd);
80  if (nCharCommaMarker != string_view_type::npos)
81  nEnd = nCharCommaMarker;
82 #endif
83 
84  return string_view_type(svFunctionSignature.data() + nStart, nEnd - nStart);
85 }
86 
87 template<class T, class char_t>
88 constexpr size_t type_strings<T, char_t>::get_num_template_parameters()
89 {
90  const string_view_type svSignature = create_signature();
91 
92  size_t nBraceCounter = 0;
93  size_t nParams = 0;
94  bool bLambda = false;
95 
96  for (size_t i = 0; i < svSignature.size(); ++i)
97  {
98  switch (svSignature[i])
99  {
100  case QX_CHAR_PREFIX(char_t, '<'):
101  if (!bLambda)
102  {
103  ++nBraceCounter;
104 
105  if (svSignature.find(lambdaMarker, i + 1) == i + 1)
106  bLambda = true;
107  else if (nParams == 0 && nBraceCounter == 1)
108  ++nParams;
109  }
110  break;
111 
112  case QX_CHAR_PREFIX(char_t, '>'):
113  --nBraceCounter;
114 
115  if (bLambda)
116  bLambda = false;
117 
118  break;
119 
120  case QX_CHAR_PREFIX(char_t, ','):
121  if (nBraceCounter == 1)
122  ++nParams;
123 
124  break;
125  }
126  }
127 
128  return nParams;
129 }
130 
131 template<class T, class char_t>
132 constexpr typename type_strings<T, char_t>::string_view_type type_strings<T, char_t>::get_signature()
133 {
134  return create_signature();
135 }
136 
137 template<class T, class char_t>
138 constexpr typename type_strings<T, char_t>::string_view_type type_strings<T, char_t>::get_name()
139 {
140  constexpr string_view_type svStartMarker = QX_STR_PREFIX(char_t, "<");
141  const string_view_type svSignature = create_signature();
142  size_t nStartMarker = svSignature.find(svStartMarker);
143 
144  if (nStartMarker != string_view_type::npos && svSignature.find(lambdaMarker, nStartMarker) == nStartMarker + 1)
145  nStartMarker = string_view_type::npos;
146 
147  return string_view_type(
148  svSignature.data(),
149  nStartMarker != string_view_type::npos ? nStartMarker : svSignature.size());
150 }
151 
152 template<class T, class char_t>
154 {
155  std::array<string_view_type, get_num_template_parameters()> tokens;
156 
157  const string_view_type svSignature = create_signature();
158 
159  size_t nTokenStart = 0;
160  size_t nBraceCounter = 0;
161  size_t nParam = 0;
162 
163  const auto add_token = [&tokens, &svSignature](size_t nToken, size_t nStart, size_t nEnd)
164  {
165  while (svSignature[nStart] == QX_CHAR_PREFIX(char_t, ' '))
166  ++nStart;
167 
168  while (svSignature[nEnd] == QX_CHAR_PREFIX(char_t, ' '))
169  --nEnd;
170 
171  constexpr string_view_type classMarker = QX_STR_PREFIX(char_t, "class ");
172  if (string_view_type(svSignature.data() + nStart, nEnd - nStart).starts_with(classMarker))
173  nStart += classMarker.size();
174 
175  tokens[nToken] = string_view_type(svSignature.data() + nStart, nEnd + 1 - nStart);
176  };
177 
178  bool bLambda = false;
179 
180  for (size_t i = 0; i < svSignature.size(); ++i)
181  {
182  switch (svSignature[i])
183  {
184  case QX_CHAR_PREFIX(char_t, '<'):
185  ++nBraceCounter;
186 
187  if (nTokenStart == 0)
188  nTokenStart = i + 1;
189  else if (!bLambda && svSignature.find(lambdaMarker, i + 1) == i + 1)
190  bLambda = true;
191 
192  break;
193 
194  case QX_CHAR_PREFIX(char_t, '>'):
195  --nBraceCounter;
196  if (bLambda)
197  bLambda = false;
198 
199  break;
200 
201  case QX_CHAR_PREFIX(char_t, ','):
202  if (nBraceCounter == 1)
203  {
204  add_token(nParam, nTokenStart, i - 1);
205  nTokenStart = i + 1;
206  ++nParam;
207  }
208  break;
209  }
210  }
211 
212  if (tokens.size() > 0)
213  {
214  size_t nTokenEnd = svSignature.size() - 1;
215 
216  if (svSignature[nTokenEnd] == QX_CHAR_PREFIX(char_t, ' '))
217  --nTokenEnd;
218 
219  if (svSignature[nTokenEnd] == QX_CHAR_PREFIX(char_t, '>'))
220  --nTokenEnd;
221 
222  add_token(nParam, nTokenStart, nTokenEnd);
223  }
224 
225  return tokens;
226 }
227 
228 } // namespace qx
The class allows you to get strings with information about the type, including its full name,...
Definition: type_strings.h:37
static constexpr auto get_template_parameters()
Get type template parameters.
static constexpr string_view_type get_name()
Get type name (short name without template parameters)
static constexpr string_view_type get_signature()
Get type signature (full name with template parameters)
#define QX_CHAR_PREFIX(value_t, ch)
Chose witch of prefixes add to char : L or none.
Definition: string_utils.h:257
#define QX_STR_PREFIX(value_t, str)
Chose witch of prefixes add to string : L or none.
Definition: string_utils.h:249