libzypp  17.25.0
SimpleStreambuf.h
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
12 #ifndef ZYPP_BASE_SIMPLESTREAMBUF_H_DEFINED
13 #define ZYPP_BASE_SIMPLESTREAMBUF_H_DEFINED
14 
15 #include <streambuf>
16 #include <vector>
17 
18 namespace zypp {
19  namespace detail {
20 
53  template<typename Impl>
54  class SimpleStreamBuf : public std::streambuf, public Impl
55  {
56 
57  public:
58 
59  SimpleStreamBuf( size_t bufsize_r = 512) : _buffer( bufsize_r ) { }
60  virtual ~SimpleStreamBuf() { close(); }
61 
62  SimpleStreamBuf * open( const char * name_r, std::ios_base::openmode mode_r = std::ios_base::in ) {
63 
64  if ( !this->openImpl( name_r, mode_r ) )
65  return nullptr;
66 
67  if ( this->canRead() ) {
68  setp( NULL, NULL );
69  setg( &(_buffer[0]), &(_buffer[0]), &(_buffer[0]) );
70  } else {
71  setp( &(_buffer[0]), &(_buffer[_buffer.size()-1]) );
72  setg( NULL, NULL, NULL );
73  }
74 
75  return this;
76  }
77 
79 
80  if ( !this->isOpen() )
81  return nullptr;
82 
83  if ( this->canWrite() )
84  sync();
85 
86  if ( !this->closeImpl() )
87  return nullptr;
88 
89  return this;
90  }
91 
92  protected:
93 
94  virtual int sync() {
95  int ret = 0;
96  if ( pbase() < pptr() ) {
97  const int_type res = overflow();
98  if ( traits_type::eq_int_type( res, traits_type::eof() ) )
99  ret = -1;
100  }
101  return ret;
102  }
103 
104  virtual int_type overflow( int_type c = traits_type::eof() ) {
105  int_type ret = traits_type::eof();
106  if ( this->canWrite() ) {
107  if ( ! traits_type::eq_int_type( c, traits_type::eof() ) )
108  {
109  *pptr() = traits_type::to_char_type( c );
110  pbump(1);
111  }
112  if ( pbase() <= pptr() )
113  {
114  if ( this->writeData( pbase(), pptr() - pbase() ) )
115  {
116  setp( &(_buffer[0]), &(_buffer[_buffer.size()-1]) );
117  ret = traits_type::not_eof( c );
118  }
119  // else: error writing the file
120  }
121  }
122  return ret;
123  }
124 
125  virtual int_type underflow() {
126  int_type ret = traits_type::eof();
127  if ( this->canRead() )
128  {
129  if ( gptr() < egptr() )
130  return traits_type::to_int_type( *gptr() );
131 
132  const std::streamsize got = this->readData( &(_buffer[0]), _buffer.size() );
133  if ( got > 0 )
134  {
135  setg( &(_buffer[0]), &(_buffer[0]), &(_buffer.data()[got]) );
136  ret = traits_type::to_int_type( *gptr() );
137  }
138  else if ( got == 0 )
139  {
140  // EOF
141  setg( &(_buffer[0]), &(_buffer[0]), &(_buffer[0]) );
142  }
143  // else: error reading the file
144  }
145  return ret;
146  }
147 
148  virtual pos_type seekpos( pos_type pos_r, std::ios_base::openmode openMode ) {
149  return seekoff( off_type(pos_r), std::ios_base::beg, openMode );
150  }
151 
152 
153  virtual pos_type seekoff( off_type off_r, std::ios_base::seekdir way_r, std::ios_base::openmode openMode ) {
154  pos_type ret = pos_type(off_type(-1));
155  if ( !this->canSeek( way_r) )
156  return ret;
157 
158  if ( this->isOpen() ) {
159  if ( openMode == std::ios_base::out ) {
160  //write the buffer out and invalidate it , no need to keep it around
161  if ( !this->canWrite() || sync() != 0 )
162  return ret;
163 
164  ret = this->seekTo( off_r, way_r, openMode );
165 
166  } else if ( openMode == std::ios_base::in ) {
167  if ( !this->canRead() )
168  return ret;
169 
170  //current physical FP, should point to end of buffer
171  const off_type buffEndOff = this->tell();
172 
173  if ( buffEndOff != off_type(-1) ) {
174  if ( way_r == std::ios_base::end ) {
175  setg( &(_buffer[0]), &(_buffer[0]), &(_buffer[0]) );
176  ret = this->seekTo( off_r, way_r, openMode );
177  }
178 
179  const off_type bufLen = egptr() - eback();
180  const off_type bufStartFileOff = buffEndOff - bufLen;
181  const off_type currPtrFileOffset = buffEndOff - ( egptr() - gptr() );
182  off_type newFOff = off_r;
183 
184  // Transform into ios_base::beg and seek.
185  if ( way_r == std::ios_base::cur ) {
186  newFOff += currPtrFileOffset;
187  way_r = std::ios_base::beg;
188  }
189 
190  //check if a seek would go out of the buffers boundaries
191  if ( way_r == std::ios_base::beg ) {
192  if ( bufStartFileOff <= newFOff && newFOff <= buffEndOff ) {
193  // Still inside buffer, adjust gptr and
194  // calculate new position.
195  setg( eback(),
196  eback() + ( newFOff - bufStartFileOff ),
197  egptr() );
198  ret = pos_type( newFOff );
199  } else {
200  // Invalidate buffer and seek.
201  setg( &(_buffer[0]), &(_buffer[0]), &(_buffer[0]) );
202  ret = this->seekTo( off_r, way_r, openMode );
203  }
204  }
205  }
206  }
207  }
208  return ret;
209  }
210 
211  private:
212  typedef std::vector<char> buffer_type;
214  };
215  }
216 }
217 #endif
zypp::detail::SimpleStreamBuf::buffer_type
std::vector< char > buffer_type
Definition: SimpleStreambuf.h:212
zypp::detail::SimpleStreamBuf::open
SimpleStreamBuf * open(const char *name_r, std::ios_base::openmode mode_r=std::ios_base::in)
Definition: SimpleStreambuf.h:62
zypp::detail::SimpleStreamBuf::seekpos
virtual pos_type seekpos(pos_type pos_r, std::ios_base::openmode openMode)
Definition: SimpleStreambuf.h:148
zypp::detail::SimpleStreamBuf::sync
virtual int sync()
Definition: SimpleStreambuf.h:94
zypp::detail::SimpleStreamBuf::_buffer
buffer_type _buffer
Definition: SimpleStreambuf.h:213
zypp::detail::SimpleStreamBuf::SimpleStreamBuf
SimpleStreamBuf(size_t bufsize_r=512)
Definition: SimpleStreambuf.h:59
zypp
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:1
zypp::detail::SimpleStreamBuf::overflow
virtual int_type overflow(int_type c=traits_type::eof())
Definition: SimpleStreambuf.h:104
zypp::detail::SimpleStreamBuf::close
SimpleStreamBuf * close()
Definition: SimpleStreambuf.h:78
Impl
zypp::detail::SimpleStreamBuf::seekoff
virtual pos_type seekoff(off_type off_r, std::ios_base::seekdir way_r, std::ios_base::openmode openMode)
Definition: SimpleStreambuf.h:153
zypp::detail::SimpleStreamBuf
Definition: SimpleStreambuf.h:54
zypp::detail::SimpleStreamBuf::underflow
virtual int_type underflow()
Definition: SimpleStreambuf.h:125
zypp::detail::SimpleStreamBuf::~SimpleStreamBuf
virtual ~SimpleStreamBuf()
Definition: SimpleStreambuf.h:60