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 <filesystem>
#include <vector> #include <vector>
#include <streambuf> #include <streambuf>
#include <functional>
#ifdef PLATFORM_WIN32 #ifdef PLATFORM_WIN32
#include "win32/windows.hpp" #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 /// FunctionT must return a view of the consumed data.
/// dispatched so as to avoid issues with partial writes. will block until
/// such time as the entire buffer has written.
/// ///
/// an exception may be thrown in the event forward progress is impossible. /// The operation will iterate until the entire view has been consumed and
/// in this event the progress may not be reported to the caller. in the /// hence may block for an indefinate period.
/// future an exception member variable may expose the information. ///
/// 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 < template <
typename DstT, typename DstT,
typename IteratorA, typename IteratorA,
typename IteratorB typename IteratorB
> >
cruft::view<IteratorA,IteratorB> decltype(auto)
write (DstT &&dst, const cruft::view<IteratorA, IteratorB> &src) write (DstT &&dst, const cruft::view<IteratorA, IteratorB> &src)
{ {
auto remain = src; constexpr auto func = &std::decay_t<DstT>::write;
while (!remain.empty ()) return drain (std::forward<DstT> (dst), func, src);
remain = remain.consume (dst.write (remain)); }
return 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);
} }