IBR-DTNSuite  0.10
iobuffer.cpp
Go to the documentation of this file.
1 /*
2  * iobuffer.cpp
3  *
4  * Copyright (C) 2011 IBR, TU Braunschweig
5  *
6  * Written-by: Johannes Morgenroth <morgenroth@ibr.cs.tu-bs.de>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21 
24 #include <string.h>
25 
26 namespace ibrcommon
27 {
28  iobuffer::iobuffer(const size_t buffer)
29  : _eof(false), _data_size(0), _buf_size(buffer), _input_buf(buffer), _interim_buf(buffer), _output_buf(buffer)
30  {
31  // Initialize get pointer. This should be zero so that underflow is called upon first read.
32  setg(0, 0, 0);
33  setp(&_input_buf[0], &_input_buf[0] + _buf_size - 1);
34  }
35 
37  {
38  }
39 
41  {
42  ibrcommon::MutexLock l(_data_cond);
43  _eof = true;
44  _data_cond.signal(true);
45  }
46 
48  {
49  int ret = std::char_traits<char>::eq_int_type(this->overflow(
50  std::char_traits<char>::eof()), std::char_traits<char>::eof()) ? -1
51  : 0;
52 
53  return ret;
54  }
55 
56  std::char_traits<char>::int_type iobuffer::overflow(std::char_traits<char>::int_type c)
57  {
58  char *ibegin = &_input_buf[0];
59  char *iend = pptr();
60 
61  // mark the buffer as free
62  setp(&_input_buf[0], &_input_buf[0] + _buf_size - 1);
63 
64  if (!std::char_traits<char>::eq_int_type(c, std::char_traits<char>::eof()))
65  {
66  *iend++ = std::char_traits<char>::to_char_type(c);
67  }
68 
69  // if there is nothing to send, just return
70  if ((iend - ibegin) == 0)
71  {
72  return std::char_traits<char>::not_eof(c);
73  }
74 
75  ibrcommon::MutexLock l(_data_cond);
76 
77  // wait until the buffer is empty
78  while (_data_size > 0)
79  {
80  if (_eof) throw ibrcommon::Exception("iobuffer was finalized");
81  _data_cond.wait();
82  }
83 
84  // set the new output data size
85  _data_size = (iend - ibegin);
86 
87  // copy the data to the interim buffer
88  ::memcpy(&_interim_buf[0], &_input_buf[0], _data_size);
89 
90  // signal the new data
91  _data_cond.signal(true);
92 
93  return std::char_traits<char>::not_eof(c);
94  }
95 
96  std::char_traits<char>::int_type iobuffer::underflow()
97  {
98  ibrcommon::MutexLock l(_data_cond);
99 
100  // wait until some data is available
101  while (_data_size == 0)
102  {
103  // return EOF if the end of the file is reached
104  if (_eof) return std::char_traits<char>::eof();
105 
106  _data_cond.wait();
107  }
108 
109  // copy the data to the output buffer
110  ::memcpy(&_output_buf[0], &_interim_buf[0], _data_size);
111 
112  // Since the input buffer content is now valid (or is new)
113  // the get pointer should be initialized (or reset).
114  setg(&_output_buf[0], &_output_buf[0], &_output_buf[0] + _data_size);
115 
116  // signal the empty buffer
117  _data_size = 0;
118  _data_cond.signal(true);
119 
120  return std::char_traits<char>::not_eof(_output_buf[0]);
121  }
122 }