xref: /haiku/src/add-ons/translators/shared/StreamBuffer.cpp (revision db10640de90f7f9519ba2da9577b7c1af3c64f6b)
1 /*****************************************************************************/
2 // StreamBuffer
3 // Written by Michael Wilber, OBOS Translation Kit Team
4 //
5 // StreamBuffer.cpp
6 //
7 // This class is for buffering data from a BPositionIO object in order to
8 // improve performance for cases when small amounts of data are frequently
9 // read from a BPositionIO object.
10 //
11 //
12 // Copyright (c) 2003 OpenBeOS Project
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining a
15 // copy of this software and associated documentation files (the "Software"),
16 // to deal in the Software without restriction, including without limitation
17 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 // and/or sell copies of the Software, and to permit persons to whom the
19 // Software is furnished to do so, subject to the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be included
22 // in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 // DEALINGS IN THE SOFTWARE.
31 /*****************************************************************************/
32 
33 #include <stdio.h>
34 #include <string.h>
35 #include "StreamBuffer.h"
36 
37 #ifndef min
38 #define min(x,y) (((x) < (y)) ? (x) : (y))
39 #endif
40 
41 #ifndef max
42 #define max(x,y) (((x) > (y)) ? (x) : (y))
43 #endif
44 
45 // ---------------------------------------------------------------
46 // Constructor
47 //
48 // Initializes the StreamBuffer to read from pstream, buffering
49 // nbuffersize bytes of data at a time. Note that if nbuffersize
50 // is smaller than MIN_BUFFER_SIZE, MIN_BUFFER_SIZE is used
51 // as the buffer size.
52 //
53 // Preconditions:
54 //
55 // Parameters: pstream,	the stream to be buffered
56 //
57 //             nbuffersize,	number of bytes to be read from
58 //			                pstream at a time
59 //
60 // Postconditions:
61 //
62 // Returns:
63 // ---------------------------------------------------------------
64 StreamBuffer::StreamBuffer(BPositionIO *pstream, size_t nbuffersize,
65 	bool binitialread)
66 {
67 	fpStream = pstream;
68 	fpBuffer = NULL;
69 	fnBufferSize = 0;
70 	fnLen = 0;
71 	fnPos = 0;
72 
73 	if (!pstream)
74 		return;
75 
76 	fnBufferSize = max(nbuffersize, MIN_BUFFER_SIZE);
77 	fpBuffer = new uint8[fnBufferSize];
78 	if (fpBuffer && binitialread)
79 		ReadStream();
80 			// Fill the buffer with data so that
81 			// object is prepared for first call to
82 			// Read()
83 }
84 
85 // ---------------------------------------------------------------
86 // Destructor
87 //
88 // Destroys data allocated for this object
89 //
90 // Preconditions:
91 //
92 // Parameters:
93 //
94 // Postconditions:
95 //
96 // Returns:
97 // ---------------------------------------------------------------
98 StreamBuffer::~StreamBuffer()
99 {
100 	fnBufferSize = 0;
101 	fnLen = 0;
102 	fnPos = 0;
103 	fpStream = NULL;
104 
105 	delete[] fpBuffer;
106 	fpBuffer = NULL;
107 }
108 
109 // ---------------------------------------------------------------
110 // InitCheck
111 //
112 // Determines whether the constructor failed or not
113 //
114 // Preconditions:
115 //
116 // Parameters:
117 //
118 // Postconditions:
119 //
120 // Returns: B_OK if object has been initialized successfully,
121 // B_ERROR if not
122 // ---------------------------------------------------------------
123 status_t
124 StreamBuffer::InitCheck()
125 {
126 	if (fpStream && fpBuffer)
127 		return B_OK;
128 	else
129 		return B_ERROR;
130 }
131 
132 // ---------------------------------------------------------------
133 // Read
134 //
135 // Copies up to nbytes of data from the stream into pinto
136 //
137 // Preconditions: ReadStream() must be called once before this
138 // function is called (the constructor does this)
139 //
140 // Parameters:	pinto,	the buffer to be copied to
141 //
142 //				nbytes,	the maximum number of bytes to copy
143 //
144 // Postconditions:
145 //
146 // Returns: the number of bytes successfully read or an
147 // error code returned by BPositionIO::Read()
148 // ---------------------------------------------------------------
149 ssize_t
150 StreamBuffer::Read(uint8 *pinto, size_t nbytes)
151 {
152 	ssize_t result = B_ERROR;
153 	size_t rd1 = 0, rd2 = 0;
154 
155 	rd1 = min(nbytes, fnLen - fnPos);
156 	memcpy(pinto, fpBuffer + fnPos, rd1);
157 	fnPos += rd1;
158 
159 	if (rd1 < nbytes) {
160 		pinto += rd1;
161 		result = ReadStream();
162 		if (result > 0) {
163 			rd2 = min(nbytes - rd1, fnLen);
164 			memcpy(pinto, fpBuffer, rd2);
165 			fnPos += rd2;
166 		} else
167 			// return error code or zero
168 			return result;
169 	}
170 
171 	return rd1 + rd2;
172 }
173 
174 // ---------------------------------------------------------------
175 // Seek
176 //
177 // Seeks the stream to the given position and refreshes the
178 // read buffer.  If the seek operation fails, the read buffer
179 // will be reset.
180 //
181 // Preconditions: fpBuffer must be allocated and fnBufferSize
182 // must be valid
183 //
184 // Parameters:
185 //
186 // Postconditions:
187 //
188 // Returns: true if the seek was successful,
189 // false if the seek operation failed
190 // ---------------------------------------------------------------
191 bool
192 StreamBuffer::Seek(off_t position)
193 {
194 	fnLen = 0;
195 	fnPos = 0;
196 
197 	if (fpStream->Seek(position, SEEK_SET) == position) {
198 		ReadStream();
199 		return true;
200 	}
201 
202 	return false;
203 }
204 
205 // ---------------------------------------------------------------
206 // ReadStream
207 //
208 // Fills the stream buffer with data read in from the stream
209 //
210 // Preconditions: fpBuffer must be allocated and fnBufferSize
211 // must be valid
212 //
213 // Parameters:
214 //
215 // Postconditions:
216 //
217 // Returns: the number of bytes successfully read or an
218 // error code returned by BPositionIO::Read()
219 // ---------------------------------------------------------------
220 ssize_t
221 StreamBuffer::ReadStream()
222 {
223 	ssize_t rd;
224 	rd = fpStream->Read(fpBuffer, fnBufferSize);
225 	if (rd >= 0) {
226 		fnLen = rd;
227 		fnPos = 0;
228 	}
229 	return rd;
230 }
231