CPP-TOOLBOX
Loading...
Searching...
No Matches
meta_utils.hpp
Go to the documentation of this file.
1#ifndef META_UTILS_HPP
2#define META_UTILS_HPP
3
4#include <fstream>
5#include <iostream>
6#include <iterator>
7#include <optional>
8#include <set>
9#include <sstream>
10#include <stdexcept>
11#include <string>
12#include <unordered_set>
13#include <vector>
14#include <functional>
15#include <cstddef> // for size_t
16#include <variant>
17
19
20namespace meta_utils {
21
32 public:
37 enum class Type {
40 };
41
66 MetaInclude(std::string project_relative_path, Type type = Type::Local)
67 : path(std::move(project_relative_path)), type(type) {}
68
76 std::string str(const std::filesystem::path &base = ".") const {
77 if (type == Type::System) {
78 return "#include <" + path + ">";
79 } else {
80 auto rel_path = std::filesystem::relative(std::filesystem::path(path), base);
81 return "#include \"" + rel_path.generic_string() + "\"";
82 }
83 }
84
85 private:
86 std::string path;
87 Type type;
88};
89
90class MetaType;
91
92using MetaTemplateParameter = std::variant<unsigned int, MetaType>;
93
94// NOTE: we can't use MetaFunctions in here because we get a cyclic dependency
95class MetaType {
96 public:
97 std::string base_type_name;
101 // NOTE: this has to exist, because sometimes you have a struct that when serialized only uses up 5 bytes, but if
102 // you use the sizeof operator on it it would return 8, this is due to padding, which is not present in the
103 // serialized state
106 std::string literal_regex;
107
108 std::vector<MetaInclude> includes_required;
109
110 bool variably_sized = false;
111
112 // Optional pointer to underlying element type (e.g., for vector<T>)
113 // also note that when something is generic, we talk about the version with
114 // nullptr here, concrete types are when this is not a nullptr
115 std::vector<MetaTemplateParameter> template_parameters;
116
123
125 MetaType(std::string name, std::string string_to_type_func, std::string type_to_string_func,
126 std::string serialize_type_func, std::string size_when_serialized_bytes_func,
127 std::string deserialize_type_func, std::string literal_regex,
128 const std::vector<MetaTemplateParameter> &element_types = {})
129 : base_type_name(std::move(name)), string_to_type_func_lambda(std::move(string_to_type_func)),
130 type_to_string_func_lambda(std::move(type_to_string_func)), serialize_type_func_lambda(serialize_type_func),
131 size_when_serialized_bytes_func_lambda(size_when_serialized_bytes_func),
132 deserialize_type_func_lambda(deserialize_type_func), literal_regex(std::move(literal_regex)),
133 template_parameters(element_types) {
134
135 std::set<std::string> variably_sized_types = {"std::vector", "std::string"};
136 variably_sized = variably_sized_types.find(base_type_name) != variably_sized_types.end();
137 }
138
139 std::string to_string() const { return to_string_rec(*this); }
140
141 std::string get_type_name() const { return get_type_name_rec(*this); }
142
143 private:
144 std::string get_type_name_rec(const MetaType &meta_type) const {
145 if (meta_type.template_parameters.empty()) {
146 return meta_type.base_type_name;
147 }
148
149 std::ostringstream oss;
150 oss << meta_type.base_type_name << "<";
151
152 for (size_t i = 0; i < meta_type.template_parameters.size(); ++i) {
153 if (i > 0) {
154 oss << ", ";
155 }
156
157 std::visit(
158 [&](auto &&param) {
159 using T = std::decay_t<decltype(param)>;
160 if constexpr (std::is_same_v<T, unsigned int>) {
161 oss << param; // print integer literal directly
162 } else if constexpr (std::is_same_v<T, MetaType>) {
163 oss << get_type_name_rec(param); // recurse on nested type
164 }
165 },
166 meta_type.template_parameters[i]);
167 }
168
169 oss << ">";
170 return oss.str();
171 }
172
173 std::string to_string_rec(const MetaType &meta_type) const {
174 std::ostringstream oss;
175 oss << "MetaType {\n";
176 oss << " name: " << meta_type.base_type_name << "\n";
177 oss << " string_to_type_func: " << meta_type.string_to_type_func_lambda << "\n";
178 oss << " type_to_string_func: " << meta_type.type_to_string_func_lambda << "\n";
179 oss << " literal_regex: " << meta_type.literal_regex << "\n";
180
181 if (!meta_type.template_parameters.empty()) {
182 oss << " element_types: [\n";
183 for (const auto &elem : meta_type.template_parameters) {
184 std::visit(
185 [&](auto &&param) {
186 using T = std::decay_t<decltype(param)>;
187 std::string elem_str;
188 if constexpr (std::is_same_v<T, unsigned int>) {
189 elem_str = "unsigned int: " + std::to_string(param);
190 } else if constexpr (std::is_same_v<T, MetaType>) {
191 elem_str = to_string_rec(param); // recurse
192 }
193
194 std::istringstream iss(elem_str);
195 std::string line;
196 while (std::getline(iss, line)) {
197 oss << " " << line << "\n";
198 }
199 },
200 elem);
201 }
202 oss << " ]\n";
203 } else {
204 oss << " element_types: []\n";
205 }
206
207 oss << "}";
208 return oss.str();
209 }
210};
211
212inline std::string create_to_string_lambda(std::string type) {
213 return "[](const " + type + " &v) { return std::to_string(v); }";
214};
215
216// CONCRETE
217// NOTE: concrete types have the good property that given a type name, we can do
218// a one to one mapping to one of the below concrete types
220 MetaType("unsigned int", "[](const std::string &s) { return static_cast<unsigned int>(std::stoul(s)); }",
221 create_to_string_lambda("unsigned int"),
222 "[](const unsigned int &v) { "
223 " std::vector<uint8_t> buf(sizeof(unsigned int)); "
224 " std::memcpy(buf.data(), &v, sizeof(unsigned int)); "
225 " return buf; }",
226 "[](const unsigned int &v) { return sizeof(unsigned int); }",
227 "[](const std::vector<uint8_t> &buf) { "
228 " unsigned int v; "
229 " std::memcpy(&v, buf.data(), sizeof(unsigned int)); "
230 " return v; }",
232
234 MetaType("uint8_t", "[](const std::string &s) { return static_cast<uint8_t>(std::stoul(s)); }",
235 create_to_string_lambda("uint8_t"),
236 "[](const uint8_t &v) { "
237 " std::vector<uint8_t> buf(sizeof(uint8_t)); "
238 " std::memcpy(buf.data(), &v, sizeof(uint8_t)); "
239 " return buf; }",
240 "[](const uint8_t &v) { return sizeof(uint8_t); }",
241 "[](const std::vector<uint8_t> &buf) { "
242 " uint8_t v; "
243 " std::memcpy(&v, buf.data(), sizeof(uint8_t)); "
244 " return v; }",
246
248 MetaType("uint32_t", "[](const std::string &s) { return static_cast<uint32_t>(std::stoul(s)); }",
249 create_to_string_lambda("uint32_t"),
250 "[](const uint32_t &v) { "
251 " std::vector<uint8_t> buf(sizeof(uint32_t)); "
252 " std::memcpy(buf.data(), &v, sizeof(uint32_t)); "
253 " return buf; }",
254 "[](const uint32_t &v) { return sizeof(uint32_t); }",
255 "[](const std::vector<uint8_t> &buf) { "
256 " uint32_t v; "
257 " std::memcpy(&v, buf.data(), sizeof(uint32_t)); "
258 " return v; }",
260
261inline MetaType SIZE_T = MetaType("size_t", "[](const std::string &s) { return static_cast<size_t>(std::stoull(s)); }",
262 create_to_string_lambda("size_t"),
263 "[](const size_t &v) { "
264 " std::vector<uint8_t> buf(sizeof(size_t)); "
265 " std::memcpy(buf.data(), &v, sizeof(size_t)); "
266 " return buf; }",
267 "[](const size_t &v) { return sizeof(size_t); }",
268 "[](const std::vector<uint8_t> &buf) { "
269 " size_t v; "
270 " std::memcpy(&v, buf.data(), sizeof(size_t)); "
271 " return v; }",
273
274inline MetaType CHAR = MetaType("char", "[](const std::string &s) { return static_cast<char>(s.empty() ? 0 : s[0]); }",
276 "[](const char &v) { "
277 " std::vector<uint8_t> buf(sizeof(char)); "
278 " std::memcpy(buf.data(), &v, sizeof(char)); "
279 " return buf; }",
280 "[](const char &v) { return sizeof(char); }",
281 "[](const std::vector<uint8_t> &buf) { "
282 " char v; "
283 " std::memcpy(&v, buf.data(), sizeof(char)); "
284 " return v; }",
286
287inline MetaType INT =
288 MetaType("int", "[](const std::string &s) { return std::stoi(s); }", create_to_string_lambda("int"),
289 "[](const int &v) { "
290 " std::vector<uint8_t> buf(sizeof(int)); "
291 " std::memcpy(buf.data(), &v, sizeof(int)); "
292 " return buf; }",
293 "[](const int &v) { return sizeof(int); }",
294 "[](const std::vector<uint8_t> &buf) { "
295 " int v; "
296 " std::memcpy(&v, buf.data(), sizeof(int)); "
297 " return v; }",
299
300inline MetaType SHORT = MetaType("short", "[](const std::string &s) { return static_cast<short>(std::stoi(s)); }",
302 "[](const short &v) { "
303 " std::vector<uint8_t> buf(sizeof(short)); "
304 " std::memcpy(buf.data(), &v, sizeof(short)); "
305 " return buf; }",
306 "[](const short &v) { return sizeof(short); }",
307 "[](const std::vector<uint8_t> &buf) { "
308 " short v; "
309 " std::memcpy(&v, buf.data(), sizeof(short)); "
310 " return v; }",
312
314 MetaType("long", "[](const std::string &s) { return std::stol(s); }", create_to_string_lambda("long"),
315 "[](const long &v) { "
316 " std::vector<uint8_t> buf(sizeof(long)); "
317 " std::memcpy(buf.data(), &v, sizeof(long)); "
318 " return buf; }",
319 "[](const long &v) { return sizeof(long); }",
320 "[](const std::vector<uint8_t> &buf) { "
321 " long v; "
322 " std::memcpy(&v, buf.data(), sizeof(long)); "
323 " return v; }",
325
327 MetaType("float", "[](const std::string &s) { return std::stof(s); }", create_to_string_lambda("float"),
328 "[](const float &v) { "
329 " std::vector<uint8_t> buf(sizeof(float)); "
330 " std::memcpy(buf.data(), &v, sizeof(float)); "
331 " return buf; }",
332 "[](const float &v) { return sizeof(float); }",
333 "[](const std::vector<uint8_t> &buf) { "
334 " float v; "
335 " std::memcpy(&v, buf.data(), sizeof(float)); "
336 " return v; }",
338
340 MetaType("double", "[](const std::string &s) { return std::stod(s); }", create_to_string_lambda("double"),
341 "[](const double &v) { "
342 " std::vector<uint8_t> buf(sizeof(double)); "
343 " std::memcpy(buf.data(), &v, sizeof(double)); "
344 " return buf; }",
345 "[](const double &v) { return sizeof(double); }",
346 "[](const std::vector<uint8_t> &buf) { "
347 " double v; "
348 " std::memcpy(&v, buf.data(), sizeof(double)); "
349 " return v; }",
351
353 MetaType("std::string",
354 "[](const std::string &s) { "
355 " if (s.size() >= 2 && s.front() == '\"' && s.back() == '\"') "
356 " return s.substr(1, s.size() - 2); "
357 " return s; }",
358 "[](const std::string &s) { return s; }",
359 "[](const std::string &v) { "
360 " std::vector<uint8_t> buf; "
361 " size_t len = v.size(); "
362 " buf.resize(sizeof(size_t) + len); "
363 " std::memcpy(buf.data(), &len, sizeof(size_t)); "
364 " std::memcpy(buf.data() + sizeof(size_t), v.data(), len); "
365 " return buf; }",
366 "[](const std::string &v) { return sizeof(size_t) + v.size(); }",
367 "[](const std::vector<uint8_t> &buf) { "
368 " if (buf.size() < sizeof(size_t)) return std::string(); "
369 " size_t len; "
370 " std::memcpy(&len, buf.data(), sizeof(size_t)); "
371 " if (buf.size() < sizeof(size_t) + len) return std::string(); "
372 " return std::string(reinterpret_cast<const char*>(buf.data() + sizeof(size_t)), len); }",
374
376 "std::filesystem::path",
377 // from string → path
378 "[](const std::string &s) { "
379 " if (s.size() >= 2 && s.front() == '\"' && s.back() == '\"') "
380 " return std::filesystem::path(s.substr(1, s.size() - 2)); "
381 " return std::filesystem::path(s); }",
382 // to string
383 "[](const std::filesystem::path &p) { return p.string(); }",
384 // to bytes
385 "[](const std::filesystem::path &p) { "
386 " std::string s = p.string(); "
387 " std::vector<uint8_t> buf; "
388 " size_t len = s.size(); "
389 " buf.resize(sizeof(size_t) + len); "
390 " std::memcpy(buf.data(), &len, sizeof(size_t)); "
391 " std::memcpy(buf.data() + sizeof(size_t), s.data(), len); "
392 " return buf; }",
393 // size in bytes
394 "[](const std::filesystem::path &p) { "
395 " std::string s = p.string(); "
396 " return sizeof(size_t) + s.size(); }",
397 // from bytes → path
398 "[](const std::vector<uint8_t> &buf) { "
399 " if (buf.size() < sizeof(size_t)) return std::filesystem::path(); "
400 " size_t len; "
401 " std::memcpy(&len, buf.data(), sizeof(size_t)); "
402 " if (buf.size() < sizeof(size_t) + len) return std::filesystem::path(); "
403 " return std::filesystem::path(std::string(reinterpret_cast<const char*>(buf.data() + sizeof(size_t)), len)); }",
405
406// TODO: .pattern() isn't a real function so we can't get the pattern out of a regex and I don't have a way to deal with
407// this yet. This is why you don't find regex in concrete types.
409 MetaType("std::regex",
410 // from string → regex
411 "[](const std::string &s) { "
412 " if (s.size() >= 2 && s.front() == '\"' && s.back() == '\"') "
413 " return std::regex(s.substr(1, s.size() - 2)); "
414 " return std::regex(s); }",
415 // to string
416 "[](const std::regex &r) { return r.pattern(); }",
417 // to bytes
418 "[](const std::regex &r) { "
419 " std::string pattern = r.pattern(); "
420 " std::vector<uint8_t> buf; "
421 " size_t len = pattern.size(); "
422 " buf.resize(sizeof(size_t) + len); "
423 " std::memcpy(buf.data(), &len, sizeof(size_t)); "
424 " std::memcpy(buf.data() + sizeof(size_t), pattern.data(), len); "
425 " return buf; }",
426 // size in bytes
427 "[](const std::regex &r) { "
428 " std::string pattern = r.pattern(); "
429 " return sizeof(size_t) + pattern.size(); }",
430 // from bytes → regex
431 "[](const std::vector<uint8_t> &buf) { "
432 " if (buf.size() < sizeof(size_t)) return std::regex(); "
433 " size_t len; "
434 " std::memcpy(&len, buf.data(), sizeof(size_t)); "
435 " if (buf.size() < sizeof(size_t) + len) return std::regex(); "
436 " return std::regex(std::string(reinterpret_cast<const char*>(buf.data() + sizeof(size_t)), len)); }",
438
439inline MetaType BOOL = MetaType("bool", "[](const std::string &s) { return s == \"true\"; }",
440 "[](const bool &v) { return v ? \"true\" : \"false\"; }",
441 "[](const bool &v) { "
442 " std::vector<uint8_t> buf(1); "
443 " buf[0] = v ? 1 : 0; "
444 " return buf; }",
445 // NOTE: we don't use sizeof(bool) because of how we serialize always one byte.
446 "[](const bool &v) { return sizeof(uint8_t); }",
447 "[](const std::vector<uint8_t> &buf) { "
448 " return buf[0] != 0; }",
449 R"(true|false|1|0)");
450
451inline meta_utils::MetaType meta_type_type("meta_utils::MetaType", "[](){}", "[](){ return \"\";}", "[](){}",
452 "[](const meta_utils::MetaType &v) { return sizeof(meta_utils::MetaType); }",
453 "[](){}", "MetaType");
454
455// GENERICS
456// NOTE: generic types cannot be defined directly as variables, there are
457// "infinitely" many types possible so we can't actually make variables for
458// them, instead we define a function that generates a concrete genric type for
459// a given generic type
460
461// NOTE: this function does not yet support recursive vector types (only one
462// layer deep support)
463std::string create_string_to_vector_of_type_func(MetaType type_parameter);
464std::string create_vector_of_type_to_string_func(MetaType type_parameter);
465std::string create_vector_of_type_serialize_func(MetaType type_parameter);
466std::string create_vector_of_type_serialized_size_func(MetaType type_parameter);
467std::string create_vector_of_type_deserialize_func(MetaType type_parameter);
468
469std::string create_string_to_array_of_type_func(MetaType type_parameter, unsigned int size);
470std::string create_array_of_type_to_string_func(MetaType type_parameter, unsigned int size);
471std::string create_array_of_type_serialize_func(MetaType type_parameter, unsigned int size);
472std::string create_array_of_type_serialized_size_func(MetaType type_parameter, unsigned int size);
473std::string create_array_of_type_deserialize_func(MetaType type_parameter, unsigned int size);
474
476 auto string_to_vector_of_generic_type_func = create_string_to_vector_of_type_func(generic_type);
477 auto vector_of_type_to_string_func = create_vector_of_type_to_string_func(generic_type);
478 auto vector_of_type_serialize_func = create_vector_of_type_serialize_func(generic_type);
479 auto vector_of_type_serialized_size_func = create_vector_of_type_serialized_size_func(generic_type);
480 auto vector_of_type_deserialize_func = create_vector_of_type_deserialize_func(generic_type);
481
482 return MetaType("std::vector",
483 string_to_vector_of_generic_type_func, // string → vector<T>
484 vector_of_type_to_string_func, // vector<T> → string
485 vector_of_type_serialize_func, // vector<T> → bytes
486 vector_of_type_serialized_size_func, // vector<T> → size in bytes
487 vector_of_type_deserialize_func, // bytes → vector<T>
488 regex_utils::any_char_greedy, {generic_type});
489}
490
491inline MetaType construct_array_metatype(MetaType generic_type, unsigned int size) {
492 auto string_to_array_of_type_func = create_string_to_array_of_type_func(generic_type, size);
493 auto array_of_type_to_string_func = create_array_of_type_to_string_func(generic_type, size);
494 auto array_of_type_serialize_func = create_array_of_type_serialize_func(generic_type, size);
495 auto array_of_type_serialized_size_func = create_array_of_type_serialized_size_func(generic_type, size);
496 auto array_of_type_deserialize_func = create_array_of_type_deserialize_func(generic_type, size);
497
498 return MetaType("std::array",
499 string_to_array_of_type_func, // string → array<T, N>
500 array_of_type_to_string_func, // array<T, N> → string
501 array_of_type_serialize_func, // array<T, N> → bytes
502 array_of_type_serialized_size_func, // array<T, N> → size in bytes
503 array_of_type_deserialize_func, // bytes → array<T, N>
504 regex_utils::any_char_greedy, {generic_type, size});
505}
506
507std::string create_string_to_unordered_map_func(MetaType key_type, MetaType value_type);
508std::string create_unordered_map_to_string_func(MetaType key_type, MetaType value_type);
509std::string create_unordered_map_serialize_func(MetaType key_type, MetaType value_type);
510std::string create_unordered_map_serialized_size_func(MetaType key_type, MetaType value_type);
511std::string create_unordered_map_deserialize_func(MetaType key_type, MetaType value_type);
512
513// NOTE: I want to generailized this for other types of maps not just unoredred in the future
515 auto string_to_map_func = create_string_to_unordered_map_func(key_type, value_type);
516 auto map_to_string_func = create_unordered_map_to_string_func(key_type, value_type);
517 auto map_serialize_func = create_unordered_map_serialize_func(key_type, value_type);
518 auto map_size_func = create_unordered_map_serialized_size_func(key_type, value_type);
519 auto map_deserialize_func = create_unordered_map_deserialize_func(key_type, value_type);
520
521 return MetaType("std::unordered_map",
522 string_to_map_func, // string → map<K, V>
523 map_to_string_func, // map<K, V> → string
524 map_serialize_func, // map<K, V> → bytes
525 map_size_func, // map<K, V> → size in bytes
526 map_deserialize_func, // bytes → map<K, V>
527 regex_utils::any_char_greedy, {key_type, value_type});
528}
529
530// NOTE: this is the only global state.
534
535using MetaTemplateParameter = std::variant<unsigned int, MetaType>;
536
537inline std::unordered_map<std::string, std::function<MetaType(std::vector<MetaTemplateParameter>)>>
539 // std::vector<T>
540 {"std::vector",
541 [](std::vector<MetaTemplateParameter> template_parameters) -> MetaType {
542 if (template_parameters.size() != 1) {
543 throw std::invalid_argument("std::vector requires exactly 1 template parameter");
544 }
545
546 const MetaType &element_type = std::get<MetaType>(template_parameters[0]);
547 return construct_vector_metatype(element_type);
548 }},
549
550 // std::array<T, N>
551 {"std::array",
552 [](std::vector<MetaTemplateParameter> template_parameters) -> MetaType {
553 if (template_parameters.size() != 2) {
554 throw std::invalid_argument("std::array requires exactly 2 template parameters");
555 }
556
557 const MetaType &element_type = std::get<MetaType>(template_parameters[0]);
558 unsigned int size = std::get<unsigned int>(template_parameters[1]);
559
560 return construct_array_metatype(element_type, size);
561 }},
562
563 // std::unordered_map<K, V>
564 {"std::unordered_map",
565 [](std::vector<MetaTemplateParameter> template_parameters) -> MetaType {
566 if (template_parameters.size() != 2) {
567 throw std::invalid_argument("std::unordered_map requires exactly 2 template parameters");
568 }
569
570 const MetaType &key_type = std::get<MetaType>(template_parameters[0]);
571 const MetaType &value_type = std::get<MetaType>(template_parameters[1]);
572
573 return construct_unordered_map_metatype(key_type, value_type);
574 }},
575};
576
577inline std::unordered_map<std::string, MetaType> create_type_name_to_meta_type_map(std::vector<MetaType> meta_types) {
578 std::unordered_map<std::string, MetaType> map;
579 for (const auto &meta_type : meta_types) {
580 map.emplace(meta_type.base_type_name, meta_type);
581 }
582 return map;
583}
584
585std::optional<MetaType> parse_meta_type_from_string(const std::string &type_str);
586
587std::string clean_type_string(const std::string &raw_type);
588
593 public:
594 std::string name;
596
597 MetaParameter() = default;
598 MetaParameter(const std::string &input);
599
600 bool operator==(const MetaParameter &other) const { return name == other.name && type == other.type; }
601
602 std::string to_string() const {
603 std::ostringstream oss;
604 oss << "MetaParameter {\n";
605 oss << " name: " << name << "\n";
606
607 std::string type_str = type.to_string();
608 std::istringstream type_iss(type_str);
609 std::string line;
610 oss << " type: \n";
611 while (std::getline(type_iss, line)) {
612 oss << " " << line << "\n";
613 }
614
615 oss << "}";
616 return oss.str();
617 }
618};
619
620std::string generate_regex_to_match_valid_invocation_of_func(const std::string &signature);
621
622template <typename T>
623concept HasNameAndNamespace = requires(T a) {
624 { a.name } -> std::same_as<std::string &>;
625 { a.name_space } -> std::same_as<std::string &>;
626};
627
628template <HasNameAndNamespace T> std::string get_fully_qualified_name(const T &obj) {
629 if (!obj.name_space.empty()) {
630 return obj.name_space + "::" + obj.name;
631 }
632 return obj.name;
633}
634
636 public:
637 std::string name;
638 std::string return_type;
639 std::string param_list;
640 std::vector<MetaParameter> parameters;
641 std::string invocation_regex;
642 std::string name_space;
643
644 bool operator==(const MetaFunctionSignature &other) const {
645 return name == other.name && parameters == other.parameters;
646 }
647
649
650 MetaFunctionSignature(const std::string &input, const std::string &name_space) : name_space(name_space) {
651 auto cleaned_input = text_utils::join_multiline(input);
652 std::string s = trim(cleaned_input);
653
654 // --- Try to parse as a regular function ---
655 bool parsed_regular = false;
656 std::string local_return_type, local_name, local_param_list;
657
658 try {
659 // Find parameters
660 auto param_end = s.rfind(')');
661 if (param_end == std::string::npos) {
662 throw std::invalid_argument("Function signature missing closing ')'");
663 }
664
665 auto param_start = s.rfind('(', param_end);
666 if (param_start == std::string::npos) {
667 throw std::invalid_argument("Function signature missing opening '('");
668 }
669
670 local_param_list = s.substr(param_start + 1, param_end - param_start - 1);
671 std::string ret_and_name = trim(s.substr(0, param_start));
672
673 // Split into return type and name
674 auto last_space = ret_and_name.rfind(' ');
675 if (last_space == std::string::npos) {
676 throw std::invalid_argument("Cannot determine function name and return type");
677 }
678
679 local_return_type = trim(ret_and_name.substr(0, last_space));
680 local_name = ret_and_name.substr(last_space + 1);
681
682 parsed_regular = true;
683 } catch (const std::invalid_argument &) {
684 // fallthrough to constructor logic
685 }
686
687 if (parsed_regular) {
688 return_type = local_return_type;
689 name = local_name;
690 param_list = local_param_list;
691 } else {
692 // --- Fall back to constructor logic (unchanged) ---
693 std::smatch match;
694 static const std::regex constructor_regex(regex_utils::constructor_signature_re);
695 if (!std::regex_match(cleaned_input, match, constructor_regex)) {
696 throw std::invalid_argument("Invalid function signature format: expected "
697 "'ReturnType name(Type1 x, Type2 y)' or a constructor");
698 } else { // constructor
699 name = match[1];
701 param_list = match[2];
702 }
703 }
704
705 // --- Common parameter handling ---
706 std::vector<std::string> param_tokens = split_comma_separated(param_list);
707 for (const std::string &param_str : param_tokens) {
708 if (!param_str.empty()) {
709 parameters.emplace_back(param_str);
710 }
711 }
712
714 }
715
716 std::string to_string() const {
718
719 sa.add(return_type, " ", name, "(");
720 for (size_t i = 0; i < parameters.size(); ++i) {
721 const auto &param = parameters[i];
722 sa.add(param.type.get_type_name(), " ", param.name);
723 if (i < parameters.size() - 1)
724 sa.add(", ");
725 }
726 sa.add(")");
727 return sa.str();
728 }
729
730 std::string to_string_repr() const {
731 std::ostringstream oss;
732 oss << "MetaFunctionSignature {\n";
733 oss << " name: " << name << "\n";
734 oss << " parameters: [\n";
735 for (const auto &param : parameters) {
736 std::istringstream iss(param.to_string());
737 std::string line;
738 while (std::getline(iss, line)) {
739 oss << " " << line << "\n";
740 }
741 }
742 oss << " ]\n";
743 oss << "}";
744 return oss.str();
745 }
746
747 private:
748 static std::vector<std::string> split_comma_separated(const std::string &input) {
749 std::vector<std::string> result;
750 std::string current;
751
752 int angle_depth = 0;
753 int paren_depth = 0;
754 int bracket_depth = 0;
755 int brace_depth = 0;
756 bool in_single_quote = false;
757 bool in_double_quote = false;
758
759 for (size_t i = 0; i < input.size(); ++i) {
760 char c = input[i];
761
762 // handle quotes
763 if (c == '\'' && !in_double_quote) {
764 in_single_quote = !in_single_quote;
765 current.push_back(c);
766 continue;
767 }
768 if (c == '"' && !in_single_quote) {
769 in_double_quote = !in_double_quote;
770 current.push_back(c);
771 continue;
772 }
773
774 // if inside quotes, just copy
775 if (in_single_quote || in_double_quote) {
776 current.push_back(c);
777 continue;
778 }
779
780 // track nesting
781 if (c == '<')
782 angle_depth++;
783 else if (c == '>' && angle_depth > 0)
784 angle_depth--;
785 else if (c == '(')
786 paren_depth++;
787 else if (c == ')' && paren_depth > 0)
788 paren_depth--;
789 else if (c == '[')
790 bracket_depth++;
791 else if (c == ']' && bracket_depth > 0)
792 bracket_depth--;
793 else if (c == '{')
794 brace_depth++;
795 else if (c == '}' && brace_depth > 0)
796 brace_depth--;
797
798 // split only on commas at top-level
799 if (c == ',' && angle_depth == 0 && paren_depth == 0 && bracket_depth == 0 && brace_depth == 0) {
800 // flush current token
801 std::string trimmed = text_utils::trim(current);
802 if (!trimmed.empty())
803 result.push_back(trimmed);
804 current.clear();
805 } else {
806 current.push_back(c);
807 }
808 }
809
810 // flush last token
811 std::string trimmed = text_utils::trim(current);
812 if (!trimmed.empty())
813 result.push_back(trimmed);
814
815 return result;
816 }
817
818 static std::string trim(const std::string &s) {
819 const auto begin = s.find_first_not_of(" \t\r\n");
820 const auto end = s.find_last_not_of(" \t\r\n");
821 return (begin == std::string::npos) ? "" : s.substr(begin, end - begin + 1);
822 }
823};
824
826 public:
828
829 MetaVariable(std::string type, std::string name, std::string value, InitStyle init_style = InitStyle::Assignment,
830 std::string name_space = "")
831 : type(std::move(type)), name(std::move(name)), value(std::move(value)), init_style(std::move(init_style)),
832 name_space(std::move(name_space)) {}
833
834 std::string type;
835 std::string name;
836 std::string value;
838 std::string name_space;
839
840 std::string to_assignment() const { return type + " " + name + " = " + value + ";"; }
841
842 std::string to_definition() const { return type + " " + name + "(" + value + ");"; }
843
844 std::string to_brace() const { return type + " " + name + "{" + value + "};"; }
845
846 std::string to_initialization() const {
847 switch (init_style) {
849 return to_assignment();
851 return to_definition();
852 case InitStyle::Brace:
853 return to_brace();
854 }
855 return {};
856 }
857};
858
860 public:
863 std::string name_space;
864
869
870 MetaFunction(const std::string &func_str, const std::string &name_space = "") : name_space(name_space) {
871 // Find the opening '{' that starts the body
872 auto body_start = func_str.find('{');
873 if (body_start == std::string::npos) {
874 throw std::invalid_argument("Function string missing body");
875 }
876
877 // Split header and body
878 std::string header = func_str.substr(0, body_start);
879 auto body_end = func_str.rfind('}');
880 std::string body_str = func_str.substr(body_start + 1, body_end - body_start - 1);
881 body_str = trim(body_str); // Assuming you have a trim function
882
883 // Add the body to the body object
884 body.add_multiline(body_str);
885
886 // --- Parse header right-to-left ---
887 header = trim(header);
888
889 // Find the last ')' to get end of parameters
890 auto param_end = header.rfind(')');
891 if (param_end == std::string::npos) {
892 throw std::invalid_argument("Function header missing closing ')'");
893 }
894
895 // Find the matching '(' for parameters
896 auto param_start = header.rfind('(', param_end);
897 if (param_start == std::string::npos) {
898 throw std::invalid_argument("Function header missing opening '('");
899 }
900
901 // Extract parameter list
902 std::string param_list = header.substr(param_start + 1, param_end - param_start - 1);
903
904 // Everything before '(' is "<return_type_and_name>"
905 std::string ret_and_name = trim(header.substr(0, param_start));
906
907 // Find the last whitespace in ret_and_name: function name is after it, return type is before it
908 auto last_space = ret_and_name.rfind(' ');
909 if (last_space == std::string::npos) {
910 throw std::invalid_argument("Cannot determine function name and return type");
911 }
912
913 std::string func_name = ret_and_name.substr(last_space + 1);
914 std::string return_type = trim(ret_and_name.substr(0, last_space));
915
916 std::string header_signature = return_type + " " + func_name + "(" + param_list + ")";
917
918 signature = MetaFunctionSignature(header_signature, name_space);
919 }
920
921 std::string to_lambda_string() const {
922 std::ostringstream oss;
923 oss << "[=](";
924
925 for (size_t i = 0; i < signature.parameters.size(); ++i) {
926 const auto &param = signature.parameters[i];
927 oss << param.type.get_type_name() << " " << param.name;
928 if (i + 1 < signature.parameters.size()) {
929 oss << ", ";
930 }
931 }
932
933 oss << ") -> " << signature.return_type << " {\n" << body.str() << "\n}";
934 return oss.str();
935 }
936
937 std::string to_string() const {
938 std::ostringstream oss;
939 oss << signature.return_type << " ";
940
941 if (!name_space.empty()) {
942 oss << name_space << "::";
943 }
944
945 oss << signature.name << "(";
946
947 for (size_t i = 0; i < signature.parameters.size(); ++i) {
948 const auto &param = signature.parameters[i];
949 oss << param.type.get_type_name() << " " << param.name;
950 if (i + 1 < signature.parameters.size()) {
951 oss << ", ";
952 }
953 }
954
955 oss << ") {\n" << body.str() << "\n}";
956 return oss.str();
957 }
958
959 private:
960 static std::string trim(const std::string &s) {
961 const auto begin = s.find_first_not_of(" \t\r\n");
962 const auto end = s.find_last_not_of(" \t\r\n");
963 return (begin == std::string::npos) ? "" : s.substr(begin, end - begin + 1);
964 }
965};
966
968
969inline std::string to_string(AccessSpecifier access) {
970 switch (access) {
972 return "public";
974 return "protected";
976 return "private";
977 }
978 return {};
979}
980
982 public:
985 bool is_static = false;
986 bool is_const = false;
987
991
992 std::string to_string() const {
993 std::ostringstream oss;
994 oss << meta_utils::to_string(access) << ":\n";
995 oss << (is_static ? "static " : "");
996 oss << (is_const ? "const " : "");
997 oss << variable.to_initialization();
998 return oss.str();
999 }
1000};
1001
1003 public:
1006 bool is_static = false;
1007 bool is_virtual = false;
1008 bool is_const = false;
1009 bool is_override = false;
1010
1016
1017 std::string to_string() const {
1018 std::ostringstream oss;
1019 oss << meta_utils::to_string(access) << ":\n";
1020
1021 if (is_static)
1022 oss << "static ";
1023 if (is_virtual)
1024 oss << "virtual ";
1025
1026 // Normal function signature
1027 oss << function.signature.return_type << " ";
1028 if (!function.name_space.empty()) {
1029 oss << function.name_space << "::";
1030 }
1031 oss << function.signature.name << "(";
1032 for (size_t i = 0; i < function.signature.parameters.size(); ++i) {
1033 const auto &param = function.signature.parameters[i];
1034 oss << param.type.get_type_name() << " " << param.name;
1035 if (i + 1 < function.signature.parameters.size())
1036 oss << ", ";
1037 }
1038 oss << ")";
1039 if (is_const)
1040 oss << " const";
1041 if (is_override)
1042 oss << " override";
1043
1044 oss << " {\n" << function.body.str() << "\n}";
1045
1046 return oss.str();
1047 }
1048};
1049
1051 public:
1052 std::string class_name; // store the class name
1053 std::vector<MetaParameter> parameters;
1054 std::vector<std::string> initializer_list;
1057
1058 MetaConstructor() = default;
1059
1060 // Updated constructor takes the class name
1061 MetaConstructor(const std::string &class_name, const std::vector<MetaParameter> &params,
1062 const std::string &body_str, AccessSpecifier access = AccessSpecifier::Public,
1063 const std::vector<std::string> &init_list = {})
1064 : class_name(class_name), parameters(params), initializer_list(init_list), access(access) {
1065 body.add_multiline(body_str);
1066 }
1067
1068 // to_string no longer needs class_name as input
1069 std::string to_string(size_t indent_level = 1) const {
1070 std::ostringstream oss;
1071 std::string pad(indent_level * 4, ' '); // 4 spaces per indent level
1072
1073 // Constructor signature
1074 oss << pad << class_name << "(";
1075 for (size_t i = 0; i < parameters.size(); ++i) {
1076 const auto &param = parameters[i];
1077 oss << param.type.get_type_name() << " " << param.name;
1078 if (i + 1 < parameters.size())
1079 oss << ", ";
1080 }
1081 oss << ")";
1082
1083 // Initializer list
1084 if (!initializer_list.empty()) {
1085 oss << " : ";
1086 for (size_t i = 0; i < initializer_list.size(); ++i) {
1087 oss << initializer_list[i];
1088 if (i + 1 < initializer_list.size())
1089 oss << ", ";
1090 }
1091 }
1092
1093 // Body
1094 oss << " {\n" << text_utils::indent(body.str(), indent_level + 1) << pad << "}\n";
1095 return oss.str();
1096 }
1097};
1098
1100 public:
1101 std::string name;
1102 std::string type;
1103 std::vector<std::string> enum_names;
1104};
1105
1107 public:
1108 std::string name;
1109 std::string name_space;
1110 bool is_final = false;
1111
1112 std::vector<MetaAttribute> attributes;
1113 std::vector<MetaConstructor> constructors;
1114 std::vector<MetaMethod> methods;
1115
1116 MetaClass(std::string name, std::string name_space = "", bool is_final = false)
1117 : name(std::move(name)), name_space(std::move(name_space)), is_final(is_final) {}
1118
1119 void add_attribute(const MetaAttribute &attr) { attributes.push_back(attr); }
1120 void add_method(const MetaMethod &method) {
1121 auto sig_str = method.function.signature.to_string();
1122
1123 // check if we already have this signature
1124 for (const auto &m : methods) {
1125 if (m.function.signature.to_string() == sig_str) {
1126 return; // duplicate → do nothing
1127 }
1128 }
1129
1130 methods.push_back(method);
1131 }
1132
1133 std::string to_string() const {
1134 std::ostringstream oss;
1135
1136 // Namespace
1137 if (!name_space.empty()) {
1138 oss << "namespace " << name_space << " {\n";
1139 }
1140
1141 // Class header
1142 oss << "class " << name;
1143 if (is_final) {
1144 oss << " final";
1145 }
1146 oss << " {\n";
1147
1148 if (!constructors.empty()) {
1149 oss << "public:\n";
1150 for (const auto &ctor : constructors) {
1151 oss << text_utils::indent(ctor.to_string(), 1); // using the indent_text function
1152 }
1153 oss << "\n";
1154 }
1155
1156 output_section(oss, AccessSpecifier::Public, attributes, methods);
1157 output_section(oss, AccessSpecifier::Protected, attributes, methods);
1158 output_section(oss, AccessSpecifier::Private, attributes, methods);
1159
1160 oss << "};\n";
1161
1162 if (!name_space.empty()) {
1163 oss << "} // namespace " << name_space << "\n";
1164 }
1165
1166 return oss.str();
1167 }
1168
1169 private:
1170 static void output_section(std::ostringstream &oss, AccessSpecifier section,
1171 const std::vector<MetaAttribute> &attrs, const std::vector<MetaMethod> &meths) {
1172 bool has_content = false;
1173
1174 for (const auto &a : attrs)
1175 if (a.access == section) {
1176 has_content = true;
1177 break;
1178 }
1179 if (!has_content) {
1180 for (const auto &m : meths)
1181 if (m.access == section) {
1182 has_content = true;
1183 break;
1184 }
1185 }
1186
1187 if (!has_content)
1188 return;
1189
1190 oss << meta_utils::to_string(section) << ":\n";
1191
1192 for (const auto &attr : attrs) {
1193 if (attr.access == section) {
1194 oss << " " << (attr.is_static ? "static " : "") << (attr.is_const ? "const " : "");
1195
1196 if (!attr.variable.value.empty()) {
1197 oss << attr.variable.to_initialization();
1198 } else {
1199 oss << attr.variable.type << " " << attr.variable.name << ";";
1200 }
1201
1202 oss << "\n";
1203 }
1204 }
1205
1206 for (const auto &method : meths) {
1207 if (method.access == section) {
1208 oss << " ";
1209 if (method.is_static)
1210 oss << "static ";
1211 if (method.is_virtual)
1212 oss << "virtual ";
1213
1214 // constructor special case: no return type
1215 if (!method.function.signature.return_type.empty())
1216 oss << method.function.signature.return_type << " ";
1217
1218 oss << method.function.signature.name << "(";
1219
1220 for (size_t i = 0; i < method.function.signature.parameters.size(); ++i) {
1221 const auto &param = method.function.signature.parameters[i];
1222 oss << param.type.get_type_name() << " " << param.name;
1223 if (i + 1 < method.function.signature.parameters.size()) {
1224 oss << ", ";
1225 }
1226 }
1227
1228 oss << ")";
1229 if (method.is_const)
1230 oss << " const";
1231 if (method.is_override)
1232 oss << " override";
1233
1234 oss << " {\n" << text_utils::indent(method.function.body.str(), 2) << "\n }\n";
1235 }
1236 }
1237 }
1238};
1239
1241
1242bool is_system_header(const std::string &line);
1243bool is_local_header(const std::string &line);
1244std::vector<std::string> get_system_headers(const std::vector<std::string> &headers);
1245
1246// NOTE: this encompasses a header+source file usually
1248 public:
1249 std::string name; // used for ifndef guards
1250
1251 // NOTE: not sure if we need both of these or just one
1252 std::vector<MetaFunction> functions;
1253 std::vector<MetaFunctionSignature> declared_function_signatures_in_header_file;
1254
1255 std::vector<MetaVariable> variables;
1256 std::vector<MetaClass> classes;
1257 std::vector<std::string> includes_required_for_declaration;
1258 std::vector<std::string> includes_required_for_definition;
1259 std::string name_space;
1260
1262
1265 functions.push_back(std::move(mf));
1266 }
1267
1268 MetaCodeCollection(const std::string &header_file_path, const std::string &cpp_file_path,
1269 const std::vector<std::string> &string_signatures_to_filter_on = {},
1271
1272 std::string header_source = read_file(header_file_path);
1273 std::string cpp_source = read_file(cpp_file_path);
1274
1275 name = extract_function_collection_name(header_source).value_or("meta_function_collection");
1276 extract_includes(header_source, includes_required_for_declaration);
1277 extract_includes(cpp_source, includes_required_for_definition);
1278
1279 name_space = extract_top_level_namespace(cpp_source).value_or("");
1280
1281 // extract_functions(cpp_file_path, name_space, signatures_to_filter_on, mode);
1282 extract_function_signatures(header_file_path, name_space, string_signatures_to_filter_on, mode);
1283 }
1284
1285 void write_to_header_and_source(const std::string &header_file_path, const std::string &cpp_file_path) {
1286 std::string header_str = generate_header_file_string();
1287 std::string cpp_str = generate_cpp_file_string();
1288
1289 fs_utils::create_file_with_content_if_different(header_file_path, header_str);
1291 }
1292
1294 std::ostringstream oss;
1295
1296 std::string guard_macro = name;
1297 std::transform(guard_macro.begin(), guard_macro.end(), guard_macro.begin(),
1298 [](unsigned char c) { return std::isalnum(c) ? static_cast<char>(std::toupper(c)) : '_'; });
1299 guard_macro += "_HPP";
1300
1301 oss << "#ifndef " << guard_macro << "\n";
1302 oss << "#define " << guard_macro << "\n\n";
1303
1304 for (const auto &include : includes_required_for_declaration) {
1305 oss << include << "\n";
1306 }
1307
1308 oss << "\n";
1309
1310 if (!name_space.empty()) {
1311 oss << "namespace " << name_space << " {\n\n";
1312 }
1313
1314 for (const auto &var : variables) {
1315 oss << "extern " << var.type << " " << var.name << ";\n";
1316 }
1317
1318 oss << "\n";
1319
1320 for (const auto &cls : classes) {
1321 oss << cls.to_string() << "\n\n";
1322 }
1323
1324 // NOTE: I don't think we need this loop?
1325 for (const auto &func : functions) {
1326 oss << func.signature.return_type << " " << func.signature.name << "(";
1327 for (size_t i = 0; i < func.signature.parameters.size(); ++i) {
1328 const auto &param = func.signature.parameters[i];
1329 oss << param.type.get_type_name() << " " << param.name;
1330 if (i < func.signature.parameters.size() - 1)
1331 oss << ", ";
1332 }
1333 oss << ");\n";
1334 }
1335
1336 for (const auto &sig : declared_function_signatures_in_header_file) {
1337 oss << sig.return_type << " " << sig.name << "(";
1338 for (size_t i = 0; i < sig.parameters.size(); ++i) {
1339 const auto &param = sig.parameters[i];
1340 oss << param.type.get_type_name() << " " << param.name;
1341 if (i < sig.parameters.size() - 1)
1342 oss << ", ";
1343 }
1344 oss << ");\n";
1345 }
1346
1347 if (!name_space.empty()) {
1348 oss << "\n} // namespace " << name_space << "\n";
1349 }
1350
1351 oss << "\n#endif // " << guard_macro << "\n";
1352 return oss.str();
1353 }
1354
1356 std::ostringstream oss;
1357
1358 for (const auto &include : includes_required_for_definition) {
1359 oss << include << "\n";
1360 }
1361
1362 oss << "\n";
1363
1364 if (!name_space.empty()) {
1365 oss << "namespace " << name_space << " {\n\n";
1366 }
1367
1368 for (const auto &var : variables) {
1369 oss << var.to_initialization() << "\n";
1370 }
1371 oss << "\n";
1372
1373 for (const auto &func : functions) {
1374 oss << func.signature.return_type << " " << func.signature.name << "(";
1375 for (size_t i = 0; i < func.signature.parameters.size(); ++i) {
1376 const auto &param = func.signature.parameters[i];
1377 oss << param.type.get_type_name() << " " << param.name;
1378 if (i < func.signature.parameters.size() - 1)
1379 oss << ", ";
1380 }
1381 oss << ") {\n";
1382 oss << func.body.str() << "\n";
1383 oss << "}\n\n";
1384 }
1385
1386 if (!name_space.empty()) {
1387 oss << "} // namespace " << name_space << "\n";
1388 }
1389
1390 return oss.str();
1391 }
1392
1393 private:
1394 static std::string read_file(const std::string &file_path) {
1395 std::ifstream file(file_path);
1396 if (!file.is_open()) {
1397 throw std::runtime_error("Failed to open file: " + file_path);
1398 }
1399 std::ostringstream ss;
1400 ss << file.rdbuf();
1401 return ss.str();
1402 }
1403
1404 static std::optional<std::string> extract_function_collection_name(const std::string &src) {
1405 std::regex define_guard_regex(R"(^\s*#ifndef\s+([A-Z0-9_]+))");
1406 std::istringstream stream(src);
1407 std::string line;
1408
1409 while (std::getline(stream, line)) {
1410 std::smatch match;
1411 if (std::regex_search(line, match, define_guard_regex)) {
1412 std::string guard_name = match[1];
1413
1414 std::transform(guard_name.begin(), guard_name.end(), guard_name.begin(),
1415 [](unsigned char c) { return std::tolower(c); });
1416
1417 const std::string suffix = "_hpp";
1418 if (guard_name.ends_with(suffix)) {
1419 guard_name.erase(guard_name.size() - suffix.size());
1420 }
1421
1422 return guard_name;
1423 }
1424 }
1425
1426 return std::nullopt;
1427 }
1428
1429 // TODO: eventually remove this because we have cpp_parser now
1430 static void extract_includes(const std::string &src, std::vector<std::string> &out) {
1431 std::regex include_regex(R"(^\s*(#include\s+["<].*[">]))");
1432 std::istringstream stream(src);
1433 std::string line;
1434 while (std::getline(stream, line)) {
1435 std::smatch match;
1436 if (std::regex_search(line, match, include_regex)) {
1437 out.push_back(match[1]);
1438 }
1439 }
1440 }
1441
1442 void extract_function_signatures(const std::string &hpp_file_path, const std::string &name_space,
1443 const std::vector<std::string> &string_signatures_to_filter_on, FilterMode mode) {
1444
1445 bool namespace_wrapped = name_space != "";
1446
1447 std::vector<std::string> function_declarations =
1449
1450 for (const std::string &func_decl : function_declarations) {
1451
1452 try {
1453
1454 auto clean_func_decl = [](const std::string &s) -> std::string {
1455 auto result = text_utils::trim(s);
1456 if (result.back() == ';') {
1457 result.pop_back();
1458 }
1459 result = text_utils::trim(result);
1461 return result;
1462 };
1463
1464 bool match_found = std::any_of(
1465 string_signatures_to_filter_on.begin(), string_signatures_to_filter_on.end(),
1466 [&](const std::string &fs) { return clean_func_decl(fs) == clean_func_decl(func_decl); });
1467
1468 bool allowed = (mode == FilterMode::Whitelist) ? match_found
1469 : (mode == FilterMode::Blacklist) ? !match_found
1470 : true;
1471
1472 if (allowed) {
1473 // NOTE: we only ever construct a meta function signature if its not blocked, helps deal with the
1474 // problem when there is a type which you don't handle yet and you use the filter to explicitly
1475 // block it.
1476 MetaFunctionSignature mfs(clean_func_decl(func_decl), name_space);
1477 declared_function_signatures_in_header_file.push_back(std::move(mfs));
1478 }
1479 } catch (const std::exception &e) {
1480 std::cout << "invalid func\n" << func_decl << std::endl;
1481 }
1482 }
1483 }
1484
1485 // void extract_functions(const std::string &cpp_file_path, const std::string &name_space,
1486 // const std::vector<std::string> &strings_signatures_to_filter_on, FilterMode mode) {
1487 //
1488 // bool namespace_wrapped = name_space != "";
1489 //
1490 // std::vector<std::string> function_strings = cpp_parsing::extract_top_level_functions(cpp_file_path);
1491 //
1492 // for (const std::string &func_str : function_strings) {
1493 //
1494 // try {
1495 // MetaFunction mf(func_str, name_space);
1496 // const auto &sig = mf.signature;
1497 //
1498 // bool match_found =
1499 // std::any_of(strings_signatures_to_filter_on.begin(), strings_signatures_to_filter_on.end(),
1500 // [&](const MetaFunctionSignature &fs) { return fs == sig; });
1501 //
1502 // bool allowed = (mode == FilterMode::Whitelist) ? match_found
1503 // : (mode == FilterMode::Blacklist) ? !match_found
1504 // : true;
1505 //
1506 // if (allowed) {
1507 // functions.push_back(std::move(mf));
1508 // }
1509 // } catch (const std::exception &e) {
1510 // std::cout << "invalid func\n" << func_str << std::endl;
1511 // }
1512 // }
1513 // }
1514
1515 std::optional<std::string> extract_top_level_namespace(const std::string &source_code) {
1516 std::regex namespace_regex(R"(\bnamespace\s+(\w+)\s*\{)");
1517 std::smatch match;
1518
1519 if (std::regex_search(source_code, match, namespace_regex)) {
1520 if (match.size() >= 2) {
1521 return match[1].str(); // the captured namespace name
1522 }
1523 }
1524
1525 return std::nullopt; // no namespace found
1526 }
1527};
1528
1530 public:
1531 std::string name;
1532 std::vector<MetaType> argument_types;
1533};
1534
1535inline std::string vector_include = "#include <vector>";
1536inline std::string string_include = "#include <string>";
1537inline std::string optional_include = "#include <optional>";
1538inline std::string regex_include = "#include <regex>";
1539
1541
1543 std::vector<std::string> lambda_conversions;
1544 std::vector<std::string> arg_to_var_conversions;
1545 std::vector<std::string> arguments_to_final_func_call;
1546};
1547
1556 const std ::string &func_postfix = "_string_invoker");
1557
1567std::string
1569 const std ::string &func_postfix = "_deferred_string_invoker");
1570
1572 std::vector<MetaFunctionSignature> mfss_with_same_return_type, std::string return_type, std::string func_postfix);
1573
1575 std::vector<MetaFunctionSignature> mfss_with_same_return_type, std::string return_type, std::string func_postfix);
1576
1587
1588void register_custom_types_into_meta_types(const std::vector<CustomTypeExtractionSettings> &settings_list);
1589void register_custom_types_into_meta_types(const CustomTypeExtractionSettings &custom_type_extraction_settings);
1590
1612
1616void generate_string_invokers_program_wide(std::vector<StringInvokerGenerationSettingsForHeaderSource> settings,
1617 const std::vector<MetaType> &all_types);
1618
1621
1623 const std::string &input_header_path, const std::string &input_source_path, bool create_top_level_invoker = false,
1624 bool create_type_grouped_invokers = false, const std::vector<std::string> &string_signatures = {},
1626
1627MetaFunction generate_interactive_invoker();
1628
1629// TODO: this is the meta program thing that we have to pass in at the top level
1631 private:
1632 std::vector<MetaType> concrete_types = meta_utils::concrete_types;
1633 std::unordered_map<std::string, MetaType> concrete_type_name_to_meta_type =
1634 create_type_name_to_meta_type_map(concrete_types);
1635
1636 std::unordered_map<std::string, std::function<meta_utils::MetaType(std::vector<MetaTemplateParameter>)>>
1637 generic_type_to_meta_type_constructor = meta_utils::generic_type_to_metatype_constructor;
1638
1639 public:
1640 void add_new_concrete_type(const MetaType &meta_type) {
1641 concrete_types.push_back(meta_type);
1642 concrete_type_name_to_meta_type = meta_utils::create_type_name_to_meta_type_map(concrete_types);
1643 }
1644
1645 const std::vector<MetaType> &get_concrete_types() const { return concrete_types; }
1646
1647 const std::unordered_map<std::string, std::function<meta_utils::MetaType(std::vector<MetaTemplateParameter>)>> &
1649 return generic_type_to_meta_type_constructor;
1650 }
1651
1652 const std::unordered_map<std::string, MetaType> &get_concrete_type_name_to_meta_type() const {
1653 return concrete_type_name_to_meta_type;
1654 }
1655};
1656
1657// TODO: remove this?
1659
1660MetaType resolve_meta_type(const std::string &type_str, const MetaTypes &types = meta_utils::meta_types);
1661
1662meta_utils::MetaClass create_meta_class_from_source(const std::string &source);
1663// NOTE: this creates a class because I didn't feel it was necessary to create a MetaStruct yet, because a struct is
1664// really a specific type of class, so in the meta world I consider a struct a class, but then if I want to write to
1665// file we would lose the fact that it's a struct... consider this later when that's an issue.
1666meta_utils::MetaClass create_meta_struct_from_source(const std::string &source);
1667meta_utils::MetaType create_meta_type_from_using(const std::string &source, const meta_utils::MetaTypes &types);
1668
1670
1671}; // namespace meta_utils
1672
1673// Helper function to combine hashes (like boost::hash_combine)
1674inline void hash_combine(std::size_t &seed, std::size_t value) noexcept {
1675 seed ^= value + 0x9e3779b9 + (seed << 6) + (seed >> 2);
1676}
1677
1678// Forward declare so we can use recursively
1679namespace std {
1680template <> struct hash<meta_utils::MetaType> {
1681 size_t operator()(const meta_utils::MetaType &mt) const noexcept {
1682 size_t seed = 0;
1683
1684 // Hash each string member
1685 hash_combine(seed, std::hash<std::string>{}(mt.base_type_name));
1686 hash_combine(seed, std::hash<std::string>{}(mt.string_to_type_func_lambda));
1687 hash_combine(seed, std::hash<std::string>{}(mt.type_to_string_func_lambda));
1688 hash_combine(seed, std::hash<std::string>{}(mt.literal_regex));
1689
1690 // Hash vector elements recursively
1691 for (const auto &elem : mt.template_parameters) {
1692 std::visit(
1693 [&](auto &&param) {
1694 using T = std::decay_t<decltype(param)>;
1695 if constexpr (std::is_same_v<T, unsigned int>) {
1696 hash_combine(seed, std::hash<unsigned int>{}(param));
1697 } else if constexpr (std::is_same_v<T, meta_utils::MetaType>) {
1698 hash_combine(seed, std::hash<meta_utils::MetaType>{}(param));
1699 }
1700 },
1701 elem);
1702 }
1703
1704 return seed;
1705 }
1706};
1707
1708} // namespace std
1709
1710#endif // META_UTILS_HPP
Definition meta_utils.hpp:981
bool is_static
Definition meta_utils.hpp:985
bool is_const
Definition meta_utils.hpp:986
MetaVariable variable
Definition meta_utils.hpp:983
AccessSpecifier access
Definition meta_utils.hpp:984
std::string to_string() const
Definition meta_utils.hpp:992
MetaAttribute(MetaVariable variable, AccessSpecifier access=AccessSpecifier::Private, bool is_static=false, bool is_const=false)
Definition meta_utils.hpp:988
Definition meta_utils.hpp:1106
std::vector< MetaAttribute > attributes
Definition meta_utils.hpp:1112
MetaClass(std::string name, std::string name_space="", bool is_final=false)
Definition meta_utils.hpp:1116
std::vector< MetaConstructor > constructors
Definition meta_utils.hpp:1113
void add_attribute(const MetaAttribute &attr)
Definition meta_utils.hpp:1119
std::vector< MetaMethod > methods
Definition meta_utils.hpp:1114
bool is_final
Definition meta_utils.hpp:1110
std::string name
Definition meta_utils.hpp:1108
std::string name_space
Definition meta_utils.hpp:1109
void add_method(const MetaMethod &method)
Definition meta_utils.hpp:1120
std::string to_string() const
Definition meta_utils.hpp:1133
Definition meta_utils.hpp:1247
std::vector< MetaClass > classes
Definition meta_utils.hpp:1256
void add_function(MetaFunction mf)
Definition meta_utils.hpp:1263
std::vector< MetaFunction > functions
Definition meta_utils.hpp:1252
std::vector< MetaVariable > variables
Definition meta_utils.hpp:1255
std::vector< MetaFunctionSignature > declared_function_signatures_in_header_file
Definition meta_utils.hpp:1253
std::string name
Definition meta_utils.hpp:1249
std::string generate_header_file_string()
Definition meta_utils.hpp:1293
std::string name_space
Definition meta_utils.hpp:1259
MetaCodeCollection(const std::string &header_file_path, const std::string &cpp_file_path, const std::vector< std::string > &string_signatures_to_filter_on={}, FilterMode mode=FilterMode::None)
Definition meta_utils.hpp:1268
void write_to_header_and_source(const std::string &header_file_path, const std::string &cpp_file_path)
Definition meta_utils.hpp:1285
std::vector< std::string > includes_required_for_declaration
Definition meta_utils.hpp:1257
std::vector< std::string > includes_required_for_definition
Definition meta_utils.hpp:1258
std::string generate_cpp_file_string()
Definition meta_utils.hpp:1355
std::vector< std::string > initializer_list
Definition meta_utils.hpp:1054
MetaConstructor(const std::string &class_name, const std::vector< MetaParameter > &params, const std::string &body_str, AccessSpecifier access=AccessSpecifier::Public, const std::vector< std::string > &init_list={})
Definition meta_utils.hpp:1061
text_utils::MultilineStringAccumulator body
Definition meta_utils.hpp:1055
std::string class_name
Definition meta_utils.hpp:1052
std::string to_string(size_t indent_level=1) const
Definition meta_utils.hpp:1069
AccessSpecifier access
Definition meta_utils.hpp:1056
std::vector< MetaParameter > parameters
Definition meta_utils.hpp:1053
Definition meta_utils.hpp:1099
std::string type
Definition meta_utils.hpp:1102
std::string name
Definition meta_utils.hpp:1101
std::vector< std::string > enum_names
Definition meta_utils.hpp:1103
Definition meta_utils.hpp:1529
std::vector< MetaType > argument_types
Definition meta_utils.hpp:1532
std::string name
Definition meta_utils.hpp:1531
Definition meta_utils.hpp:635
std::string param_list
Definition meta_utils.hpp:639
MetaFunctionSignature()
Definition meta_utils.hpp:648
std::vector< MetaParameter > parameters
Definition meta_utils.hpp:640
std::string invocation_regex
Definition meta_utils.hpp:641
std::string name_space
Definition meta_utils.hpp:642
MetaFunctionSignature(const std::string &input, const std::string &name_space)
Definition meta_utils.hpp:650
bool operator==(const MetaFunctionSignature &other) const
Definition meta_utils.hpp:644
std::string to_string() const
Definition meta_utils.hpp:716
std::string to_string_repr() const
Definition meta_utils.hpp:730
std::string return_type
Definition meta_utils.hpp:638
std::string name
Definition meta_utils.hpp:637
Definition meta_utils.hpp:859
std::string name_space
Definition meta_utils.hpp:863
MetaFunction()
Definition meta_utils.hpp:865
MetaFunction(const std::string &func_str, const std::string &name_space="")
Definition meta_utils.hpp:870
std::string to_lambda_string() const
Definition meta_utils.hpp:921
MetaFunction(MetaFunctionSignature signature, text_utils::MultilineStringAccumulator body, std::string name_space="")
Definition meta_utils.hpp:866
text_utils::MultilineStringAccumulator body
Definition meta_utils.hpp:862
std::string to_string() const
Definition meta_utils.hpp:937
MetaFunctionSignature signature
Definition meta_utils.hpp:861
Type
Distinguishes between local and system include types.
Definition meta_utils.hpp:37
@ Local
Include file from the project directory (uses quotes: "...")
Definition meta_utils.hpp:38
@ System
Include file from system paths (uses angle brackets: <...>)
Definition meta_utils.hpp:39
std::string str(const std::filesystem::path &base=".") const
Converts the MetaInclude into a valid C++ #include directive string.
Definition meta_utils.hpp:76
MetaInclude(std::string project_relative_path, Type type=Type::Local)
Constructs a MetaInclude with the given path and type.
Definition meta_utils.hpp:66
Definition meta_utils.hpp:1002
MetaMethod(MetaFunction function, AccessSpecifier access=AccessSpecifier::Public, bool is_static=false, bool is_virtual=false, bool is_const=false, bool is_override=false)
Definition meta_utils.hpp:1012
AccessSpecifier access
Definition meta_utils.hpp:1005
bool is_static
Definition meta_utils.hpp:1006
bool is_const
Definition meta_utils.hpp:1008
MetaMethod()
Definition meta_utils.hpp:1011
std::string to_string() const
Definition meta_utils.hpp:1017
bool is_override
Definition meta_utils.hpp:1009
MetaFunction function
Definition meta_utils.hpp:1004
bool is_virtual
Definition meta_utils.hpp:1007
std::string to_string() const
Definition meta_utils.hpp:602
MetaType type
Definition meta_utils.hpp:595
bool operator==(const MetaParameter &other) const
Definition meta_utils.hpp:600
std::string name
Definition meta_utils.hpp:594
Definition meta_utils.hpp:95
std::string size_when_serialized_bytes_func_lambda
Definition meta_utils.hpp:104
std::string get_type_name() const
Definition meta_utils.hpp:141
MetaType(std::string name, std::string string_to_type_func, std::string type_to_string_func, std::string serialize_type_func, std::string size_when_serialized_bytes_func, std::string deserialize_type_func, std::string literal_regex, const std::vector< MetaTemplateParameter > &element_types={})
Definition meta_utils.hpp:125
std::string to_string() const
Definition meta_utils.hpp:139
std::vector< MetaInclude > includes_required
Definition meta_utils.hpp:108
std::string serialize_type_func_lambda
Definition meta_utils.hpp:100
std::vector< MetaTemplateParameter > template_parameters
Definition meta_utils.hpp:115
bool operator==(const MetaType &other) const
Definition meta_utils.hpp:117
std::string literal_regex
Definition meta_utils.hpp:106
std::string type_to_string_func_lambda
Definition meta_utils.hpp:99
std::string deserialize_type_func_lambda
Definition meta_utils.hpp:105
bool variably_sized
Definition meta_utils.hpp:110
std::string base_type_name
Definition meta_utils.hpp:97
MetaType()
Definition meta_utils.hpp:124
std::string string_to_type_func_lambda
Definition meta_utils.hpp:98
Definition meta_utils.hpp:1630
void add_new_concrete_type(const MetaType &meta_type)
Definition meta_utils.hpp:1640
const std::unordered_map< std::string, MetaType > & get_concrete_type_name_to_meta_type() const
Definition meta_utils.hpp:1652
const std::unordered_map< std::string, std::function< meta_utils::MetaType(std::vector< MetaTemplateParameter >)> > & get_generic_type_to_meta_type_constructor() const
Definition meta_utils.hpp:1648
const std::vector< MetaType > & get_concrete_types() const
Definition meta_utils.hpp:1645
Definition meta_utils.hpp:825
InitStyle init_style
Definition meta_utils.hpp:837
std::string name
Definition meta_utils.hpp:835
std::string to_initialization() const
Definition meta_utils.hpp:846
std::string value
Definition meta_utils.hpp:836
std::string to_brace() const
Definition meta_utils.hpp:844
std::string to_definition() const
Definition meta_utils.hpp:842
InitStyle
Definition meta_utils.hpp:827
@ Definition
Definition meta_utils.hpp:827
@ Brace
Definition meta_utils.hpp:827
@ Assignment
Definition meta_utils.hpp:827
std::string type
Definition meta_utils.hpp:834
std::string name_space
Definition meta_utils.hpp:838
MetaVariable(std::string type, std::string name, std::string value, InitStyle init_style=InitStyle::Assignment, std::string name_space="")
Definition meta_utils.hpp:829
std::string to_assignment() const
Definition meta_utils.hpp:840
Definition text_utils.hpp:81
void add_multiline(const std::string &multiline_str)
Add multiple lines with indentation applied.
Definition text_utils.hpp:111
Definition text_utils.hpp:52
void add(Args &&...args)
Append values to the accumulator.
Definition text_utils.hpp:62
std::string str() const
Get the accumulated string.
Definition text_utils.hpp:72
Definition meta_utils.hpp:623
@ s
Definition input_state.hpp:45
@ a
Definition input_state.hpp:27
@ c
Definition input_state.hpp:29
@ m
Definition input_state.hpp:39
@ i
Definition input_state.hpp:35
@ T
Definition input_state.hpp:73
@ e
Definition input_state.hpp:31
void hash_combine(std::size_t &seed, std::size_t value) noexcept
Definition meta_utils.hpp:1674
std::vector< std::string > extract_top_level_function_declarations(const std::string &header_code_path)
Definition cpp_parsing.cpp:332
bool create_file_with_content_if_different(const std::filesystem::path &file_path, const std::string &content)
Create or update a file only if the new content differs from the current one.
Definition fs_utils.cpp:242
Definition meta_utils.cpp:9
MetaType REGEX
Definition meta_utils.hpp:408
MetaType construct_vector_metatype(MetaType generic_type)
Definition meta_utils.hpp:475
std::string create_array_of_type_to_string_func(MetaType type_parameter, unsigned int size)
Definition meta_utils.cpp:263
std::string optional_include
Definition meta_utils.hpp:1537
MetaType UINT8_T
Definition meta_utils.hpp:233
std::string create_vector_of_type_serialized_size_func(MetaType type_parameter)
Definition meta_utils.cpp:158
std::vector< MetaType > concrete_types
Definition meta_utils.hpp:531
MetaType resolve_meta_type(const std::string &type_str, const MetaTypes &types)
Definition meta_utils.cpp:523
std::string clean_type_string(const std::string &raw_type)
Definition meta_utils.cpp:1300
std::string create_unordered_map_deserialize_func(MetaType key_type, MetaType value_type)
Definition meta_utils.cpp:487
MetaCodeCollection generate_string_invokers_from_header_and_source(const StringInvokerGenerationSettingsForHeaderSource &sigsfhs)
Definition meta_utils.cpp:2055
MetaType FLOAT
Definition meta_utils.hpp:326
std::variant< unsigned int, MetaType > MetaTemplateParameter
Definition meta_utils.hpp:92
MetaFunction generate_interactive_invoker()
Definition meta_utils.cpp:2209
MetaType UINT32_T
Definition meta_utils.hpp:247
std::string create_vector_of_type_serialize_func(MetaType type_parameter)
Definition meta_utils.cpp:120
FilterMode
Definition meta_utils.hpp:1240
@ None
Definition meta_utils.hpp:1240
@ Whitelist
Definition meta_utils.hpp:1240
@ Blacklist
Definition meta_utils.hpp:1240
std::unordered_map< std::string, MetaType > create_type_name_to_meta_type_map(std::vector< MetaType > meta_types)
Definition meta_utils.hpp:577
std::optional< MetaType > parse_meta_type_from_string(const std::string &type_str)
Definition meta_utils.cpp:1252
std::string generate_deferred_string_invoker_for_function_collection_that_has_same_return_type(std::vector< MetaFunctionSignature > mfss_with_same_return_type, std::string return_type, std::string func_postfix)
Definition meta_utils.cpp:1744
std::string create_vector_of_type_to_string_func(MetaType type_parameter)
Definition meta_utils.cpp:99
std::string create_string_to_vector_of_type_func(MetaType type_parameter)
Definition meta_utils.cpp:71
meta_utils::MetaType create_meta_type_from_using(const std::string &source, const meta_utils::MetaTypes &types)
Definition meta_utils.cpp:725
MetaType SHORT
Definition meta_utils.hpp:300
std::string generate_string_invoker_for_function(const MetaFunctionSignature &sig, const std ::string &func_postfix)
Generate an invoker function from it's meta function signature.
Definition meta_utils.cpp:1384
std::string string_include
Definition meta_utils.hpp:1536
MetaTypes meta_types
Definition meta_utils.hpp:1658
std::string create_array_of_type_deserialize_func(MetaType type_parameter, unsigned int size)
Definition meta_utils.cpp:343
MetaType construct_class_metatype(const MetaClass &cls, const MetaTypes &types)
Definition meta_utils.cpp:838
std::string vector_include
Definition meta_utils.hpp:1535
MetaType CHAR
Definition meta_utils.hpp:274
std::string regex_include
Definition meta_utils.hpp:1538
std::string create_array_of_type_serialized_size_func(MetaType type_parameter, unsigned int size)
Definition meta_utils.cpp:316
MetaType construct_array_metatype(MetaType generic_type, unsigned int size)
Definition meta_utils.hpp:491
MetaType BOOL
Definition meta_utils.hpp:439
MetaType INT
Definition meta_utils.hpp:287
std::string generate_string_invoker_for_function_with_string_return_type(const MetaFunctionSignature &sig)
Definition meta_utils.cpp:1320
MetaType SIZE_T
Definition meta_utils.hpp:261
void register_custom_types_into_meta_types(const std::vector< CustomTypeExtractionSettings > &settings_list)
Definition meta_utils.cpp:1827
MetaType FILESYSTEM_PATH
Definition meta_utils.hpp:375
std::string generate_deferred_string_invoker_for_function(const MetaFunctionSignature &sig, const std ::string &func_postfix)
Generate a deferred invoker function from it's meta function signature.
Definition meta_utils.cpp:1417
std::string create_string_to_array_of_type_func(MetaType type_parameter, unsigned int size)
Definition meta_utils.cpp:233
bool is_system_header(const std::string &line)
Definition meta_utils.cpp:2189
std::string create_array_of_type_serialize_func(MetaType type_parameter, unsigned int size)
Definition meta_utils.cpp:285
MetaType STRING
Definition meta_utils.hpp:352
meta_utils::MetaClass create_meta_class_from_source(const std::string &source)
Definition meta_utils.cpp:715
std::string create_unordered_map_serialized_size_func(MetaType key_type, MetaType value_type)
Definition meta_utils.cpp:467
MetaType DOUBLE
Definition meta_utils.hpp:339
bool is_local_header(const std::string &line)
Definition meta_utils.cpp:2194
std::string create_unordered_map_to_string_func(MetaType key_type, MetaType value_type)
Definition meta_utils.cpp:414
std::string to_string(AccessSpecifier access)
Definition meta_utils.hpp:969
void generate_string_invokers_program_wide(std::vector< StringInvokerGenerationSettingsForHeaderSource > settings, const std::vector< MetaType > &all_types)
generates the meta program
Definition meta_utils.cpp:1872
std::unordered_map< std::string, std::function< MetaType(std::vector< MetaTemplateParameter >)> > generic_type_to_metatype_constructor
Definition meta_utils.hpp:538
std::string generate_regex_to_match_valid_invocation_of_func(const std::string &signature)
Definition meta_utils.cpp:1162
meta_utils::MetaType meta_type_type("meta_utils::MetaType", "[](){}", "[](){ return \"\";}", "[](){}", "[](const meta_utils::MetaType &v) { return sizeof(meta_utils::MetaType); }", "[](){}", "MetaType")
std::string create_unordered_map_serialize_func(MetaType key_type, MetaType value_type)
Definition meta_utils.cpp:437
std::string create_vector_of_type_deserialize_func(MetaType type_parameter)
Definition meta_utils.cpp:184
meta_utils::MetaClass create_meta_struct_from_source(const std::string &source)
Definition meta_utils.cpp:720
std::string trim(const std::string &s)
Definition meta_utils.cpp:1077
MetaType LONG
Definition meta_utils.hpp:313
std::string generate_string_invoker_for_function_collection_that_has_same_return_type(std::vector< MetaFunctionSignature > mfss_with_same_return_type, std::string return_type, std::string func_postfix)
Definition meta_utils.cpp:1602
MetaType construct_unordered_map_metatype(MetaType key_type, MetaType value_type)
Definition meta_utils.hpp:514
std::vector< std::string > get_system_headers(const std::vector< std::string > &headers)
Definition meta_utils.cpp:2199
std::string create_to_string_lambda(std::string type)
Definition meta_utils.hpp:212
AccessSpecifier
Definition meta_utils.hpp:967
@ Public
Definition meta_utils.hpp:967
@ Private
Definition meta_utils.hpp:967
@ Protected
Definition meta_utils.hpp:967
std::string get_fully_qualified_name(const T &obj)
Definition meta_utils.hpp:628
MetaType UNSIGNED_INT
Definition meta_utils.hpp:219
std::string create_string_to_unordered_map_func(MetaType key_type, MetaType value_type)
Definition meta_utils.cpp:381
const std::string unsigned_int_regex
Definition regex_utils.hpp:78
const std::string float_regex
Definition regex_utils.hpp:79
const std::string any_char_greedy
Definition regex_utils.hpp:46
const std::string string_literal(R"("(?:[^"\\]|\\.)*")")
const std::string char_literal(R"('(?:[^'\\]|\\.)')")
const std::string int_regex
Definition regex_utils.hpp:77
std::string constructor_signature_re
Definition regex_utils.hpp:109
Definition hashing.hpp:8
std::string indent(const std::string &text, int indent_level, int spaces_per_indent)
Indent text by a given number of levels.
Definition text_utils.cpp:293
std::string join_multiline(const std::string &input, bool replace_newlines_with_space)
Join a string with newlines removed or replaced.
Definition text_utils.cpp:165
std::string remove_consecutive_duplicates(const std::string &input, const std::string &dedup_chars)
Remove consecutive duplicate characters from a string.
Definition text_utils.cpp:11
std::string trim(const std::string &s)
Trim whitespace from both ends of a string.
Definition text_utils.cpp:125
Definition meta_utils.hpp:1577
CustomTypeExtractionSettings(const std::string &header_file_path, const std::vector< std::string > &type_names_for_potential_filtering={}, FilterMode mode=FilterMode::None)
Definition meta_utils.hpp:1578
const std::vector< std::string > type_names_for_potential_filtering
Definition meta_utils.hpp:1584
const std::string header_file_path
Definition meta_utils.hpp:1583
meta_utils::FilterMode mode
Definition meta_utils.hpp:1585
StringInvokerGenerationSettingsForHeaderSource(std::string header_file_path, std::string source_file_path, bool create_top_level_invoker=false, bool create_type_grouped_invokers=false, std::vector< std::string > string_signatures_for_potential_filtering={}, meta_utils::FilterMode mode=meta_utils::FilterMode::None)
Definition meta_utils.hpp:1596
meta_utils::FilterMode mode
Definition meta_utils.hpp:1610
std::string source_file_path
Definition meta_utils.hpp:1606
const std::vector< std::string > string_signatures_for_potential_filtering
Definition meta_utils.hpp:1609
bool create_type_grouped_invokers
Definition meta_utils.hpp:1608
std::string header_file_path
Definition meta_utils.hpp:1605
bool create_top_level_invoker
Definition meta_utils.hpp:1607
Definition meta_utils.hpp:1542
std::vector< std::string > lambda_conversions
Definition meta_utils.hpp:1543
std::vector< std::string > arg_to_var_conversions
Definition meta_utils.hpp:1544
std::vector< std::string > arguments_to_final_func_call
Definition meta_utils.hpp:1545
size_t operator()(const meta_utils::MetaType &mt) const noexcept
Definition meta_utils.hpp:1681