| 1 | #include <Common/Exception.h> |
| 2 | #include <IO/ReadBuffer.h> |
| 3 | #include <IO/WriteBuffer.h> |
| 4 | #include <IO/copyData.h> |
| 5 | |
| 6 | |
| 7 | namespace DB |
| 8 | { |
| 9 | |
| 10 | namespace |
| 11 | { |
| 12 | |
| 13 | void copyDataImpl(ReadBuffer & from, WriteBuffer & to, bool check_bytes, size_t bytes, const std::atomic<int> * is_cancelled) |
| 14 | { |
| 15 | /// If read to the end of the buffer, eof() either fills the buffer with new data and moves the cursor to the beginning, or returns false. |
| 16 | while (bytes > 0 && !from.eof()) |
| 17 | { |
| 18 | if (is_cancelled && *is_cancelled) |
| 19 | return; |
| 20 | |
| 21 | /// buffer() - a piece of data available for reading; position() - the cursor of the place to which you have already read. |
| 22 | size_t count = std::min(bytes, static_cast<size_t>(from.buffer().end() - from.position())); |
| 23 | to.write(from.position(), count); |
| 24 | from.position() += count; |
| 25 | bytes -= count; |
| 26 | } |
| 27 | |
| 28 | if (check_bytes && bytes > 0) |
| 29 | throw Exception("Attempt to read after EOF." , ErrorCodes::ATTEMPT_TO_READ_AFTER_EOF); |
| 30 | } |
| 31 | |
| 32 | void copyDataImpl(ReadBuffer & from, WriteBuffer & to, bool check_bytes, size_t bytes, std::function<void()> cancellation_hook) |
| 33 | { |
| 34 | /// If read to the end of the buffer, eof() either fills the buffer with new data and moves the cursor to the beginning, or returns false. |
| 35 | while (bytes > 0 && !from.eof()) |
| 36 | { |
| 37 | if (cancellation_hook) |
| 38 | cancellation_hook(); |
| 39 | |
| 40 | /// buffer() - a piece of data available for reading; position() - the cursor of the place to which you have already read. |
| 41 | size_t count = std::min(bytes, static_cast<size_t>(from.buffer().end() - from.position())); |
| 42 | to.write(from.position(), count); |
| 43 | from.position() += count; |
| 44 | bytes -= count; |
| 45 | } |
| 46 | |
| 47 | if (check_bytes && bytes > 0) |
| 48 | throw Exception("Attempt to read after EOF." , ErrorCodes::ATTEMPT_TO_READ_AFTER_EOF); |
| 49 | } |
| 50 | |
| 51 | } |
| 52 | |
| 53 | void copyData(ReadBuffer & from, WriteBuffer & to) |
| 54 | { |
| 55 | copyDataImpl(from, to, false, std::numeric_limits<size_t>::max(), nullptr); |
| 56 | } |
| 57 | |
| 58 | void copyData(ReadBuffer & from, WriteBuffer & to, const std::atomic<int> & is_cancelled) |
| 59 | { |
| 60 | copyDataImpl(from, to, false, std::numeric_limits<size_t>::max(), &is_cancelled); |
| 61 | } |
| 62 | |
| 63 | void copyData(ReadBuffer & from, WriteBuffer & to, std::function<void()> cancellation_hook) |
| 64 | { |
| 65 | copyDataImpl(from, to, false, std::numeric_limits<size_t>::max(), cancellation_hook); |
| 66 | } |
| 67 | |
| 68 | void copyData(ReadBuffer & from, WriteBuffer & to, size_t bytes) |
| 69 | { |
| 70 | copyDataImpl(from, to, true, bytes, nullptr); |
| 71 | } |
| 72 | |
| 73 | void copyData(ReadBuffer & from, WriteBuffer & to, size_t bytes, const std::atomic<int> & is_cancelled) |
| 74 | { |
| 75 | copyDataImpl(from, to, true, bytes, &is_cancelled); |
| 76 | } |
| 77 | |
| 78 | void copyData(ReadBuffer & from, WriteBuffer & to, size_t bytes, std::function<void()> cancellation_hook) |
| 79 | { |
| 80 | copyDataImpl(from, to, true, bytes, cancellation_hook); |
| 81 | } |
| 82 | |
| 83 | } |
| 84 | |