Cinder

  • Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

include/cinder/Stream.h

Go to the documentation of this file.
00001 /*
00002  Copyright (c) 2010, The Barbarian Group
00003  All rights reserved.
00004 
00005  Redistribution and use in source and binary forms, with or without modification, are permitted provided that
00006  the following conditions are met:
00007 
00008     * Redistributions of source code must retain the above copyright notice, this list of conditions and
00009     the following disclaimer.
00010     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
00011     the following disclaimer in the documentation and/or other materials provided with the distribution.
00012 
00013  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
00014  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00015  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
00016  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00017  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00018  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00019  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00020  POSSIBILITY OF SUCH DAMAGE.
00021 */
00022 
00023 #pragma once 
00024 
00025 #include "cinder/Cinder.h"
00026 #include "cinder/Buffer.h"
00027 #include "cinder/Exception.h"
00028 
00029 #include <boost/noncopyable.hpp>
00030 
00031 #include <string>
00032 #ifndef __OBJC__
00033 #   include <boost/iostreams/concepts.hpp>
00034 #   include <boost/iostreams/stream.hpp>
00035 #endif
00036 
00037 namespace cinder {
00038 
00039 class StreamBase : private boost::noncopyable {
00040  public:
00041     virtual ~StreamBase() {}
00042     
00043     enum Endianness { STREAM_BIG_ENDIAN, STREAM_LITTLE_ENDIAN };
00044  
00046     static uint8_t      getNativeEndianness()
00047 #ifdef CINDER_LITTLE_ENDIAN
00048         { return STREAM_LITTLE_ENDIAN; }
00049  #else
00050         { return STREAM_BIG_ENDIAN; }
00051  #endif 
00052  
00054     const std::string&      getFileName() const { return mFileName; }
00055 
00057     void                    setFileName( const std::string &aFileName ) { mFileName = aFileName; }
00058 
00060     virtual off_t       tell() const = 0;
00061 
00063     virtual void        seekAbsolute( off_t absoluteOffset ) = 0;
00064     
00066     virtual void        seekRelative( off_t relativeOffset ) = 0;
00067  
00068  protected:
00069     StreamBase() {}
00070 
00071     std::string             mFileName;
00072 };
00073 
00074 class OStream : public virtual StreamBase {
00075  public:
00076     virtual ~OStream() {}
00077 
00078     template<typename T>
00079     void        write( T t );
00080     template<typename T>
00081     void        writeEndian( T t, uint8_t endian ) { if ( endian == STREAM_BIG_ENDIAN ) writeBig( t ); else writeLittle( t ); }
00082     template<typename T>
00083     void        writeBig( T t );
00084     template<typename T>
00085     void        writeLittle( T t );
00086 
00087     void        write( const Buffer &buffer );
00088     void        writeData( const void *src, size_t size );
00089 
00090  protected:
00091     OStream() : StreamBase() {}
00092  
00093     virtual void        IOWrite( const void *t, size_t size ) = 0;
00094 };
00095 
00096 
00097 typedef shared_ptr<class OStream>   OStreamRef;
00098 
00099 class IStream : public virtual StreamBase {
00100  public:
00101     virtual ~IStream() {};
00102 
00103     template<typename T>
00104     void        read( T *t );
00105     template<typename T>
00106     void        readEndian( T *t, uint8_t endian ) { if ( endian == STREAM_BIG_ENDIAN ) readBig( t ); else readLittle( t ); }
00107     template<typename T>
00108     void        readBig( T *t );
00109     template<typename T>
00110     void        readLittle( T *t );
00111     
00112     void        readFixedString( char *t, size_t maxSize, bool nullTerminate );
00113     void        readFixedString( std::string *t, size_t size );
00114     std::string readLine();
00115     
00116     void            readData( void *dest, size_t size );
00117     virtual size_t  readDataAvailable( void *dest, size_t maxSize ) = 0;
00118 
00119     virtual off_t       size() const = 0;   
00120     virtual bool        isEof() const = 0;
00121 
00122  protected:
00123     IStream() : StreamBase() {}
00124 
00125     virtual void        IORead( void *t, size_t size ) = 0;
00126         
00127     static const int    MINIMUM_BUFFER_SIZE = 8; // minimum bytes of random access a stream must offer relative to the file start
00128 };
00129 typedef shared_ptr<IStream>     IStreamRef;
00130 
00131 
00132 class IoStream : public IStream, public OStream {
00133  public:
00134     IoStream() : IStream(), OStream() {}
00135     virtual ~IoStream() {}
00136 };
00137 typedef shared_ptr<IoStream>        IoStreamRef;
00138 
00139 
00140 typedef shared_ptr<class IStreamFile>   IStreamFileRef;
00141 
00142 class IStreamFile : public IStream {
00143  public:
00145     static IStreamFileRef createRef( FILE *file, bool ownsFile = true, int32_t defaultBufferSize = 2048 );
00146     ~IStreamFile();
00147 
00148     size_t      readDataAvailable( void *dest, size_t maxSize );
00149     
00150     void        seekAbsolute( off_t absoluteOffset );
00151     void        seekRelative( off_t relativeOffset );
00152     off_t       tell() const;
00153     off_t       size() const;
00154     
00155     bool        isEof() const;
00156     
00157     FILE*       getFILE() { return mFile; }
00158 
00159  protected:
00160     IStreamFile( FILE *aFile, bool aOwnsFile = true, int32_t aDefaultBufferSize = 2048 );
00161 
00162     virtual void        IORead( void *t, size_t size );
00163  
00164     FILE                    *mFile;
00165     bool                    mOwnsFile;
00166     size_t                  mBufferSize, mDefaultBufferSize;
00167     shared_ptr<uint8_t> mBuffer;
00168     off_t                   mBufferOffset; // actual offset to do IO from; incremented by IO
00169     off_t                   mBufferFileOffset; // beginning of the buffer in the file
00170     mutable off_t           mSize;
00171     mutable bool            mSizeCached;
00172 };
00173 
00174 
00175 typedef shared_ptr<class OStreamFile>   OStreamFileRef;
00176 
00177 class OStreamFile : public OStream {
00178   public:
00180     static OStreamFileRef   createRef( FILE *file, bool ownsFile = true );
00181     ~OStreamFile();
00182 
00183     virtual off_t       tell() const;
00184     virtual void        seekAbsolute( off_t absoluteOffset );
00185     virtual void        seekRelative( off_t relativeOffset );
00186 
00187     FILE*               getFILE() { return mFile; }
00188 
00189     
00190   protected:
00191     OStreamFile( FILE *aFile, bool aOwnsFile = true );
00192 
00193     virtual void        IOWrite( const void *t, size_t size );
00194 
00195     FILE*               mFile;
00196     bool                mOwnsFile;
00197 };
00198 
00199 
00200 typedef shared_ptr<class IoStreamFile>      IoStreamFileRef;
00201 
00202 class IoStreamFile : public IoStream {
00203  public:
00205     static IoStreamFileRef createRef( FILE *file, bool ownsFile = true, int32_t defaultBufferSize = 2048 );
00206     ~IoStreamFile();
00207 
00208     size_t      readDataAvailable( void *dest, size_t maxSize );
00209     
00210     void        seekAbsolute( off_t absoluteOffset );
00211     void        seekRelative( off_t relativeOffset );
00212     off_t       tell() const;
00213     off_t       size() const;
00214     
00215     bool        isEof() const;
00216     
00217     FILE*       getFILE() { return mFile; }
00218 
00219  protected:
00220     IoStreamFile( FILE *aFile, bool aOwnsFile = true, int32_t aDefaultBufferSize = 2048 );
00221     
00222     virtual void        IORead( void *t, size_t size );
00223     virtual void        IOWrite( const void *t, size_t size );
00224  
00225     FILE                    *mFile;
00226     bool                    mOwnsFile;
00227     int32_t                 mBufferSize, mDefaultBufferSize;
00228     shared_ptr<uint8_t>     mBuffer;
00229     off_t                   mBufferOffset; // actual offset to do IO from; incremented by IO
00230     off_t                   mBufferFileOffset; // beginning of the buffer in the file
00231     mutable off_t           mSize;
00232     mutable bool            mSizeCached;
00233 };
00234 
00235 
00236 typedef shared_ptr<class IStreamMem>    IStreamMemRef;
00237 class IStreamMem : public IStream {
00238  public:
00240     static IStreamMemRef        createRef( const void *data, size_t size );
00241     ~IStreamMem();
00242 
00243     size_t      readDataAvailable( void *dest, size_t maxSize );
00244     
00245     void        seekAbsolute( off_t absoluteOffset );
00246     void        seekRelative( off_t relativeOffset );
00248     off_t       tell() const;
00250     off_t       size() const { return static_cast<off_t>( mDataSize ); }
00251 
00253     bool        isEof() const;
00254     
00256     const void* getData() { return reinterpret_cast<const void*>( mData ); }
00257 
00258  protected:
00259     IStreamMem( const void *aData, size_t aDataSize );
00260 
00261     virtual void    IORead( void *t, size_t size );
00262  
00263     const uint8_t   *mData;
00264     size_t          mDataSize;
00265     size_t          mOffset;
00266 };
00267 
00268 
00269 class OStreamMem : public OStream {
00270  public:
00271     ~OStreamMem();
00272 
00273     virtual off_t       tell() const { return static_cast<off_t>( mOffset ); }
00274     virtual void        seekAbsolute( off_t absoluteOffset );
00275     virtual void        seekRelative( off_t relativeOffset );
00276 
00277     void*               getBuffer() { return mBuffer; }
00278     
00279  protected:
00280     OStreamMem( size_t bufferSizeHint );
00281 
00282     virtual void        IOWrite( const void *t, size_t size );
00283 
00284     void            *mBuffer;
00285     size_t          mDataSize;
00286     size_t          mOffset;
00287 };
00288 
00289 typedef shared_ptr<OStreamMem>      OStreamMemRef;
00290 
00291 
00292 // This class is a utility to save and restore a stream's state
00293 class IStreamStateRestore {
00294  public:
00295     IStreamStateRestore( IStream &aStream ) : mStream( aStream ), mOffset( aStream.tell() ) {}
00296     ~IStreamStateRestore() {
00297         mStream.seekAbsolute( mOffset );
00298     }
00299     
00300  private:
00301     IStream     &mStream;
00302     off_t       mOffset;
00303 };
00304 
00306 IStreamFileRef  loadFileStream( const std::string &path );
00308 OStreamFileRef  writeFileStream( const std::string &path, bool createParents = true );
00310 IoStreamFileRef readWriteFileStream( const std::string &path );
00311 
00313 void loadStreamMemory( IStreamRef is, shared_ptr<uint8_t> *resultData, size_t *resultDataSize );
00315 Buffer loadStreamBuffer( IStreamRef is );
00316 
00317 
00318 // Stream exception
00319 class StreamExc : public Exception {
00320 };
00321 
00322 class StreamExcOutOfMemory : public StreamExc {
00323 };
00324 
00325 #ifndef __OBJC__
00326 class cinder_stream_source {
00327  public:
00328     typedef char char_type;
00329     typedef boost::iostreams::source_tag category;
00330 
00331     cinder_stream_source( cinder::IStreamRef aStream ) : mStream( aStream ) {}
00332 
00333     std::streamsize read( char *s, std::streamsize n )
00334     {
00335         if( mStream->isEof() )
00336             return -1;
00337         
00338         return (std::streamsize)mStream->readDataAvailable( s, (size_t)n );
00339     }
00340 
00341  protected:
00342     IStreamRef      mStream; // a little kludgy but this is for convenience
00343 };
00344 
00345 typedef boost::iostreams::stream<cinder_stream_source> cinder_istream;
00346 
00347 class cinder_stream_sink {
00348  public:
00349     typedef char char_type;
00350     typedef boost::iostreams::sink_tag category;
00351 
00352     cinder_stream_sink( OStreamRef aStream ) : mStream( aStream ) {}
00353 
00354     std::streamsize write( const char *s, std::streamsize n )
00355     {
00356         mStream->writeData( s, (size_t)n );
00357         return n;
00358     }
00359 
00360  protected:
00361     OStreamRef      mStream;
00362 };
00363 
00364 typedef boost::iostreams::stream<cinder_stream_sink> cinder_ostream;
00365 
00366 class cinder_stream_bidirectional_device {
00367  public:
00368     typedef char char_type;
00369     typedef boost::iostreams::seekable_device_tag category;
00370 
00371     cinder_stream_bidirectional_device( cinder::IoStreamRef aStream ) : mStream( aStream ) {}
00372 
00373     std::streamsize read( char *s, std::streamsize n )
00374     {
00375         return static_cast<std::streamsize>( mStream->readDataAvailable( s, (size_t)n ) );
00376     }
00377 
00378     std::streamsize write( const char *s, std::streamsize n )
00379     {
00380         mStream->writeData( s, (size_t)n );
00381         return n;
00382     }
00383 
00384     boost::iostreams::stream_offset seek( boost::iostreams::stream_offset off, std::ios_base::seekdir way)
00385     {
00386         if( way == std::ios_base::beg ) {
00387             mStream->seekAbsolute( (off_t)off );
00388         }
00389         else if( way == std::ios_base::cur ) {
00390             mStream->seekRelative( (off_t)off );
00391         }
00392         else { // way == std::ios_base::end
00393             mStream->seekAbsolute( -(off_t)off );
00394         }
00395         return mStream->tell();
00396     }
00397 
00398  protected:
00399     IoStreamRef     mStream;
00400 };
00401 
00402 typedef boost::iostreams::stream<cinder_stream_bidirectional_device> cinder_iostream;
00403 
00404 #endif // ! __OBJC__
00405 
00406 } // namespace cinder