438 static std::vector<FormatInstruction>
compile(
439 const std::string& pattern,
442 std::vector<FormatInstruction> instructions;
444 buffer.reserve(pattern.size());
445 bool strip_ansi =
false;
447 for (
size_t i = 0; i < pattern.size(); ++i) {
451 if (!buffer.empty()) {
457 bool left_align =
false;
458 bool center_align =
false;
459 bool truncate =
false;
463 while ((i + 1) < pattern.size() && (
464 std::isdigit(pattern[i + 1]) ||
465 pattern[i + 1] ==
'-' ||
466 pattern[i + 1] ==
'=')) {
467 char next = pattern[++i];
470 }
else if (next ==
'=') {
472 }
else if (std::isdigit(next)) {
473 width = width * 10 + (next -
'0');
477 if ((i + 1) < pattern.size() && pattern[i + 1] ==
'!') {
484 if ((i + 1) < pattern.size()) {
485 char next = pattern[++i];
489 instructions.emplace_back(context, FormatType::Year, width, left_align, center_align, truncate, strip_ansi);
492 if ((i + 1) < pattern.size() && pattern[i + 1] ==
's') {
493 instructions.emplace_back(context, FormatType::MilliSecondTimeStamp, width, left_align, center_align, truncate, strip_ansi);
497 instructions.emplace_back(context, FormatType::Month, width, left_align, center_align, truncate, strip_ansi);
500 instructions.emplace_back(context, FormatType::Day, width, left_align, center_align, truncate, strip_ansi);
503 instructions.emplace_back(context, FormatType::Hour, width, left_align, center_align, truncate, strip_ansi);
506 instructions.emplace_back(context, FormatType::Minute, width, left_align, center_align, truncate, strip_ansi);
509 if ((i + 1) < pattern.size() && pattern[i + 1] ==
'C') {
514 instructions.emplace_back(context, FormatType::Second, width, left_align, center_align, truncate, strip_ansi);
517 if ((i + 1) < pattern.size() && pattern[i + 1] ==
'c') {
522 instructions.emplace_back(context, FormatType::Millisecond, width, left_align, center_align, truncate, strip_ansi);
525 instructions.emplace_back(context, FormatType::TwoDigitYear, width, left_align, center_align, truncate, strip_ansi);
528 instructions.emplace_back(context, FormatType::DateTime, width, left_align, center_align, truncate, strip_ansi);
531 instructions.emplace_back(context, FormatType::ShortDate, width, left_align, center_align, truncate, strip_ansi);
535 instructions.emplace_back(context, FormatType::TimeISO8601, width, left_align, center_align, truncate, strip_ansi);
538 instructions.emplace_back(context, FormatType::DateISO8601, width, left_align, center_align, truncate, strip_ansi);
541 if ((i + 1) < pattern.size() && pattern[i + 1] ==
'c') {
547 if ((i + 1) < pattern.size() && pattern[i + 1] ==
'C') {
552 instructions.emplace_back(context, FormatType::TimeStamp, width, left_align, center_align, truncate, strip_ansi);
557 if ((i + 1) < pattern.size() && pattern[i + 1] ==
's') {
558 instructions.emplace_back(context, FormatType::FileName, width, left_align, center_align, truncate, strip_ansi);
562 instructions.emplace_back(context, FormatType::AbbreviatedMonthName, width, left_align, center_align, truncate, strip_ansi);
565 instructions.emplace_back(context, FormatType::FullMonthName, width, left_align, center_align, truncate, strip_ansi);
568 instructions.emplace_back(context, FormatType::AbbreviatedWeekdayName, width, left_align, center_align, truncate, strip_ansi);
571 instructions.emplace_back(context, FormatType::FullWeekdayName, width, left_align, center_align, truncate, strip_ansi);
576 instructions.emplace_back(context, FormatType::LogLevel, width, left_align, center_align, truncate, strip_ansi);
579 instructions.emplace_back(context, FormatType::ShortLogLevel, width, left_align, center_align, truncate, strip_ansi);
584 instructions.emplace_back(context, FormatType::ThreadId, width, left_align, center_align, truncate, strip_ansi);
589 if ((i + 1) < pattern.size() && pattern[i + 1] ==
'f' && (i + 2) < pattern.size() && pattern[i + 2] ==
'n') {
590 instructions.emplace_back(context, FormatType::FullFileName, width, left_align, center_align, truncate, strip_ansi);
594 if ((i + 1) < pattern.size() && pattern[i + 1] ==
'n') {
595 instructions.emplace_back(context, FormatType::FileName, width, left_align, center_align, truncate, strip_ansi);
599 instructions.emplace_back(context, FormatType::FileName, width, left_align, center_align, truncate, strip_ansi);
602 instructions.emplace_back(context, FormatType::FullFileName, width, left_align, center_align, truncate, strip_ansi);
605 instructions.emplace_back(context, FormatType::SourceFileAndLine, width, left_align, center_align, truncate, strip_ansi);
608 instructions.emplace_back(context, FormatType::LineNumber, width, left_align, center_align, truncate, strip_ansi);
611 instructions.emplace_back(context, FormatType::FunctionName, width, left_align, center_align, truncate, strip_ansi);
616 instructions.emplace_back(context, FormatType::StartColor, 0,
false,
false,
false, strip_ansi);
619 instructions.emplace_back(context, FormatType::EndColor, 0,
false,
false,
false, strip_ansi);
624 instructions.emplace_back(context, FormatType::Message, width, left_align, center_align, truncate, strip_ansi);
629 if ((i + 2) < pattern.size() && pattern[i + 1] ==
'(') {
630 size_t end = pattern.find(
')', i + 2);
631 if (end == std::string::npos) {
635 std::string params = pattern.substr(i + 2, end - i - 2);
636 auto no_args_instructions =
compile(params, CompileContext::NoArgsFallback);
637 instructions.insert(instructions.end(), no_args_instructions.begin(), no_args_instructions.end());
654 if (!buffer.empty()) {