io: add pwrite wrappers
This commit is contained in:
parent
825d359b9d
commit
bb812ba81c
79
io.hpp
79
io.hpp
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user