108 lines
2.5 KiB
C++
108 lines
2.5 KiB
C++
#ifndef AOC_UTILS_HPP
|
|
#define AOC_UTILS_HPP
|
|
|
|
#include <type_traits>
|
|
#include <cstddef>
|
|
#include <limits>
|
|
#include <numbers>
|
|
#include <memory>
|
|
#include <system_error>
|
|
#include <expected>
|
|
#include <fstream>
|
|
#include <ranges>
|
|
#include <vector>
|
|
#include <string>
|
|
|
|
#include "aoc/types.hpp"
|
|
|
|
namespace aoc {
|
|
template <typename T>
|
|
concept Integral = std::is_integral<T>::value;
|
|
|
|
// Aliases
|
|
namespace nums = std::numbers;
|
|
|
|
template <typename T>
|
|
using lim = std::numeric_limits<T>;
|
|
|
|
inline constexpr auto pi = std::numbers::pi;
|
|
|
|
template <typename T>
|
|
inline constexpr auto pi_v = std::numbers::pi_v<T>;
|
|
|
|
struct error {
|
|
std::string msg;
|
|
std::error_code err;
|
|
};
|
|
|
|
inline auto make_error(std::string const& str, std::errc ec) -> std::unexpected<error> {
|
|
return std::unexpected(error{str, std::make_error_code(ec)});
|
|
}
|
|
|
|
inline auto read_text(std::string const& path) -> std::expected<std::string, aoc::error> {
|
|
std::fstream strm(path, std::ios::in | std::ios::binary);
|
|
if (!strm.is_open())
|
|
return aoc::make_error(path, std::errc::no_such_file_or_directory);
|
|
|
|
return std::string{
|
|
std::istreambuf_iterator<c8>(strm),
|
|
std::istreambuf_iterator<c8>()
|
|
};
|
|
}
|
|
|
|
// ranges and view aliases
|
|
template <typename T>
|
|
using vec = std::vector<T>;
|
|
|
|
inline constexpr auto split = std::views::split;
|
|
|
|
[[maybe_unused]]constexpr auto map_to_str = std::views::transform([](auto const& str) {
|
|
return std::string(std::begin(str), std::end(str));
|
|
});
|
|
|
|
[[maybe_unused]]constexpr auto map_to_sv = std::views::transform([](auto const& str) {
|
|
return std::string_view(std::begin(str), std::end(str));
|
|
});
|
|
|
|
[[maybe_unused]]constexpr auto filter_non_empty = std::views::filter([](auto const& str) {
|
|
return !str.empty();
|
|
});
|
|
|
|
template <class F>
|
|
struct pipe {
|
|
F f;
|
|
};
|
|
|
|
template <class F>
|
|
pipe(F) -> pipe<F>;
|
|
|
|
template <class F>
|
|
auto operator|(std::string s, pipe<F> p) -> decltype(auto) {
|
|
return p.f(std::move(s));
|
|
}
|
|
|
|
inline auto ltrim(std::string s) -> std::string {
|
|
s.erase(
|
|
std::begin(s),
|
|
std::find_if(s.begin(), s.end(), [](char ch) {
|
|
return !std::isspace(static_cast<char>(ch));
|
|
}));
|
|
return s;
|
|
}
|
|
|
|
inline auto rtrim(std::string s) -> std::string {
|
|
s.erase(
|
|
std::find_if(s.rbegin(), s.rend(), [](char ch) {
|
|
return !std::isspace(static_cast<char>(ch));
|
|
}).base(),
|
|
s.end());
|
|
return s;
|
|
}
|
|
|
|
inline auto trim(std::string s) -> std::string {
|
|
return ltrim(rtrim(std::move(s)));
|
|
}
|
|
}
|
|
|
|
#endif // !AOC_UTILS_HPP
|