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 template<class T, class char_t>
14 constexpr typename type_strings<T, char_t>::string_view_type type_strings<T, char_t>::create_full_signature()
15 {
16 #if QX_MSVC
17  return QX_STR_PREFIX(char_t, __FUNCSIG__);
18 #elif QX_CLANG || QX_GNU
19  if constexpr (std::is_same_v<char_t, char>)
20  return __PRETTY_FUNCTION__;
21  else
22  return convert_string_literal<char_t, __PRETTY_FUNCTION__>();
23 #endif
24 }
25 
26 template<class T, class char_t>
27 constexpr typename type_strings<T, char_t>::string_view_type type_strings<T, char_t>::create_signature()
28 {
29  // Make an output for built-in types compiler independent.
30  // Note: this won't work for complied types (for example, std::array<int, 5>)
31 
32  if constexpr (std::is_same_v<T, void>)
33  return "void";
34 
35  else if constexpr (std::is_same_v<T, bool>)
36  return "bool";
37 
38  else if constexpr (std::is_same_v<T, char>)
39  return "char";
40 
41  else if constexpr (std::is_same_v<T, signed char>)
42  return "signed char";
43 
44  else if constexpr (std::is_same_v<T, unsigned char>)
45  return "unsigned char";
46 
47  else if constexpr (std::is_same_v<T, wchar_t>)
48  return "wchar_t";
49 
50  else if constexpr (std::is_same_v<T, char8_t>)
51  return "char8_t";
52 
53  else if constexpr (std::is_same_v<T, char16_t>)
54  return "char16_t";
55 
56  else if constexpr (std::is_same_v<T, char32_t>)
57  return "char32_t";
58 
59  else if constexpr (std::is_same_v<T, std::int8_t>)
60  return "int8_t";
61 
62  else if constexpr (std::is_same_v<T, std::uint8_t>)
63  return "uint8_t";
64 
65  else if constexpr (std::is_same_v<T, std::int16_t>)
66  return "int16_t";
67 
68  else if constexpr (std::is_same_v<T, std::uint16_t>)
69  return "uint16_t";
70 
71  else if constexpr (std::is_same_v<T, std::int32_t>)
72  return "int32_t";
73 
74  else if constexpr (std::is_same_v<T, std::uint32_t>)
75  return "uint32_t";
76 
77  else if constexpr (std::is_same_v<T, std::int64_t>)
78  return "int64_t";
79 
80  else if constexpr (std::is_same_v<T, std::uint64_t>)
81  return "uint64_t";
82 
83  else if constexpr (std::is_same_v<T, float>)
84  return "float";
85 
86  else if constexpr (std::is_same_v<T, double>)
87  return "double";
88 
89  else if constexpr (std::is_same_v<T, long double>)
90  return "long double";
91 
92  else if constexpr (std::is_same_v<T, std::nullptr_t>)
93  return "nullptr_t";
94 
95  constexpr string_view_type svFunctionSignature = create_full_signature();
96 
97 #if QX_MSVC
98  constexpr string_view_type svStartMarker = QX_STR_PREFIX(char_t, "type_strings<");
99  constexpr string_view_type svEndMarker = QX_STR_PREFIX(char_t, ">::create_full_signature(");
100 #elif QX_CLANG
101  constexpr string_view_type svStartMarker = QX_STR_PREFIX(char_t, "T = ");
102  constexpr string_view_type svEndMarker = QX_STR_PREFIX(char_t, ", char_t = ");
103 #elif QX_GNU
104  constexpr string_view_type svStartMarker = QX_STR_PREFIX(char_t, "T = ");
105  constexpr string_view_type svEndMarker = QX_STR_PREFIX(char_t, ";");
106 #endif
107 
108  size_t nStartMarker = svFunctionSignature.find(svStartMarker);
109  size_t nStart = nStartMarker != string_view_type::npos ? (nStartMarker + svStartMarker.size()) : 0;
110 
111  constexpr string_view_type classMarker = QX_STR_PREFIX(char_t, "class ");
112  size_t nClassMarker = svFunctionSignature.find(classMarker, nStart);
113  if (nClassMarker != string_view_type::npos)
114  nStart = nClassMarker + classMarker.size();
115 
116  size_t nEndMarker = svFunctionSignature.find(svEndMarker, nStart);
117  size_t nEnd = nEndMarker != string_view_type::npos ? nEndMarker : svFunctionSignature.size();
118 
119 #if QX_MSVC
120  size_t nCharCommaMarker = svFunctionSignature.rfind(QX_CHAR_PREFIX(char_t, ','), nEnd);
121  if (nCharCommaMarker != string_view_type::npos)
122  nEnd = nCharCommaMarker;
123 #endif
124 
125  return string_view_type(svFunctionSignature.data() + nStart, nEnd - nStart);
126 }
127 
128 template<class T, class char_t>
129 constexpr size_t type_strings<T, char_t>::get_num_template_parameters()
130 {
131  const string_view_type svSignature = create_signature();
132 
133  size_t nBraceCounter = 0;
134  size_t nParams = 0;
135  bool bLambda = false;
136 
137  for (size_t i = 0; i < svSignature.size(); ++i)
138  {
139  switch (svSignature[i])
140  {
141  case QX_CHAR_PREFIX(char_t, '<'):
142  if (!bLambda)
143  {
144  ++nBraceCounter;
145 
146  if (svSignature.find(lambdaMarker, i + 1) == i + 1)
147  bLambda = true;
148  else if (nParams == 0 && nBraceCounter == 1)
149  ++nParams;
150  }
151  break;
152 
153  case QX_CHAR_PREFIX(char_t, '>'):
154  --nBraceCounter;
155 
156  if (bLambda)
157  bLambda = false;
158 
159  break;
160 
161  case QX_CHAR_PREFIX(char_t, ','):
162  if (nBraceCounter == 1)
163  ++nParams;
164 
165  break;
166  }
167  }
168 
169  return nParams;
170 }
171 
172 template<class T, class char_t>
173 constexpr typename type_strings<T, char_t>::string_view_type type_strings<T, char_t>::get_signature()
174 {
175  return create_signature();
176 }
177 
178 template<class T, class char_t>
179 constexpr typename type_strings<T, char_t>::string_view_type type_strings<T, char_t>::get_name()
180 {
181  constexpr string_view_type svStartMarker = QX_STR_PREFIX(char_t, "<");
182  const string_view_type svSignature = create_signature();
183  size_t nStartMarker = svSignature.find(svStartMarker);
184 
185  if (nStartMarker != string_view_type::npos && svSignature.find(lambdaMarker, nStartMarker) == nStartMarker + 1)
186  nStartMarker = string_view_type::npos;
187 
188  return string_view_type(
189  svSignature.data(),
190  nStartMarker != string_view_type::npos ? nStartMarker : svSignature.size());
191 }
192 
193 template<class T, class char_t>
195 {
196  std::array<string_view_type, get_num_template_parameters()> tokens;
197 
198  const string_view_type svSignature = create_signature();
199 
200  size_t nTokenStart = 0;
201  size_t nBraceCounter = 0;
202  size_t nParam = 0;
203 
204  const auto add_token = [&tokens, &svSignature](size_t nToken, size_t nStart, size_t nEnd)
205  {
206  while (svSignature[nStart] == QX_CHAR_PREFIX(char_t, ' '))
207  ++nStart;
208 
209  while (svSignature[nEnd] == QX_CHAR_PREFIX(char_t, ' '))
210  --nEnd;
211 
212  constexpr string_view_type classMarker = QX_STR_PREFIX(char_t, "class ");
213  if (string_view_type(svSignature.data() + nStart, nEnd - nStart).starts_with(classMarker))
214  nStart += classMarker.size();
215 
216  tokens[nToken] = string_view_type(svSignature.data() + nStart, nEnd + 1 - nStart);
217  };
218 
219  bool bLambda = false;
220 
221  for (size_t i = 0; i < svSignature.size(); ++i)
222  {
223  switch (svSignature[i])
224  {
225  case QX_CHAR_PREFIX(char_t, '<'):
226  ++nBraceCounter;
227 
228  if (nTokenStart == 0)
229  nTokenStart = i + 1;
230  else if (!bLambda && svSignature.find(lambdaMarker, i + 1) == i + 1)
231  bLambda = true;
232 
233  break;
234 
235  case QX_CHAR_PREFIX(char_t, '>'):
236  --nBraceCounter;
237  if (bLambda)
238  bLambda = false;
239 
240  break;
241 
242  case QX_CHAR_PREFIX(char_t, ','):
243  if (nBraceCounter == 1)
244  {
245  add_token(nParam, nTokenStart, i - 1);
246  nTokenStart = i + 1;
247  ++nParam;
248  }
249  break;
250  }
251  }
252 
253  if (tokens.size() > 0)
254  {
255  size_t nTokenEnd = svSignature.size() - 1;
256 
257  if (svSignature[nTokenEnd] == QX_CHAR_PREFIX(char_t, ' '))
258  --nTokenEnd;
259 
260  if (svSignature[nTokenEnd] == QX_CHAR_PREFIX(char_t, '>'))
261  --nTokenEnd;
262 
263  add_token(nParam, nTokenStart, nTokenEnd);
264  }
265 
266  return tokens;
267 }
268 
269 } // namespace qx
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:255
#define QX_STR_PREFIX(value_t, str)
Chose witch of prefixes add to string : L or none.
Definition: string_utils.h:247