| 205 | |
| 206 | template<class...Args> |
| 207 | codeunit_sequence produce_format(const format_mold_view& format_mold, const Args&...args) |
| 208 | { |
| 209 | constexpr u64 argument_count = sizeof...(Args); |
| 210 | const std::array<argument_value_package, argument_count> arguments {{ argument_value_package{ args } ... }}; |
| 211 | |
| 212 | enum class indexing_type : u8 |
| 213 | { |
| 214 | unknown, |
| 215 | manual, |
| 216 | automatic |
| 217 | }; |
| 218 | indexing_type index_type = indexing_type::unknown; |
| 219 | u64 next_index = 0; |
| 220 | codeunit_sequence result; |
| 221 | for(const auto [ type, run ] : format_mold) |
| 222 | { |
| 223 | switch (type) |
| 224 | { |
| 225 | case format_mold_view::run_type::plain_text: |
| 226 | result += run; |
| 227 | break; |
| 228 | case format_mold_view::run_type::escaped_brace: |
| 229 | result += run.read_at(0); |
| 230 | break; |
| 231 | case format_mold_view::run_type::formatter: |
| 232 | { |
| 233 | const auto [ index_run, specification ] = run.subview(1, run.size() - 2).split(u8":"_cuqv); |
| 234 | u64 current_index = next_index; |
| 235 | if (index_run.is_empty()) |
| 236 | { |
| 237 | OPEN_STRING_CHECK(index_type != indexing_type::manual, u8"Manual index is not allowed mixing with automatic index!"); |
| 238 | index_type = indexing_type::automatic; |
| 239 | ++next_index; |
| 240 | } |
| 241 | else |
| 242 | { |
| 243 | OPEN_STRING_CHECK(index_type != indexing_type::automatic, u8"Automatic index is not allowed mixing with manual index!"); |
| 244 | index_type = indexing_type::manual; |
| 245 | [[maybe_unused]] const auto [ last, error ] = |
| 246 | std::from_chars((const char*)index_run.data(), (const char*)index_run.cend().data(), current_index); |
| 247 | OPEN_STRING_CHECK(last == (const char*)index_run.cend().data(), u8"Invalid format index [{}]!", index_run); |
| 248 | } |
| 249 | OPEN_STRING_CHECK(current_index < argument_count, u8"Invalid format index [{}]: Index should be less than count of argument [{}]!", current_index, argument_count); |
| 250 | result += arguments[current_index].produce(specification); |
| 251 | } |
| 252 | break; |
| 253 | case format_mold_view::run_type::ending: |
| 254 | // Unreachable |
| 255 | break; |
| 256 | } |
| 257 | } |
| 258 | return result; |
| 259 | } |
| 260 | } |
| 261 | |
| 262 | template<class Format, class...Args> |