Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members  

BufferedInputStream.cpp

00001 /*
00002  * NOTE: "zlib/libpng" style License
00003  *
00004  *                 ----=== s t d n e t ===----
00005  *
00006  * Copyright (c) 2002 Warwick Molloy   w-molloy@users.sf.net
00007  *
00008  * Copyright (c) 2002 Stdnet Community
00009  * HTTP://Sourceforge.net/projects/stdnet
00010  *
00011  * All references to "software" refer to the stdnet.
00012  *
00013  * This software is provided 'as-is', without any express or
00014  * implied warranty. In no event will the authors be held liable
00015  * for any damages arising from the use of this software.
00016  *
00017  * Permission is granted to anyone to use this software for any
00018  * purpose, including commercial applications, and to alter it
00019  * and redistribute it freely, subject to the following
00020  * restrictions:
00021  *
00022  * 1.  The origin of this software must not be misrepresented;
00023  *     you must not claim that you wrote the original software.
00024  *     If you use this software in a product, an acknowledgment
00025  *     in the product documentation would be appreciated but
00026  *     is not required.
00027  *
00028  * 2.  Altered source versions must be plainly marked as such,
00029  *     and must not be misrepresented as being the original
00030  *     software.
00031  *
00032  * 3.  This notice may not be removed or altered from any source
00033  *     distribution.
00034  */
00035 
00036 #include <memory.h>
00037 
00038 #include <stdnet/config.h>
00039 #include <stdnet/io/BufferedInputStream>
00040 
00041 namespace stdbase {
00042     namespace io {
00043 
00044 int BufferedInputStream::
00045     available() throw (IOException)
00046 {
00047     int len;
00048 
00049     if (end_pos >= start_pos)
00050     {
00051         len = end_pos - start_pos;
00052     }
00053     else if ( start_pos > end_pos )
00054     {   // wrap around..
00055         len = (BUFFER_MAX - start_pos) + end_pos - 1;
00056     }
00057     return len;
00058 }
00059 
00060 /*
00061  *  Closes the stream and releases any resources.
00062  */
00063 
00064 /*
00065 void BufferedInputStream::
00066     close() throw (IOException)
00067 {
00068     FilterInputStream::close();
00069 }
00070 */
00071 
00072 /*
00073  *  Marks the current position in the input stream incase
00074  *  the caller need return to this point - done by calling
00075  *  reset().
00076  *
00077  *  @param readlimit the maximum limit of bytes before the
00078  *  marked position becomes invalid.
00079  */
00080 void BufferedInputStream::
00081     mark( int readlimit)
00082 {
00083     mark_pos = start_pos;
00084     mark_read_limit = readlimit;
00085     mark_read_count = 0;
00086 }
00087 
00088 /*
00089  *  Returns the caller to a previously marked position in
00090  *  the input stream (if supported).
00091  *
00092  *  @throws IOException if mark/reset not supported or if the
00093  *  number of bytes read exceeds the mark readlimit when mark()
00094  *  was called.
00095  */
00096 void BufferedInputStream::
00097     reset() throw (IOException)
00098 {
00099     if ( mark_read_limit == MARK_READ_LIMIT_EXCEEDED ||
00100          mark_read_limit == MARK_READ_LIMIT_NULL ||
00101          mark_pos == MARK_POS_UNSET ||
00102          mark_pos == MARK_POS_OVERWRITTEN )
00103     {
00104         //  Can't reset.  Let caller know about it.
00105         //
00106         throw IOException();
00107     }
00108 
00109     start_pos = mark_pos;
00110     mark_read_limit = MARK_READ_LIMIT_NULL;
00111     mark_pos = 0;
00112     mark_read_count = 0;
00113 }
00114 
00115 /*
00116  *  Test to see whether the InputStream implementation supports
00117  *  the mark()/reset() methods.
00118  */
00119 bool BufferedInputStream::
00120     markSupported()
00121 {
00122     return true;
00123 }
00124 
00125 /*
00126  *  Read a buffer of bytes - NEEDS Array.
00127  */
00128 int BufferedInputStream::
00129     read( byte buffer[], int len) throw (IOException)
00130 {
00131     prepare_buffer();
00132     
00133     int ready       = available();
00134     int copy1_size  = len < ready ? len : ready;
00135     int remainder   = len;
00136     int inlen       = 0;
00137 
00138     if ( start_pos < end_pos && end_pos <= BUFFER_MAX )
00139     {
00140         // -- normal case --
00141         //
00142         memcpy( buffer,
00143             & this->buffer[ start_pos ],
00144             copy1_size
00145         );
00146         advance_start_pos( copy1_size );
00147         remainder -= copy1_size;
00148     }
00149     else
00150     {
00151         // -- wrapped case --
00152         //
00153         int block1 = BUFFER_MAX - start_pos;
00154         int block2 = end_pos - 1;
00155         int L1, L2;
00156 
00157         if ( block1 > copy1_size )
00158         {
00159             L1 = copy1_size;
00160             L2 = 0;
00161         }
00162         else
00163         {
00164             L1 = block1;
00165             L2 = block2 > (copy1_size - block1) ?
00166                     copy1_size - block1: block2;
00167         }
00168 
00169         memcpy(
00170             buffer,
00171             & this->buffer[ start_pos ],
00172             L1
00173         );
00174 
00175         memcpy(
00176             buffer,
00177             this->buffer,
00178             L2
00179         );
00180         remainder -= L1 + L2;
00181         advance_start_pos( L1 + L2);
00182     }
00183 
00184     if ( remainder > 0 )
00185     {
00186         inlen = FilterInputStream:: read(
00187                                         & buffer[ copy1_size ],
00188                                         remainder
00189                                     );
00190     }
00191     return inlen + copy1_size;
00192 }
00193     
00194 /*
00195  *  Read a single byte from the stream and return it as an
00196  *  integer.
00197  *
00198  *  @return the number of bytes read.
00199  */
00200 int BufferedInputStream::
00201     read() throw (IOException)
00202 {
00203     prepare_buffer();
00204     
00205     char    ch = buffer[ start_pos ];
00206     
00207     advance_start_pos( 1 );
00208 
00209     return ch;
00210 }
00211 
00212 /*
00213  *  Skip the next n bytes from the input stream.
00214  *
00215  *  @return the number of bytes skipped.
00216 long BufferedInputStream::
00217     skip( long n ) throw (IOException)
00218 {
00219 }
00220  */
00221 
00225 
00226 void    BufferedInputStream::
00227     prepare_buffer() throw (IOException)
00228 {
00229     //  The range of valid data is in (start_pos, end_pos].
00230     //  It begins and includes the start_pos and goes upto
00231     //  but not including the end_pos.
00232     //
00233     if ( end_pos == start_pos )
00234     {
00235         if ( end_pos == BUFFER_MAX )
00236         {
00237             //  The circular buffer has wrapped around.
00238             end_pos = start_pos = 0;
00239         }
00240 
00241         //  Need to read data in...
00242         int len;
00243         int remainder = BUFFER_MAX - end_pos;
00244         int size = remainder <  BUFF_CHUNK ? remainder : BUFF_CHUNK;
00245         
00246         len = FilterInputStream::   read(
00247                                         (byte *)& buffer[ end_pos ],
00248                                         size
00249                                     );
00250         if ( len < 0 )
00251             throw IOException();
00252 
00253         end_pos += len;
00254     }
00255 
00256     //  Check that the end_pos hasn't wrapped around and
00257     //  overwritten the mark position.
00258     //
00259     if ( mark_pos != MARK_POS_UNSET &&
00260          start_pos > end_pos &&
00261          end_pos > mark_pos )
00262     {
00263         mark_pos = MARK_POS_OVERWRITTEN;
00264         mark_read_limit = MARK_READ_LIMIT_EXCEEDED;
00265     }
00266     if ( mark_read_limit > 0 &&
00267          mark_read_count > mark_read_limit )
00268     {
00269         mark_pos = MARK_POS_UNSET;
00270         mark_read_limit = MARK_READ_LIMIT_EXCEEDED;
00271     }
00272 }
00273 
00274 //  Increment the start_pos by the given amount.
00275 //
00276 void BufferedInputStream::
00277     advance_start_pos( int count )
00278     throw (IOException)
00279 {
00280     if ( count > BUFFER_MAX )
00281         throw IOException();
00282     
00283     start_pos += count;
00284     if ( start_pos > BUFFER_MAX )
00285         start_pos -= BUFFER_MAX;
00286 
00287     if ( mark_pos != MARK_POS_UNSET )
00288         mark_read_count += count;
00289 }
00290 
00291 
00295 
00296 system::reference< BufferedInputStream > BufferedInputStream::
00297         create( InputStreamRef r)
00298 {
00299     return BufferedInputStreamRef( new BufferedInputStream( r ));
00300 }
00301 
00302 
00306 
00307 BufferedInputStream::
00308     BufferedInputStream( InputStreamRef input)
00309         :   FilterInputStream( input ),
00310             start_pos( 0 ),
00311             end_pos( 0 ),
00312             mark_pos( MARK_POS_UNSET ),
00313             mark_read_limit( MARK_READ_LIMIT_NULL ),
00314             mark_read_count( 0 )
00315 {};
00316 
00317     } // -- end io --
00318 } // -- end stdbase --
00319 
00320 

Generated at Tue Aug 13 14:19:39 2002 for stdnet2 by doxygen1.2.9.1 written by Dimitri van Heesch, © 1997-2001