in utils/src/utils/Cron.cpp [374:457]
std::unique_ptr<CronField> parseCronField(const std::string& field_str) {
try {
if (field_str == "*") {
return std::make_unique<AllValuesField>();
}
if (field_str == "?") {
return std::make_unique<NotCheckedField>();
}
if (field_str == "L") {
if constexpr (std::is_same<day, FieldType>())
return std::make_unique<LastNthDayInMonthField>(days(0));
if constexpr (std::is_same<weekday, FieldType>())
return std::make_unique<SingleValueField<weekday>>(Saturday);
throw BadCronExpression("L can only be used in the Day of month/Day of week fields");
}
if (field_str == "LW") {
if constexpr (!std::is_same<day, FieldType>())
throw BadCronExpression("LW can only be used in the Day of month field");
return std::make_unique<LastWeekDayField>();
}
if (field_str.find('#') != std::string::npos) {
if constexpr (!std::is_same<weekday, FieldType>())
throw BadCronExpression("# can only be used in the Day of week field");
auto operands = string::split(field_str, "#");
if (operands.size() != 2)
throw BadCronExpression("Invalid field " + field_str);
if (auto second_operand = fromChars<uint8_t>(operands[1]))
return std::make_unique<NthWeekdayField>(parse<weekday>(operands[0]), *second_operand);
}
if (field_str.find('-') != std::string::npos) {
auto operands = string::split(field_str, "-");
if (operands.size() != 2)
throw BadCronExpression("Invalid field " + field_str);
if (operands[0] == "L") {
if constexpr (std::is_same<day, FieldType>())
return std::make_unique<LastNthDayInMonthField>(parse<days>(operands[1]));
}
return std::make_unique<RangeField<FieldType>>(parse<FieldType>(operands[0]), parse<FieldType>(operands[1]));
}
if (field_str.ends_with('L')) {
if constexpr (!std::is_same<weekday, FieldType>())
throw BadCronExpression("<X>L can only be used in the Day of week field");
auto prefix = field_str.substr(0, field_str.size()-1);
return std::make_unique<LastSpecificDayOfTheWeekOfTheMonth>(parse<weekday>(prefix));
}
if (field_str.find('/') != std::string::npos) {
auto operands = string::split(field_str, "/");
if (operands.size() != 2)
throw BadCronExpression("Invalid field " + field_str);
if (operands[0] == "*")
operands[0] = "0";
if (auto second_operand = fromChars<int>(operands[1]))
return std::make_unique<IncrementField<FieldType>>(parse<FieldType>(operands[0]), *second_operand);
}
if (field_str.find(',') != std::string::npos) {
auto operands_str = string::split(field_str, ",");
std::vector<FieldType> operands;
std::transform(operands_str.begin(), operands_str.end(), std::back_inserter(operands), parse<FieldType>);
return std::make_unique<ListField<FieldType>>(std::move(operands));
}
if (field_str.ends_with('W')) {
if constexpr (!std::is_same<day, FieldType>())
throw BadCronExpression("W can only be used in the Day of month field");
auto operands_str = string::split(field_str, "W");
if (operands_str.size() != 2)
throw BadCronExpression("Invalid field " + field_str);
return std::make_unique<ClosestWeekdayToTheNthDayOfTheMonth>(parse<day>(operands_str[0]));
}
return std::make_unique<SingleValueField<FieldType>>(parse<FieldType>(field_str));
} catch (const std::exception& e) {
throw BadCronExpression("Couldn't parse cron field: " + field_str + " " + e.what());
}
}