From bb812ba81c236e184e9abea395696e77e1b7c325 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Mon, 17 Dec 2018 12:42:50 +1100 Subject: [PATCH] io: add pwrite wrappers --- io.hpp | 79 +++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 67 insertions(+), 12 deletions(-) diff --git a/io.hpp b/io.hpp index f3f306dd..37f78308 100644 --- a/io.hpp +++ b/io.hpp @@ -18,6 +18,8 @@ #include #include #include +#include + #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 const &src, + Args&& ...args + ) { + static_assert (std::is_pointer_v); + static_assert (std::is_pointer_v); + + auto cursor = reinterpret_cast (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 + decltype(auto) write (DstT &&dst, const cruft::view &src) { - auto remain = src; - while (!remain.empty ()) - remain = remain.consume (dst.write (remain)); - return src; + constexpr auto func = &std::decay_t::write; + return drain (std::forward (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 &src, size_t offset) + { + return drain (std::forward (dst), &std::decay_t::pwrite, src, offset); }