1 // distribution boxbackup-0.11_trunk_2979 (svn version: 2979)
2 // Box Backup, http://www.boxbackup.org/
3 //
4 // Copyright (c) 2003-2010, Ben Summers and contributors.
5 // All rights reserved.
6 //
7 // Note that this project uses mixed licensing. Any file with this license
8 // attached, or where the code LICENSE-DUAL appears on the first line, falls
9 // under this license. See the file COPYING.txt for more information.
10 //
11 // This file is dual licensed. You may use and distribute it providing that you
12 // comply EITHER with the terms of the BSD license, OR the GPL license. It is
13 // not necessary to comply with both licenses, only one.
14 //
15 // The BSD license option follows:
16 //
17 // Redistribution and use in source and binary forms, with or without
18 // modification, are permitted provided that the following conditions are met:
19 //
20 // 1. Redistributions of source code must retain the above copyright
21 // notice, this list of conditions and the following disclaimer.
22 //
23 // 2. Redistributions in binary form must reproduce the above copyright
24 // notice, this list of conditions and the following disclaimer in the
25 // documentation and/or other materials provided with the distribution.
26 //
27 // 3. Neither the name of the Box Backup nor the names of its contributors may
28 // be used to endorse or promote products derived from this software without
29 // specific prior written permission.
30 //
31 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
32 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
35 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
36 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
38 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
40 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 //
42 // [http://en.wikipedia.org/wiki/BSD_licenses#3-clause_license_.28.22New_BSD_License.22.29]
43 //
44 // The GPL license option follows:
45 //
46 // This program is free software; you can redistribute it and/or
47 // modify it under the terms of the GNU General Public License
48 // as published by the Free Software Foundation; either version 2
49 // of the License, or (at your option) any later version.
50 //
51 // This program is distributed in the hope that it will be useful,
52 // but WITHOUT ANY WARRANTY; without even the implied warranty of
53 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
54 // GNU General Public License for more details.
55 //
56 // You should have received a copy of the GNU General Public License
57 // along with this program; if not, write to the Free Software
58 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
59 //
60 // [http://www.gnu.org/licenses/old-licenses/gpl-2.0.html#SEC4]
61 // --------------------------------------------------------------------------
62 //
63 // File
64 // Name: CollectInBufferStream.cpp
65 // Purpose: Collect data in a buffer, and then read it out.
66 // Created: 2003/08/26
67 //
68 // --------------------------------------------------------------------------
69
70 #include "Box.h"
71
72 #include <string.h>
73
74 #include "CollectInBufferStream.h"
75 #include "CommonException.h"
76
77 #include "MemLeakFindOn.h"
78
79 #define INITIAL_BUFFER_SIZE 1024
80 #define MAX_BUFFER_ADDITION (1024*64)
81
82 // --------------------------------------------------------------------------
83 //
84 // Function
85 // Name: CollectInBufferStream::CollectInBufferStream()
86 // Purpose: Constructor
87 // Created: 2003/08/26
88 //
89 // --------------------------------------------------------------------------
CollectInBufferStream()90 CollectInBufferStream::CollectInBufferStream()
91 : mBuffer(INITIAL_BUFFER_SIZE),
92 mBufferSize(INITIAL_BUFFER_SIZE),
93 mBytesInBuffer(0),
94 mReadPosition(0),
95 mInWritePhase(true)
96 {
97 }
98
99 // --------------------------------------------------------------------------
100 //
101 // Function
102 // Name: CollectInBufferStream::~CollectInBufferStream()
103 // Purpose: Destructor
104 // Created: 2003/08/26
105 //
106 // --------------------------------------------------------------------------
~CollectInBufferStream()107 CollectInBufferStream::~CollectInBufferStream()
108 {
109 }
110
111 // --------------------------------------------------------------------------
112 //
113 // Function
114 // Name: CollectInBufferStream::Read(void *, int, int)
115 // Purpose: As interface. But only works in read phase
116 // Created: 2003/08/26
117 //
118 // --------------------------------------------------------------------------
Read(void * pBuffer,int NBytes,int Timeout)119 int CollectInBufferStream::Read(void *pBuffer, int NBytes, int Timeout)
120 {
121 if(mInWritePhase != false) { THROW_EXCEPTION(CommonException, CollectInBufferStreamNotInCorrectPhase) }
122
123 // Adjust to number of bytes left
124 if(NBytes > (mBytesInBuffer - mReadPosition))
125 {
126 NBytes = (mBytesInBuffer - mReadPosition);
127 }
128 ASSERT(NBytes >= 0);
129 if(NBytes <= 0) return 0; // careful now
130
131 // Copy in the requested number of bytes and adjust the read pointer
132 ::memcpy(pBuffer, ((char*)mBuffer) + mReadPosition, NBytes);
133 mReadPosition += NBytes;
134
135 return NBytes;
136 }
137
138 // --------------------------------------------------------------------------
139 //
140 // Function
141 // Name: CollectInBufferStream::BytesLeftToRead()
142 // Purpose: As interface. But only works in read phase
143 // Created: 2003/08/26
144 //
145 // --------------------------------------------------------------------------
BytesLeftToRead()146 IOStream::pos_type CollectInBufferStream::BytesLeftToRead()
147 {
148 if(mInWritePhase != false) { THROW_EXCEPTION(CommonException, CollectInBufferStreamNotInCorrectPhase) }
149
150 return (mBytesInBuffer - mReadPosition);
151 }
152
153 // --------------------------------------------------------------------------
154 //
155 // Function
156 // Name: CollectInBufferStream::Write(void *, int)
157 // Purpose: As interface. But only works in write phase
158 // Created: 2003/08/26
159 //
160 // --------------------------------------------------------------------------
Write(const void * pBuffer,int NBytes)161 void CollectInBufferStream::Write(const void *pBuffer, int NBytes)
162 {
163 if(mInWritePhase != true) { THROW_EXCEPTION(CommonException, CollectInBufferStreamNotInCorrectPhase) }
164
165 // Enough space in the buffer
166 if((mBytesInBuffer + NBytes) > mBufferSize)
167 {
168 // Need to reallocate... what's the block size we'll use?
169 int allocateBlockSize = mBufferSize;
170 if(allocateBlockSize > MAX_BUFFER_ADDITION)
171 {
172 allocateBlockSize = MAX_BUFFER_ADDITION;
173 }
174
175 // Write it the easy way. Although it's not the most efficient...
176 int newSize = mBufferSize;
177 while(newSize < (mBytesInBuffer + NBytes))
178 {
179 newSize += allocateBlockSize;
180 }
181
182 // Reallocate buffer
183 mBuffer.Resize(newSize);
184
185 // Store new size
186 mBufferSize = newSize;
187 }
188
189 // Copy in data and adjust counter
190 ::memcpy(((char*)mBuffer) + mBytesInBuffer, pBuffer, NBytes);
191 mBytesInBuffer += NBytes;
192 }
193
194 // --------------------------------------------------------------------------
195 //
196 // Function
197 // Name: CollectInBufferStream::GetPosition()
198 // Purpose: In write phase, returns the number of bytes written, in read
199 // phase, the number of bytes to go
200 // Created: 2003/08/26
201 //
202 // --------------------------------------------------------------------------
GetPosition() const203 IOStream::pos_type CollectInBufferStream::GetPosition() const
204 {
205 return mInWritePhase?mBytesInBuffer:mReadPosition;
206 }
207
208 // --------------------------------------------------------------------------
209 //
210 // Function
211 // Name: CollectInBufferStream::Seek(pos_type, int)
212 // Purpose: As interface. But read phase only.
213 // Created: 2003/08/26
214 //
215 // --------------------------------------------------------------------------
Seek(pos_type Offset,int SeekType)216 void CollectInBufferStream::Seek(pos_type Offset, int SeekType)
217 {
218 if(mInWritePhase != false) { THROW_EXCEPTION(CommonException, CollectInBufferStreamNotInCorrectPhase) }
219
220 int newPos = 0;
221 switch(SeekType)
222 {
223 case IOStream::SeekType_Absolute:
224 newPos = Offset;
225 break;
226 case IOStream::SeekType_Relative:
227 newPos = mReadPosition + Offset;
228 break;
229 case IOStream::SeekType_End:
230 newPos = mBytesInBuffer + Offset;
231 break;
232 default:
233 THROW_EXCEPTION(CommonException, IOStreamBadSeekType)
234 break;
235 }
236
237 // Make sure it doesn't go over
238 if(newPos > mBytesInBuffer)
239 {
240 newPos = mBytesInBuffer;
241 }
242 // or under
243 if(newPos < 0)
244 {
245 newPos = 0;
246 }
247
248 // Set the new read position
249 mReadPosition = newPos;
250 }
251
252 // --------------------------------------------------------------------------
253 //
254 // Function
255 // Name: CollectInBufferStream::StreamDataLeft()
256 // Purpose: As interface
257 // Created: 2003/08/26
258 //
259 // --------------------------------------------------------------------------
StreamDataLeft()260 bool CollectInBufferStream::StreamDataLeft()
261 {
262 return mInWritePhase?(false):(mReadPosition < mBytesInBuffer);
263 }
264
265 // --------------------------------------------------------------------------
266 //
267 // Function
268 // Name: CollectInBufferStream::StreamClosed()
269 // Purpose: As interface
270 // Created: 2003/08/26
271 //
272 // --------------------------------------------------------------------------
StreamClosed()273 bool CollectInBufferStream::StreamClosed()
274 {
275 return !mInWritePhase;
276 }
277
278 // --------------------------------------------------------------------------
279 //
280 // Function
281 // Name: CollectInBufferStream::SetForReading()
282 // Purpose: Switch to read phase, after all data written
283 // Created: 2003/08/26
284 //
285 // --------------------------------------------------------------------------
SetForReading()286 void CollectInBufferStream::SetForReading()
287 {
288 if(mInWritePhase != true) { THROW_EXCEPTION(CommonException, CollectInBufferStreamNotInCorrectPhase) }
289
290 // Move to read phase
291 mInWritePhase = false;
292 }
293
294 // --------------------------------------------------------------------------
295 //
296 // Function
297 // Name: CollectInBufferStream::GetBuffer()
298 // Purpose: Returns the buffer
299 // Created: 2003/09/05
300 //
301 // --------------------------------------------------------------------------
GetBuffer() const302 void *CollectInBufferStream::GetBuffer() const
303 {
304 return mBuffer.GetPtr();
305 }
306
307 // --------------------------------------------------------------------------
308 //
309 // Function
310 // Name: CollectInBufferStream::GetSize()
311 // Purpose: Returns the buffer size
312 // Created: 2003/09/05
313 //
314 // --------------------------------------------------------------------------
GetSize() const315 int CollectInBufferStream::GetSize() const
316 {
317 return mBytesInBuffer;
318 }
319
320 // --------------------------------------------------------------------------
321 //
322 // Function
323 // Name: CollectInBufferStream::Reset()
324 // Purpose: Reset the stream, so it is empty and ready to be written to.
325 // Created: 8/12/03
326 //
327 // --------------------------------------------------------------------------
Reset()328 void CollectInBufferStream::Reset()
329 {
330 mInWritePhase = true;
331 mBytesInBuffer = 0;
332 mReadPosition = 0;
333 }
334
335