IBR-DTNSuite  0.8
ibrcommon/ibrcommon/data/iobuffer.cpp
Go to the documentation of this file.
00001 /*
00002  * iobuffer.cpp
00003  *
00004  *  Created on: 14.02.2011
00005  *      Author: morgenro
00006  */
00007 
00008 #include "ibrcommon/data/iobuffer.h"
00009 #include "ibrcommon/thread/MutexLock.h"
00010 #include <string.h>
00011 
00012 namespace ibrcommon
00013 {
00014         iobuffer::iobuffer(const size_t buffer)
00015          : _eof(false), _data_size(0), _buf_size(buffer), _input_buf(new char[buffer]), _interim_buf(new char[buffer]), _output_buf(new char[buffer])
00016         {
00017                 // Initialize get pointer.  This should be zero so that underflow is called upon first read.
00018                 setg(0, 0, 0);
00019                 setp(_input_buf, _input_buf + _buf_size - 1);
00020         }
00021 
00022         iobuffer::~iobuffer()
00023         {
00024                 delete[] _input_buf;
00025                 delete[] _output_buf;
00026                 delete[] _interim_buf;
00027         }
00028 
00029         void iobuffer::finalize()
00030         {
00031                 ibrcommon::MutexLock l(_data_cond);
00032                 _eof = true;
00033                 _data_cond.signal(true);
00034         }
00035 
00036         int iobuffer::sync()
00037         {
00038                 int ret = std::char_traits<char>::eq_int_type(this->overflow(
00039                                 std::char_traits<char>::eof()), std::char_traits<char>::eof()) ? -1
00040                                 : 0;
00041 
00042                 return ret;
00043         }
00044 
00045         std::char_traits<char>::int_type iobuffer::overflow(std::char_traits<char>::int_type c)
00046         {
00047                 char *ibegin = _input_buf;
00048                 char *iend = pptr();
00049 
00050                 // mark the buffer as free
00051                 setp(_input_buf, _input_buf + _buf_size - 1);
00052 
00053                 if (!std::char_traits<char>::eq_int_type(c, std::char_traits<char>::eof()))
00054                 {
00055                         *iend++ = std::char_traits<char>::to_char_type(c);
00056                 }
00057 
00058                 // if there is nothing to send, just return
00059                 if ((iend - ibegin) == 0)
00060                 {
00061                         return std::char_traits<char>::not_eof(c);
00062                 }
00063 
00064                 ibrcommon::MutexLock l(_data_cond);
00065 
00066                 // wait until the buffer is empty
00067                 while (_data_size > 0)
00068                 {
00069                         if (_eof) throw ibrcommon::Exception("iobuffer was finalized");
00070                         _data_cond.wait();
00071                 }
00072 
00073                 // set the new output data size
00074                 _data_size = (iend - ibegin);
00075 
00076                 // copy the data to the interim buffer
00077                 ::memcpy(_interim_buf, _input_buf, _data_size);
00078 
00079                 // signal the new data
00080                 _data_cond.signal(true);
00081 
00082                 return std::char_traits<char>::not_eof(c);
00083         }
00084 
00085         std::char_traits<char>::int_type iobuffer::underflow()
00086         {
00087                 ibrcommon::MutexLock l(_data_cond);
00088 
00089                 // wait until some data is available
00090                 while (_data_size == 0)
00091                 {
00092                         // return EOF if the end of the file is reached
00093                         if (_eof) return std::char_traits<char>::eof();
00094 
00095                         _data_cond.wait();
00096                 }
00097 
00098                 // copy the data to the output buffer
00099                 ::memcpy(_output_buf, _interim_buf, _data_size);
00100 
00101                 // Since the input buffer content is now valid (or is new)
00102                 // the get pointer should be initialized (or reset).
00103                 setg(_output_buf, _output_buf, _output_buf + _data_size);
00104 
00105                 // signal the empty buffer
00106                 _data_size = 0;
00107                 _data_cond.signal(true);
00108 
00109                 return std::char_traits<char>::not_eof((unsigned char) _output_buf[0]);
00110         }
00111 }