449 static std::vector<FormatInstruction>
compile(
450 const std::string& pattern,
453 std::vector<FormatInstruction> instructions;
455 buffer.reserve(pattern.size());
456 bool strip_ansi =
false;
458 for (
size_t i = 0; i < pattern.size(); ++i) {
462 if (!buffer.empty()) {
468 bool left_align =
false;
469 bool center_align =
false;
470 bool truncate =
false;
474 while ((i + 1) < pattern.size() && (
475 std::isdigit(pattern[i + 1]) ||
476 pattern[i + 1] ==
'-' ||
477 pattern[i + 1] ==
'=')) {
478 char next = pattern[++i];
481 }
else if (next ==
'=') {
483 }
else if (std::isdigit(next)) {
484 width = width * 10 + (next -
'0');
488 if ((i + 1) < pattern.size() && pattern[i + 1] ==
'!') {
495 if ((i + 1) < pattern.size()) {
496 char next = pattern[++i];
500 instructions.emplace_back(context, FormatType::Year, width, left_align, center_align, truncate, strip_ansi);
503 if ((i + 1) < pattern.size() && pattern[i + 1] ==
's') {
504 instructions.emplace_back(context, FormatType::MilliSecondTimeStamp, width, left_align, center_align, truncate, strip_ansi);
508 instructions.emplace_back(context, FormatType::Month, width, left_align, center_align, truncate, strip_ansi);
511 instructions.emplace_back(context, FormatType::Day, width, left_align, center_align, truncate, strip_ansi);
514 instructions.emplace_back(context, FormatType::Hour, width, left_align, center_align, truncate, strip_ansi);
517 instructions.emplace_back(context, FormatType::Minute, width, left_align, center_align, truncate, strip_ansi);
520 if ((i + 1) < pattern.size() && pattern[i + 1] ==
'C') {
525 instructions.emplace_back(context, FormatType::Second, width, left_align, center_align, truncate, strip_ansi);
528 if ((i + 1) < pattern.size() && pattern[i + 1] ==
'c') {
533 instructions.emplace_back(context, FormatType::Millisecond, width, left_align, center_align, truncate, strip_ansi);
536 instructions.emplace_back(context, FormatType::TwoDigitYear, width, left_align, center_align, truncate, strip_ansi);
539 instructions.emplace_back(context, FormatType::DateTime, width, left_align, center_align, truncate, strip_ansi);
542 instructions.emplace_back(context, FormatType::ShortDate, width, left_align, center_align, truncate, strip_ansi);
546 instructions.emplace_back(context, FormatType::TimeISO8601, width, left_align, center_align, truncate, strip_ansi);
549 instructions.emplace_back(context, FormatType::DateISO8601, width, left_align, center_align, truncate, strip_ansi);
552 if ((i + 1) < pattern.size() && pattern[i + 1] ==
'c') {
557 instructions.emplace_back(context, FormatType::TimeStamp, width, left_align, center_align, truncate, strip_ansi);
561 if ((i + 1) < pattern.size() && pattern[i + 1] ==
'C') {
566 instructions.emplace_back(context, FormatType::TimeStamp, width, left_align, center_align, truncate, strip_ansi);
570 if ((i + 1) < pattern.size() && pattern[i + 1] ==
's') {
571 instructions.emplace_back(context, FormatType::FileName, width, left_align, center_align, truncate, strip_ansi);
575 instructions.emplace_back(context, FormatType::AbbreviatedMonthName, width, left_align, center_align, truncate, strip_ansi);
578 instructions.emplace_back(context, FormatType::FullMonthName, width, left_align, center_align, truncate, strip_ansi);
581 instructions.emplace_back(context, FormatType::AbbreviatedWeekdayName, width, left_align, center_align, truncate, strip_ansi);
584 instructions.emplace_back(context, FormatType::FullWeekdayName, width, left_align, center_align, truncate, strip_ansi);
589 instructions.emplace_back(context, FormatType::LogLevel, width, left_align, center_align, truncate, strip_ansi);
592 instructions.emplace_back(context, FormatType::ShortLogLevel, width, left_align, center_align, truncate, strip_ansi);
597 instructions.emplace_back(context, FormatType::ThreadId, width, left_align, center_align, truncate, strip_ansi);
602 if ((i + 1) < pattern.size() && pattern[i + 1] ==
'f' && (i + 2) < pattern.size() && pattern[i + 2] ==
'n') {
603 instructions.emplace_back(context, FormatType::FullFileName, width, left_align, center_align, truncate, strip_ansi);
607 if ((i + 1) < pattern.size() && pattern[i + 1] ==
'n') {
608 instructions.emplace_back(context, FormatType::FileName, width, left_align, center_align, truncate, strip_ansi);
612 instructions.emplace_back(context, FormatType::FileName, width, left_align, center_align, truncate, strip_ansi);
615 instructions.emplace_back(context, FormatType::FullFileName, width, left_align, center_align, truncate, strip_ansi);
618 instructions.emplace_back(context, FormatType::SourceFileAndLine, width, left_align, center_align, truncate, strip_ansi);
621 instructions.emplace_back(context, FormatType::LineNumber, width, left_align, center_align, truncate, strip_ansi);
624 instructions.emplace_back(context, FormatType::FunctionName, width, left_align, center_align, truncate, strip_ansi);
629 instructions.emplace_back(context, FormatType::StartColor, 0,
false,
false,
false, strip_ansi);
632 instructions.emplace_back(context, FormatType::EndColor, 0,
false,
false,
false, strip_ansi);
637 instructions.emplace_back(context, FormatType::Message, width, left_align, center_align, truncate, strip_ansi);
642 if ((i + 2) < pattern.size() && pattern[i + 1] ==
'(') {
643 size_t end = pattern.find(
')', i + 2);
644 if (end == std::string::npos) {
648 std::string params = pattern.substr(i + 2, end - i - 2);
649 auto no_args_instructions =
compile(params, CompileContext::NoArgsFallback);
650 instructions.insert(instructions.end(), no_args_instructions.begin(), no_args_instructions.end());
667 if (!buffer.empty()) {