diff options
| author | Julian Hurst <ark@mansus.space> | 2025-03-10 02:41:31 +0100 |
|---|---|---|
| committer | Julian Hurst <ark@mansus.space> | 2025-03-10 02:41:31 +0100 |
| commit | 9b0fdeea0b7dd80e5d198b1e95b6ceb077153050 (patch) | |
| tree | 19e4dda136e52cf026e8aab9ba2f043cbaba4a6f | |
| parent | 741f56de2c1bd4bce52dd35bc921111284e995ab (diff) | |
| download | timer-9b0fdeea0b7dd80e5d198b1e95b6ceb077153050.tar.gz | |
Improve duration argument parsing
| -rw-r--r-- | timer.ha | 87 |
1 files changed, 71 insertions, 16 deletions
@@ -7,7 +7,7 @@ use strings; use strconv; use math; -type uniterror = !void; +type parseerror = !void; fn timer_handler(file: *ev::file) void = { const loop = ev::getloop(file); @@ -59,21 +59,61 @@ fn human_readable(duration: time::duration) str = { return fmt::asprintf("{%}:{%}:{%}", hours, mods, mins, mods, secs, mods); }; -fn parse_duration(duration: const str) (time::duration | uniterror | strconv::invalid | strconv::overflow) = { - const s = strings::toutf8(duration); - const unit = s[len(s)-1]; - const unit = switch (unit) { - case 's' => - yield time::SECOND; - case 'm' => - yield time::MINUTE; - case 'h' => - yield time::HOUR; - case => - return uniterror; +fn parse_duration(duration: const str) (time::duration | parseerror | strconv::invalid | strconv::overflow) = { + const spl = strings::split(duration, ":"); + defer free(spl); + if (len(spl) >= 4 || len(spl) < 1) { + return parseerror; }; - const d = strconv::stoi(strings::sub(duration, 0, len(duration) - 1))?; - return d * unit; + const hours = if (len(spl) == 3) { + yield strconv::stoi(spl[0])?; + } else { + yield 0; + }; + + const mins = if (len(spl) >= 2) { + yield strconv::stoi(spl[len(spl)-2])?; + } else { + yield 0; + }; + + const secs = strconv::stoi(spl[len(spl)-1])?; + + const hours = hours * time::HOUR; + const mins = mins * time::MINUTE; + const secs = secs * time::SECOND; + return hours + mins + secs; +}; + +fn parse_duration_hms(duration: const str) (time::duration | parseerror | strconv::invalid | strconv::overflow) = { + let start = 0z; + const hours = match (strings::index(duration, 'h')) { + case let i: size => + const s = strconv::stoi(strings::sub(duration, start, i))!; + start = i + 1; + yield s; + case void => + yield 0; + }; + const mins = match (strings::index(duration, 'm')) { + case let i: size => + const s = strconv::stoi(strings::sub(duration, start, i))!; + start = i + 1; + yield s; + case void => + yield 0; + }; + const secs = match (strings::index(duration, 's')) { + case let i: size => + fmt::error(start)!; + yield strconv::stoi(strings::sub(duration, start, i))!; + case void => + yield 0; + }; + const hours = hours * time::HOUR; + const mins = mins * time::MINUTE; + const secs = secs * time::SECOND; + return hours + mins + secs; }; export fn main() void = { @@ -89,7 +129,22 @@ export fn main() void = { }; const duration = cmd.args[0]; - const duration = parse_duration(duration)!; + + const f = if (strings::contains(duration, ':')) { + yield &parse_duration; + } else { + yield &parse_duration_hms; + }; + const duration = match (f(duration)) { + case let d: time::duration => + yield d; + case parseerror => + fmt::fatal("Error parsing the given duration"); + case let e: strconv::invalid => + fmt::fatal(strconv::strerror(e)); + case let e: strconv::overflow => + fmt::fatal(strconv::strerror(e)); + }; const loop = ev::newloop()!; |
