Loading...
Searching...
No Matches
ParseDuration.hpp
1#pragma once
2#include <Process/TimeValue.hpp>
3
4#include <QString>
5#include <QStringList>
6
7#include <cmath>
8#include <optional>
9
10namespace JS
11{
18inline std::optional<TimeVal> parseDuration(const QString& text)
19{
20 const QString s = text.trimmed();
21 if(s.isEmpty())
22 return std::nullopt;
23
24 // llround is undefined past the int64 range
25 const auto fromFlicks = [](double flicks) -> std::optional<TimeVal> {
26 if(!(flicks >= 0. && flicks < 0x1p63))
27 return std::nullopt;
28 return TimeVal{int64_t(std::llround(flicks))};
29 };
30 const auto fromSeconds = [&](double sec) {
31 return fromFlicks(sec * ossia::flicks_per_second<double>);
32 };
33
34 bool ok = false;
35 if(const double flicks = s.toDouble(&ok); ok)
36 return fromFlicks(flicks);
37
38 static constexpr struct
39 {
40 const char* suffix;
41 double seconds;
42 } units[] = {{"ms", 1e-3}, {"min", 60.}, {"s", 1.}, {"h", 3600.}};
43 for(const auto& u : units)
44 {
45 if(s.endsWith(QLatin1String(u.suffix), Qt::CaseInsensitive))
46 {
47 const double v = s.chopped(qsizetype(strlen(u.suffix))).trimmed().toDouble(&ok);
48 return ok ? fromSeconds(v * u.seconds) : std::nullopt;
49 }
50 }
51
52 const QStringList parts = s.split(QLatin1Char(':'));
53 if(parts.size() < 2 || parts.size() > 3)
54 return std::nullopt;
55 double sec = 0.;
56 for(qsizetype i = 0; i < parts.size(); ++i)
57 {
58 const bool last = i == parts.size() - 1;
59 const double v = last ? parts[i].toDouble(&ok) : double(parts[i].toUInt(&ok));
60 if(!ok || v < 0. || (i > 0 && v >= 60.))
61 return std::nullopt;
62 sec = sec * 60. + v;
63 }
64 return fromSeconds(sec);
65}
66}
STL namespace.
Definition TimeValue.hpp:21