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