From 345957e2e6be6a9da92054eb4d4b67e44fa32405 Mon Sep 17 00:00:00 2001 From: Matthew Abruzzo Date: Wed, 18 Sep 2024 10:10:21 -0400 Subject: [PATCH] a few minor updates. --- src/grcli/args/EscapedArgsConfig.h | 2 +- src/grcli/cmd_bench.C | 2 +- src/grcli/operation.C | 99 +++++++++++++++++++++--------- src/grcli/operation.h | 6 ++ 4 files changed, 77 insertions(+), 32 deletions(-) diff --git a/src/grcli/args/EscapedArgsConfig.h b/src/grcli/args/EscapedArgsConfig.h index d43665d8..88eb547f 100644 --- a/src/grcli/args/EscapedArgsConfig.h +++ b/src/grcli/args/EscapedArgsConfig.h @@ -30,7 +30,7 @@ struct EscapedArgsSpec { } if (escaped == nullptr) { - std::fprintf(stderr, "the %s arg is missing an option\n"); + std::fprintf(stderr, "the %s arg is missing an option\n", leading_arg); std::exit(1); } fn(escaped); diff --git a/src/grcli/cmd_bench.C b/src/grcli/cmd_bench.C index 8c26f888..208c3ee2 100644 --- a/src/grcli/cmd_bench.C +++ b/src/grcli/cmd_bench.C @@ -84,7 +84,7 @@ } else { auto my_test = [&driver](benchmark::State& st) { driver(st); }; - benchmark::RegisterBenchmark("scenario", my_test); + benchmark::RegisterBenchmark(string_repr(op_spec.value()), my_test); // construct argv and argc // ToDo: there is probably a smarter way to do this without copying the diff --git a/src/grcli/operation.C b/src/grcli/operation.C index 024a2262..88804630 100644 --- a/src/grcli/operation.C +++ b/src/grcli/operation.C @@ -1,5 +1,7 @@ +#include #include #include +#include #include #include #include @@ -7,48 +9,85 @@ #include "operation.h" #include "utils.h" -static const std::regex flt_regex("^" FLT_PATTERN "$"); +namespace{ // anonymous namespace contents only visible in this file -bool try_parse_op_spec(const char* arg, std::optional& op_spec) -{ - if (!starts_with(arg, "-O")) return false; +struct OperationProps{ + OperationKind kind; + const char* name; + bool requires_dt; +}; - std::string_view arg_view(arg); +const OperationProps op_prop_list[] = { + {OperationKind::calc_cooling_time, "calc-cooling-time", false}, + {OperationKind::calc_dust_temperature, "calc-dust-temperature", false}, + {OperationKind::calc_pressure, "calc-pressure", false}, + {OperationKind::calc_temperature, "calc-temperature", false}, + {OperationKind::solve_chemistry, "solve-chemistry-dt=", true}, +}; - OperationKind kind; - double dt = -1.0; - if (arg_view == "-Ocalc-cooling-time") { - kind = OperationKind::calc_cooling_time; - } else if (arg_view == "-Ocalc-dust-temperature") { - kind = OperationKind::calc_dust_temperature; - } else if (arg_view == "-Ocalc-pressure") { - kind = OperationKind::calc_pressure; - } else if (arg_view == "-Ocalc-temperature") { - kind = OperationKind::calc_temperature; - } else if (starts_with(arg_view, "-Osolve-chemistry-dt=")) { - kind = OperationKind::solve_chemistry; - std::string dt_str = std::string(arg_view.substr(21)); - if (!std::regex_match(dt_str, flt_regex)) { - std::fprintf(stderr, - "problem parsing `%s`. Were you trying to specify " - "`-Osolve-chemistry-dt=`?\n", arg); - std::exit(1); +const std::regex flt_regex("^" FLT_PATTERN "$"); + +/// Convert the command line argument to an OperationSpec +/// +/// op_spec_str_view is simply a view of ``arg`` without the leading flag. +OperationSpec op_spec_from_arg_(const char* arg, + std::string_view op_spec_str_view) { + + + for (const OperationProps& op_prop : op_prop_list){ + if (op_prop.requires_dt && starts_with(op_spec_str_view, op_prop.name)){ + std::string dt_str = std::string( + op_spec_str_view.substr(std::strlen(op_prop.name)) + ); + if (!std::regex_match(dt_str, flt_regex)) { + std::fprintf(stderr, + "problem parsing `%s`. Were you trying to specify `-O%s`?\n", + arg, op_prop.name); + std::exit(1); + } + return {op_prop.kind, std::stod(dt_str)}; + } else if ((!op_prop.requires_dt) && op_spec_str_view == op_prop.name) { + return {op_prop.kind, -1.0}; } - dt = std::stod(dt_str); - } else { - std::fprintf( - stderr, "the `%s` argument corresponds to an unknown operations\n", - arg); - std::exit(1); } + // if we made it this far, then there is an error + std::fprintf( + stderr, "the `%s` argument corresponds to an unknown operations\n", + arg); + std::exit(1); +} + +} // anonymous namespace + + +bool try_parse_op_spec(const char* arg, std::optional& op_spec) +{ + if (!starts_with(arg, "-O")) return false; + std::string_view op_str_view(arg+2); + OperationSpec tmp = op_spec_from_arg_(arg, op_str_view); + if (op_spec.has_value()) { std::fprintf(stderr, "`%s` is the 2nd arg to specify an operation\n", arg); std::exit(1); } - std::optional rslt{OperationSpec{kind,dt}}; + std::optional rslt{tmp}; op_spec = rslt; return true; } + +std::string string_repr(const OperationSpec& op_spec) { + for (const OperationProps& op_prop : op_prop_list) { + if (op_prop.kind == op_spec.kind) { + if (!op_prop.requires_dt) return op_prop.name; + return op_prop.name + std::to_string(op_spec.dt); + } + } + GRCLI_ERROR( + "Something went wrong while converting an operation spec to a string. " + "Somehow we didn't recognize the OperationKind. Did we add a new one " + "recently and forget to update op_prop_list?" + ); +} diff --git a/src/grcli/operation.h b/src/grcli/operation.h index c0f721ae..36f1139c 100644 --- a/src/grcli/operation.h +++ b/src/grcli/operation.h @@ -24,4 +24,10 @@ struct OperationSpec { /// * Otherwise, this returns false bool try_parse_op_spec(const char* arg, std::optional& op_spec); +/// produce a string representation of the operation +/// +/// In the event that there is a timestep associated with the operation, it may +/// not be perfectly represented +std::string string_repr(const OperationSpec& spec); + #endif /* GRCLI_OPERATION_H */