wibble 0.1.28
posix.h
Go to the documentation of this file.
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 // http://www.icce.rug.nl/documents/cplusplus/cplusplus21.html#CONCRETE
00010 // 21.2.1: Classes for output operations
00011 
00012 namespace wibble {
00013 namespace stream {
00014 
00015 class PosixBuf : public std::streambuf
00016 {
00017 private:
00018     // The output buffer
00019     char* m_buf;
00020     size_t m_buf_size;
00021     int m_fd;
00022 
00023     // Disallow copy
00024     PosixBuf(const PosixBuf&);
00025     PosixBuf& operator=(const PosixBuf&);
00026 
00027 public:
00028     // PosixBuf functions
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         // TODO: setp or anything like that, to tell the streambuf that there's
00080         // no buffer anymore?
00081         setp(0, 0);
00082         return res;
00083     }
00084 
00086     int fd() const { return m_fd; }
00087 
00088 
00089     // Functions from strbuf
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