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 (c) 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(k_svLambdaMarker, 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(k_svLambdaMarker, nStartMarker) == nStartMarker + 1)
186  nStartMarker = string_view_type::npos;
187 
188  return svSignature.substr(0, nStartMarker);
189 }
190 
191 template<class T, class char_t>
193 {
194  std::array<string_view_type, get_num_template_parameters()> tokens;
195 
196  const string_view_type svSignature = create_signature();
197 
198  size_t nTokenStart = 0;
199  size_t nBraceCounter = 0;
200  size_t nParam = 0;
201 
202  const auto add_token = [&tokens, &svSignature](size_t nToken, size_t nStart, size_t nEnd)
203  {
204  while (svSignature[nStart] == QX_CHAR_PREFIX(char_t, ' '))
205  ++nStart;
206 
207  while (svSignature[nEnd] == QX_CHAR_PREFIX(char_t, ' '))
208  --nEnd;
209 
210  constexpr string_view_type classMarker = QX_STR_PREFIX(char_t, "class ");
211  if (svSignature.substr(nStart, nEnd - nStart).starts_with(classMarker))
212  nStart += classMarker.size();
213 
214  tokens[nToken] = svSignature.substr(nStart, nEnd + 1 - nStart);
215  };
216 
217  bool bLambda = false;
218 
219  for (size_t i = 0; i < svSignature.size(); ++i)
220  {
221  switch (svSignature[i])
222  {
223  case QX_CHAR_PREFIX(char_t, '<'):
224  ++nBraceCounter;
225 
226  if (nTokenStart == 0)
227  nTokenStart = i + 1;
228  else if (!bLambda && svSignature.find(k_svLambdaMarker, i + 1) == i + 1)
229  bLambda = true;
230 
231  break;
232 
233  case QX_CHAR_PREFIX(char_t, '>'):
234  --nBraceCounter;
235  if (bLambda)
236  bLambda = false;
237 
238  break;
239 
240  case QX_CHAR_PREFIX(char_t, ','):
241  if (nBraceCounter == 1)
242  {
243  add_token(nParam, nTokenStart, i - 1);
244  nTokenStart = i + 1;
245  ++nParam;
246  }
247  break;
248  }
249  }
250 
251  if (tokens.size() > 0)
252  {
253  size_t nTokenEnd = svSignature.size() - 1;
254 
255  if (svSignature[nTokenEnd] == QX_CHAR_PREFIX(char_t, ' '))
256  --nTokenEnd;
257 
258  if (svSignature[nTokenEnd] == QX_CHAR_PREFIX(char_t, '>'))
259  --nTokenEnd;
260 
261  add_token(nParam, nTokenStart, nTokenEnd);
262  }
263 
264  return tokens;
265 }
266 
267 } // 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:128
#define QX_STR_PREFIX(value_t, str)
Chose witch of prefixes add to string : L or none.
Definition: string_utils.h:120