Repository: google/benchmark
File: src/benchmark_runner.cc (C++)

Code before:
    return ret;
  }

  std::string min_time_str;
  if (value.back() != 's') {
    BM_VLOG(2) << "Value passed to --benchmark_min_time should have a suffix. "
                  "Eg., `30s` for 30-seconds.";
    min_time_str = value;
  } else {
    min_time_str = value.substr(0, value.length() - 1);
  }
  double min_time = std::atof(min_time_str.c_str());

  BM_CHECK(min_time > 0 &&
           !(min_time == 0 && (min_time_str != "0" || min_time_str != "0.0")))
      << "Malformed seconds value passed to --benchmark_min_time: `" << value
      << "`. Expected --benchmark_min_time=<float>x.";

  ret.tag = BenchTimeType::TIME;
  ret.time = min_time;

  return ret;
}

double GetMinTime(const benchmark::internal::BenchmarkInstance& b) {
  if (!IsZero(b.min_time())) return b.min_time();
  BenchTimeType iters_or_time = ParseBenchMinTime(FLAGS_benchmark_min_time);
  // If the flag was used to specify number of iters, then return 0 for time.
  if (iters_or_time.tag == BenchTimeType::ITERS) return 0;

  return iters_or_time.time;
}

bool BenchMinTimeHasIters() {
  return !FLAGS_benchmark_min_time.empty() &&
         FLAGS_benchmark_min_time.back() == 'x';
}

IterationCount GetIters(const benchmark::internal::BenchmarkInstance& b) {
  if (b.iterations() != 0) return b.iterations();

  // We've already checked that this flag is currently used to pass
  // iters but do a sanity check anyway.
  BenchTimeType parsed = ParseBenchMinTime(FLAGS_benchmark_min_time);
  assert(parsed.tag == BenchTimeType::ITERS);
  return parsed.iters;
}

}  // end namespace

BenchmarkRunner::BenchmarkRunner(

Review comment (refactor):
so here we accept 0 is an invalid value for time, but we accept it as a valid time on the command line.  maybe we can simplify your error checks by just not allowing 0 as a valid minimum time.

Code after:
  if (value.empty()) {
    ret.tag = BenchTimeType::TIME;
    ret.time = 0.0;
    return ret;
  }

  if (value.back() == 'x') {
    const char* iters_str = value.c_str();
    char* p_end;
    // Reset errno before it's changed by strtol.
    errno = 0;
    IterationCount num_iters = std::strtol(iters_str, &p_end, 10);

    // After a valid parse, p_end should have been set to
    // point to the 'x' suffix.
    BM_CHECK(errno == 0 && p_end != nullptr && *p_end == 'x')
        << "Malformed iters value passed to --benchmark_min_time: `" << value
        << "`. Expected --benchmark_min_time=<integer>x.";

    ret.tag = BenchTimeType::ITERS;
    ret.iters = num_iters;
    return ret;
  }

  const char* time_str = value.c_str();
  bool has_suffix = value.back() == 's';
  if (!has_suffix) {
    BM_VLOG(0) << "Value passed to --benchmark_min_time should have a suffix. "
                  "Eg., `30s` for 30-seconds.";
  }

  char* p_end;
  // Reset errno before it's changed by strtod.
  errno = 0;
  double min_time = std::strtod(time_str, &p_end);

  // After a successfull parse, p_end should point to the suffix 's'
  // or the end of the string, if the suffix was omitted.
  BM_CHECK(errno == 0 && p_end != nullptr &&
           (has_suffix && *p_end == 's' || *p_end == '\0'))
      << "Malformed seconds value passed to --benchmark_min_time: `" << value
      << "`. Expected --benchmark_min_time=<float>x.";

  ret.tag = BenchTimeType::TIME;
  ret.time = min_time;

  return ret;
}

BenchmarkRunner::BenchmarkRunner(
    const benchmark::internal::BenchmarkInstance& b_,