libzypp 17.31.23
simplestreambuf.h
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
12#ifndef ZYPP_CORE_BASE_SIMPLESTREAMBUF_H_DEFINED
13#define ZYPP_CORE_BASE_SIMPLESTREAMBUF_H_DEFINED
14
15#include <streambuf>
16#include <vector>
17
18namespace 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
RepoManager implementation.
std::vector< char > buffer_type
virtual pos_type seekoff(off_type off_r, std::ios_base::seekdir way_r, std::ios_base::openmode openMode)
virtual int_type overflow(int_type c=traits_type::eof())
SimpleStreamBuf(size_t bufsize_r=512)
virtual pos_type seekpos(pos_type pos_r, std::ios_base::openmode openMode)
SimpleStreamBuf * open(const char *name_r, std::ios_base::openmode mode_r=std::ios_base::in)
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:2