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