io: add pwrite wrappers

This commit is contained in:
Danny Robson 2018-12-17 12:42:50 +11:00
parent 825d359b9d
commit bb812ba81c

79
io.hpp
View File

@ -18,6 +18,8 @@
#include <filesystem>
#include <vector>
#include <streambuf>
#include <functional>
#ifdef PLATFORM_WIN32
#include "win32/windows.hpp"
@ -55,27 +57,80 @@ namespace cruft {
///////////////////////////////////////////////////////////////////////////
/// writes all data from the provided view into the file-like-object
/// Repeatedly calls FunctionT to transfer data from a supplied view to a
/// file-like-object.
///
/// writing will continually iterate until the entire buffer has been
/// dispatched so as to avoid issues with partial writes. will block until
/// such time as the entire buffer has written.
/// FunctionT must return a view of the consumed data.
///
/// an exception may be thrown in the event forward progress is impossible.
/// in this event the progress may not be reported to the caller. in the
/// future an exception member variable may expose the information.
/// The operation will iterate until the entire view has been consumed and
/// hence may block for an indefinate period.
///
/// An exception may be throw in the event forward progress is impossible
/// (depending on the supplied FunctionT).
template <
typename DstT,
typename FunctionT,
typename IteratorA,
typename IteratorB,
typename ...Args
>
[[nodiscard]] decltype(auto)
drain (
DstT &&dst,
FunctionT &&func,
cruft::view<IteratorA,IteratorB> const &src,
Args&& ...args
) {
static_assert (std::is_pointer_v<IteratorA>);
static_assert (std::is_pointer_v<IteratorB>);
auto cursor = reinterpret_cast<std::byte const*> (src.data ());
auto remain = src.size ();
while (remain) {
auto count = std::invoke (func, dst, cursor, remain, args...);
cursor += count;
remain -= count;
}
return src;
}
///////////////////////////////////////////////////////////////////////////
/// Drains all data from the supplied view `src` to the file-like-object
/// `dst` by way of repeated calls to `write`.
///
/// Returns a view over the consumed data. This SHOULD always be identical
/// to `src`.
template <
typename DstT,
typename IteratorA,
typename IteratorB
>
cruft::view<IteratorA,IteratorB>
decltype(auto)
write (DstT &&dst, const cruft::view<IteratorA, IteratorB> &src)
{
auto remain = src;
while (!remain.empty ())
remain = remain.consume (dst.write (remain));
return src;
constexpr auto func = &std::decay_t<DstT>::write;
return drain (std::forward<DstT> (dst), func, src);
}
///------------------------------------------------------------------------
/// Drain the supplied data view into the destination object by calling
/// pwrite repeatedly.
///
/// Returns a view over the consumed data. This SHOULD always be identical
/// to `src`.
template <
typename DstT,
typename IteratorA,
typename IteratorB
>
decltype(auto)
pwrite (DstT &&dst, const cruft::view<IteratorA, IteratorB> &src, size_t offset)
{
return drain (std::forward<DstT> (dst), &std::decay_t<DstT>::pwrite, src, offset);
}