38 kept.reserve(items.size());
39 for (std::size_t
i = 0;
i < items.size(); ++
i)
47 kept.push_back(std::move(items[
i]));
50 items = std::move(
kept);
58 if (!items.empty() ||
defaults.empty())
63 Log::Warn(
"settings: {} has no valid entries; using built-in defaults",
what);
85 Log::Warn(
"settings: {} has no valid entries; using built-in defaults",
what);
93 const std::vector<std::string>&
defaults, std::string_view
what)
98 [](
const std::string&
entry, std::size_t) -> std::optional<std::string> {
101 return std::format(
"bad duration '{}'",
entry);
static std::string Trim(std::string_view str)
void Warn(std::format_string< Args... > fmt, Args &&... args)
void NormalizeTag(std::string &value, std::size_t maxLen, std::string_view fallback, std::string_view what)
Declarative helpers for post-load config validation: skip bad entries with a warning instead of faili...
void FilterValid(std::vector< T > &items, std::invocable< const T &, std::size_t > auto &&validate, std::string_view what)
bool FallbackIfEmpty(std::vector< T > &items, const std::vector< T > &defaults, std::string_view what)
std::vector< int > ParseDurations(const std::vector< std::string > &entries, const std::vector< std::string > &defaults, std::string_view what)
int ParseDuration(std::string_view text)
static std::string ReadFile(const std::filesystem::path &path)