From 8dc59e114c3c62083fb99c54a4b5f1b9c92de6c8 Mon Sep 17 00:00:00 2001 From: ge Date: Mon, 13 Jan 2025 20:34:25 +0300 Subject: [PATCH] add cmd/dataunit, example --- .gitignore | 2 +- cmd/dataunit/dataunit.v | 88 +++++++++++++++++++++++++++++++++++++++++ examples/parse_units.v | 36 +++++++++++++++++ 3 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 cmd/dataunit/dataunit.v create mode 100644 examples/parse_units.v diff --git a/.gitignore b/.gitignore index 21da90b..fe407aa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ # Binaries for programs and plugins main -dataunit +/dataunit *.exe *.exe~ *.so diff --git a/cmd/dataunit/dataunit.v b/cmd/dataunit/dataunit.v new file mode 100644 index 0000000..4454cfe --- /dev/null +++ b/cmd/dataunit/dataunit.v @@ -0,0 +1,88 @@ +// This is free and unencumbered software released into the public domain. + +// Anyone is free to copy, modify, publish, use, compile, sell, or +// distribute this software, either in source code form or as a compiled +// binary, for any purpose, commercial or non-commercial, and by any +// means. + +// In jurisdictions that recognize copyright laws, the author or authors +// of this software dedicate any and all copyright interest in the +// software to the public domain. We make this dedication for the benefit +// of the public at large and to the detriment of our heirs and +// successors. We intend this dedication to be an overt act of +// relinquishment in perpetuity of all present and future rights to this +// software under copyright law. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +// For more information, please refer to + +/* + dataunit - a simple CLI tool for data units convertion. +*/ + +module main + +import os +import flag +import dataunits + +@[name: 'dataunit'] +struct FlagConfig { + help bool + from string @[short: f] + to string @[short: t] +mut: + value f64 @[ignore] +} + +fn main() { + mut flags, no_matches := flag.to_struct[FlagConfig](os.args, skip: 1, style: .v) or { + eprintln('cmdline parsing error, see -help for info') + exit(2) + } + if no_matches.len > 1 { + eprintln('unrecognized arguments: ${no_matches[1..]}') + exit(2) + } else if no_matches.len == 1 { + flags.value = no_matches[0].f64() + } + if flags.help { + println('convert the value between data size units.') + println('usage: dataunit -f -t ') + println('options:') + println(' -help print this help message and exit') + println(' -f, -from source data unit') + println(' -t, -to destination data unit') + exit(0) + } + if flags.from == '' || flags.to == '' { + eprintln('no -from or -to flag set, see -help for info') + exit(2) + } + if flags.value == 0 { + eprintln('no value passed, see -help for info') + exit(2) + } + src := dataunits.from_string(flags.from, case_insensitive: true) or { + eprintln('invalid source unit: ${err}') + exit(1) + } + dst := dataunits.from_string(flags.to, case_insensitive: true) or { + eprintln('invalid destination unit: ${err}') + exit(1) + } + result := '${dataunits.convert(flags.value, src, dst):.20f}' + splitted := result.split('.') + if splitted[1].contains_only('0') { + println(splitted[0]) + } else { + println(result.trim_right('0')) + } +} diff --git a/examples/parse_units.v b/examples/parse_units.v new file mode 100644 index 0000000..714cf3d --- /dev/null +++ b/examples/parse_units.v @@ -0,0 +1,36 @@ +import os +import regex +import dataunits + +struct Memory { + value f64 + unit dataunits.DataSize +} + +fn (m Memory) str() string { + return '${m.value} ${dataunits.to_string(m.unit) or { '' }}' +} + +fn (m Memory) mib() f64 { + return dataunits.convert(m.value, m.unit, dataunits.mib) +} + +fn Memory.from_string(s string) !Memory { + mut re := regex.regex_opt(r'^(\d+)([a-zA-Z]+)$')! + re.match_string(s) + if re.groups.len < 2 { + return error('unable to parse string ${s}') + } + value := re.get_group_by_id(s, 0).f64() + unit := dataunits.from_string(re.get_group_by_id(s, 1))! + return Memory{value, unit} +} + +fn main() { + mem := Memory.from_string(os.input('Enter memory value (e.g. 10Gi): ')) or { + eprintln('Error: ${err}') + exit(1) + } + println('Input: ${mem}') + println('Memory size: ${mem.mib()} MiB') +}