00001 #ifndef WIBBLE_STREAM_POSIX_H
00002 #define WIBBLE_STREAM_POSIX_H
00003
00004 #include <wibble/exception.h>
00005 #include <streambuf>
00006 #include <unistd.h>
00007
00008
00009
00010
00011 namespace wibble {
00012 namespace stream {
00013
00014 class PosixBuf : public std::streambuf
00015 {
00016 private:
00017
00018 char* m_buf;
00019 size_t m_buf_size;
00020 int m_fd;
00021
00022
00023 PosixBuf(const PosixBuf&);
00024 PosixBuf& operator=(const PosixBuf&);
00025
00026 public:
00027
00028
00029 PosixBuf() : m_buf(0), m_buf_size(0), m_fd(-1) {}
00030 PosixBuf(int fd, size_t bufsize = 4096) : m_buf(0), m_buf_size(0), m_fd(-1)
00031 {
00032 attach(fd, bufsize);
00033 }
00034 ~PosixBuf()
00035 {
00036 if (m_buf)
00037 {
00038 sync();
00039 delete[] m_buf;
00040 }
00041 if (m_fd != -1)
00042 {
00043 ::close(m_fd);
00044 }
00045 }
00046
00053 void attach(int fd, size_t bufsize = 4096)
00054 {
00055 m_buf = new char[1024];
00056 if (!m_buf)
00057 throw wibble::exception::Consistency("allocating 1024 bytes for posix stream buffer", "allocation failed");
00058 m_fd = fd;
00059 m_buf_size = 1024;
00060 setp(m_buf, m_buf + m_buf_size);
00061 }
00062
00070 int detach()
00071 {
00072 sync();
00073 int res = m_fd;
00074 delete[] m_buf;
00075 m_buf = 0;
00076 m_buf_size = 0;
00077 m_fd = -1;
00078
00079
00080 setp(0, 0);
00081 return res;
00082 }
00083
00085 int fd() const { return m_fd; }
00086
00087
00088
00089
00090 int overflow(int c)
00091 {
00092 sync();
00093 if (c != EOF)
00094 {
00095 *pptr() = c;
00096 pbump(1);
00097 }
00098 return c;
00099 }
00100 int sync()
00101 {
00102 if (pptr() > pbase())
00103 {
00104 int amount = pptr() - pbase();
00105 int res = ::write(m_fd, m_buf, amount);
00106 if (res != amount)
00107 throw wibble::exception::System("writing to file");
00108 setp(m_buf, m_buf + m_buf_size);
00109 }
00110 return 0;
00111 }
00112 };
00113
00114 }
00115 }
00116
00117 #endif