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  static_assert(
20  std::is_same_v<char_t, char>,
21  "Can't use __PRETTY_FUNCTION__ with wchar_t as it is not a macro but a function");
22 
23  return __PRETTY_FUNCTION__;
24 #endif
25 }
26 
27 template<class T, class char_t>
28 constexpr typename type_strings<T, char_t>::string_view_type type_strings<T, char_t>::create_signature()
29 {
30  constexpr string_view_type svFunctionSignature = create_full_signature();
31 
32 #if QX_MSVC
33  constexpr string_view_type svStartMarker = QX_STR_PREFIX(char_t, "type_strings<");
34  constexpr string_view_type svEndMarker = QX_STR_PREFIX(char_t, ">::create_full_signature(");
35 #elif QX_CLANG
36  constexpr string_view_type svStartMarker = QX_STR_PREFIX(char_t, "T = ");
37  constexpr string_view_type svEndMarker = QX_STR_PREFIX(char_t, ", char_t = ");
38 #elif QX_GNU
39  constexpr string_view_type svStartMarker = QX_STR_PREFIX(char_t, "T = ");
40  constexpr string_view_type svEndMarker = QX_STR_PREFIX(char_t, ";");
41 #endif
42 
43  size_t nStartMarker = svFunctionSignature.find(svStartMarker);
44  size_t nStart = nStartMarker != string_view_type::npos ? (nStartMarker + svStartMarker.size()) : 0;
45 
46  constexpr string_view_type classMarker = QX_STR_PREFIX(char_t, "class ");
47  size_t nClassMarker = svFunctionSignature.find(classMarker, nStart);
48  if (nClassMarker != string_view_type::npos)
49  nStart = nClassMarker + classMarker.size();
50 
51  size_t nEndMarker = svFunctionSignature.find(svEndMarker, nStart);
52  size_t nEnd = nEndMarker != string_view_type::npos ? nEndMarker : svFunctionSignature.size();
53 
54 #if QX_MSVC
55  size_t nCharCommaMarker = svFunctionSignature.rfind(QX_CHAR_PREFIX(char_t, ','), nEnd);
56  if (nCharCommaMarker != string_view_type::npos)
57  nEnd = nCharCommaMarker;
58 #endif
59 
60  return string_view_type(svFunctionSignature.data() + nStart, nEnd - nStart);
61 }
62 
63 template<class T, class char_t>
64 constexpr size_t type_strings<T, char_t>::get_num_template_parameters()
65 {
66  const string_view_type svSignature = create_signature();
67 
68  size_t nBraceCounter = 0;
69  size_t nParams = 0;
70  bool bLambda = false;
71 
72  for (size_t i = 0; i < svSignature.size(); ++i)
73  {
74  switch (svSignature[i])
75  {
76  case QX_CHAR_PREFIX(char_t, '<'):
77  if (!bLambda)
78  {
79  ++nBraceCounter;
80 
81  if (svSignature.find(lambdaMarker, i + 1) == i + 1)
82  bLambda = true;
83  else if (nParams == 0 && nBraceCounter == 1)
84  ++nParams;
85  }
86  break;
87 
88  case QX_CHAR_PREFIX(char_t, '>'):
89  --nBraceCounter;
90 
91  if (bLambda)
92  bLambda = false;
93 
94  break;
95 
96  case QX_CHAR_PREFIX(char_t, ','):
97  if (nBraceCounter == 1)
98  ++nParams;
99 
100  break;
101  }
102  }
103 
104  return nParams;
105 }
106 
107 template<class T, class char_t>
108 constexpr typename type_strings<T, char_t>::string_view_type type_strings<T, char_t>::get_signature()
109 {
110  return create_signature();
111 }
112 
113 template<class T, class char_t>
114 constexpr typename type_strings<T, char_t>::string_view_type type_strings<T, char_t>::get_name()
115 {
116  constexpr string_view_type svStartMarker = QX_STR_PREFIX(char_t, "<");
117  const string_view_type svSignature = create_signature();
118  size_t nStartMarker = svSignature.find(svStartMarker);
119 
120  if (nStartMarker != string_view_type::npos && svSignature.find(lambdaMarker, nStartMarker) == nStartMarker + 1)
121  nStartMarker = string_view_type::npos;
122 
123  return string_view_type(
124  svSignature.data(),
125  nStartMarker != string_view_type::npos ? nStartMarker : svSignature.size());
126 }
127 
128 template<class T, class char_t>
130 {
131  std::array<string_view_type, get_num_template_parameters()> tokens;
132 
133  const string_view_type svSignature = create_signature();
134 
135  size_t nTokenStart = 0;
136  size_t nBraceCounter = 0;
137  size_t nParam = 0;
138 
139  const auto add_token = [&tokens, &svSignature](size_t nToken, size_t nStart, size_t nEnd)
140  {
141  while (svSignature[nStart] == QX_CHAR_PREFIX(char_t, ' '))
142  ++nStart;
143 
144  while (svSignature[nEnd] == QX_CHAR_PREFIX(char_t, ' '))
145  --nEnd;
146 
147  constexpr string_view_type classMarker = QX_STR_PREFIX(char_t, "class ");
148  if (string_view_type(svSignature.data() + nStart, nEnd - nStart).starts_with(classMarker))
149  nStart += classMarker.size();
150 
151  tokens[nToken] = string_view_type(svSignature.data() + nStart, nEnd + 1 - nStart);
152  };
153 
154  bool bLambda = false;
155 
156  for (size_t i = 0; i < svSignature.size(); ++i)
157  {
158  switch (svSignature[i])
159  {
160  case QX_CHAR_PREFIX(char_t, '<'):
161  ++nBraceCounter;
162 
163  if (nTokenStart == 0)
164  nTokenStart = i + 1;
165  else if (!bLambda && svSignature.find(lambdaMarker, i + 1) == i + 1)
166  bLambda = true;
167 
168  break;
169 
170  case QX_CHAR_PREFIX(char_t, '>'):
171  --nBraceCounter;
172  if (bLambda)
173  bLambda = false;
174 
175  break;
176 
177  case QX_CHAR_PREFIX(char_t, ','):
178  if (nBraceCounter == 1)
179  {
180  add_token(nParam, nTokenStart, i - 1);
181  nTokenStart = i + 1;
182  ++nParam;
183  }
184  break;
185  }
186  }
187 
188  if (tokens.size() > 0)
189  {
190  size_t nTokenEnd = svSignature.size() - 1;
191 
192  if (svSignature[nTokenEnd] == QX_CHAR_PREFIX(char_t, ' '))
193  --nTokenEnd;
194 
195  if (svSignature[nTokenEnd] == QX_CHAR_PREFIX(char_t, '>'))
196  --nTokenEnd;
197 
198  add_token(nParam, nTokenStart, nTokenEnd);
199  }
200 
201  return tokens;
202 }
203 
204 } // 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:257
#define QX_STR_PREFIX(value_t, str)
Chose witch of prefixes add to string : L or none.
Definition: string_utils.h:249