mirror of
https://github.com/fmtlib/fmt.git
synced 2025-02-14 09:39:51 +00:00
Add glibc stream support
This commit is contained in:
parent
b5669512b1
commit
ffce3632b7
@ -1471,14 +1471,44 @@ template <typename F> class file_base {
|
||||
|
||||
// A FILE wrapper for glibc.
|
||||
template <typename F> class glibc_file : public file_base<F> {
|
||||
private:
|
||||
enum {
|
||||
line_buffered = 0x200, // _IO_LINE_BUF
|
||||
unbuffered = 2 // _IO_UNBUFFERED
|
||||
};
|
||||
|
||||
public:
|
||||
using file_base<F>::file_base;
|
||||
|
||||
auto is_buffered() const -> bool {
|
||||
return (this->file_->_flags & unbuffered) == 0;
|
||||
}
|
||||
|
||||
// Returns the file's read buffer as a string_view.
|
||||
auto get_read_buffer() const -> span<const char> {
|
||||
return {this->file_->_IO_read_ptr,
|
||||
to_unsigned(this->file_->_IO_read_end - this->file_->_IO_read_ptr)};
|
||||
}
|
||||
|
||||
auto get_write_buffer() const -> span<char> {
|
||||
char*& ptr = this->file_->_IO_write_ptr;
|
||||
char*& end = this->file_->_IO_buf_end;
|
||||
if (!ptr || ptr == end) {
|
||||
// Force buffer initialization by placing and removing a char in a buffer.
|
||||
putc_unlocked(0, this->file_);
|
||||
--ptr;
|
||||
}
|
||||
FMT_ASSERT(ptr < end, "");
|
||||
return {ptr, static_cast<size_t>(end - ptr)};
|
||||
}
|
||||
|
||||
void advance_write_buffer(size_t size) { this->file_->_IO_write_ptr += size; }
|
||||
|
||||
bool needs_flush() const {
|
||||
if ((this->file_->_flags & line_buffered) == 0) return false;
|
||||
char* end = this->file_->_IO_write_end;
|
||||
return memchr(end, '\n', to_unsigned(this->file_->_IO_write_ptr - end));
|
||||
}
|
||||
};
|
||||
|
||||
// A FILE wrapper for Apple's libc.
|
||||
@ -1488,11 +1518,16 @@ template <typename F> class apple_file : public file_base<F> {
|
||||
return this->file_->_p - this->file_->_bf._base;
|
||||
}
|
||||
|
||||
enum {
|
||||
line_buffered = 1, // __SNBF
|
||||
unbuffered = 2 // __SLBF
|
||||
};
|
||||
|
||||
public:
|
||||
using file_base<F>::file_base;
|
||||
|
||||
auto is_buffered() const -> bool {
|
||||
return (this->file_->_flags & 2) == 0; // 2 is __SNBF.
|
||||
return (this->file_->_flags & unbuffered) == 0;
|
||||
}
|
||||
|
||||
auto get_read_buffer() const -> span<const char> {
|
||||
@ -1519,7 +1554,7 @@ template <typename F> class apple_file : public file_base<F> {
|
||||
}
|
||||
|
||||
bool needs_flush() const {
|
||||
if ((this->file_->_flags & 1) == 0) return false; // 1 is __SLBF.
|
||||
if ((this->file_->_flags & line_buffered) == 0) return false;
|
||||
return memchr(this->file_->_p + this->file_->_w, '\n',
|
||||
to_unsigned(-this->file_->_w));
|
||||
}
|
||||
@ -1561,6 +1596,10 @@ template <typename F, FMT_ENABLE_IF(sizeof(F::_p) != 0)>
|
||||
auto get_file(F* f, int) -> apple_file<F> {
|
||||
return f;
|
||||
}
|
||||
template <typename F, FMT_ENABLE_IF(sizeof(F::_IO_read_ptr) != 0)>
|
||||
inline auto get_file(F* f, int) -> glibc_file<F> {
|
||||
return f;
|
||||
}
|
||||
inline auto get_file(FILE* f, ...) -> fallback_file<FILE> { return f; }
|
||||
|
||||
using file_ref = decltype(get_file(static_cast<FILE*>(nullptr), 0));
|
||||
|
Loading…
x
Reference in New Issue
Block a user