Parse a format specification from the string after ':' Returns pointer past the parsed spec (should be at '}')
| 64 | // Parse a format specification from the string after ':' |
| 65 | // Returns pointer past the parsed spec (should be at '}') |
| 66 | inline const char* parse_format_spec(const char* p, FormatSpec& spec) { |
| 67 | if (!p || *p == '}') return p; |
| 68 | |
| 69 | // Check for fill and align (fill char followed by align char) |
| 70 | // Align chars are: < > ^ |
| 71 | if (p[0] && p[1] && (p[1] == '<' || p[1] == '>' || p[1] == '^')) { |
| 72 | spec.fill = p[0]; |
| 73 | spec.align = p[1]; |
| 74 | p += 2; |
| 75 | } else if (*p == '<' || *p == '>' || *p == '^') { |
| 76 | spec.align = *p++; |
| 77 | } |
| 78 | |
| 79 | // Sign: + - or space |
| 80 | if (*p == '+' || *p == '-' || *p == ' ') { |
| 81 | spec.sign = *p++; |
| 82 | } |
| 83 | |
| 84 | // Alternate form: # |
| 85 | if (*p == '#') { |
| 86 | spec.alternate = true; |
| 87 | ++p; |
| 88 | } |
| 89 | |
| 90 | // Zero padding: 0 (only if no alignment specified) |
| 91 | if (*p == '0' && spec.align == '\0') { |
| 92 | spec.zero_pad = true; |
| 93 | ++p; |
| 94 | } |
| 95 | |
| 96 | // Width |
| 97 | while (*p >= '0' && *p <= '9') { |
| 98 | spec.width = spec.width * 10 + (*p - '0'); |
| 99 | ++p; |
| 100 | } |
| 101 | |
| 102 | // Precision: .N |
| 103 | if (*p == '.') { |
| 104 | ++p; |
| 105 | spec.precision = 0; |
| 106 | while (*p >= '0' && *p <= '9') { |
| 107 | spec.precision = spec.precision * 10 + (*p - '0'); |
| 108 | ++p; |
| 109 | } |
| 110 | } |
| 111 | |
| 112 | // Type specifier |
| 113 | if (*p && *p != '}') { |
| 114 | spec.type = *p++; |
| 115 | } |
| 116 | |
| 117 | return p; |
| 118 | } |
| 119 | |
| 120 | // Apply width/alignment to a formatted string |
| 121 | inline void apply_width_align(fl::string& result, const fl::string& value, const FormatSpec& spec) { |