448 static std::vector<FormatInstruction>
compile(
449 const std::string& pattern,
452 std::vector<FormatInstruction> instructions;
454 buffer.reserve(pattern.size());
455 bool strip_ansi =
false;
457 for (
size_t i = 0; i < pattern.size(); ++i) {
461 if (!buffer.empty()) {
467 bool left_align =
false;
468 bool center_align =
false;
469 bool truncate =
false;
473 while ((i + 1) < pattern.size() && (
474 std::isdigit(pattern[i + 1]) ||
475 pattern[i + 1] ==
'-' ||
476 pattern[i + 1] ==
'=')) {
477 char next = pattern[++i];
480 }
else if (next ==
'=') {
482 }
else if (std::isdigit(next)) {
483 width = width * 10 + (next -
'0');
487 if ((i + 1) < pattern.size() && pattern[i + 1] ==
'!') {
494 if ((i + 1) < pattern.size()) {
495 char next = pattern[++i];
499 instructions.emplace_back(context, FormatType::Year, width, left_align, center_align, truncate, strip_ansi);
502 if ((i + 1) < pattern.size() && pattern[i + 1] ==
's') {
503 instructions.emplace_back(context, FormatType::MilliSecondTimeStamp, width, left_align, center_align, truncate, strip_ansi);
507 instructions.emplace_back(context, FormatType::Month, width, left_align, center_align, truncate, strip_ansi);
510 instructions.emplace_back(context, FormatType::Day, width, left_align, center_align, truncate, strip_ansi);
513 instructions.emplace_back(context, FormatType::Hour, width, left_align, center_align, truncate, strip_ansi);
516 instructions.emplace_back(context, FormatType::Minute, width, left_align, center_align, truncate, strip_ansi);
519 if ((i + 1) < pattern.size() && pattern[i + 1] ==
'C') {
524 instructions.emplace_back(context, FormatType::Second, width, left_align, center_align, truncate, strip_ansi);
527 if ((i + 1) < pattern.size() && pattern[i + 1] ==
'c') {
532 instructions.emplace_back(context, FormatType::Millisecond, width, left_align, center_align, truncate, strip_ansi);
535 instructions.emplace_back(context, FormatType::TwoDigitYear, width, left_align, center_align, truncate, strip_ansi);
538 instructions.emplace_back(context, FormatType::DateTime, width, left_align, center_align, truncate, strip_ansi);
541 instructions.emplace_back(context, FormatType::ShortDate, width, left_align, center_align, truncate, strip_ansi);
545 instructions.emplace_back(context, FormatType::TimeISO8601, width, left_align, center_align, truncate, strip_ansi);
548 instructions.emplace_back(context, FormatType::DateISO8601, width, left_align, center_align, truncate, strip_ansi);
551 if ((i + 1) < pattern.size() && pattern[i + 1] ==
'c') {
556 instructions.emplace_back(context, FormatType::TimeStamp, width, left_align, center_align, truncate, strip_ansi);
560 if ((i + 1) < pattern.size() && pattern[i + 1] ==
'C') {
565 instructions.emplace_back(context, FormatType::TimeStamp, width, left_align, center_align, truncate, strip_ansi);
569 if ((i + 1) < pattern.size() && pattern[i + 1] ==
's') {
570 instructions.emplace_back(context, FormatType::FileName, width, left_align, center_align, truncate, strip_ansi);
574 instructions.emplace_back(context, FormatType::AbbreviatedMonthName, width, left_align, center_align, truncate, strip_ansi);
577 instructions.emplace_back(context, FormatType::FullMonthName, width, left_align, center_align, truncate, strip_ansi);
580 instructions.emplace_back(context, FormatType::AbbreviatedWeekdayName, width, left_align, center_align, truncate, strip_ansi);
583 instructions.emplace_back(context, FormatType::FullWeekdayName, width, left_align, center_align, truncate, strip_ansi);
588 instructions.emplace_back(context, FormatType::LogLevel, width, left_align, center_align, truncate, strip_ansi);
591 instructions.emplace_back(context, FormatType::ShortLogLevel, width, left_align, center_align, truncate, strip_ansi);
596 instructions.emplace_back(context, FormatType::ThreadId, width, left_align, center_align, truncate, strip_ansi);
601 if ((i + 1) < pattern.size() && pattern[i + 1] ==
'f' && (i + 2) < pattern.size() && pattern[i + 2] ==
'n') {
602 instructions.emplace_back(context, FormatType::FullFileName, width, left_align, center_align, truncate, strip_ansi);
606 if ((i + 1) < pattern.size() && pattern[i + 1] ==
'n') {
607 instructions.emplace_back(context, FormatType::FileName, width, left_align, center_align, truncate, strip_ansi);
611 instructions.emplace_back(context, FormatType::FileName, width, left_align, center_align, truncate, strip_ansi);
614 instructions.emplace_back(context, FormatType::FullFileName, width, left_align, center_align, truncate, strip_ansi);
617 instructions.emplace_back(context, FormatType::SourceFileAndLine, width, left_align, center_align, truncate, strip_ansi);
620 instructions.emplace_back(context, FormatType::LineNumber, width, left_align, center_align, truncate, strip_ansi);
623 instructions.emplace_back(context, FormatType::FunctionName, width, left_align, center_align, truncate, strip_ansi);
628 instructions.emplace_back(context, FormatType::StartColor, 0,
false,
false,
false, strip_ansi);
631 instructions.emplace_back(context, FormatType::EndColor, 0,
false,
false,
false, strip_ansi);
636 instructions.emplace_back(context, FormatType::Message, width, left_align, center_align, truncate, strip_ansi);
641 if ((i + 2) < pattern.size() && pattern[i + 1] ==
'(') {
642 size_t end = pattern.find(
')', i + 2);
643 if (end == std::string::npos) {
647 std::string params = pattern.substr(i + 2, end - i - 2);
648 auto no_args_instructions =
compile(params, CompileContext::NoArgsFallback);
649 instructions.insert(instructions.end(), no_args_instructions.begin(), no_args_instructions.end());
666 if (!buffer.empty()) {