#ifdef UTIL_PIPESTREAM_H template <size_t buffersize> sizedpipestream<buffersize>::sizedpipestream() : wbufferpos(0), rbufferpos(buffersize), rbuffersize(buffersize), maxopsize(-1), is_eof(false), enable_multiline_strings(true) { // Give a compile time error if an invalid buffsize is specified // This is necessary for much easier primitive reading/writing // The buffer must be either 0 or at least large enough to hold any // primitive (probably 8 or 16 bytes) char buffer_size_must_be_0_or_over_16 [(buffersize != 0 && buffersize < sizeof(intmax_t)) ? -1 : 1]; buffer_size_must_be_0_or_over_16[0] = '\0'; // Create the pipe pipe(fds); } template <size_t buffersize> sizedpipestream<buffersize>::~sizedpipestream() { close(); } template <size_t buffersize> void sizedpipestream<buffersize>::close() { close_write(); close_read(); } template <size_t buffersize> void sizedpipestream<buffersize>::close_read() { if (fds[READ_END] == -1) return; ::close(fds[READ_END]); fds[READ_END] = -1; } template <size_t buffersize> void sizedpipestream<buffersize>::close_write() { if (fds[WRITE_END] == -1) return; flush(); ::close(fds[WRITE_END]); fds[WRITE_END] = -1; } template <size_t buffersize> int sizedpipestream<buffersize>::steal_output(int fd) { ::close(fd); dup2(fds[WRITE_END], fd); return 0; } template <size_t buffersize> int sizedpipestream<buffersize>::steal_input(int fd) { ::close(fd); dup2(fds[READ_END], fd); return 0; } template <size_t buffersize> int sizedpipestream<buffersize>::get_read_fd() { return fds[READ_END]; } template <size_t buffersize> int sizedpipestream<buffersize>::get_write_fd() { return fds[WRITE_END]; } template <size_t buffersize> void sizedpipestream<buffersize>::flush() { if (buffersize == 0 || wbufferpos == 0 || fds[WRITE_END] == -1) return; writen(fds[WRITE_END], &wbuffer[0], wbufferpos); wbufferpos = 0; } template <size_t buffersize> int sizedpipestream<buffersize>::fill(size_t byte_count) { if (buffersize == 0 || rbufferpos == 0 || fds[READ_END] == -1) return -1; if (buffersize - rbufferpos < byte_count) { memmove(&rbuffer[0], &rbuffer[rbufferpos], rbuffersize - rbufferpos); rbuffersize -= rbufferpos; rbufferpos = 0; } while (rbuffersize - rbufferpos < byte_count) { ssize_t read_count = ::read(fds[READ_END], &rbuffer[rbuffersize], buffersize - rbuffersize); if (read_count == 0) return 0; if (read_count == -1) { if (errno == EINTR) continue; return -1; } rbuffersize += read_count; } return rbuffersize - rbufferpos; } template <size_t buffersize> sizedpipestream<buffersize> & sizedpipestream<buffersize>::operator<<(const string & str) { if (buffersize == 0) { writen(fds[WRITE_END], str.c_str(), str.length()+1); return *this; } size_t len = str.length(); for (size_t i = 0; i < len; i++) { if (wbufferpos == buffersize) flush(); wbuffer[wbufferpos++] = str[i]; } if (wbufferpos == buffersize) flush(); wbuffer[wbufferpos++] = '\0'; return *this; } template <size_t buffersize> sizedpipestream<buffersize> & sizedpipestream<buffersize>::operator<<(const char * str) { if (buffersize == 0) { writen(fds[WRITE_END], str, strlen(str)+1); return *this; } for (size_t i = 0; str[i] != '\0'; i++) { if (wbufferpos == buffersize) flush(); wbuffer[wbufferpos++] = str[i]; } if (wbufferpos == buffersize) flush(); wbuffer[wbufferpos++] = '\0'; return *this; } template <size_t buffersize> sizedpipestream<buffersize> & sizedpipestream<buffersize>::operator>>(char * & str) { size_t capacity = 4; str = new char[capacity]; size_t len = 0; int error = 0; char c = '\0'; do { error = read_primitive<char>(c); if (len == maxopsize) continue; if (len == capacity) { char * temp = str; str = new char[capacity*2]; memcpy(str, temp, capacity); capacity *= 2; delete [] temp; } str[len++] = c; } while (error > 0 && c != '\0' && (enable_multiline_strings || c != '\n')); str[len-1] = '\0'; if (!enable_multiline_strings && len > 2 && str[len-2] == '\r') str[len-2] = '\0'; maxopsize = -1; return *this; } template <size_t buffersize> sizedpipestream<buffersize> & sizedpipestream<buffersize>::operator>>(string & str) { char * cstr = NULL; operator>>(cstr); str = cstr; delete [] cstr; return *this; } template <size_t buffersize> sizedpipestream<buffersize> & sizedpipestream<buffersize>::operator<< (pipestream_manip::enable_multiline_strings_t value) { enable_multiline_strings = value.value; return *this; } template <size_t buffersize> sizedpipestream<buffersize> & sizedpipestream<buffersize>::operator>> (pipestream_manip::setmax_t max) { maxopsize = max.max; return *this; } template <size_t buffersize> inline bool sizedpipestream<buffersize>::eof() { return is_eof; } template <size_t buffersize> inline sizedpipestream<buffersize> & sizedpipestream<buffersize>::operator<<(const signed char & value) { return write_primitive(value); } template <size_t buffersize> inline sizedpipestream<buffersize> & sizedpipestream<buffersize>::operator<<(const signed short & value) { return write_primitive(value); } template <size_t buffersize> inline sizedpipestream<buffersize> & sizedpipestream<buffersize>::operator<<(const signed int & value) { return write_primitive(value); } template <size_t buffersize> inline sizedpipestream<buffersize> & sizedpipestream<buffersize>::operator<<(const signed long & value) { return write_primitive(value); } template <size_t buffersize> inline sizedpipestream<buffersize> & sizedpipestream<buffersize>::operator<<(const unsigned char & value) { return write_primitive(value); } template <size_t buffersize> inline sizedpipestream<buffersize> & sizedpipestream<buffersize>::operator<<(const unsigned short & value) { return write_primitive(value); } template <size_t buffersize> inline sizedpipestream<buffersize> & sizedpipestream<buffersize>::operator<<(const unsigned int & value) { return write_primitive(value); } template <size_t buffersize> inline sizedpipestream<buffersize> & sizedpipestream<buffersize>::operator<<(const unsigned long & value) { return write_primitive(value); } template <size_t buffersize> inline sizedpipestream<buffersize> & sizedpipestream<buffersize>::operator>>(signed char & value) { read_primitive(value); return *this; } template <size_t buffersize> inline sizedpipestream<buffersize> & sizedpipestream<buffersize>::operator>>(signed short & value) { read_primitive(value); return *this; } template <size_t buffersize> inline sizedpipestream<buffersize> & sizedpipestream<buffersize>::operator>>(signed int & value) { read_primitive(value); return *this; } template <size_t buffersize> inline sizedpipestream<buffersize> & sizedpipestream<buffersize>::operator>>(signed long & value) { read_primitive(value); return *this; } template <size_t buffersize> inline sizedpipestream<buffersize> & sizedpipestream<buffersize>::operator>>(unsigned char & value) { read_primitive(value); return *this; } template <size_t buffersize> inline sizedpipestream<buffersize> & sizedpipestream<buffersize>::operator>>(unsigned short & value) { read_primitive(value); return *this; } template <size_t buffersize> inline sizedpipestream<buffersize> & sizedpipestream<buffersize>::operator>>(unsigned int & value) { read_primitive(value); return *this; } template <size_t buffersize> inline sizedpipestream<buffersize> & sizedpipestream<buffersize>::operator>>(unsigned long & value) { read_primitive(value); return *this; } template <size_t buffersize> template <typename T> sizedpipestream<buffersize> & sizedpipestream<buffersize>::write_primitive(T value) { if (fds[WRITE_END] == -1) return *this; if (buffersize == 0) { writen(fds[WRITE_END], &value, sizeof value); return *this; } if (buffersize - wbufferpos < sizeof value) flush(); *reinterpret_cast<T*>(&wbuffer[wbufferpos]) = value; wbufferpos += sizeof value; return *this; } template <size_t buffersize> template <typename T> int sizedpipestream<buffersize>::read_primitive(T & value) { if (fds[READ_END] == -1) return -1; if (buffersize == 0) return readn(fds[READ_END], &value, sizeof value); if (rbuffersize - rbufferpos < sizeof value) { int error = fill(sizeof value); if (error == 0) is_eof = true; if (error <= 0) return error; } value = *reinterpret_cast<T*>(&rbuffer[rbufferpos]); rbufferpos += sizeof value; return sizeof value; } #endif