LCOV - code coverage report
Current view: top level - cli - cli_args.cpp (source / functions) Coverage Total Hit
Test: hashbrowns Coverage Lines: 28.4 % 190 54
Test Date: 2026-04-10 19:00:18 Functions: 100.0 % 2 2
Legend: Lines: hit not hit

            Line data    Source code
       1              : #include "cli_args.h"
       2              : 
       3              : #include <algorithm>
       4              : #include <cctype>
       5              : #include <unordered_set>
       6              : 
       7              : namespace hashbrowns {
       8              : namespace cli {
       9              : 
      10            2 : CliArgs parse_args(int argc, char* argv[]) {
      11            2 :     CliArgs a;
      12            4 :     static const std::unordered_set<std::string> kValidProfiles = {"smoke", "ci", "series", "crossover", "deep"};
      13              : 
      14              :     // --- Pre-scan for early-exit flags ---
      15           12 :     for (int i = 1; i < argc; ++i) {
      16           30 :         std::string arg = argv[i];
      17           10 :         if (arg == "--no-banner")
      18            0 :             a.no_banner = true;
      19           10 :         if (arg == "--quiet") {
      20            0 :             a.quiet     = true;
      21            0 :             a.no_banner = true;
      22              :         }
      23           10 :         if (arg == "--version") {
      24            0 :             a.version_only = true;
      25            0 :             a.no_banner    = true;
      26              :         }
      27           10 :     }
      28              : 
      29            2 :     if (a.version_only)
      30            0 :         return a;
      31              : 
      32              :     // --- Full parse ---
      33            7 :     for (int i = 1; i < argc; ++i) {
      34           15 :         std::string arg = argv[i];
      35              : 
      36            5 :         if (arg == "--help" || arg == "-h") {
      37            0 :             a.show_help = true;
      38            0 :             a.demo_mode = false;
      39            5 :         } else if (arg == "--version") {
      40            0 :             a.demo_mode = false;
      41            5 :         } else if (arg == "--wizard" || arg == "-wizard") {
      42            0 :             a.wizard_mode = true;
      43            0 :             a.demo_mode   = false;
      44            5 :         } else if (arg == "--size" && i + 1 < argc) {
      45            3 :             a.opt_size          = static_cast<std::size_t>(std::stoull(argv[++i]));
      46            1 :             a.opt_size_explicit = true;
      47            1 :             a.demo_mode         = false;
      48            4 :         } else if (arg == "--runs" && i + 1 < argc) {
      49            3 :             a.opt_runs          = std::stoi(argv[++i]);
      50            1 :             a.opt_runs_explicit = true;
      51            1 :             a.demo_mode         = false;
      52            3 :         } else if (arg == "--warmup" && i + 1 < argc) {
      53            0 :             a.opt_warmup          = std::stoi(argv[++i]);
      54            0 :             a.opt_warmup_explicit = true;
      55            0 :             a.demo_mode           = false;
      56            3 :         } else if (arg == "--bootstrap" && i + 1 < argc) {
      57            0 :             a.opt_bootstrap          = std::stoi(argv[++i]);
      58            0 :             a.opt_bootstrap_explicit = true;
      59            0 :             a.demo_mode              = false;
      60            3 :         } else if (arg == "--series-count" && i + 1 < argc) {
      61            0 :             a.opt_series_count          = std::stoi(argv[++i]);
      62            0 :             a.opt_series_count_explicit = true;
      63            0 :             a.demo_mode                 = false;
      64            3 :         } else if (arg == "--series-out" && i + 1 < argc) {
      65            0 :             a.opt_series_out          = std::string(argv[++i]);
      66            0 :             a.opt_series_out_explicit = true;
      67            0 :             a.demo_mode               = false;
      68            3 :         } else if (arg == "--series-sizes" && i + 1 < argc) {
      69            0 :             std::string list  = argv[++i];
      70            0 :             std::size_t start = 0, pos = 0;
      71            0 :             while ((pos = list.find(',', start)) != std::string::npos) {
      72            0 :                 auto tok = list.substr(start, pos - start);
      73            0 :                 if (!tok.empty())
      74            0 :                     a.opt_series_sizes.push_back(static_cast<std::size_t>(std::stoull(tok)));
      75            0 :                 start = pos + 1;
      76            0 :             }
      77            0 :             if (start < list.size())
      78            0 :                 a.opt_series_sizes.push_back(static_cast<std::size_t>(std::stoull(list.substr(start))));
      79            0 :             a.opt_series_sizes_explicit = true;
      80            0 :             a.demo_mode                 = false;
      81            3 :         } else if (arg == "--series-runs" && i + 1 < argc) {
      82            0 :             a.opt_series_runs          = std::stoi(argv[++i]);
      83            0 :             a.opt_series_runs_explicit = true;
      84            0 :             a.demo_mode                = false;
      85            3 :         } else if (arg == "--structures" && i + 1 < argc) {
      86            0 :             std::string list  = argv[++i];
      87            0 :             std::size_t start = 0, pos = 0;
      88            0 :             while ((pos = list.find(',', start)) != std::string::npos) {
      89            0 :                 a.opt_structures.push_back(list.substr(start, pos - start));
      90            0 :                 start = pos + 1;
      91              :             }
      92            0 :             if (start < list.size())
      93            0 :                 a.opt_structures.push_back(list.substr(start));
      94            0 :             a.opt_structures_explicit = true;
      95            0 :             a.demo_mode               = false;
      96            3 :         } else if (arg == "--output" && i + 1 < argc) {
      97            0 :             a.opt_output          = std::string(argv[++i]);
      98            0 :             a.opt_output_explicit = true;
      99            0 :             a.demo_mode           = false;
     100            3 :         } else if (arg == "--profile" && i + 1 < argc) {
     101            6 :             std::string profile = argv[++i];
     102            2 :             std::transform(profile.begin(), profile.end(), profile.begin(), [](unsigned char c) {
     103            4 :                 return static_cast<char>(std::tolower(c));
     104              :             });
     105            2 :             a.opt_profile = profile;
     106            2 :             a.opt_profile_valid = (kValidProfiles.find(profile) != kValidProfiles.end());
     107            2 :             a.demo_mode = false;
     108            3 :         } else if (arg == "--memory-tracking") {
     109            0 :             a.opt_memory_tracking          = true;
     110            0 :             a.opt_memory_tracking_explicit = true;
     111            0 :             a.demo_mode                    = false;
     112            1 :         } else if (arg == "--crossover-analysis") {
     113            0 :             a.opt_crossover          = true;
     114            0 :             a.opt_crossover_explicit = true;
     115            0 :             a.demo_mode              = false;
     116            1 :         } else if (arg == "--max-size" && i + 1 < argc) {
     117            0 :             a.opt_max_size          = static_cast<std::size_t>(std::stoull(argv[++i]));
     118            0 :             a.opt_max_size_explicit = true;
     119            0 :             a.demo_mode             = false;
     120            1 :         } else if (arg == "--pattern" && i + 1 < argc) {
     121            0 :             std::string p = argv[++i];
     122            0 :             if (p == "sequential")
     123            0 :                 a.opt_pattern = BenchmarkConfig::Pattern::SEQUENTIAL;
     124            0 :             else if (p == "random")
     125            0 :                 a.opt_pattern = BenchmarkConfig::Pattern::RANDOM;
     126            0 :             else if (p == "mixed")
     127            0 :                 a.opt_pattern = BenchmarkConfig::Pattern::MIXED;
     128            0 :             a.opt_pattern_explicit = true;
     129            0 :             a.demo_mode            = false;
     130            1 :         } else if (arg == "--seed" && i + 1 < argc) {
     131            0 :             a.opt_seed          = static_cast<unsigned long long>(std::stoull(argv[++i]));
     132            0 :             a.opt_seed_explicit = true;
     133            0 :             a.demo_mode         = false;
     134            1 :         } else if (arg == "--pin-cpu") {
     135            0 :             a.opt_pin_cpu          = true;
     136            0 :             a.opt_pin_cpu_explicit = true;
     137            0 :             if (i + 1 < argc) {
     138            0 :                 std::string maybe = argv[i + 1];
     139            0 :                 if (!maybe.empty() && std::all_of(maybe.begin(), maybe.end(), ::isdigit)) {
     140            0 :                     ++i;
     141            0 :                     a.opt_cpu_index          = std::stoi(maybe);
     142            0 :                     a.opt_cpu_index_explicit = true;
     143              :                 }
     144            0 :             }
     145            0 :             a.demo_mode = false;
     146            1 :         } else if (arg == "--no-turbo") {
     147            0 :             a.opt_no_turbo          = true;
     148            0 :             a.opt_no_turbo_explicit = true;
     149            0 :             a.demo_mode             = false;
     150            1 :         } else if (arg == "--max-seconds" && i + 1 < argc) {
     151            0 :             a.opt_max_seconds          = std::stod(argv[++i]);
     152            0 :             a.opt_max_seconds_explicit = true;
     153            0 :             a.demo_mode                = false;
     154            1 :         } else if (arg == "--out-format" && i + 1 < argc) {
     155            3 :             std::string f = argv[++i];
     156            1 :             a.opt_out_fmt             = (f == "json") ? BenchmarkConfig::OutputFormat::JSON : BenchmarkConfig::OutputFormat::CSV;
     157            1 :             a.opt_out_format_explicit = true;
     158            1 :             a.demo_mode               = false;
     159            1 :         } else if (arg == "--hash-strategy" && i + 1 < argc) {
     160            0 :             std::string s = argv[++i];
     161            0 :             if (s == "open")
     162            0 :                 a.opt_hash_strategy = HashStrategy::OPEN_ADDRESSING;
     163            0 :             else if (s == "chain")
     164            0 :                 a.opt_hash_strategy = HashStrategy::SEPARATE_CHAINING;
     165            0 :             a.opt_hash_strategy_explicit = true;
     166            0 :             a.demo_mode                  = false;
     167            0 :         } else if (arg == "--hash-capacity" && i + 1 < argc) {
     168            0 :             a.opt_hash_capacity          = static_cast<std::size_t>(std::stoull(argv[++i]));
     169            0 :             a.opt_hash_capacity_explicit = true;
     170            0 :             a.demo_mode                  = false;
     171            0 :         } else if (arg == "--hash-load" && i + 1 < argc) {
     172            0 :             a.opt_hash_load          = std::stod(argv[++i]);
     173            0 :             a.opt_hash_load_explicit = true;
     174            0 :             a.demo_mode              = false;
     175            0 :         } else if (arg == "--baseline" && i + 1 < argc) {
     176            0 :             a.opt_baseline_path = std::string(argv[++i]);
     177            0 :             a.demo_mode         = false;
     178            0 :         } else if (arg == "--baseline-report-json" && i + 1 < argc) {
     179            0 :             a.opt_baseline_report_json = std::string(argv[++i]);
     180            0 :             a.demo_mode                = false;
     181            0 :         } else if (arg == "--baseline-threshold" && i + 1 < argc) {
     182            0 :             a.opt_baseline_threshold = std::stod(argv[++i]);
     183            0 :             a.demo_mode              = false;
     184            0 :         } else if (arg == "--baseline-noise" && i + 1 < argc) {
     185            0 :             a.opt_baseline_noise = std::stod(argv[++i]);
     186            0 :             a.demo_mode          = false;
     187            0 :         } else if (arg == "--baseline-scope" && i + 1 < argc) {
     188            0 :             std::string s = argv[++i];
     189            0 :             if (s == "mean")
     190            0 :                 a.opt_baseline_scope = BaselineConfig::MetricScope::MEAN;
     191            0 :             else if (s == "p95")
     192            0 :                 a.opt_baseline_scope = BaselineConfig::MetricScope::P95;
     193            0 :             else if (s == "ci_high")
     194            0 :                 a.opt_baseline_scope = BaselineConfig::MetricScope::CI_HIGH;
     195            0 :             else if (s == "any")
     196            0 :                 a.opt_baseline_scope = BaselineConfig::MetricScope::ANY;
     197            0 :             a.demo_mode = false;
     198            0 :         } else if (arg == "--baseline-strict-profile-intent") {
     199            0 :             a.opt_baseline_strict_profile_intent = true;
     200            0 :             a.demo_mode                          = false;
     201            0 :         } else if (arg == "--op-tests") {
     202            0 :             a.opt_op_tests = true;
     203            0 :             a.demo_mode    = false;
     204            0 :         } else if (arg == "--no-banner" || arg == "--quiet") {
     205            0 :             a.demo_mode = false;
     206            0 :         } else if (arg.rfind("--", 0) == 0) {
     207            0 :             a.demo_mode = false;
     208              :         }
     209            5 :     }
     210              : 
     211            2 :     return a;
     212            0 : }
     213              : 
     214              : } // namespace cli
     215              : } // namespace hashbrowns
        

Generated by: LCOV version 2.0-1