C++ Utilities
5.36.0
Useful C++ classes and routines such as argument parser, IO and conversion utilities
Toggle main menu visibility
Loading...
Searching...
No Matches
io
copy.h
Go to the documentation of this file.
1
#ifndef IOUTILITIES_COPY_H
2
#define IOUTILITIES_COPY_H
3
4
#include "
./nativefilestream.h
"
5
#if defined(CPP_UTILITIES_USE_PLATFORM_SPECIFIC_API_FOR_OPTIMIZING_COPY_HELPER) && defined(CPP_UTILITIES_USE_NATIVE_FILE_BUFFER) \
6
&& defined(PLATFORM_LINUX)
7
#define CPP_UTILITIES_USE_SEND_FILE
8
#include "
../conversion/stringbuilder.h
"
9
#endif
10
11
#ifdef CPP_UTILITIES_USE_SEND_FILE
12
#include <errno.h>
13
#include <sys/sendfile.h>
14
#endif
15
16
#include <cstdint>
17
#include <functional>
18
#include <iostream>
19
#ifdef CPP_UTILITIES_USE_SEND_FILE
20
#include <algorithm>
21
#include <cstring>
22
#endif
23
24
namespace
CppUtilities
{
25
31
template
<std::
size_t
bufferSize>
class
CPP_UTILITIES_EXPORT
CopyHelper
{
32
public
:
33
CopyHelper
();
34
void
copy
(std::istream &input, std::ostream &output, std::uint64_t count);
35
void
callbackCopy
(std::istream &input, std::ostream &output, std::uint64_t count,
const
std::function<
bool
(
void
)> &isAborted,
36
const
std::function<
void
(
double
)> &callback);
37
void
copy
(
NativeFileStream
&input,
NativeFileStream
&output, std::uint64_t count);
38
void
callbackCopy
(
NativeFileStream
&input,
NativeFileStream
&output, std::uint64_t count,
const
std::function<
bool
(
void
)> &isAborted,
39
const
std::function<
void
(
double
)> &callback);
40
char
*
buffer
();
41
42
private
:
43
char
m_buffer[bufferSize];
44
};
45
49
template
<std::
size_t
bufferSize>
CopyHelper<bufferSize>::CopyHelper
()
50
{
51
}
52
58
template
<std::
size_t
bufferSize>
void
CopyHelper<bufferSize>::copy
(std::istream &input, std::ostream &output, std::uint64_t count)
59
{
60
while
(count > bufferSize) {
61
input.read(m_buffer, bufferSize);
62
output.write(m_buffer, bufferSize);
63
count -= bufferSize;
64
}
65
input.read(m_buffer,
static_cast<
std::streamsize
>
(count));
66
output.write(m_buffer,
static_cast<
std::streamsize
>
(count));
67
}
68
79
template
<std::
size_t
bufferSize>
80
void
CopyHelper<bufferSize>::callbackCopy
(std::istream &input, std::ostream &output, std::uint64_t count,
const
std::function<
bool
(
void
)> &isAborted,
81
const
std::function<
void
(
double
)> &callback)
82
{
83
const
auto
totalBytes = count;
84
while
(count > bufferSize) {
85
input.read(m_buffer, bufferSize);
86
output.write(m_buffer, bufferSize);
87
count -= bufferSize;
88
if
(isAborted()) {
89
return
;
90
}
91
callback(
static_cast<
double
>
(totalBytes - count) /
static_cast<
double
>
(totalBytes));
92
}
93
input.read(m_buffer,
static_cast<
std::streamsize
>
(count));
94
output.write(m_buffer,
static_cast<
std::streamsize
>
(count));
95
callback(1.0);
96
}
97
105
template
<std::
size_t
bufferSize>
void
CopyHelper<bufferSize>::copy
(
NativeFileStream
&input,
NativeFileStream
&output, std::uint64_t count)
106
{
107
#ifdef CPP_UTILITIES_USE_SEND_FILE
108
if
(output.fileDescriptor() != -1 && input.fileDescriptor() != -1 && output.fileDescriptor() != input.fileDescriptor()) {
109
const
auto
inputTellg = output.tellg();
110
const
auto
inputTellp = output.tellp();
111
const
auto
outputTellg = output.tellg();
112
const
auto
outputTellp = output.tellp();
113
input.flush();
114
output.flush();
115
const
auto
totalBytes =
static_cast<
std::streamoff
>
(count);
116
while
(count) {
117
const
auto
bytesCopied = ::sendfile64(output.fileDescriptor(), input.fileDescriptor(),
nullptr
, count);
118
if
(bytesCopied < 0) {
119
if
((errno == EINVAL || errno == ENOSYS) &&
static_cast<
std::uint64_t
>
(totalBytes) == count) {
120
// try again the unoptimized version, maybe the filesystem doesn't support sendfile
121
goto
unoptimized_version;
122
}
123
throw
std::ios_base::failure(
argsToString
(
"sendfile64() failed: "
, std::strerror(errno)));
124
}
125
count -=
static_cast<
std::uint64_t
>
(bytesCopied);
126
}
127
input.sync();
128
output.sync();
129
output.seekg(outputTellg + totalBytes);
130
output.seekp(outputTellp + totalBytes);
131
input.seekg(inputTellg + totalBytes);
132
input.seekp(inputTellp + totalBytes);
133
return
;
134
}
135
unoptimized_version:
136
#endif
137
copy
(
static_cast<
std::istream &
>
(input),
static_cast<
std::ostream &
>
(output), count);
138
}
139
151
template
<std::
size_t
bufferSize>
152
void
CopyHelper<bufferSize>::callbackCopy
(
NativeFileStream
&input,
NativeFileStream
&output, std::uint64_t count,
153
const
std::function<
bool
(
void
)> &isAborted,
const
std::function<
void
(
double
)> &callback)
154
{
155
#ifdef CPP_UTILITIES_USE_SEND_FILE
156
if
(output.fileDescriptor() != -1 && input.fileDescriptor() != -1 && output.fileDescriptor() != input.fileDescriptor()) {
157
const
auto
inputTellg = output.tellg();
158
const
auto
inputTellp = output.tellp();
159
const
auto
outputTellg = output.tellg();
160
const
auto
outputTellp = output.tellp();
161
input.flush();
162
output.flush();
163
const
auto
totalBytes =
static_cast<
std::streamoff
>
(count);
164
while
(count) {
165
const
auto
bytesToCopy =
static_cast<
std::size_t
>
(std::min(count,
static_cast<
std::uint64_t
>
(bufferSize)));
166
const
auto
bytesCopied = ::sendfile64(output.fileDescriptor(), input.fileDescriptor(),
nullptr
, bytesToCopy);
167
if
(bytesCopied < 0) {
168
if
((errno == EINVAL || errno == ENOSYS) &&
static_cast<
std::uint64_t
>
(totalBytes) == count) {
169
// try again the unoptimized version, maybe the filesystem doesn't support sendfile
170
goto
unoptimized_version;
171
}
172
throw
std::ios_base::failure(
argsToString
(
"sendfile64() failed: "
, std::strerror(errno)));
173
}
174
count -=
static_cast<
std::uint64_t
>
(bytesCopied);
175
if
(isAborted()) {
176
return
;
177
}
178
callback(
static_cast<
double
>
(totalBytes -
static_cast<
std::streamoff
>
(count)) /
static_cast<
double
>
(totalBytes));
179
}
180
input.sync();
181
output.sync();
182
output.seekg(outputTellg + totalBytes);
183
output.seekp(outputTellp + totalBytes);
184
input.seekg(inputTellg + totalBytes);
185
input.seekp(inputTellp + totalBytes);
186
callback(1.0);
187
return
;
188
}
189
unoptimized_version:
190
#endif
191
callbackCopy
(
static_cast<
std::istream &
>
(input),
static_cast<
std::ostream &
>
(output), count, isAborted, callback);
192
}
193
197
template
<std::
size_t
bufferSize>
char
*
CopyHelper<bufferSize>::buffer
()
198
{
199
return
m_buffer;
200
}
201
}
// namespace CppUtilities
202
203
#endif
// IOUTILITIES_COPY_H
CppUtilities::CopyHelper::buffer
char * buffer()
Returns the internal buffer.
Definition
copy.h:197
CppUtilities::CopyHelper::copy
void copy(std::istream &input, std::ostream &output, std::uint64_t count)
Copies count bytes from input to output.
Definition
copy.h:58
CppUtilities::CopyHelper::callbackCopy
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:80
CppUtilities::CopyHelper::CopyHelper
CopyHelper()
Constructs a new copy helper.
Definition
copy.h:49
CPP_UTILITIES_EXPORT
#define CPP_UTILITIES_EXPORT
Marks the symbol to be exported by the c++utilities library.
Definition
global.h:14
CppUtilities
Contains all utilities provided by the c++utilities library.
Definition
argumentparser.h:18
CppUtilities::NativeFileStream
std::fstream NativeFileStream
Definition
nativefilestream.h:134
CppUtilities::argsToString
StringType argsToString(Args &&...args)
Definition
stringbuilder.h:260
nativefilestream.h
stringbuilder.h
Generated on
for C++ Utilities by
1.18.0