Claw 1.7.3
buffered_istream.tpp
1/*
2 CLAW - a C++ Library Absolutely Wonderful
3
4 CLAW is a free library without any particular aim but being useful to
5 anyone.
6
7 Copyright (C) 2005-2011 Julien Jorge
8
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Lesser General Public
11 License as published by the Free Software Foundation; either
12 version 2.1 of the License, or (at your option) any later version.
13
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public
20 License along with this library; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22
23 contact: julien.jorge@gamned.org
24*/
25/**
26 * \file buffered_istream.tpp
27 * \brief Implementation of the claw::buffered_istream class.
28 * \author Julien Jorge
29 */
30#include <cassert>
31
32/*----------------------------------------------------------------------------*/
33/**
34 * \brief Constructor.
35 * \param f The file associated to the stream.
36 */
37template<typename Stream>
38claw::buffered_istream<Stream>::buffered_istream( stream_type& f )
39 : m_stream(f), m_begin(NULL), m_end(NULL), m_current(NULL),
40 m_buffer_size(1024)
41{
42 m_begin = new char[m_buffer_size];
43 m_end = m_begin;
44 m_current = m_end;
45} // buffered_istream::buffered_istream()
46
47/*----------------------------------------------------------------------------*/
48/**
49 * \brief Destructor.
50 */
51template<typename Stream>
52claw::buffered_istream<Stream>::~buffered_istream()
53{
54 close();
55
56 if (m_begin)
57 delete[] m_begin;
58} // buffered_istream::~buffered_istream()
59
60/*----------------------------------------------------------------------------*/
61/**
62 * \brief Tell how many bytes are ready in the buffer.
63 */
64template<typename Stream>
65unsigned int claw::buffered_istream<Stream>::remaining() const
66{
67 return m_end - m_current;
68} // buffered_istream::remaining()
69
70/*----------------------------------------------------------------------------*/
71/**
72 * \brief Increase the number of ready bytes to a given number.
73 * \param n The number of bytes you need.
74 * \remark This method reads n - remaining() bytes from the file.
75 */
76template<typename Stream>
77bool claw::buffered_istream<Stream>::read_more( unsigned int n )
78{
79 if ( n <= remaining() )
80 return true;
81
82 unsigned int r = remaining();
83
84 // we'll reach the end of the buffer
85 if ( m_current + n > m_begin + m_buffer_size )
86 {
87 // try to avoid reallocation
88 if (n <= m_buffer_size)
89 std::copy(m_current, m_end, m_begin);
90 else // not enough space in the buffer
91 {
92 m_buffer_size = n;
93
94 char* new_buffer = new char[m_buffer_size];
95
96 std::copy(m_current, m_end, new_buffer);
97
98 delete[] m_begin;
99
100 m_begin = new_buffer;
101 }
102
103 m_current = m_begin;
104 m_end = m_current + r;
105 }
106
107 m_stream.read( m_end, n-r );
108 m_end += m_stream.gcount();
109
110 return !!m_stream;
111} // buffered_istream::read_more()
112
113/*----------------------------------------------------------------------------*/
114/**
115 * \brief Get the input buffer.
116 */
117template<typename Stream>
118const char* claw::buffered_istream<Stream>::get_buffer() const
119{
120 return m_current;
121} // buffered_istream::get_buffer()
122
123/*----------------------------------------------------------------------------*/
124/**
125 * \brief Get the next value in the buffer and move one byte forward.
126 */
127template<typename Stream>
128char claw::buffered_istream<Stream>::get_next()
129{
130 assert( remaining() >= 1 );
131
132 char result = *m_current;
133 ++m_current;
134
135 return result;
136} // buffered_istream::get_next()
137
138/*----------------------------------------------------------------------------*/
139/**
140 * \brief Read a range of data.
141 * \param buf The buffer in which we write the read data.
142 * \param n The number of bytes to read.
143 */
144template<typename Stream>
145bool claw::buffered_istream<Stream>::read( char* buf, unsigned int n )
146{
147 while ( (n != 0) && !!(*this) )
148 {
149 if ( n > remaining() )
150 read_more(m_buffer_size);
151
152 unsigned int len = std::min(n, remaining());
153
154 std::copy( m_current, m_current + len, buf );
155 buf += len;
156 n -= len;
157 m_current += len;
158 }
159
160 return n==0;
161} // buffered_istream::read()
162
163/*----------------------------------------------------------------------------*/
164/**
165 * \brief Move some bytes forward.
166 * \param n The number of bytes to skip.
167 */
168template<typename Stream>
169void claw::buffered_istream<Stream>::move( unsigned int n )
170{
171 assert( m_current + n <= m_end );
172 m_current += n;
173} // buffered_istream::move()
174
175/*----------------------------------------------------------------------------*/
176/**
177 * \brief Closes this buffer (not the stream).
178 *
179 * The cursor of the stream is repositioned according to the remaining data, and
180 * the buffer is cleared.
181 */
182template<typename Stream>
183void claw::buffered_istream<Stream>::close()
184{
185 m_stream.seekg( m_current - m_end, std::ios_base::cur );
186 m_current = m_begin;
187 m_end = m_begin;
188} // buffered_istream::close()
189
190/*----------------------------------------------------------------------------*/
191/**
192 * \brief Tell if there is still datas in the buffer/stream.
193 */
194template<typename Stream>
195claw::buffered_istream<Stream>::operator bool() const
196{
197 return m_stream || (remaining() > 0);
198} // buffered_istream::operator bool()