file_util: File descriptor streams
This commit is contained in:
parent
00ac4bea63
commit
f80d8ebf5b
@ -10,14 +10,16 @@ class file_ptr {
|
||||
explicit file_ptr(const string& path, const string& mode = "a+");
|
||||
~file_ptr();
|
||||
|
||||
file_ptr(const file_ptr& o) = delete;
|
||||
file_ptr& operator=(const file_ptr& o) = delete;
|
||||
explicit operator bool();
|
||||
operator bool() const;
|
||||
|
||||
operator bool();
|
||||
explicit operator FILE*();
|
||||
operator FILE*() const;
|
||||
|
||||
FILE* operator()();
|
||||
explicit operator int();
|
||||
operator int() const;
|
||||
|
||||
protected:
|
||||
private:
|
||||
FILE* m_ptr = nullptr;
|
||||
string m_path;
|
||||
string m_mode;
|
||||
@ -28,10 +30,65 @@ class file_descriptor {
|
||||
explicit file_descriptor(const string& path, int flags = 0);
|
||||
explicit file_descriptor(int fd);
|
||||
~file_descriptor();
|
||||
operator int();
|
||||
|
||||
file_descriptor& operator=(const int);
|
||||
|
||||
explicit operator bool();
|
||||
operator bool() const;
|
||||
|
||||
explicit operator int();
|
||||
operator int() const;
|
||||
|
||||
protected:
|
||||
int m_fd{0};
|
||||
void close();
|
||||
|
||||
private:
|
||||
int m_fd{-1};
|
||||
};
|
||||
|
||||
class fd_streambuf : public std::streambuf {
|
||||
public:
|
||||
using traits_type = std::streambuf::traits_type;
|
||||
|
||||
explicit fd_streambuf(int fd);
|
||||
~fd_streambuf();
|
||||
|
||||
explicit operator int();
|
||||
operator int() const;
|
||||
|
||||
void open(int fd);
|
||||
void close();
|
||||
|
||||
protected:
|
||||
int sync();
|
||||
int overflow(int c);
|
||||
int underflow();
|
||||
|
||||
private:
|
||||
file_descriptor m_fd;
|
||||
char m_out[BUFSIZ];
|
||||
char m_in[BUFSIZ - 1];
|
||||
};
|
||||
|
||||
template <typename StreamType = std::ostream>
|
||||
class fd_stream : public StreamType {
|
||||
public:
|
||||
using type = fd_stream<StreamType>;
|
||||
|
||||
explicit fd_stream(int fd) : m_buf(fd) {
|
||||
StreamType::rdbuf(&m_buf);
|
||||
}
|
||||
|
||||
explicit operator int() {
|
||||
return static_cast<const type&>(*this);
|
||||
}
|
||||
|
||||
operator int() const {
|
||||
return m_buf;
|
||||
}
|
||||
|
||||
protected:
|
||||
fd_streambuf m_buf;
|
||||
};
|
||||
|
||||
namespace file_util {
|
||||
|
@ -2,72 +2,164 @@
|
||||
#include <sys/stat.h>
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <streambuf>
|
||||
|
||||
#include "errors.hpp"
|
||||
#include "utils/file.hpp"
|
||||
|
||||
POLYBAR_NS
|
||||
|
||||
/**
|
||||
* Deconstruct file wrapper
|
||||
*/
|
||||
// implementation of file_ptr {{{
|
||||
|
||||
file_ptr::file_ptr(const string& path, const string& mode) : m_path(string(path)), m_mode(string(mode)) {
|
||||
m_ptr = fopen(m_path.c_str(), m_mode.c_str());
|
||||
}
|
||||
|
||||
/**
|
||||
* Deconstruct file wrapper
|
||||
*/
|
||||
file_ptr::~file_ptr() {
|
||||
if (m_ptr != nullptr) {
|
||||
fclose(m_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logical operator testing if the file handler was created
|
||||
*/
|
||||
file_ptr::operator bool() {
|
||||
return static_cast<const file_ptr&>(*this);
|
||||
}
|
||||
file_ptr::operator bool() const {
|
||||
return m_ptr != nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call operator returning a pointer to the file handler
|
||||
*/
|
||||
FILE* file_ptr::operator()() {
|
||||
file_ptr::operator FILE*() {
|
||||
return static_cast<const file_ptr&>(*this);
|
||||
}
|
||||
file_ptr::operator FILE*() const {
|
||||
return m_ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct file descriptor wrapper
|
||||
*/
|
||||
file_ptr::operator int() {
|
||||
return static_cast<const file_ptr&>(*this);
|
||||
}
|
||||
file_ptr::operator int() const {
|
||||
return fileno(*this);
|
||||
}
|
||||
|
||||
// }}}
|
||||
// implementation of file_descriptor {{{
|
||||
|
||||
file_descriptor::file_descriptor(const string& path, int flags) {
|
||||
if ((m_fd = open(path.c_str(), flags)) == -1) {
|
||||
throw system_error("Failed to open file descriptor");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct file descriptor wrapper from an existing handle
|
||||
*/
|
||||
file_descriptor::file_descriptor(int fd) : m_fd(fd) {}
|
||||
|
||||
/**
|
||||
* Deconstruct file descriptor wrapper
|
||||
*/
|
||||
file_descriptor::~file_descriptor() {
|
||||
if (m_fd > 0) {
|
||||
close(m_fd);
|
||||
file_descriptor::file_descriptor(int fd) : m_fd(fd) {
|
||||
if (!*this) {
|
||||
throw system_error("Given file descriptor is not valid");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Conversion operator returning the fd handle
|
||||
*/
|
||||
file_descriptor::~file_descriptor() {
|
||||
close();
|
||||
}
|
||||
|
||||
file_descriptor& file_descriptor::operator=(const int fd) {
|
||||
close();
|
||||
m_fd = fd;
|
||||
return *this;
|
||||
}
|
||||
|
||||
file_descriptor::operator int() {
|
||||
return static_cast<const file_descriptor&>(*this);
|
||||
}
|
||||
file_descriptor::operator int() const {
|
||||
return m_fd;
|
||||
}
|
||||
|
||||
file_descriptor::operator bool() {
|
||||
return static_cast<const file_descriptor&>(*this);
|
||||
}
|
||||
file_descriptor::operator bool() const {
|
||||
errno = 0; // reset since fcntl only changes it on error
|
||||
if ((fcntl(m_fd, F_GETFD) == -1) || errno == EBADF) {
|
||||
errno = EBADF;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void file_descriptor::close() {
|
||||
if (m_fd == -1) {
|
||||
return;
|
||||
} else if (::close(m_fd) == -1) {
|
||||
throw system_error("Failed to close file descriptor");
|
||||
}
|
||||
m_fd = -1;
|
||||
}
|
||||
|
||||
// }}}
|
||||
// implementation of file_streambuf {{{
|
||||
|
||||
fd_streambuf::fd_streambuf(int fd) : m_fd(fd) {}
|
||||
|
||||
fd_streambuf::~fd_streambuf() {
|
||||
sync();
|
||||
}
|
||||
|
||||
fd_streambuf::operator int() {
|
||||
return static_cast<const fd_streambuf&>(*this);
|
||||
}
|
||||
fd_streambuf::operator int() const {
|
||||
return m_fd;
|
||||
}
|
||||
|
||||
void fd_streambuf::open(int fd) {
|
||||
if (m_fd) {
|
||||
sync();
|
||||
}
|
||||
m_fd = fd;
|
||||
setg(m_in, m_in, m_in);
|
||||
setp(m_out, m_out + sizeof(m_in));
|
||||
}
|
||||
|
||||
void fd_streambuf::close() {
|
||||
if (m_fd) {
|
||||
sync();
|
||||
m_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int fd_streambuf::sync() {
|
||||
if (pbase() != pptr()) {
|
||||
auto size = pptr() - pbase();
|
||||
auto bytes = ::write(m_fd, m_out, size);
|
||||
if (bytes > 0) {
|
||||
std::copy(pbase() + bytes, pptr(), pbase());
|
||||
setp(pbase(), epptr());
|
||||
pbump(size - bytes);
|
||||
}
|
||||
}
|
||||
return pptr() != epptr() ? 0 : -1;
|
||||
}
|
||||
|
||||
int fd_streambuf::overflow(int c) {
|
||||
if (!traits_type::eq_int_type(c, traits_type::eof())) {
|
||||
*pptr() = traits_type::to_char_type(c);
|
||||
pbump(1);
|
||||
}
|
||||
return sync() == -1 ? traits_type::eof() : traits_type::not_eof(c);
|
||||
}
|
||||
|
||||
int fd_streambuf::underflow() {
|
||||
if (gptr() == egptr()) {
|
||||
auto pback = std::min(gptr() - eback(), std::ptrdiff_t(m_in));
|
||||
std::copy(egptr() - pback, egptr(), eback());
|
||||
auto bytes = ::read(m_fd, eback() + pback, BUFSIZ);
|
||||
setg(eback(), eback() + pback, eback() + pback + std::max(0L, bytes));
|
||||
}
|
||||
return gptr() == egptr() ? traits_type::eof() : traits_type::to_int_type(*gptr());
|
||||
}
|
||||
|
||||
// }}}
|
||||
|
||||
namespace file_util {
|
||||
/**
|
||||
* Checks if the given file exist
|
||||
@ -86,7 +178,7 @@ namespace file_util {
|
||||
string contents((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
|
||||
return contents;
|
||||
} catch (std::ios_base::failure& e) {
|
||||
return string{""};
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,7 +187,7 @@ namespace file_util {
|
||||
*/
|
||||
bool is_fifo(string filename) {
|
||||
auto fileptr = factory_util::unique<file_ptr>(filename);
|
||||
int fd = fileno((*fileptr)());
|
||||
int fd = fileno(*fileptr);
|
||||
struct stat statbuf {};
|
||||
fstat(fd, &statbuf);
|
||||
return S_ISFIFO(statbuf.st_mode);
|
||||
|
Loading…
Reference in New Issue
Block a user