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