00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifndef __PEEKABOT_CHUNKED_BUFFER_HH
00010 #define __PEEKABOT_CHUNKED_BUFFER_HH
00011
00012
00013 #include "Types.hh"
00014
00015
00016 namespace peekabot
00017 {
00018
00019
00028 class ChunkedBuffer
00029 {
00038 class Chunk
00039 {
00040 const size_t m_capacity;
00041 size_t m_wptr;
00042 size_t m_rptr;
00043 uint8_t *m_data;
00044
00045 public:
00046
00052 Chunk(size_t _size) throw();
00053
00054 ~Chunk() throw();
00055
00064 inline size_t write(const void *buf, size_t n) throw()
00065 {
00066 size_t written = std::min(m_capacity-m_wptr, n);
00067
00068 memcpy((uint8_t *)m_data+m_wptr, buf, written);
00069 m_wptr += written;
00070
00071 return written;
00072 }
00073
00083 inline size_t overwrite(const void *buf, size_t n, size_t pos) throw()
00084 {
00085 size_t written = std::min(n, m_wptr-pos);
00086
00087 memcpy((uint8_t *)m_data+pos, buf, written);
00088
00089 return written;
00090 }
00091
00092
00102 inline size_t peek(void *buf, size_t n) throw()
00103 {
00104 size_t read = std::min(get_available_count(), n);
00105
00106 memcpy(buf, (uint8_t *)m_data+m_rptr, read);
00107
00108 return read;
00109 }
00110
00119 inline size_t read(void *buf, size_t n) throw()
00120 {
00121 size_t read = std::min(get_available_count(), n);
00122
00123 memcpy(buf, (uint8_t *)m_data+m_rptr, read);
00124 m_rptr += read;
00125
00126 return read;
00127 }
00128
00137 inline size_t discard(size_t n) throw()
00138 {
00139 size_t read = std::min(get_available_count(), n);
00140
00141 m_rptr += read;
00142
00143 return read;
00144 }
00145
00149 inline size_t get_available_count() const throw()
00150 {
00151 return m_wptr-m_rptr;
00152 }
00153
00158 inline size_t get_remaining_capacity() const throw()
00159 {
00160 return m_capacity-m_wptr;
00161 }
00162
00163
00168 inline size_t get_bytes_read() const throw()
00169 {
00170 return m_rptr;
00171 }
00172
00173
00179 inline size_t get_bytes_written() const throw()
00180 {
00181 return m_wptr;
00182 }
00183
00184 void clear() throw();
00185 };
00186
00187
00188
00189
00200 struct Node
00201 {
00202 Node(Node *next, Node *prev, Chunk *chunk) throw();
00203
00204 ~Node() throw();
00205
00206 Node *m_next;
00207 Node *m_prev;
00208 Chunk *m_chunk;
00209 };
00210
00211
00215 const size_t m_chunk_size;
00216
00217
00221 size_t m_size;
00222
00231 size_t m_chunk_count;
00232
00236 Node *m_read_node;
00237
00241 Node *m_write_node;
00242
00243
00244 private:
00249 void grow_on_demand() throw();
00250
00254 void shrink_on_demand() throw();
00255
00256
00257
00258
00259 public:
00260 ChunkedBuffer(size_t chunk_size) throw();
00261
00262 ChunkedBuffer(const ChunkedBuffer &buf) throw();
00263
00264 ~ChunkedBuffer() throw();
00265
00280 size_t read(void *buf, size_t max_bytes) throw();
00281
00295 size_t discard(size_t max_bytes) throw();
00296
00302 uint8_t read_byte() throw();
00303
00313 size_t peek(void *buf, size_t max_bytes) const throw();
00314
00323 bool peek(uint8_t &x) const throw();
00324
00334 void write(const void *buf, size_t n) throw();
00335
00339 void write_byte(uint8_t x) throw();
00340
00341
00354 bool overwrite(const void *buf, size_t n, size_t pos) throw();
00355
00361 void clear() throw();
00362
00367 size_t get_size() const throw();
00368
00372 bool is_empty() const throw();
00373
00377 size_t get_chunk_size() const throw();
00378
00379
00380
00381 class StreambufAdapter : public std::streambuf
00382 {
00383 ChunkedBuffer &m_buf;
00384 public:
00385 StreambufAdapter(ChunkedBuffer &buf);
00386
00387 protected:
00388 virtual int_type overflow(int_type c);
00389
00390 virtual int_type underflow();
00391
00392 virtual int_type uflow();
00393
00394 virtual std::streamsize xsputn(const char *s, std::streamsize n);
00395
00396 virtual std::streamsize xsgetn(char *s, std::streamsize n);
00397 };
00398 };
00399
00400 }
00401
00402
00403 #endif // __PEEKABOT_CHUNKED_BUFFER_HH