From a19c28924d28f3633727bf86f92a0aaeb9ed7692 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 20 Dec 2025 15:11:51 +0000 Subject: Add utility for parsing an ISO like duration --- src/util.hpp | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'src') diff --git a/src/util.hpp b/src/util.hpp index ad55604..8f2a585 100644 --- a/src/util.hpp +++ b/src/util.hpp @@ -1,6 +1,8 @@ #pragma once +#include #include +#include #include namespace WebStat { @@ -31,4 +33,46 @@ namespace WebStat { { (cmd->bindParam(firstParam++, std::forward(param)), ...); } + + namespace detail { + template + void + add(std::chrono::duration & subtotal, Rep value) + { + if constexpr (requires { subtotal += AddPeriod {value}; }) { + subtotal += AddPeriod {value}; + } + } + } + + template + std::chrono::duration + parseDuration(std::string_view input) + { + static constexpr std::initializer_list< + std::pair & subtotal, Rep value), std::string_view>> + DURATION_UNITS { + {detail::add, "ms"}, + {detail::add, "s"}, + {detail::add, "m"}, + {detail::add, "h"}, + {detail::add, "d"}, + {detail::add, "w"}, + }; + + std::chrono::duration out {}; + auto inputSubRange = scn::ranges::subrange {input}; + + while (auto result = scn::scan(inputSubRange, "{}{:[a-z]}")) { + const auto & [count, chars] = result->values(); + if (auto unit = std::ranges::find( + DURATION_UNITS, chars, &std::decay_t::second); + unit != DURATION_UNITS.end()) { + unit->first(out, count); + } + inputSubRange = result->range(); + } + + return out; + } } -- cgit v1.2.3