IBR-DTNSuite
0.8
|
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 }