446 static std::vector<FormatInstruction>
compile(
447 const std::string& pattern,
450 std::vector<FormatInstruction> instructions;
452 buffer.reserve(pattern.size());
453 bool strip_ansi =
false;
455 for (
size_t i = 0; i < pattern.size(); ++i) {
459 if (!buffer.empty()) {
465 bool left_align =
false;
466 bool center_align =
false;
467 bool truncate =
false;
471 while ((i + 1) < pattern.size() && (
472 std::isdigit(pattern[i + 1]) ||
473 pattern[i + 1] ==
'-' ||
474 pattern[i + 1] ==
'=')) {
475 char next = pattern[++i];
478 }
else if (next ==
'=') {
480 }
else if (std::isdigit(next)) {
481 width = width * 10 + (next -
'0');
485 if ((i + 1) < pattern.size() && pattern[i + 1] ==
'!') {
492 if ((i + 1) < pattern.size()) {
493 char next = pattern[++i];
497 instructions.emplace_back(context, FormatType::Year, width, left_align, center_align, truncate, strip_ansi);
500 if ((i + 1) < pattern.size() && pattern[i + 1] ==
's') {
501 instructions.emplace_back(context, FormatType::MilliSecondTimeStamp, width, left_align, center_align, truncate, strip_ansi);
505 instructions.emplace_back(context, FormatType::Month, width, left_align, center_align, truncate, strip_ansi);
508 instructions.emplace_back(context, FormatType::Day, width, left_align, center_align, truncate, strip_ansi);
511 instructions.emplace_back(context, FormatType::Hour, width, left_align, center_align, truncate, strip_ansi);
514 instructions.emplace_back(context, FormatType::Minute, width, left_align, center_align, truncate, strip_ansi);
517 if ((i + 1) < pattern.size() && pattern[i + 1] ==
'C') {
522 instructions.emplace_back(context, FormatType::Second, width, left_align, center_align, truncate, strip_ansi);
525 if ((i + 1) < pattern.size() && pattern[i + 1] ==
'c') {
530 instructions.emplace_back(context, FormatType::Millisecond, width, left_align, center_align, truncate, strip_ansi);
533 instructions.emplace_back(context, FormatType::TwoDigitYear, width, left_align, center_align, truncate, strip_ansi);
536 instructions.emplace_back(context, FormatType::DateTime, width, left_align, center_align, truncate, strip_ansi);
539 instructions.emplace_back(context, FormatType::ShortDate, width, left_align, center_align, truncate, strip_ansi);
543 instructions.emplace_back(context, FormatType::TimeISO8601, width, left_align, center_align, truncate, strip_ansi);
546 instructions.emplace_back(context, FormatType::DateISO8601, width, left_align, center_align, truncate, strip_ansi);
549 if ((i + 1) < pattern.size() && pattern[i + 1] ==
'c') {
555 if ((i + 1) < pattern.size() && pattern[i + 1] ==
'C') {
560 instructions.emplace_back(context, FormatType::TimeStamp, width, left_align, center_align, truncate, strip_ansi);
565 if ((i + 1) < pattern.size() && pattern[i + 1] ==
's') {
566 instructions.emplace_back(context, FormatType::FileName, width, left_align, center_align, truncate, strip_ansi);
570 instructions.emplace_back(context, FormatType::AbbreviatedMonthName, width, left_align, center_align, truncate, strip_ansi);
573 instructions.emplace_back(context, FormatType::FullMonthName, width, left_align, center_align, truncate, strip_ansi);
576 instructions.emplace_back(context, FormatType::AbbreviatedWeekdayName, width, left_align, center_align, truncate, strip_ansi);
579 instructions.emplace_back(context, FormatType::FullWeekdayName, width, left_align, center_align, truncate, strip_ansi);
584 instructions.emplace_back(context, FormatType::LogLevel, width, left_align, center_align, truncate, strip_ansi);
587 instructions.emplace_back(context, FormatType::ShortLogLevel, width, left_align, center_align, truncate, strip_ansi);
592 instructions.emplace_back(context, FormatType::ThreadId, width, left_align, center_align, truncate, strip_ansi);
597 if ((i + 1) < pattern.size() && pattern[i + 1] ==
'f' && (i + 2) < pattern.size() && pattern[i + 2] ==
'n') {
598 instructions.emplace_back(context, FormatType::FullFileName, width, left_align, center_align, truncate, strip_ansi);
602 if ((i + 1) < pattern.size() && pattern[i + 1] ==
'n') {
603 instructions.emplace_back(context, FormatType::FileName, width, left_align, center_align, truncate, strip_ansi);
607 instructions.emplace_back(context, FormatType::FileName, width, left_align, center_align, truncate, strip_ansi);
610 instructions.emplace_back(context, FormatType::FullFileName, width, left_align, center_align, truncate, strip_ansi);
613 instructions.emplace_back(context, FormatType::SourceFileAndLine, width, left_align, center_align, truncate, strip_ansi);
616 instructions.emplace_back(context, FormatType::LineNumber, width, left_align, center_align, truncate, strip_ansi);
619 instructions.emplace_back(context, FormatType::FunctionName, width, left_align, center_align, truncate, strip_ansi);
624 instructions.emplace_back(context, FormatType::StartColor, 0,
false,
false,
false, strip_ansi);
627 instructions.emplace_back(context, FormatType::EndColor, 0,
false,
false,
false, strip_ansi);
632 instructions.emplace_back(context, FormatType::Message, width, left_align, center_align, truncate, strip_ansi);
637 if ((i + 2) < pattern.size() && pattern[i + 1] ==
'(') {
638 size_t end = pattern.find(
')', i + 2);
639 if (end == std::string::npos) {
643 std::string params = pattern.substr(i + 2, end - i - 2);
644 auto no_args_instructions =
compile(params, CompileContext::NoArgsFallback);
645 instructions.insert(instructions.end(), no_args_instructions.begin(), no_args_instructions.end());
662 if (!buffer.empty()) {