8#ifndef BOOST_NOWIDE_FILEBUF_HPP_INCLUDED
9#define BOOST_NOWIDE_FILEBUF_HPP_INCLUDED
12#if BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT
13#include <boost/nowide/cstdio.hpp>
14#include <boost/nowide/detail/is_path.hpp>
15#include <boost/nowide/stackstring.hpp>
31 BOOST_NOWIDE_DECL std::streampos ftell(FILE* file);
33 BOOST_NOWIDE_DECL
int fseek(FILE* file, std::streamoff offset,
int origin);
36#if !BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT && !defined(BOOST_NOWIDE_DOXYGEN)
37 using std::basic_filebuf;
47 template<typename CharType, typename Traits = std::char_traits<CharType>>
60 using Traits = std::char_traits<char>;
65#pragma warning(disable : 4351)
71 file_(nullptr), buffer_(nullptr), buffer_size_(BUFSIZ), owns_buffer_(false), unbuffered_read_(false),
72 last_char_(), mode_(std::ios_base::openmode(0))
74 setg(
nullptr,
nullptr,
nullptr);
75 setp(
nullptr,
nullptr);
86 basic_filebuf& operator=(basic_filebuf&& other)
noexcept
92 void swap(basic_filebuf& rhs)
94 std::basic_streambuf<char>::swap(rhs);
96 swap(file_, rhs.file_);
97 swap(buffer_, rhs.buffer_);
98 swap(buffer_size_, rhs.buffer_size_);
99 swap(owns_buffer_, rhs.owns_buffer_);
100 swap(unbuffered_read_, rhs.unbuffered_read_);
101 swap(last_char_[0], rhs.last_char_[0]);
102 swap(mode_, rhs.mode_);
105 if(pbase() == rhs.last_char_)
106 setp(last_char_, (pptr() == epptr()) ? last_char_ : last_char_ + 1);
107 if(eback() == rhs.last_char_)
108 setg(last_char_, (gptr() == rhs.last_char_) ? last_char_ : last_char_ + 1, last_char_ + 1);
110 if(rhs.pbase() == last_char_)
111 rhs.setp(rhs.last_char_, (rhs.pptr() == rhs.epptr()) ? rhs.last_char_ : rhs.last_char_ + 1);
112 if(rhs.eback() == last_char_)
114 rhs.setg(rhs.last_char_,
115 (rhs.gptr() == last_char_) ? rhs.last_char_ : rhs.last_char_ + 1,
120 virtual ~basic_filebuf()
130 return open(s.c_str(), mode);
138 return open(name.
get(), mode);
145 validate_cvt(this->getloc());
146 const bool ate = (mode & std::ios_base::ate) != 0;
148 mode &= ~std::ios_base::ate;
149 const wchar_t* smode = get_mode(mode);
152 file_ = detail::wfopen(s, smode);
155 if(ate && detail::fseek(file_, 0, SEEK_END) != 0)
161 set_unbuffered_read();
164 template<
typename Path>
165 detail::enable_if_path_t<Path, basic_filebuf*> open(
const Path& file_name, std::ios_base::openmode mode)
167 return open(file_name.c_str(), mode);
176 bool res = sync() == 0;
177 if(std::fclose(file_) != 0)
180 mode_ = std::ios_base::openmode(0);
185 owns_buffer_ =
false;
187 setg(
nullptr,
nullptr,
nullptr);
188 setp(
nullptr,
nullptr);
189 return res ? this :
nullptr;
196 return file_ !=
nullptr;
200 std::streambuf* setbuf(
char* s, std::streamsize n)
override
205 setg(
nullptr,
nullptr,
nullptr);
206 setp(
nullptr,
nullptr);
210 owns_buffer_ =
false;
213 buffer_size_ = (n >= 0) ?
static_cast<size_t>(n) : 0;
214 set_unbuffered_read();
228 const bool has_prev_write = pptr() != buffer_;
229 result = overflow() != EOF;
230 if(has_prev_write && std::fflush(file_) != 0)
233 result = stop_reading();
234 return result ? 0 : -1;
237 int overflow(
int c = EOF)
override
239 if(!(mode_ & (std::ios_base::out | std::ios_base::app)))
245 size_t n = pptr() - pbase();
248 if(std::fwrite(pbase(), 1, n, file_) != n)
251 setp(buffer_, buffer_ + buffer_size_);
254 *buffer_ = Traits::to_char_type(c);
262 setp(buffer_, buffer_ + buffer_size_);
263 *buffer_ = Traits::to_char_type(c);
265 }
else if(std::fputc(c, file_) == EOF)
271 setp(last_char_, last_char_);
274 return Traits::not_eof(c);
277 std::streamsize xsputn(
const char* s, std::streamsize n)
override
280 if(n <=
static_cast<std::streamsize
>(buffer_size_))
281 return std::basic_streambuf<char>::xsputn(s, n);
282 if(!(mode_ & (std::ios_base::out | std::ios_base::app)) || !stop_reading())
287 const char*
const base = pbase();
288 const size_t num_buffered = pptr() - base;
289 if(num_buffered != 0)
291 const auto num_written = std::fwrite(base, 1, num_buffered, file_);
292 setp(
const_cast<char*
>(base + num_written), epptr());
293 if(num_written != num_buffered)
297 const auto num_written = std::fwrite(s, 1,
static_cast<size_t>(n), file_);
298 if(num_written > 0u && base != last_char_)
299 setp(last_char_, last_char_);
303 int underflow()
override
305 if(!(mode_ & std::ios_base::in) || !stop_writing())
309 const int c = std::fgetc(file_);
312 last_char_[0] = Traits::to_char_type(c);
313 setg(last_char_, last_char_, last_char_ + 1);
317 const size_t n = std::fread(buffer_, 1, buffer_size_, file_);
318 setg(buffer_, buffer_, buffer_ + n);
322 return Traits::to_int_type(*gptr());
325 std::streamsize xsgetn(
char* s, std::streamsize n)
override
328 if(n <=
static_cast<std::streamsize
>(unbuffered_read_ ? 1u : buffer_size_))
329 return std::basic_streambuf<char>::xsgetn(s, n);
330 if(!(mode_ & std::ios_base::in) || !stop_writing())
333 std::streamsize num_copied = 0;
335 const auto num_buffered = egptr() - gptr();
336 if(num_buffered != 0)
338 const auto num_read = num_buffered > n ? n : num_buffered;
339 traits_type::copy(s, gptr(),
static_cast<size_t>(num_read));
342 num_copied = num_read;
343 setg(eback(), gptr() + num_read, egptr());
348 const auto num_read = std::fread(s, 1,
static_cast<size_t>(n), file_);
353 num_copied += num_read;
358 int pbackfail(
int c = EOF)
override
368 if(c != EOF && *gptr() != Traits::to_char_type(c))
369 *gptr() = Traits::to_char_type(c);
370 return Traits::not_eof(c);
373 std::streampos seekoff(std::streamoff off,
374 std::ios_base::seekdir seekdir,
375 std::ios_base::openmode = std::ios_base::in | std::ios_base::out)
override
388 case std::ios_base::beg: whence = SEEK_SET;
break;
389 case std::ios_base::cur: whence = SEEK_CUR;
break;
390 case std::ios_base::end: whence = SEEK_END;
break;
391 default: assert(
false);
return EOF;
393 if(detail::fseek(file_, off, whence) != 0)
395 return detail::ftell(file_);
397 std::streampos seekpos(std::streampos pos,
398 std::ios_base::openmode m = std::ios_base::in | std::ios_base::out)
override
401 return seekoff(pos, std::ios_base::beg, m);
403 void imbue(
const std::locale& loc)
override
415 buffer_ =
new char[buffer_size_];
420 void set_unbuffered_read()
426 unbuffered_read_ = !(mode_ & std::ios_base::binary) || buffer_size_ == 0u;
429 void validate_cvt(
const std::locale& loc)
431 if(!std::use_facet<std::codecvt<char, char, std::mbstate_t>>(loc).always_noconv())
432 throw std::runtime_error(
"Converting codecvts are not supported");
441 const auto off = gptr() - egptr();
442 setg(
nullptr,
nullptr,
nullptr);
445#if defined(__clang__)
446#pragma clang diagnostic push
447#pragma clang diagnostic ignored "-Wtautological-constant-out-of-range-compare"
450 if(off < std::numeric_limits<std::streamoff>::min())
452#if defined(__clang__)
453#pragma clang diagnostic pop
455 return detail::fseek(file_,
static_cast<std::streamoff
>(off), SEEK_CUR) == 0;
464 const char*
const base = pbase();
465 const size_t n = pptr() - base;
466 setp(
nullptr,
nullptr);
467 if(n && std::fwrite(base, 1, n, file_) != n)
473 static const wchar_t* get_mode(std::ios_base::openmode mode)
481 if(mode == (std::ios_base::out))
483 if(mode == (std::ios_base::out | std::ios_base::app))
485 if(mode == (std::ios_base::app))
487 if(mode == (std::ios_base::out | std::ios_base::trunc))
489 if(mode == (std::ios_base::in))
491 if(mode == (std::ios_base::in | std::ios_base::out))
493 if(mode == (std::ios_base::in | std::ios_base::out | std::ios_base::trunc))
495 if(mode == (std::ios_base::in | std::ios_base::out | std::ios_base::app))
497 if(mode == (std::ios_base::in | std::ios_base::app))
499 if(mode == (std::ios_base::binary | std::ios_base::out))
501 if(mode == (std::ios_base::binary | std::ios_base::out | std::ios_base::app))
503 if(mode == (std::ios_base::binary | std::ios_base::app))
505 if(mode == (std::ios_base::binary | std::ios_base::out | std::ios_base::trunc))
507 if(mode == (std::ios_base::binary | std::ios_base::in))
509 if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::out))
511 if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::out | std::ios_base::trunc))
513 if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::out | std::ios_base::app))
515 if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::app))
524 bool unbuffered_read_;
526 std::ios::openmode mode_;
535 template<
typename CharType,
typename Traits>
This is the implementation of std::filebuf which is used when BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT is...
Definition: filebuf.hpp:59
basic_filebuf * close()
Definition: filebuf.hpp:172
basic_filebuf * open(const char *s, std::ios_base::openmode mode)
Definition: filebuf.hpp:135
basic_filebuf * open(const std::string &s, std::ios_base::openmode mode)
Definition: filebuf.hpp:128
basic_filebuf * open(const wchar_t *s, std::ios_base::openmode mode)
Opens the file with the given name, see std::filebuf::open.
Definition: filebuf.hpp:141
basic_filebuf()
Definition: filebuf.hpp:70
bool is_open() const
Definition: filebuf.hpp:194
This forward declaration defines the basic_filebuf type which is used when BOOST_NOWIDE_USE_FILEBUF_R...
Definition: filebuf.hpp:48
A class that allows to create a temporary wide or narrow UTF strings from wide or narrow UTF source.
Definition: stackstring.hpp:32
output_char * get()
Return the converted, NULL-terminated string or NULL if no string was converted.
Definition: stackstring.hpp:126
void swap(basic_filebuf< CharType, Traits > &lhs, basic_filebuf< CharType, Traits > &rhs)
Swap the basic_filebuf instances.
Definition: filebuf.hpp:536