#pragma once #include #include #include #include #include constexpr auto all = std::numeric_limits::max(); namespace math { template [[maybe_unused]] constexpr auto is_between(decltype(lb) x) -> bool { return (ub > x) && (x > lb); } template [[maybe_unused]] constexpr auto is_larger(decltype(lb) x) -> bool { return (x > lb); } template [[maybe_unused]] constexpr auto is_smaller(decltype(ub) x) -> bool { return (ub > x); } template [[maybe_unused]] auto numerical_suffix(T value) -> std::string { std::string suffixes[4] = {"th", "st", "nd", "rd"}; value %= 100; if (math::is_between<11,13>(value)) return "th"; value %= 10; if (math::is_larger<3>(value)) return "th"; return suffixes[value % 4]; } } struct ip_validator { bool operator()(const std::string& addr) const { return net::getaddrinfo(addr, "0") != nullptr; }}; template [[maybe_unused]] T get_input(const std::string& prompt, const std::string& on_error, std::function validator) noexcept { T user_input{}; try { while (true) { printf("%s", prompt.c_str()); std::cin >> user_input; if (std::cin.fail() || !validator(user_input)) { std::cout << on_error << std::endl; std::cin.clear(); std::cin.ignore(all, '\n'); continue; } break; } return user_input; } catch (std::exception&) { return user_input; } /* This should not happen ..... cin/cout are not configured to throw...*/ } struct always_true_validator { template bool operator()(T) const { return true; }}; template [[maybe_unused]] T get_input(const std::string& prompt) { return get_input(prompt, "", always_true_validator()); }