12#include <unordered_set>
67 : path(
std::move(project_relative_path)), type(type) {}
76 std::string
str(
const std::filesystem::path &base =
".")
const {
78 return "#include <" + path +
">";
80 auto rel_path = std::filesystem::relative(std::filesystem::path(path), base);
81 return "#include \"" + rel_path.generic_string() +
"\"";
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 = {})
135 std::set<std::string> variably_sized_types = {
"std::vector",
"std::string"};
139 std::string
to_string()
const {
return to_string_rec(*
this); }
144 std::string get_type_name_rec(
const MetaType &meta_type)
const {
149 std::ostringstream oss;
159 using T = std::decay_t<
decltype(param)>;
160 if constexpr (std::is_same_v<T, unsigned int>) {
162 }
else if constexpr (std::is_same_v<T, MetaType>) {
163 oss << get_type_name_rec(param);
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";
181 if (!meta_type.template_parameters.empty()) {
182 oss <<
" element_types: [\n";
183 for (
const auto &elem : meta_type.template_parameters) {
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);
194 std::istringstream iss(elem_str);
196 while (std::getline(iss, line)) {
197 oss <<
" " << line <<
"\n";
204 oss <<
" element_types: []\n";
213 return "[](const " + type +
" &v) { return std::to_string(v); }";
220 MetaType(
"unsigned int",
"[](const std::string &s) { return static_cast<unsigned int>(std::stoul(s)); }",
222 "[](const unsigned int &v) { "
223 " std::vector<uint8_t> buf(sizeof(unsigned int)); "
224 " std::memcpy(buf.data(), &v, sizeof(unsigned int)); "
226 "[](const unsigned int &v) { return sizeof(unsigned int); }",
227 "[](const std::vector<uint8_t> &buf) { "
229 " std::memcpy(&v, buf.data(), sizeof(unsigned int)); "
234 MetaType(
"uint8_t",
"[](const std::string &s) { return static_cast<uint8_t>(std::stoul(s)); }",
236 "[](const uint8_t &v) { "
237 " std::vector<uint8_t> buf(sizeof(uint8_t)); "
238 " std::memcpy(buf.data(), &v, sizeof(uint8_t)); "
240 "[](const uint8_t &v) { return sizeof(uint8_t); }",
241 "[](const std::vector<uint8_t> &buf) { "
243 " std::memcpy(&v, buf.data(), sizeof(uint8_t)); "
248 MetaType(
"uint32_t",
"[](const std::string &s) { return static_cast<uint32_t>(std::stoul(s)); }",
250 "[](const uint32_t &v) { "
251 " std::vector<uint8_t> buf(sizeof(uint32_t)); "
252 " std::memcpy(buf.data(), &v, sizeof(uint32_t)); "
254 "[](const uint32_t &v) { return sizeof(uint32_t); }",
255 "[](const std::vector<uint8_t> &buf) { "
257 " std::memcpy(&v, buf.data(), sizeof(uint32_t)); "
263 "[](const size_t &v) { "
264 " std::vector<uint8_t> buf(sizeof(size_t)); "
265 " std::memcpy(buf.data(), &v, sizeof(size_t)); "
267 "[](const size_t &v) { return sizeof(size_t); }",
268 "[](const std::vector<uint8_t> &buf) { "
270 " std::memcpy(&v, buf.data(), sizeof(size_t)); "
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)); "
280 "[](const char &v) { return sizeof(char); }",
281 "[](const std::vector<uint8_t> &buf) { "
283 " std::memcpy(&v, buf.data(), sizeof(char)); "
289 "[](const int &v) { "
290 " std::vector<uint8_t> buf(sizeof(int)); "
291 " std::memcpy(buf.data(), &v, sizeof(int)); "
293 "[](const int &v) { return sizeof(int); }",
294 "[](const std::vector<uint8_t> &buf) { "
296 " std::memcpy(&v, buf.data(), sizeof(int)); "
302 "[](const short &v) { "
303 " std::vector<uint8_t> buf(sizeof(short)); "
304 " std::memcpy(buf.data(), &v, sizeof(short)); "
306 "[](const short &v) { return sizeof(short); }",
307 "[](const std::vector<uint8_t> &buf) { "
309 " std::memcpy(&v, buf.data(), sizeof(short)); "
315 "[](const long &v) { "
316 " std::vector<uint8_t> buf(sizeof(long)); "
317 " std::memcpy(buf.data(), &v, sizeof(long)); "
319 "[](const long &v) { return sizeof(long); }",
320 "[](const std::vector<uint8_t> &buf) { "
322 " std::memcpy(&v, buf.data(), sizeof(long)); "
328 "[](const float &v) { "
329 " std::vector<uint8_t> buf(sizeof(float)); "
330 " std::memcpy(buf.data(), &v, sizeof(float)); "
332 "[](const float &v) { return sizeof(float); }",
333 "[](const std::vector<uint8_t> &buf) { "
335 " std::memcpy(&v, buf.data(), sizeof(float)); "
341 "[](const double &v) { "
342 " std::vector<uint8_t> buf(sizeof(double)); "
343 " std::memcpy(buf.data(), &v, sizeof(double)); "
345 "[](const double &v) { return sizeof(double); }",
346 "[](const std::vector<uint8_t> &buf) { "
348 " std::memcpy(&v, buf.data(), sizeof(double)); "
354 "[](const std::string &s) { "
355 " if (s.size() >= 2 && s.front() == '\"' && s.back() == '\"') "
356 " return s.substr(1, s.size() - 2); "
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); "
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(); "
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); }",
376 "std::filesystem::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); }",
383 "[](const std::filesystem::path &p) { return p.string(); }",
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); "
394 "[](const std::filesystem::path &p) { "
395 " std::string s = p.string(); "
396 " return sizeof(size_t) + s.size(); }",
398 "[](const std::vector<uint8_t> &buf) { "
399 " if (buf.size() < sizeof(size_t)) return std::filesystem::path(); "
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)); }",
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); }",
416 "[](const std::regex &r) { return r.pattern(); }",
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); "
427 "[](const std::regex &r) { "
428 " std::string pattern = r.pattern(); "
429 " return sizeof(size_t) + pattern.size(); }",
431 "[](const std::vector<uint8_t> &buf) { "
432 " if (buf.size() < sizeof(size_t)) return std::regex(); "
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)); }",
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; "
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)");
452 "[](const meta_utils::MetaType &v) { return sizeof(meta_utils::MetaType); }",
453 "[](){}",
"MetaType");
483 string_to_vector_of_generic_type_func,
484 vector_of_type_to_string_func,
485 vector_of_type_serialize_func,
486 vector_of_type_serialized_size_func,
487 vector_of_type_deserialize_func,
499 string_to_array_of_type_func,
500 array_of_type_to_string_func,
501 array_of_type_serialize_func,
502 array_of_type_serialized_size_func,
503 array_of_type_deserialize_func,
521 return MetaType(
"std::unordered_map",
526 map_deserialize_func,
537inline std::unordered_map<std::string, std::function<MetaType(std::vector<MetaTemplateParameter>)>>
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");
546 const MetaType &element_type = std::get<MetaType>(template_parameters[0]);
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");
557 const MetaType &element_type = std::get<MetaType>(template_parameters[0]);
558 unsigned int size = std::get<unsigned int>(template_parameters[1]);
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");
570 const MetaType &key_type = std::get<MetaType>(template_parameters[0]);
571 const MetaType &value_type = std::get<MetaType>(template_parameters[1]);
578 std::unordered_map<std::string, MetaType> map;
580 map.emplace(meta_type.base_type_name, meta_type);
603 std::ostringstream oss;
604 oss <<
"MetaParameter {\n";
605 oss <<
" name: " <<
name <<
"\n";
607 std::string type_str =
type.to_string();
608 std::istringstream type_iss(type_str);
611 while (std::getline(type_iss, line)) {
612 oss <<
" " << line <<
"\n";
624 {
a.name } -> std::same_as<std::string &>;
625 {
a.name_space } -> std::same_as<std::string &>;
629 if (!obj.name_space.empty()) {
630 return obj.name_space +
"::" + obj.name;
652 std::string
s = trim(cleaned_input);
655 bool parsed_regular =
false;
656 std::string local_return_type, local_name, local_param_list;
660 auto param_end =
s.rfind(
')');
661 if (param_end == std::string::npos) {
662 throw std::invalid_argument(
"Function signature missing closing ')'");
665 auto param_start =
s.rfind(
'(', param_end);
666 if (param_start == std::string::npos) {
667 throw std::invalid_argument(
"Function signature missing opening '('");
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));
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");
679 local_return_type = trim(ret_and_name.substr(0, last_space));
680 local_name = ret_and_name.substr(last_space + 1);
682 parsed_regular =
true;
683 }
catch (
const std::invalid_argument &) {
687 if (parsed_regular) {
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");
706 std::vector<std::string> param_tokens = split_comma_separated(
param_list);
707 for (
const std::string ¶m_str : param_tokens) {
708 if (!param_str.empty()) {
722 sa.
add(param.type.get_type_name(),
" ", param.name);
731 std::ostringstream oss;
732 oss <<
"MetaFunctionSignature {\n";
733 oss <<
" name: " <<
name <<
"\n";
734 oss <<
" parameters: [\n";
736 std::istringstream iss(param.to_string());
738 while (std::getline(iss, line)) {
739 oss <<
" " << line <<
"\n";
748 static std::vector<std::string> split_comma_separated(
const std::string &input) {
749 std::vector<std::string> result;
754 int bracket_depth = 0;
756 bool in_single_quote =
false;
757 bool in_double_quote =
false;
759 for (
size_t i = 0;
i < input.size(); ++
i) {
763 if (
c ==
'\'' && !in_double_quote) {
764 in_single_quote = !in_single_quote;
765 current.push_back(
c);
768 if (
c ==
'"' && !in_single_quote) {
769 in_double_quote = !in_double_quote;
770 current.push_back(
c);
775 if (in_single_quote || in_double_quote) {
776 current.push_back(
c);
783 else if (
c ==
'>' && angle_depth > 0)
787 else if (
c ==
')' && paren_depth > 0)
791 else if (
c ==
']' && bracket_depth > 0)
795 else if (
c ==
'}' && brace_depth > 0)
799 if (
c ==
',' && angle_depth == 0 && paren_depth == 0 && bracket_depth == 0 && brace_depth == 0) {
802 if (!trimmed.empty())
803 result.push_back(trimmed);
806 current.push_back(
c);
812 if (!trimmed.empty())
813 result.push_back(trimmed);
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);
872 auto body_start = func_str.find(
'{');
873 if (body_start == std::string::npos) {
874 throw std::invalid_argument(
"Function string missing 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);
884 body.add_multiline(body_str);
887 header = trim(header);
890 auto param_end = header.rfind(
')');
891 if (param_end == std::string::npos) {
892 throw std::invalid_argument(
"Function header missing closing ')'");
896 auto param_start = header.rfind(
'(', param_end);
897 if (param_start == std::string::npos) {
898 throw std::invalid_argument(
"Function header missing opening '('");
902 std::string param_list = header.substr(param_start + 1, param_end - param_start - 1);
905 std::string ret_and_name = trim(header.substr(0, param_start));
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");
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));
916 std::string header_signature = return_type +
" " + func_name +
"(" + param_list +
")";
922 std::ostringstream oss;
925 for (
size_t i = 0;
i <
signature.parameters.size(); ++
i) {
927 oss << param.type.get_type_name() <<
" " << param.name;
933 oss <<
") -> " <<
signature.return_type <<
" {\n" <<
body.str() <<
"\n}";
938 std::ostringstream oss;
947 for (
size_t i = 0;
i <
signature.parameters.size(); ++
i) {
949 oss << param.type.get_type_name() <<
" " << param.name;
955 oss <<
") {\n" <<
body.str() <<
"\n}";
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);
993 std::ostringstream oss;
997 oss <<
variable.to_initialization();
1018 std::ostringstream oss;
1027 oss <<
function.signature.return_type <<
" ";
1028 if (!
function.name_space.empty()) {
1029 oss <<
function.name_space <<
"::";
1031 oss <<
function.signature.name <<
"(";
1032 for (
size_t i = 0;
i <
function.signature.parameters.size(); ++
i) {
1033 const auto ¶m =
function.signature.parameters[
i];
1034 oss << param.type.get_type_name() <<
" " << param.name;
1035 if (
i + 1 <
function.signature.parameters.size())
1044 oss <<
" {\n" <<
function.body.str() <<
"\n}";
1063 const std::vector<std::string> &init_list = {})
1070 std::ostringstream oss;
1071 std::string pad(indent_level * 4,
' ');
1077 oss << param.type.get_type_name() <<
" " << param.name;
1125 if (
m.function.signature.to_string() == sig_str) {
1134 std::ostringstream oss;
1142 oss <<
"class " <<
name;
1163 oss <<
"} // namespace " <<
name_space <<
"\n";
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;
1174 for (
const auto &
a : attrs)
1175 if (
a.access == section) {
1180 for (
const auto &
m : meths)
1181 if (
m.access == section) {
1192 for (
const auto &attr : attrs) {
1193 if (attr.access == section) {
1194 oss <<
" " << (attr.is_static ?
"static " :
"") << (attr.is_const ?
"const " :
"");
1196 if (!attr.variable.value.empty()) {
1197 oss << attr.variable.to_initialization();
1199 oss << attr.variable.type <<
" " << attr.variable.name <<
";";
1206 for (
const auto &method : meths) {
1207 if (method.access == section) {
1209 if (method.is_static)
1211 if (method.is_virtual)
1215 if (!method.function.signature.return_type.empty())
1216 oss << method.function.signature.return_type <<
" ";
1218 oss << method.function.signature.name <<
"(";
1220 for (
size_t i = 0;
i < method.function.signature.parameters.size(); ++
i) {
1221 const auto ¶m = method.function.signature.parameters[
i];
1222 oss << param.type.get_type_name() <<
" " << param.name;
1223 if (
i + 1 < method.function.signature.parameters.size()) {
1229 if (method.is_const)
1231 if (method.is_override)
1269 const std::vector<std::string> &string_signatures_to_filter_on = {},
1272 std::string header_source = read_file(header_file_path);
1273 std::string cpp_source = read_file(cpp_file_path);
1275 name = extract_function_collection_name(header_source).value_or(
"meta_function_collection");
1279 name_space = extract_top_level_namespace(cpp_source).value_or(
"");
1282 extract_function_signatures(header_file_path,
name_space, string_signatures_to_filter_on, mode);
1294 std::ostringstream oss;
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";
1301 oss <<
"#ifndef " << guard_macro <<
"\n";
1302 oss <<
"#define " << guard_macro <<
"\n\n";
1305 oss << include <<
"\n";
1311 oss <<
"namespace " <<
name_space <<
" {\n\n";
1315 oss <<
"extern " << var.type <<
" " << var.name <<
";\n";
1320 for (
const auto &cls :
classes) {
1321 oss << cls.to_string() <<
"\n\n";
1326 oss << func.signature.return_type <<
" " << func.signature.name <<
"(";
1327 for (
size_t i = 0;
i < func.signature.parameters.size(); ++
i) {
1328 const auto ¶m = func.signature.parameters[
i];
1329 oss << param.type.get_type_name() <<
" " << param.name;
1330 if (
i < func.signature.parameters.size() - 1)
1337 oss << sig.return_type <<
" " << sig.name <<
"(";
1338 for (
size_t i = 0;
i < sig.parameters.size(); ++
i) {
1339 const auto ¶m = sig.parameters[
i];
1340 oss << param.type.get_type_name() <<
" " << param.name;
1341 if (
i < sig.parameters.size() - 1)
1348 oss <<
"\n} // namespace " <<
name_space <<
"\n";
1351 oss <<
"\n#endif // " << guard_macro <<
"\n";
1356 std::ostringstream oss;
1359 oss << include <<
"\n";
1365 oss <<
"namespace " <<
name_space <<
" {\n\n";
1369 oss << var.to_initialization() <<
"\n";
1374 oss << func.signature.return_type <<
" " << func.signature.name <<
"(";
1375 for (
size_t i = 0;
i < func.signature.parameters.size(); ++
i) {
1376 const auto ¶m = func.signature.parameters[
i];
1377 oss << param.type.get_type_name() <<
" " << param.name;
1378 if (
i < func.signature.parameters.size() - 1)
1382 oss << func.body.str() <<
"\n";
1387 oss <<
"} // namespace " <<
name_space <<
"\n";
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);
1399 std::ostringstream ss;
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);
1409 while (std::getline(stream, line)) {
1411 if (std::regex_search(line, match, define_guard_regex)) {
1412 std::string guard_name = match[1];
1414 std::transform(guard_name.begin(), guard_name.end(), guard_name.begin(),
1415 [](
unsigned char c) { return std::tolower(c); });
1417 const std::string suffix =
"_hpp";
1418 if (guard_name.ends_with(suffix)) {
1419 guard_name.erase(guard_name.size() - suffix.size());
1426 return std::nullopt;
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);
1434 while (std::getline(stream, line)) {
1436 if (std::regex_search(line, match, include_regex)) {
1437 out.push_back(match[1]);
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) {
1447 std::vector<std::string> function_declarations =
1450 for (
const std::string &func_decl : function_declarations) {
1454 auto clean_func_decl = [](
const std::string &
s) -> std::string {
1456 if (result.back() ==
';') {
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); });
1476 MetaFunctionSignature mfs(clean_func_decl(func_decl),
name_space);
1479 }
catch (
const std::exception &
e) {
1480 std::cout <<
"invalid func\n" << func_decl << std::endl;
1515 std::optional<std::string> extract_top_level_namespace(
const std::string &source_code) {
1516 std::regex namespace_regex(R
"(\bnamespace\s+(\w+)\s*\{)");
1519 if (std::regex_search(source_code, match, namespace_regex)) {
1520 if (match.size() >= 2) {
1521 return match[1].str();
1525 return std::nullopt;
1556 const std ::string &func_postfix =
"_string_invoker");
1569 const std ::string &func_postfix =
"_deferred_string_invoker");
1572 std::vector<MetaFunctionSignature> mfss_with_same_return_type, std::string return_type, std::string func_postfix);
1575 std::vector<MetaFunctionSignature> mfss_with_same_return_type, std::string return_type, std::string func_postfix);
1617 const std::vector<MetaType> &all_types);
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 = {},
1633 std::unordered_map<std::string, MetaType> concrete_type_name_to_meta_type =
1636 std::unordered_map<std::string, std::function<
meta_utils::MetaType(std::vector<MetaTemplateParameter>)>>
1641 concrete_types.push_back(meta_type);
1647 const std::unordered_map<std::string, std::function<
meta_utils::MetaType(std::vector<MetaTemplateParameter>)>> &
1649 return generic_type_to_meta_type_constructor;
1653 return concrete_type_name_to_meta_type;
1675 seed ^= value + 0x9e3779b9 + (seed << 6) + (seed >> 2);
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));
1691 for (
const auto &elem : mt.template_parameters) {
1694 using T = std::decay_t<
decltype(param)>;
1695 if constexpr (std::is_same_v<T, unsigned int>) {
1697 }
else if constexpr (std::is_same_v<T, meta_utils::MetaType>) {
1698 hash_combine(seed, std::hash<meta_utils::MetaType>{}(param));
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
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
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
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