# 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 static_cast<std::streamsize>( mStream->readDataAvailable( s, 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, 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, n ) );
    00376     }
    00377
    00378     std::streamsize write( const char *s, std::streamsize n )
    00379     {
    00380         mStream->writeData( s, 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