Complete function to convert printf-like format to std::format
| 721 | |
| 722 | // Complete function to convert printf-like format to std::format |
| 723 | std::string printf_to_std_format(const std::string& format) |
| 724 | { |
| 725 | // Compile the regex objects |
| 726 | static std::regex printf_escape_regex_obj{ std::string(printf_escape_regex) }; |
| 727 | static std::regex printf_specifier_regex_obj{ std::string(printf_specifier_regex) }; |
| 728 | static std::regex std_format_begin_escape_regex_obj{ std::string(std_format_begin_escape_regex) }; |
| 729 | static std::regex std_format_end_escape_regex_obj{ std::string(std_format_end_escape_regex) }; |
| 730 | |
| 731 | std::string std_format; |
| 732 | size_t pos = 0; |
| 733 | int argIndex = 0; // Track argument index for std::format |
| 734 | |
| 735 | while (pos < format.size()) |
| 736 | { |
| 737 | if (format[pos] != '%') |
| 738 | { |
| 739 | // Copy plain text until '%' or end |
| 740 | size_t start = pos; |
| 741 | while (pos < format.size() && format[pos] != '%') |
| 742 | { |
| 743 | pos++; |
| 744 | } |
| 745 | std_format += format.substr(start, pos - start); |
| 746 | } |
| 747 | else |
| 748 | { |
| 749 | std::smatch match; |
| 750 | // Handle '%' by checking for escape sequence |
| 751 | if (std::regex_search(format.begin() + pos, format.end(), match, printf_escape_regex_obj, |
| 752 | std::regex_constants::match_continuous)) |
| 753 | { |
| 754 | // Handle escaped percentages (%%): add a single % to output |
| 755 | std_format += "%"; |
| 756 | pos += match.length(); |
| 757 | } |
| 758 | // Handle any variable specifier |
| 759 | else if (std::regex_search(format.begin() + pos, format.end(), match, |
| 760 | printf_specifier_regex_obj, std::regex_constants::match_continuous)) |
| 761 | { |
| 762 | // Parse the format Specifier components |
| 763 | PrintfSpecifier spec; |
| 764 | for (size_t classType = 3; classType < match.size(); classType += printf_groups_per_class) |
| 765 | { |
| 766 | if (!match[classType].str().empty()) |
| 767 | { |
| 768 | spec.Type = static_cast<ClassType>(classType); |
| 769 | // Parse flags |
| 770 | std::string flags = match[classType + FLAGS].str(); |
| 771 | for (char flag : flags) |
| 772 | { |
| 773 | switch (flag) |
| 774 | { |
| 775 | case ' ': |
| 776 | spec.HasSpaceFill = true; |
| 777 | break; |
| 778 | case '-': |
| 779 | spec.HasLeftJustify = true; |
| 780 | break; |