mirror of
https://github.com/polybar/polybar.git
synced 2024-11-18 13:55:11 -05:00
file_util: File descriptor streams
This commit is contained in:
parent
00ac4bea63
commit
f80d8ebf5b
2 changed files with 188 additions and 39 deletions
|
@ -10,14 +10,16 @@ class file_ptr {
|
||||||
explicit file_ptr(const string& path, const string& mode = "a+");
|
explicit file_ptr(const string& path, const string& mode = "a+");
|
||||||
~file_ptr();
|
~file_ptr();
|
||||||
|
|
||||||
file_ptr(const file_ptr& o) = delete;
|
explicit operator bool();
|
||||||
file_ptr& operator=(const file_ptr& o) = delete;
|
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;
|
FILE* m_ptr = nullptr;
|
||||||
string m_path;
|
string m_path;
|
||||||
string m_mode;
|
string m_mode;
|
||||||
|
@ -28,10 +30,65 @@ class file_descriptor {
|
||||||
explicit file_descriptor(const string& path, int flags = 0);
|
explicit file_descriptor(const string& path, int flags = 0);
|
||||||
explicit file_descriptor(int fd);
|
explicit file_descriptor(int fd);
|
||||||
~file_descriptor();
|
~file_descriptor();
|
||||||
operator int();
|
|
||||||
|
file_descriptor& operator=(const int);
|
||||||
|
|
||||||
|
explicit operator bool();
|
||||||
|
operator bool() const;
|
||||||
|
|
||||||
|
explicit operator int();
|
||||||
|
operator int() const;
|
||||||
|
|
||||||
protected:
|
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 {
|
namespace file_util {
|
||||||
|
|
|
@ -2,72 +2,164 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <streambuf>
|
||||||
|
|
||||||
#include "errors.hpp"
|
#include "errors.hpp"
|
||||||
#include "utils/file.hpp"
|
#include "utils/file.hpp"
|
||||||
|
|
||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
|
|
||||||
/**
|
// implementation of file_ptr {{{
|
||||||
* Deconstruct file wrapper
|
|
||||||
*/
|
|
||||||
file_ptr::file_ptr(const string& path, const string& mode) : m_path(string(path)), m_mode(string(mode)) {
|
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());
|
m_ptr = fopen(m_path.c_str(), m_mode.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Deconstruct file wrapper
|
|
||||||
*/
|
|
||||||
file_ptr::~file_ptr() {
|
file_ptr::~file_ptr() {
|
||||||
if (m_ptr != nullptr) {
|
if (m_ptr != nullptr) {
|
||||||
fclose(m_ptr);
|
fclose(m_ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Logical operator testing if the file handler was created
|
|
||||||
*/
|
|
||||||
file_ptr::operator bool() {
|
file_ptr::operator bool() {
|
||||||
|
return static_cast<const file_ptr&>(*this);
|
||||||
|
}
|
||||||
|
file_ptr::operator bool() const {
|
||||||
return m_ptr != nullptr;
|
return m_ptr != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
file_ptr::operator FILE*() {
|
||||||
* Call operator returning a pointer to the file handler
|
return static_cast<const file_ptr&>(*this);
|
||||||
*/
|
}
|
||||||
FILE* file_ptr::operator()() {
|
file_ptr::operator FILE*() const {
|
||||||
return m_ptr;
|
return m_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
file_ptr::operator int() {
|
||||||
* Construct file descriptor wrapper
|
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) {
|
file_descriptor::file_descriptor(const string& path, int flags) {
|
||||||
if ((m_fd = open(path.c_str(), flags)) == -1) {
|
if ((m_fd = open(path.c_str(), flags)) == -1) {
|
||||||
throw system_error("Failed to open file descriptor");
|
throw system_error("Failed to open file descriptor");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
file_descriptor::file_descriptor(int fd) : m_fd(fd) {
|
||||||
* Construct file descriptor wrapper from an existing handle
|
if (!*this) {
|
||||||
*/
|
throw system_error("Given file descriptor is not valid");
|
||||||
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() {
|
||||||
* Conversion operator returning the fd handle
|
close();
|
||||||
*/
|
}
|
||||||
|
|
||||||
|
file_descriptor& file_descriptor::operator=(const int fd) {
|
||||||
|
close();
|
||||||
|
m_fd = fd;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
file_descriptor::operator int() {
|
file_descriptor::operator int() {
|
||||||
|
return static_cast<const file_descriptor&>(*this);
|
||||||
|
}
|
||||||
|
file_descriptor::operator int() const {
|
||||||
return m_fd;
|
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 {
|
namespace file_util {
|
||||||
/**
|
/**
|
||||||
* Checks if the given file exist
|
* Checks if the given file exist
|
||||||
|
@ -86,7 +178,7 @@ namespace file_util {
|
||||||
string contents((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
|
string contents((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
|
||||||
return contents;
|
return contents;
|
||||||
} catch (std::ios_base::failure& e) {
|
} catch (std::ios_base::failure& e) {
|
||||||
return string{""};
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +187,7 @@ namespace file_util {
|
||||||
*/
|
*/
|
||||||
bool is_fifo(string filename) {
|
bool is_fifo(string filename) {
|
||||||
auto fileptr = factory_util::unique<file_ptr>(filename);
|
auto fileptr = factory_util::unique<file_ptr>(filename);
|
||||||
int fd = fileno((*fileptr)());
|
int fd = fileno(*fileptr);
|
||||||
struct stat statbuf {};
|
struct stat statbuf {};
|
||||||
fstat(fd, &statbuf);
|
fstat(fd, &statbuf);
|
||||||
return S_ISFIFO(statbuf.st_mode);
|
return S_ISFIFO(statbuf.st_mode);
|
||||||
|
|
Loading…
Reference in a new issue