/* Examples from the P1031 Low level file i/o Technical Specification (C) 2018 Niall Douglas (2 commits) File Created: Aug 2018 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License in the accompanying file Licence.txt or at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Distributed under the Boost Software License, Version 1.0. (See accompanying file Licence.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ #include "../include/llfio.hpp" using namespace LLFIO_V2_NAMESPACE; using namespace std; #define throws(x) #define VALUE .value() inline io_handle::buffers_type read_all(io_handle &h, io_handle::io_request reqs, deadline d = deadline()) throws(file_io_error) { // Record beginning if deadline is specified chrono::steady_clock::time_point began_steady; if(d && d.steady) began_steady = chrono::steady_clock::now(); // Take copy of input buffers onto stack, and set output buffers to buffers supplied auto *input_buffers_mem = reinterpret_cast(alloca(reqs.buffers.size() * sizeof(io_handle::buffer_type))); auto *input_buffers_sizes = reinterpret_cast(alloca(reqs.buffers.size() * sizeof(io_handle::size_type))); io_handle::buffers_type output_buffers(reqs.buffers); io_handle::io_request creq({input_buffers_mem, reqs.buffers.size()}, 0); for(size_t n = 0; n < reqs.buffers.size(); n++) { // Copy input buffer to stack and retain original size creq.buffers[n] = reqs.buffers[n]; input_buffers_sizes[n] = reqs.buffers[n].size(); // Set output buffer length to zero output_buffers[n] = io_handle::buffer_type{output_buffers[n].data(), 0}; } // Track which output buffer we are currently filling size_t idx = 0; do { // New deadline for this loop deadline nd; if(d) { if(d.steady) { auto ns = chrono::duration_cast((began_steady + chrono::nanoseconds(d.nsecs)) - chrono::steady_clock::now()); if(ns.count() < 0) nd.nsecs = 0; else nd.nsecs = ns.count(); } else nd = d; } // Partial fill buffers with current request io_handle::buffers_type filled = h.read(creq, nd) VALUE; (void) filled; // Adjust output buffers by what was filled, and prepare input // buffers for next round of partial fill for(size_t n = 0; n < creq.buffers.size(); n++) { // Add the amount of this buffer filled to next offset read and to output buffer auto &input_buffer = creq.buffers[n]; auto &output_buffer = output_buffers[idx + n]; creq.offset += input_buffer.size(); output_buffer = io_handle::buffer_type{output_buffer.data(), output_buffer.size() + input_buffer.size()}; // Adjust input buffer to amount remaining input_buffer = io_handle::buffer_type{input_buffer.data() + input_buffer.size(), input_buffers_sizes[idx + n] - output_buffer.size()}; } // Remove completely filled input buffers while(!creq.buffers.empty() && creq.buffers[0].size() == 0) { creq.buffers = io_handle::buffers_type(creq.buffers.data() + 1, creq.buffers.size() - 1); ++idx; } } while(!creq.buffers.empty()); return output_buffers; } int main() { return 0; }