-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFileStreamWrapper.cpp
More file actions
131 lines (101 loc) · 3.23 KB
/
FileStreamWrapper.cpp
File metadata and controls
131 lines (101 loc) · 3.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include "../classes/FileStreamWrapper.h"
#ifdef __MINGW32__
#include <ext/stdio_filebuf.h>
#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>
namespace {
void addAccess(int & result, std::ios_base::openmode mode, std::ios_base::openmode modeCheck, int flag)
{
if( (mode & modeCheck) == modeCheck ) {
result |= flag;
}
}
int wOpenMode(std::ios_base::openmode mode)
{
int result = 0;
if( (mode & (std::ios_base::in | std::ios_base::out)) == (std::ios_base::in | std::ios_base::out) ) {
result = _O_RDWR;
} else if( (mode & std::ios_base::in) == std::ios_base::in ) {
result = _O_RDONLY;
} else if( (mode & std::ios_base::out) == std::ios_base::out ) {
result = _O_WRONLY;
}
addAccess(result,mode,std::ios_base::out,_O_CREAT);
addAccess(result,mode,std::ios_base::binary,_O_BINARY);
addAccess(result,mode,std::ios_base::app,_O_APPEND);
addAccess(result,mode,std::ios_base::trunc,_O_TRUNC);
return result;
}
int wOpenFlags(std::ios_base::openmode mode)
{
int result = 0;
if( (mode & (std::ios_base::in | std::ios_base::out)) == (std::ios_base::in | std::ios_base::out) ) {
result = _S_IREAD | _S_IWRITE;
} else if( (mode & std::ios_base::in) == std::ios_base::in ) {
result = _S_IREAD;
} else if( (mode & std::ios_base::out) == std::ios_base::out ) {
result = _S_IWRITE;
}
return result;
}
}
#endif
#include <iostream>
namespace fs {
// MINGW does not implement the fucking wchar_t * fstream constructor overload, so I have to manually create a __gnu_cxx::stdio_filebuf
// TODO something is wrong here. filebuf is doing seg faults and other awful things
// #define MITIGATION_FIX
int checkFd(int fd)
{
if( fd == -1 ) {
std::cerr << "error " << errno << std::endl;
fd = 0;
}
return fd;
}
class FileStreamWrapperImpl {
public:
__gnu_cxx::stdio_filebuf<char> fb;
FileStreamWrapperImpl(wchar_t const * filename, std::ios_base::openmode mode):
fb(checkFd(_wopen(filename,wOpenMode(mode),wOpenFlags(mode))),mode)
{
}
};
#ifdef MITIGATION_FIX
// TODO mitigation to the __gnu_cxx::stdio_filebuf problem. it won't work with non-ascii names
FileStreamWrapper::FileStreamWrapper(Filename const & filename, std::ios_base::openmode mode):
std::fstream(filename.toUTF8(),mode)
{
}
FileStreamWrapper::FileStreamWrapper(FileStreamWrapper && other)
{
std::ios::rdbuf(other.rdbuf());
other.std::ios::rdbuf(0);
}
void FileStreamWrapper::open(Filename const & filename, std::ios_base::openmode mode)
{
open(filename.toUTF8(),mode);
}
#else
FileStreamWrapper::FileStreamWrapper(Filename const & filename, std::ios_base::openmode mode):
impl(new FileStreamWrapperImpl(filename.wstr.c_str(),mode))
{
std::ios::rdbuf(&impl->fb);
}
FileStreamWrapper::FileStreamWrapper(FileStreamWrapper && other):
impl(std::move(other.impl))
{
std::ios::rdbuf(&impl->fb);
}
void FileStreamWrapper::open(Filename const & filename, std::ios_base::openmode mode)
{
impl.reset();
impl.reset(new FileStreamWrapperImpl(filename.wstr.c_str(),mode));
basic_ios<char>::rdbuf(&impl->fb);
}
#endif
FileStreamWrapper::~FileStreamWrapper()
{
}
}