Remove redundant void argument list in function def
[openal-soft.git] / Alc / compat.h
blobdc652bcad18c6a31ddb294b49c4e2c29dbdf308b
1 #ifndef AL_COMPAT_H
2 #define AL_COMPAT_H
4 #ifdef __cplusplus
6 #ifdef _WIN32
8 #define WIN32_LEAN_AND_MEAN
9 #include <windows.h>
11 #include <array>
12 #include <string>
13 #include <fstream>
15 inline std::string wstr_to_utf8(const WCHAR *wstr)
17 std::string ret;
19 int len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, nullptr, 0, nullptr, nullptr);
20 if(len > 0)
22 ret.resize(len);
23 WideCharToMultiByte(CP_UTF8, 0, wstr, -1, &ret[0], len, nullptr, nullptr);
24 ret.pop_back();
27 return ret;
30 inline std::wstring utf8_to_wstr(const char *str)
32 std::wstring ret;
34 int len = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
35 if(len > 0)
37 ret.resize(len);
38 MultiByteToWideChar(CP_UTF8, 0, str, -1, &ret[0], len);
39 ret.pop_back();
42 return ret;
46 namespace al {
48 // Windows' std::ifstream fails with non-ANSI paths since the standard only
49 // specifies names using const char* (or std::string). MSVC has a non-standard
50 // extension using const wchar_t* (or std::wstring?) to handle Unicode paths,
51 // but not all Windows compilers support it. So we have to make our own istream
52 // that accepts UTF-8 paths and forwards to Unicode-aware I/O functions.
53 class filebuf final : public std::streambuf {
54 std::array<char_type,4096> mBuffer;
55 HANDLE mFile{INVALID_HANDLE_VALUE};
57 int_type underflow() override
59 if(mFile != INVALID_HANDLE_VALUE && gptr() == egptr())
61 // Read in the next chunk of data, and set the pointers on success
62 DWORD got = 0;
63 if(ReadFile(mFile, mBuffer.data(), (DWORD)mBuffer.size(), &got, nullptr))
64 setg(mBuffer.data(), mBuffer.data(), mBuffer.data()+got);
66 if(gptr() == egptr())
67 return traits_type::eof();
68 return traits_type::to_int_type(*gptr());
71 pos_type seekoff(off_type offset, std::ios_base::seekdir whence, std::ios_base::openmode mode) override
73 if(mFile == INVALID_HANDLE_VALUE || (mode&std::ios_base::out) || !(mode&std::ios_base::in))
74 return traits_type::eof();
76 LARGE_INTEGER fpos;
77 switch(whence)
79 case std::ios_base::beg:
80 fpos.QuadPart = offset;
81 if(!SetFilePointerEx(mFile, fpos, &fpos, FILE_BEGIN))
82 return traits_type::eof();
83 break;
85 case std::ios_base::cur:
86 // If the offset remains in the current buffer range, just
87 // update the pointer.
88 if((offset >= 0 && offset < off_type(egptr()-gptr())) ||
89 (offset < 0 && -offset <= off_type(gptr()-eback())))
91 // Get the current file offset to report the correct read
92 // offset.
93 fpos.QuadPart = 0;
94 if(!SetFilePointerEx(mFile, fpos, &fpos, FILE_CURRENT))
95 return traits_type::eof();
96 setg(eback(), gptr()+offset, egptr());
97 return fpos.QuadPart - off_type(egptr()-gptr());
99 // Need to offset for the file offset being at egptr() while
100 // the requested offset is relative to gptr().
101 offset -= off_type(egptr()-gptr());
102 fpos.QuadPart = offset;
103 if(!SetFilePointerEx(mFile, fpos, &fpos, FILE_CURRENT))
104 return traits_type::eof();
105 break;
107 case std::ios_base::end:
108 fpos.QuadPart = offset;
109 if(!SetFilePointerEx(mFile, fpos, &fpos, FILE_END))
110 return traits_type::eof();
111 break;
113 default:
114 return traits_type::eof();
116 setg(nullptr, nullptr, nullptr);
117 return fpos.QuadPart;
120 pos_type seekpos(pos_type pos, std::ios_base::openmode mode) override
122 // Simplified version of seekoff
123 if(mFile == INVALID_HANDLE_VALUE || (mode&std::ios_base::out) || !(mode&std::ios_base::in))
124 return traits_type::eof();
126 LARGE_INTEGER fpos;
127 fpos.QuadPart = pos;
128 if(!SetFilePointerEx(mFile, fpos, &fpos, FILE_BEGIN))
129 return traits_type::eof();
131 setg(nullptr, nullptr, nullptr);
132 return fpos.QuadPart;
135 public:
136 bool open(const wchar_t *filename, std::ios_base::openmode mode)
138 if((mode&std::ios_base::out) || !(mode&std::ios_base::in))
139 return false;
140 HANDLE f{CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, nullptr,
141 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr)};
142 if(f == INVALID_HANDLE_VALUE) return false;
144 if(mFile != INVALID_HANDLE_VALUE)
145 CloseHandle(mFile);
146 mFile = f;
148 setg(nullptr, nullptr, nullptr);
149 return true;
151 bool open(const char *filename, std::ios_base::openmode mode)
153 std::wstring wname{utf8_to_wstr(filename)};
154 return open(wname.c_str(), mode);
157 bool is_open() const noexcept { return mFile != INVALID_HANDLE_VALUE; }
159 filebuf() = default;
160 ~filebuf() override
162 if(mFile != INVALID_HANDLE_VALUE)
163 CloseHandle(mFile);
164 mFile = INVALID_HANDLE_VALUE;
168 // Inherit from std::istream to use our custom streambuf
169 class ifstream final : public std::istream {
170 filebuf mStreamBuf;
172 public:
173 ifstream(const std::wstring &filename, std::ios_base::openmode mode = std::ios_base::in)
174 : ifstream(filename.c_str(), mode) { }
175 ifstream(const wchar_t *filename, std::ios_base::openmode mode = std::ios_base::in)
176 : std::istream{nullptr}
178 init(&mStreamBuf);
180 // Set the failbit if the file failed to open.
181 if((mode&std::ios_base::out) ||
182 !mStreamBuf.open(filename, mode|std::ios_base::in))
183 clear(failbit);
186 ifstream(const std::string &filename, std::ios_base::openmode mode = std::ios_base::in)
187 : ifstream(filename.c_str(), mode) { }
188 ifstream(const char *filename, std::ios_base::openmode mode = std::ios_base::in)
189 : std::istream{nullptr}
191 init(&mStreamBuf);
193 // Set the failbit if the file failed to open.
194 if((mode&std::ios_base::out) ||
195 !mStreamBuf.open(filename, mode|std::ios_base::in))
196 clear(failbit);
199 bool is_open() const noexcept { return mStreamBuf.is_open(); }
202 } // namespace al
204 #define HAVE_DYNLOAD 1
206 #else /* _WIN32 */
208 #include <fstream>
210 namespace al {
212 using filebuf = std::filebuf;
213 using ifstream = std::ifstream;
215 } // namespace al
217 #if defined(HAVE_DLFCN_H)
218 #define HAVE_DYNLOAD 1
219 #endif
221 #endif /* _WIN32 */
223 #include <string>
225 struct PathNamePair { std::string path, fname; };
226 const PathNamePair &GetProcBinary(void);
228 #ifdef HAVE_DYNLOAD
229 void *LoadLib(const char *name);
230 void CloseLib(void *handle);
231 void *GetSymbol(void *handle, const char *name);
232 #endif
234 #endif /* __cplusplus */
236 #endif /* AL_COMPAT_H */