12 auto filebuf::underflow() -> int_type
14 if(mFile
!= INVALID_HANDLE_VALUE
&& gptr() == egptr())
16 // Read in the next chunk of data, and set the pointers on success
18 if(ReadFile(mFile
, mBuffer
.data(), static_cast<DWORD
>(mBuffer
.size()), &got
, nullptr))
19 setg(mBuffer
.data(), mBuffer
.data(), mBuffer
.data()+got
);
22 return traits_type::eof();
23 return traits_type::to_int_type(*gptr());
26 auto filebuf::seekoff(off_type offset
, std::ios_base::seekdir whence
, std::ios_base::openmode mode
) -> pos_type
28 if(mFile
== INVALID_HANDLE_VALUE
|| (mode
&std::ios_base::out
) || !(mode
&std::ios_base::in
))
29 return traits_type::eof();
34 case std::ios_base::beg
:
35 fpos
.QuadPart
= offset
;
36 if(!SetFilePointerEx(mFile
, fpos
, &fpos
, FILE_BEGIN
))
37 return traits_type::eof();
40 case std::ios_base::cur
:
41 // If the offset remains in the current buffer range, just
42 // update the pointer.
43 if((offset
>= 0 && offset
< off_type(egptr()-gptr())) ||
44 (offset
< 0 && -offset
<= off_type(gptr()-eback())))
46 // Get the current file offset to report the correct read
49 if(!SetFilePointerEx(mFile
, fpos
, &fpos
, FILE_CURRENT
))
50 return traits_type::eof();
51 setg(eback(), gptr()+offset
, egptr());
52 return fpos
.QuadPart
- off_type(egptr()-gptr());
54 // Need to offset for the file offset being at egptr() while
55 // the requested offset is relative to gptr().
56 offset
-= off_type(egptr()-gptr());
57 fpos
.QuadPart
= offset
;
58 if(!SetFilePointerEx(mFile
, fpos
, &fpos
, FILE_CURRENT
))
59 return traits_type::eof();
62 case std::ios_base::end
:
63 fpos
.QuadPart
= offset
;
64 if(!SetFilePointerEx(mFile
, fpos
, &fpos
, FILE_END
))
65 return traits_type::eof();
69 return traits_type::eof();
71 setg(nullptr, nullptr, nullptr);
75 auto filebuf::seekpos(pos_type pos
, std::ios_base::openmode mode
) -> pos_type
77 // Simplified version of seekoff
78 if(mFile
== INVALID_HANDLE_VALUE
|| (mode
&std::ios_base::out
) || !(mode
&std::ios_base::in
))
79 return traits_type::eof();
83 if(!SetFilePointerEx(mFile
, fpos
, &fpos
, FILE_BEGIN
))
84 return traits_type::eof();
86 setg(nullptr, nullptr, nullptr);
92 if(mFile
!= INVALID_HANDLE_VALUE
)
94 mFile
= INVALID_HANDLE_VALUE
;
97 bool filebuf::open(const wchar_t *filename
, std::ios_base::openmode mode
)
99 if((mode
&std::ios_base::out
) || !(mode
&std::ios_base::in
))
101 HANDLE f
{CreateFileW(filename
, GENERIC_READ
, FILE_SHARE_READ
, nullptr, OPEN_EXISTING
,
102 FILE_ATTRIBUTE_NORMAL
, nullptr)};
103 if(f
== INVALID_HANDLE_VALUE
) return false;
105 if(mFile
!= INVALID_HANDLE_VALUE
)
109 setg(nullptr, nullptr, nullptr);
112 bool filebuf::open(const char *filename
, std::ios_base::openmode mode
)
114 std::wstring wname
{utf8_to_wstr(filename
)};
115 return open(wname
.c_str(), mode
);
119 ifstream::ifstream(const wchar_t *filename
, std::ios_base::openmode mode
)
120 : std::istream
{nullptr}
124 // Set the failbit if the file failed to open.
125 if((mode
&std::ios_base::out
) || !mStreamBuf
.open(filename
, mode
|std::ios_base::in
))
129 ifstream::ifstream(const char *filename
, std::ios_base::openmode mode
)
130 : std::istream
{nullptr}
134 // Set the failbit if the file failed to open.
135 if((mode
&std::ios_base::out
) || !mStreamBuf
.open(filename
, mode
|std::ios_base::in
))
139 /* This is only here to ensure the compiler doesn't define an implicit
140 * destructor, which it tries to automatically inline and subsequently complain
141 * it can't inline without excessive code growth.
143 ifstream::~ifstream() { }