| 96 | } |
| 97 | |
| 98 | void copyFromIStreamWithProgressCallback(std::istream & istr, char * to, size_t n, const std::function<bool(size_t)> & progress_callback, size_t * out_bytes_copied, bool * out_cancelled) |
| 99 | { |
| 100 | const size_t chunk = DBMS_DEFAULT_BUFFER_SIZE; |
| 101 | if (out_cancelled) |
| 102 | *out_cancelled = false; |
| 103 | |
| 104 | size_t copied = 0; |
| 105 | while (copied < n) |
| 106 | { |
| 107 | size_t to_copy = std::min(chunk, n - copied); |
| 108 | istr.read(to + copied, to_copy); |
| 109 | size_t gcount = istr.gcount(); |
| 110 | |
| 111 | copied += gcount; |
| 112 | |
| 113 | bool cancelled = false; |
| 114 | if (gcount && progress_callback) |
| 115 | cancelled = progress_callback(copied); |
| 116 | *out_bytes_copied = copied; |
| 117 | |
| 118 | if (gcount != to_copy) |
| 119 | { |
| 120 | if (!istr.eof()) |
| 121 | throw Exception( |
| 122 | ErrorCodes::CANNOT_READ_FROM_ISTREAM, |
| 123 | "{} at offset {}", |
| 124 | istr.fail() ? "Cannot read from istream" : "Unexpected state of istream", |
| 125 | copied); |
| 126 | |
| 127 | break; |
| 128 | } |
| 129 | |
| 130 | if (cancelled) |
| 131 | { |
| 132 | if (out_cancelled != nullptr) |
| 133 | *out_cancelled = true; |
| 134 | break; |
| 135 | } |
| 136 | } |
| 137 | |
| 138 | *out_bytes_copied = copied; |
| 139 | } |
| 140 | |
| 141 | } |