C++ Utilities 5.22.0
Useful C++ classes and routines such as argument parser, IO and conversion utilities
Loading...
Searching...
No Matches
copy.h
Go to the documentation of this file.
1#ifndef IOUTILITIES_COPY_H
2#define IOUTILITIES_COPY_H
3
5#if defined(CPP_UTILITIES_USE_NATIVE_FILE_BUFFER) && defined(PLATFORM_LINUX)
6#define CPP_UTILITIES_USE_SEND_FILE
7#include "../conversion/stringbuilder.h"
8#endif
9
10#ifdef CPP_UTILITIES_USE_SEND_FILE
11#include <errno.h>
12#include <sys/sendfile.h>
13#endif
14
15#include <functional>
16#include <iostream>
17#ifdef CPP_UTILITIES_USE_SEND_FILE
18#include <algorithm>
19#include <cstring>
20#endif
21
22namespace CppUtilities {
23
29template <std::size_t bufferSize> class CPP_UTILITIES_EXPORT CopyHelper {
30public:
31 CopyHelper();
32 void copy(std::istream &input, std::ostream &output, std::uint64_t count);
33 void callbackCopy(std::istream &input, std::ostream &output, std::uint64_t count, const std::function<bool(void)> &isAborted,
34 const std::function<void(double)> &callback);
35 void copy(NativeFileStream &input, NativeFileStream &output, std::uint64_t count);
36 void callbackCopy(NativeFileStream &input, NativeFileStream &output, std::uint64_t count, const std::function<bool(void)> &isAborted,
37 const std::function<void(double)> &callback);
38 char *buffer();
39
40private:
41 char m_buffer[bufferSize];
42};
43
47template <std::size_t bufferSize> CopyHelper<bufferSize>::CopyHelper()
48{
49}
50
56template <std::size_t bufferSize> void CopyHelper<bufferSize>::copy(std::istream &input, std::ostream &output, std::uint64_t count)
57{
58 while (count > bufferSize) {
59 input.read(m_buffer, bufferSize);
60 output.write(m_buffer, bufferSize);
61 count -= bufferSize;
62 }
63 input.read(m_buffer, static_cast<std::streamsize>(count));
64 output.write(m_buffer, static_cast<std::streamsize>(count));
65}
66
77template <std::size_t bufferSize>
78void CopyHelper<bufferSize>::callbackCopy(std::istream &input, std::ostream &output, std::uint64_t count, const std::function<bool(void)> &isAborted,
79 const std::function<void(double)> &callback)
80{
81 const auto totalBytes = count;
82 while (count > bufferSize) {
83 input.read(m_buffer, bufferSize);
84 output.write(m_buffer, bufferSize);
85 count -= bufferSize;
86 if (isAborted()) {
87 return;
88 }
89 callback(static_cast<double>(totalBytes - count) / static_cast<double>(totalBytes));
90 }
91 input.read(m_buffer, static_cast<std::streamsize>(count));
92 output.write(m_buffer, static_cast<std::streamsize>(count));
93 callback(1.0);
94}
95
103template <std::size_t bufferSize> void CopyHelper<bufferSize>::copy(NativeFileStream &input, NativeFileStream &output, std::uint64_t count)
104{
105#ifdef CPP_UTILITIES_USE_SEND_FILE
106 if (output.fileDescriptor() != -1 && input.fileDescriptor() != -1) {
107 const auto inputTellg = output.tellg();
108 const auto inputTellp = output.tellp();
109 const auto outputTellg = output.tellg();
110 const auto outputTellp = output.tellp();
111 input.flush();
112 output.flush();
113 const auto totalBytes = static_cast<std::streamoff>(count);
114 while (count) {
115 const auto bytesCopied = ::sendfile64(output.fileDescriptor(), input.fileDescriptor(), nullptr, count);
116 if (bytesCopied < 0) {
117 throw std::ios_base::failure(argsToString("sendfile64() failed: ", std::strerror(errno)));
118 }
119 count -= static_cast<std::size_t>(bytesCopied);
120 }
121 input.sync();
122 output.sync();
123 output.seekg(outputTellg + totalBytes);
124 output.seekp(outputTellp + totalBytes);
125 input.seekg(inputTellg + totalBytes);
126 input.seekp(inputTellp + totalBytes);
127 return;
128 }
129#endif
130 copy(static_cast<std::istream &>(input), static_cast<std::ostream &>(output), count);
131}
132
144template <std::size_t bufferSize>
146 const std::function<bool(void)> &isAborted, const std::function<void(double)> &callback)
147{
148#ifdef CPP_UTILITIES_USE_SEND_FILE
149 if (output.fileDescriptor() != -1 && input.fileDescriptor() != -1) {
150 const auto inputTellg = output.tellg();
151 const auto inputTellp = output.tellp();
152 const auto outputTellg = output.tellg();
153 const auto outputTellp = output.tellp();
154 input.flush();
155 output.flush();
156 const auto totalBytes = static_cast<std::streamoff>(count);
157 while (count) {
158 const auto bytesCopied = ::sendfile64(output.fileDescriptor(), input.fileDescriptor(), nullptr, std::min(count, bufferSize));
159 if (bytesCopied < 0) {
160 throw std::ios_base::failure(argsToString("sendfile64() failed: ", std::strerror(errno)));
161 }
162 count -= static_cast<std::uint64_t>(bytesCopied);
163 if (isAborted()) {
164 return;
165 }
166 callback(static_cast<double>(totalBytes - static_cast<std::streamoff>(count)) / static_cast<double>(totalBytes));
167 }
168 input.sync();
169 output.sync();
170 output.seekg(outputTellg + totalBytes);
171 output.seekp(outputTellp + totalBytes);
172 input.seekg(inputTellg + totalBytes);
173 input.seekp(inputTellp + totalBytes);
174 callback(1.0);
175 return;
176 }
177#endif
178 callbackCopy(static_cast<std::istream &>(input), static_cast<std::ostream &>(output), count, isAborted, callback);
179}
180
184template <std::size_t bufferSize> char *CopyHelper<bufferSize>::buffer()
185{
186 return m_buffer;
187}
188} // namespace CppUtilities
189
190#endif // IOUTILITIES_COPY_H
The CopyHelper class helps to copy bytes from one stream to another.
Definition: copy.h:29
char * buffer()
Returns the internal buffer.
Definition: copy.h:184
void copy(std::istream &input, std::ostream &output, std::uint64_t count)
Copies count bytes from input to output.
Definition: copy.h:56
void callbackCopy(std::istream &input, std::ostream &output, std::uint64_t count, const std::function< bool(void)> &isAborted, const std::function< void(double)> &callback)
Copies count bytes from input to output.
Definition: copy.h:78
CopyHelper()
Constructs a new copy helper.
Definition: copy.h:47
#define CPP_UTILITIES_EXPORT
Marks the symbol to be exported by the c++utilities library.
Contains all utilities provides by the c++utilities library.
StringType argsToString(Args &&...args)
std::fstream NativeFileStream