47# if ! defined(_WIN32) \
48 && (defined(__unix__) || defined(__unix) \
49 || (defined(__APPLE__) && defined(__MACH__)))
52# if defined(_POSIX_VERSION)
53# define KBLIB_POSIX_TMPFILE
62template <
typename D = std::string,
63 typename std::enable_if_t<is_contiguous_v<D>,
int> = 0>
65 in.seekg(0, std::ios::end);
66 auto size = in.tellg();
67 out.resize(
static_cast<std::size_t
>(
size));
68 in.seekg(0, std::ios::beg);
69 in.read(
reinterpret_cast<char*
>(out.data()),
size);
73template <
typename D = std::string,
74 typename std::enable_if_t<not is_contiguous_v<D>,
int> = 0>
76 in.seekg(0, std::ios::end);
77 auto size = in.tellg();
78 out.resize(
static_cast<std::size_t
>(
size));
79 in.seekg(0, std::ios::beg);
80 std::copy((std::istreambuf_iterator<char>(in)),
81 std::istreambuf_iterator<char>(), out.begin());
96template <
typename D = std::
string,
typename string>
98 static_assert(std::is_trivially_copyable_v<typename D::value_type>,
99 "D must be a sequence of trivial types");
100 static_assert(
sizeof(
typename D::value_type) == 1,
101 "D must be a sequence of char-sized objects.");
102 std::optional<D> out;
103 if (std::ifstream in(filename, std::ios::in | std::ios::binary); in) {
122template <
typename D = std::
string,
typename string>
124 static_assert(std::is_trivially_copyable<typename D::value_type>::value,
125 "D must be a sequence of trivial types");
126 static_assert(
sizeof(
typename D::value_type) == 1,
127 "D must be a sequence of char-sized objects.");
129 std::ifstream in(filename, std::ios::in | std::ios::binary);
131 in.exceptions(std::ios_base::failbit | std::ios_base::badbit);
134 throw std::system_error(std::make_error_code(std::errc::io_error),
135 "could not open file " + std::string(filename));
146inline auto getline(std::istream& is) -> std::string {
158inline auto eat_word(std::istream& is) -> std::istream& {
173[[deprecated(
"Use std::ws instead")]]
inline std::istream&
eat_space(
211template <
typename CharT,
typename Traits>
212auto nl(std::basic_istream<CharT, Traits>& is)
213 -> std::basic_istream<CharT, Traits>& {
214 auto n =
static_cast<typename Traits::int_type
>(is.widen(
'\n'));
215 for (
typename Traits::int_type c = is.peek();
217 and
std::isspace(
static_cast<CharT
>(c), is.getloc()) and c != n;
221 if (is.peek() == n) {
227template <
typename T,
typename U>
239struct unicode_widen<char8_t, char32_t> : std::true_type {};
243#if KBLIB_CHAR_IS_UTF8
246struct unicode_widen<char, char16_t> : std::true_type {};
249struct unicode_widen<char, char32_t> : std::true_type {};
253template <
typename T,
typename U>
254constexpr static bool unicode_widen_v = unicode_widen<T, U>::value;
261template <
typename CharT>
263 auto _f = [c](
auto& istream) ->
decltype(istream) {
264 using SCharT =
typename std::decay_t<
decltype(istream)>::char_type;
268 std::is_same_v<CharT, char_type>
269 or (not std::is_same_v<CharT, char8_t>
270 and not std::is_same_v<char_type, char8_t>),
271 "No support for char8_t conversions.");
274 auto widen_equal = [&](
auto di) {
278 auto d =
static_cast<SCharT
>(di);
288 (std::is_same<CharT, SCharT>::value
289 or std::is_same<CharT, char>::value),
290 "Stream character type incompatible with argument type.");
292# define IF_CONSTEXPR constexpr
298 }
else if IF_CONSTEXPR (unicode_widen_v<CharT, SCharT>) {
301 return istream.widen(c) == d;
306 if (widen_equal(istream.peek())) {
309 istream.setstate(std::ios_base::failbit);
320template <
typename CharT>
322 auto _f = [c](
auto& istream) ->
decltype(istream) {
338template <
typename CharT,
typename... O,
339 template <
typename,
typename...>
class string>
340inline auto get_line(string<CharT, O...>& str) ->
auto {
341 auto _f = [&](
auto& istream) ->
decltype(istream) {
359template <
typename CharT,
typename... O,
360 template <
typename,
typename...>
class string>
361inline auto get_line(string<CharT, O...>& str, CharT delim) ->
auto {
362 auto _f = [&, delim](
auto& istream) ->
decltype(istream) {
372template <
typename F,
typename CharT,
typename Tr>
373std::basic_istream<CharT, Tr>&
operator>>(std::basic_istream<CharT, Tr>& is,
381template <
typename F,
typename CharT,
typename Tr>
382std::basic_ostream<CharT, Tr>&
operator<<(std::basic_ostream<CharT, Tr>& is,
417 template <
typename SB1_t,
typename SB2_t>
419 :
public std::basic_streambuf<typename SB1_t::char_type,
420 typename SB1_t::traits_type> {
422 using base_type = std::basic_streambuf<
typename SB1_t::char_type,
423 typename SB1_t::traits_type>;
424 static_assert(std::is_same<
typename SB1_t::char_type,
425 typename SB2_t::char_type>::value,
426 "Backing streams must be compatible.");
427 static_assert(std::is_same<
typename SB1_t::traits_type,
428 typename SB2_t::traits_type>::value,
429 "Backing streams must be compatible.");
431 using typename base_type::char_type;
432 using typename base_type::traits_type;
434 using typename base_type::int_type;
435 using typename base_type::off_type;
436 using typename base_type::pos_type;
442 this->setp(
nullptr,
nullptr);
446 auto bool_to_failure(
bool B)
const noexcept -> int_type {
451 auto imbue(
const std::locale& loc) ->
void override {
457 auto sync() ->
int override {
return a->pubsync() | b->pubsync(); }
459 auto xsputn(
const char_type* s, std::streamsize count)
460 -> std::streamsize
override {
461 auto a_ct =
a->sputn(s, count);
462 auto b_ct = b->sputn(s, count);
464 std::streamsize successful =
std::min(a_ct, b_ct);
466 if (successful == count) {
477 if (traits_type::not_eof(r_a) and traits_type::not_eof(r_b)) {
491 template <
typename Stream>
493 = std::remove_pointer_t<decltype(std::declval<Stream&>().rdbuf())>;
497template <
typename StreamA,
typename StreamB>
499 :
public std::basic_ostream<typename StreamA::char_type,
500 typename StreamA::traits_type> {
505 using ostream_type = std::basic_ostream<
typename StreamA::char_type,
506 typename StreamA::traits_type>;
509 using typename ostream_type::char_type;
510 using typename ostream_type::traits_type;
512 using typename ostream_type::int_type;
513 using typename ostream_type::off_type;
514 using typename ostream_type::pos_type;
518 , buf(
a.rdbuf(), b.rdbuf()) {}
523#if 1 || KBLIB_USE_CXX17
524template <
typename StreamA,
typename StreamB>
532template <
typename F,
typename D = std::default_delete<F>,
533 typename P =
typename D::po
inter>
538 static_cast<D&
>(
this)(fs);
539 std::filesystem::remove(path);
543# ifdef KBLIB_POSIX_TMPFILE
546 void operator()(
int fd)
const noexcept { close(fd); }
551using fd_deleter = file_deleter<int, detail_io::fd_closer>;
554template <
typename File = std::fstream>
556 std::ios_base::openmode mode
557 = std::ios_base::in | std::ios_base::out) {
558 return std::unique_ptr<File, file_deleter<File>>{
559 new std::fstream{path, mode}, {path}};
562template <
typename File = std::fstream>
563[[nodiscard]]
auto tmpfile(
const std::filesystem::path& path,
564 std::ios_base::openmode mode
565 = std::ios_base::in | std::ios_base::out) {
566# ifdef KBLIB_POSIX_TMPFILE
567 auto p = std::make_unique<File>(path, mode);
568 std::filesystem::remove(path);
571 return scoped_file<File>(path, mode);
basic_teestream(StreamA &a, StreamB &b)
auto rdbuf() const -> buf_type *
basic_teestreambuf()=delete
auto overflow(int_type ch) -> int_type override
auto sync() -> int override
auto imbue(const std::locale &loc) -> void override
std::basic_streambuf< typename SB1_t::char_type, typename SB1_t::traits_type > base_type
basic_teestreambuf(SB1_t *a, SB2_t *b)
auto xsputn(const char_type *s, std::streamsize count) -> std::streamsize override
This header provides some features of C++17 <type_traits> and other headers for C++14,...
std::remove_pointer_t< decltype(std::declval< Stream & >().rdbuf())> buf_for
auto to_char_type(IntT ch)
auto to_int_type(CharT ch)
constexpr auto size(const C &c) -> decltype(c.size())
constexpr struct kblib::nums::min_t min
auto eat_word(std::istream &is) -> std::istream &
Consume all non-spaces to first break, then eat that, too.
std::basic_ostream< CharT, Tr > & operator<<(std::basic_ostream< CharT, Tr > &is, get_manip< F > func)
Actually calls the manipulator.
constexpr auto to_signed(I x) -> std::make_signed_t< I >
Cast integral argument to corresponding signed type.
auto nl(std::basic_istream< CharT, Traits > &is) -> std::basic_istream< CharT, Traits > &
Read in spaces until the end of the line is found.
constexpr auto a(const std::initializer_list< T > &a) -> auto
Index an array literal without naming its type.
auto try_get_file_contents(const string &filename) -> D
Read the entire contents of a file into a container, such as std::string or std::vector<char>....
auto tee(StreamA &a, StreamB &b) -> basic_teestream< StreamA, StreamB >
auto get_contents(std::istream &in, D &out) -> auto
auto unformatted_expect(CharT c) -> auto
Read a character from an input stream only if it equals c. Acts as an UnformattedInputOperation,...
auto get_line(string< CharT, O... > &str, CharT delim) -> auto
Read a delimited string into a std::basic_string-like class template.
auto get_file_contents(const string &filename) -> std::optional< D >
Read the entire contents of a file into a container, such as std::string or std::vector<char>....
std::istream & eat_space(std::istream &is)
Eat spaces, don't eat an extra.
auto getline(std::istream &is) -> std::string
By-value std::getline wrapper.
auto expect(CharT c) -> auto
Read a character from an input stream only if it equals c. Acts as a FormattedInputOperation,...
auto isspace(char c) -> bool
typename std::decay< T >::type decay_t
auto tmpfile(const std::filesystem::path &path, std::ios_base::openmode mode=std::ios_base::in|std::ios_base::out)
constexpr auto copy(InputIt first, EndIt last, OutputIt out) -> OutputIt
Copies all elements of [first, last) to out. It also allows for a sentinel end iterator.
auto scoped_file(const std::filesystem::path &path, std::ios_base::openmode mode=std::ios_base::in|std::ios_base::out)
std::basic_istream< CharT, Tr > & operator>>(std::basic_istream< CharT, Tr > &is, get_manip< F > func)
Actually calls the manipulator.
KBLIB_CONSTANT auto eof
Names the EOF value for the given character type in std::char_traits.
std::filesystem::path path
A helper class for wrapping stream manipulators.
Contains some type traits not in the standard library that are useful in the implementation of kblib.