wibble
0.1.28
|
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