Skip to content

Commit 708e3fe

Browse files
authored
Fix a bug when a text was written to a file in binary format on Windows (#138)
Also add more tests for text translation (LF to CRLF) on Windows
1 parent e4bac59 commit 708e3fe

File tree

2 files changed

+112
-15
lines changed

2 files changed

+112
-15
lines changed

src/file.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ std::ifstream file::input_stream() const {
109109
}
110110

111111
std::ofstream file::output_stream(std::ios::openmode mode) const {
112-
binary ? mode |= std::ios::binary : mode ^= std::ios::binary;
112+
binary ? mode |= std::ios::binary : mode &= ~std::ios::binary;
113113
return std::ofstream(path(), mode);
114114
}
115115

tests/file.cpp

Lines changed: 111 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -156,17 +156,25 @@ TEST(file, write_text) {
156156
tmpfile.write("Hello\n");
157157

158158
{
159-
auto stream = std::ifstream(tmpfile.path());
159+
auto stream = std::ifstream(tmpfile.path(), std::ios::binary);
160160
auto content = std::string(std::istreambuf_iterator<char>(stream), {});
161+
#ifdef _WIN32
162+
EXPECT_EQ(content, "Hello\r\n");
163+
#else
161164
EXPECT_EQ(content, "Hello\n");
165+
#endif
162166
}
163167

164168
tmpfile.write("world!\n");
165169

166170
{
167-
auto stream = std::ifstream(tmpfile.path());
171+
auto stream = std::ifstream(tmpfile.path(), std::ios::binary);
168172
auto content = std::string(std::istreambuf_iterator<char>(stream), {});
173+
#ifdef _WIN32
174+
EXPECT_EQ(content, "world!\r\n");
175+
#else
169176
EXPECT_EQ(content, "world!\n");
177+
#endif
170178
}
171179
}
172180

@@ -195,22 +203,30 @@ TEST(file, append_binary) {
195203
/// Tests text file appending
196204
TEST(file, append_text) {
197205
file tmpfile = file::text();
198-
std::ofstream(tmpfile.path()) << "Hello,\n ";
206+
std::ofstream(tmpfile.path()) << "Hello,";
199207

200-
tmpfile.append("world");
208+
tmpfile.append("\n world");
201209

202210
{
203-
auto stream = std::ifstream(tmpfile.path());
211+
auto stream = std::ifstream(tmpfile.path(), std::ios::binary);
204212
auto content = std::string(std::istreambuf_iterator<char>(stream), {});
213+
#ifdef _WIN32
214+
EXPECT_EQ(content, "Hello,\r\n world");
215+
#else
205216
EXPECT_EQ(content, "Hello,\n world");
217+
#endif
206218
}
207219

208-
tmpfile.append("!");
220+
tmpfile.append("!\n");
209221

210222
{
211-
auto stream = std::ifstream(tmpfile.path());
223+
auto stream = std::ifstream(tmpfile.path(), std::ios::binary);
212224
auto content = std::string(std::istreambuf_iterator<char>(stream), {});
213-
EXPECT_EQ(content, "Hello,\n world!");
225+
#ifdef _WIN32
226+
EXPECT_EQ(content, "Hello,\r\n world!\r\n");
227+
#else
228+
EXPECT_EQ(content, "Hello,\n world!\n");
229+
#endif
214230
}
215231
}
216232

@@ -241,7 +257,7 @@ TEST(file, input_stream_text) {
241257
}
242258

243259
/// Tests binary file writing to output_stream
244-
TEST(file, output_stream_binary) {
260+
TEST(file, output_stream_write_binary) {
245261
file tmpfile = file();
246262
std::ofstream ostream = tmpfile.output_stream();
247263
ostream << "Hello\n" << std::flush;
@@ -262,23 +278,60 @@ TEST(file, output_stream_binary) {
262278
}
263279

264280
/// Tests text file writing to output_stream
265-
TEST(file, output_stream_text) {
281+
TEST(file, output_stream_write_text) {
266282
file tmpfile = file::text();
267283
std::ofstream ostream = tmpfile.output_stream();
268284
ostream << "Hello\n" << std::flush;
269285

270286
{
271-
auto stream = std::ifstream(tmpfile.path());
287+
auto stream = std::ifstream(tmpfile.path(), std::ios::binary);
288+
auto content = std::string(std::istreambuf_iterator<char>(stream), {});
289+
#ifdef _WIN32
290+
EXPECT_EQ(content, "Hello\r\n");
291+
#else
292+
EXPECT_EQ(content, "Hello\n");
293+
#endif
294+
}
295+
296+
tmpfile.write("world!\n");
297+
298+
{
299+
auto stream = std::ifstream(tmpfile.path(), std::ios::binary);
300+
auto content = std::string(std::istreambuf_iterator<char>(stream), {});
301+
#ifdef _WIN32
302+
EXPECT_EQ(content, "world!\r\n");
303+
#else
304+
EXPECT_EQ(content, "world!\n");
305+
#endif
306+
}
307+
}
308+
309+
/// Tests text file writing to output_stream even when binary was requested
310+
TEST(file, output_stream_write_text_binary) {
311+
file tmpfile = file::text();
312+
std::ofstream ostream = tmpfile.output_stream(std::ios::binary);
313+
ostream << "Hello\n" << std::flush;
314+
315+
{
316+
auto stream = std::ifstream(tmpfile.path(), std::ios::binary);
272317
auto content = std::string(std::istreambuf_iterator<char>(stream), {});
318+
#ifdef _WIN32
319+
EXPECT_EQ(content, "Hello\r\n");
320+
#else
273321
EXPECT_EQ(content, "Hello\n");
322+
#endif
274323
}
275324

276325
tmpfile.write("world!\n");
277326

278327
{
279-
auto stream = std::ifstream(tmpfile.path());
328+
auto stream = std::ifstream(tmpfile.path(), std::ios::binary);
280329
auto content = std::string(std::istreambuf_iterator<char>(stream), {});
330+
#ifdef _WIN32
331+
EXPECT_EQ(content, "world!\r\n");
332+
#else
281333
EXPECT_EQ(content, "world!\n");
334+
#endif
282335
}
283336
}
284337

@@ -321,9 +374,13 @@ TEST(file, output_stream_append_text) {
321374
}
322375

323376
{
324-
auto stream = std::ifstream(tmpfile.path());
377+
auto stream = std::ifstream(tmpfile.path(), std::ios::binary);
325378
auto content = std::string(std::istreambuf_iterator<char>(stream), {});
379+
#ifdef _WIN32
380+
EXPECT_EQ(content, "Hello,\r\n world");
381+
#else
326382
EXPECT_EQ(content, "Hello,\n world");
383+
#endif
327384
}
328385

329386
{
@@ -332,9 +389,49 @@ TEST(file, output_stream_append_text) {
332389
}
333390

334391
{
335-
auto stream = std::ifstream(tmpfile.path());
392+
auto stream = std::ifstream(tmpfile.path(), std::ios::binary);
336393
auto content = std::string(std::istreambuf_iterator<char>(stream), {});
394+
#ifdef _WIN32
395+
EXPECT_EQ(content, "Hello,\r\n world!");
396+
#else
337397
EXPECT_EQ(content, "Hello,\n world!");
398+
#endif
399+
}
400+
}
401+
402+
/// Tests text file appending to output_stream even when binary was requested
403+
TEST(file, output_stream_append_text_binary) {
404+
file tmpfile = file::text();
405+
std::ofstream(tmpfile.path()) << "Hello,\n ";
406+
407+
{
408+
auto ostream = tmpfile.output_stream(std::ios::app | std::ios::binary);
409+
ostream << "world" << std::flush;
410+
}
411+
412+
{
413+
auto stream = std::ifstream(tmpfile.path(), std::ios::binary);
414+
auto content = std::string(std::istreambuf_iterator<char>(stream), {});
415+
#ifdef _WIN32
416+
EXPECT_EQ(content, "Hello,\r\n world");
417+
#else
418+
EXPECT_EQ(content, "Hello,\n world");
419+
#endif
420+
}
421+
422+
{
423+
auto ostream = tmpfile.output_stream(std::ios::app | std::ios::binary);
424+
ostream << "!" << std::flush;
425+
}
426+
427+
{
428+
auto stream = std::ifstream(tmpfile.path(), std::ios::binary);
429+
auto content = std::string(std::istreambuf_iterator<char>(stream), {});
430+
#ifdef _WIN32
431+
EXPECT_EQ(content, "Hello,\r\n world!");
432+
#else
433+
EXPECT_EQ(content, "Hello,\n world!");
434+
#endif
338435
}
339436
}
340437

0 commit comments

Comments
 (0)