diff --git a/2019/CMakeLists.txt b/2019/CMakeLists.txt index d321718..f09fe54 100644 --- a/2019/CMakeLists.txt +++ b/2019/CMakeLists.txt @@ -2,9 +2,11 @@ cmake_minimum_required(VERSION 3.15) project(aoc2019) +find_package(Boost REQUIRED COMPONENTS program_options) + add_library(AoCSolutions src/solutions.hpp src/solutions.cpp src/day01.cpp) target_compile_features(AoCSolutions PUBLIC cxx_std_17) add_executable(runner src/runner.cpp) target_compile_features(runner PUBLIC cxx_std_17) -target_link_libraries(runner AoCSolutions) +target_link_libraries(runner AoCSolutions Boost::program_options) diff --git a/2019/src/runner.cpp b/2019/src/runner.cpp index 30543fd..e07fb05 100644 --- a/2019/src/runner.cpp +++ b/2019/src/runner.cpp @@ -1,34 +1,48 @@ #include "solutions.hpp" #include -#include -#include +#include -template -Int int_from_cstr(Int &value, const char *begin) { - const char *end = begin + std::strlen(begin); - auto result = std::from_chars(begin, end, value, Radix); - if (result.ec != std::errc()) { - throw std::invalid_argument("Unparseable integer"); - } +namespace po = boost::program_options; - return value; +struct AoCOptions { + int day; + bool part2; +}; + +AoCOptions parse_options(const int argc, const char* argv[]) { + AoCOptions options{}; + po::options_description desc("Allowed options"); + desc.add_options() + ("day", po::value(&options.day)->required(), "The day to run.") + ("part2,2", po::bool_switch(&options.part2), "Whether to run part 2."); + + po::positional_options_description positionals; + positionals.add("day", 1); + + po::variables_map vm; + + po::store(po::command_line_parser(argc, argv).options(desc).positional(positionals).run(), vm); + po::notify(vm); + + return options; } int main(int argc, const char *argv[]) { - if (argc < 2) { - std::cerr << "Specify a day to run.\n"; + try { + const auto options = parse_options(argc, argv); + + const aoc2019::solution_t solution = aoc2019::get_implementation(options.day, options.part2); + if (solution != nullptr) { + solution(std::cin, std::cout); + return 0; + } else { + std::cerr << "Unimplemented.\n"; + return 1; + } + } catch (po::required_option &ignored) { return 1; - } - - int day; - int_from_cstr(day, argv[1]); - - const aoc2019::solution_t solution = aoc2019::get_implementation(day); - if (solution != nullptr) { - solution(std::cin, std::cout); - return 0; - } else { - std::cerr << "Unimplemented.\n"; + } catch (std::out_of_range &ignored) { + std::cerr << "Invalid day.\n"; return 1; } }