1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
#pragma once
#include <chrono>
#include <command.h>
#include <scn/scan.h>
#include <tuple>
namespace WebStat {
template<auto Deleter> struct DeleteWith {
auto
operator()(auto obj)
{
return Deleter(obj);
}
};
template<typename... T>
auto
visit(auto && visitor, const std::tuple<T...> & values)
{
std::apply(
[&](auto &&... value) {
(visitor(value), ...);
},
values);
}
using FilePtr = std::unique_ptr<std::FILE, DeleteWith<&fclose>>;
template<typename... T>
void
bindMany(const DB::CommandPtr & cmd, unsigned int firstParam, T &&... param)
{
(cmd->bindParam(firstParam++, std::forward<T>(param)), ...);
}
namespace detail {
template<typename Rep, typename Period, typename AddPeriod>
void
add(std::chrono::duration<Rep, Period> & subtotal, Rep value)
{
if constexpr (requires { subtotal += AddPeriod {value}; }) {
subtotal += AddPeriod {value};
}
}
}
template<typename Rep, typename Period>
std::chrono::duration<Rep, Period>
parseDuration(std::string_view input)
{
static constexpr std::initializer_list<
std::pair<void (*)(std::chrono::duration<Rep, Period> & subtotal, Rep value), std::string_view>>
DURATION_UNITS {
{detail::add<Rep, Period, std::chrono::milliseconds>, "ms"},
{detail::add<Rep, Period, std::chrono::seconds>, "s"},
{detail::add<Rep, Period, std::chrono::minutes>, "m"},
{detail::add<Rep, Period, std::chrono::hours>, "h"},
{detail::add<Rep, Period, std::chrono::days>, "d"},
{detail::add<Rep, Period, std::chrono::weeks>, "w"},
};
std::chrono::duration<Rep, Period> out {};
auto inputSubRange = scn::ranges::subrange {input};
while (auto result = scn::scan<Rep, std::string>(inputSubRange, "{}{:[a-z]}")) {
const auto & [count, chars] = result->values();
if (auto unit = std::ranges::find(
DURATION_UNITS, chars, &std::decay_t<decltype(*DURATION_UNITS.begin())>::second);
unit != DURATION_UNITS.end()) {
unit->first(out, count);
}
inputSubRange = result->range();
}
return out;
}
}
|