00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #pragma once
00024
00025 #include "cinder/Cinder.h"
00026 #include "cinder/Buffer.h"
00027 #include "cinder/Exception.h"
00028 #include "cinder/Filesystem.h"
00029
00030 #include <boost/noncopyable.hpp>
00031
00032 #include <string>
00033 #ifndef __OBJC__
00034 # include <boost/iostreams/concepts.hpp>
00035 # include <boost/iostreams/stream.hpp>
00036 #endif
00037
00038 namespace cinder {
00039
00040 class StreamBase : private boost::noncopyable {
00041 public:
00042 virtual ~StreamBase() {}
00043
00044 enum Endianness { STREAM_BIG_ENDIAN, STREAM_LITTLE_ENDIAN };
00045
00047 static uint8_t getNativeEndianness()
00048 #ifdef CINDER_LITTLE_ENDIAN
00049 { return STREAM_LITTLE_ENDIAN; }
00050 #else
00051 { return STREAM_BIG_ENDIAN; }
00052 #endif
00053
00055 const std::string& getFileName() const { return mFileName; }
00057 void setFileName( const std::string &aFileName ) { mFileName = aFileName; }
00058
00060 bool getDeleteOnDestroy() const { return mDeleteOnDestroy; }
00062 void setDeleteOnDestroy( bool enable = true ) { mDeleteOnDestroy = enable; }
00063
00065 virtual off_t tell() const = 0;
00066
00068 virtual void seekAbsolute( off_t absoluteOffset ) = 0;
00069
00071 virtual void seekRelative( off_t relativeOffset ) = 0;
00072
00073 protected:
00074 StreamBase() : mDeleteOnDestroy( false ) {}
00075
00076 std::string mFileName;
00077 bool mDeleteOnDestroy;
00078 };
00079
00080 class OStream : public virtual StreamBase {
00081 public:
00082 virtual ~OStream() {}
00083
00085 void write( const std::string &s ) { writeData( s.c_str(), s.length() + 1 ); }
00086 void write( const ci::fs::path &p ) { writeData( p.string().c_str(), p.string().length() + 1 ); }
00087 template<typename T>
00088 void write( T t ) { IOWrite( &t, sizeof(T) ); }
00089 template<typename T>
00090 void writeEndian( T t, uint8_t endian ) { if ( endian == STREAM_BIG_ENDIAN ) writeBig( t ); else writeLittle( t ); }
00091 template<typename T>
00092 void writeBig( T t );
00093 template<typename T>
00094 void writeLittle( T t );
00095
00096 void write( const Buffer &buffer );
00097 void writeData( const void *src, size_t size );
00098
00099 protected:
00100 OStream() : StreamBase() {}
00101
00102 virtual void IOWrite( const void *t, size_t size ) = 0;
00103 };
00104
00105
00106 typedef std::shared_ptr<class OStream> OStreamRef;
00107
00108 class IStream : public virtual StreamBase {
00109 public:
00110 virtual ~IStream() {};
00111
00112 template<typename T>
00113 void read( T *t ) { IORead( t, sizeof(T) ); }
00114 template<typename T>
00115 void readEndian( T *t, uint8_t endian ) { if ( endian == STREAM_BIG_ENDIAN ) readBig( t ); else readLittle( t ); }
00116 template<typename T>
00117 void readBig( T *t );
00118 template<typename T>
00119 void readLittle( T *t );
00120
00122 void read( std::string *s );
00123 void read( ci::fs::path *p );
00124 void readFixedString( char *t, size_t maxSize, bool nullTerminate );
00125 void readFixedString( std::string *t, size_t size );
00126 std::string readLine();
00127
00128 void readData( void *dest, size_t size );
00129 virtual size_t readDataAvailable( void *dest, size_t maxSize ) = 0;
00130
00131 virtual off_t size() const = 0;
00132 virtual bool isEof() const = 0;
00133
00134 protected:
00135 IStream() : StreamBase() {}
00136
00137 virtual void IORead( void *t, size_t size ) = 0;
00138
00139 static const int MINIMUM_BUFFER_SIZE = 8;
00140 };
00141 typedef std::shared_ptr<IStream> IStreamRef;
00142
00143
00144 class IoStream : public IStream, public OStream {
00145 public:
00146 IoStream() : IStream(), OStream() {}
00147 virtual ~IoStream() {}
00148 };
00149 typedef std::shared_ptr<IoStream> IoStreamRef;
00150
00151
00152 typedef std::shared_ptr<class IStreamFile> IStreamFileRef;
00153
00154 class IStreamFile : public IStream {
00155 public:
00157 static IStreamFileRef createRef( FILE *file, bool ownsFile = true, int32_t defaultBufferSize = 2048 );
00158 ~IStreamFile();
00159
00160 size_t readDataAvailable( void *dest, size_t maxSize );
00161
00162 void seekAbsolute( off_t absoluteOffset );
00163 void seekRelative( off_t relativeOffset );
00164 off_t tell() const;
00165 off_t size() const;
00166
00167 bool isEof() const;
00168
00169 FILE* getFILE() { return mFile; }
00170
00171 protected:
00172 IStreamFile( FILE *aFile, bool aOwnsFile = true, int32_t aDefaultBufferSize = 2048 );
00173
00174 virtual void IORead( void *t, size_t size );
00175
00176 FILE *mFile;
00177 bool mOwnsFile;
00178 size_t mBufferSize, mDefaultBufferSize;
00179 std::shared_ptr<uint8_t> mBuffer;
00180 off_t mBufferOffset;
00181 off_t mBufferFileOffset;
00182 mutable off_t mSize;
00183 mutable bool mSizeCached;
00184 };
00185
00186
00187 typedef std::shared_ptr<class OStreamFile> OStreamFileRef;
00188
00189 class OStreamFile : public OStream {
00190 public:
00192 static OStreamFileRef createRef( FILE *file, bool ownsFile = true );
00193 ~OStreamFile();
00194
00195 virtual off_t tell() const;
00196 virtual void seekAbsolute( off_t absoluteOffset );
00197 virtual void seekRelative( off_t relativeOffset );
00198
00199 FILE* getFILE() { return mFile; }
00200
00201
00202 protected:
00203 OStreamFile( FILE *aFile, bool aOwnsFile = true );
00204
00205 virtual void IOWrite( const void *t, size_t size );
00206
00207 FILE* mFile;
00208 bool mOwnsFile;
00209 };
00210
00211
00212 typedef std::shared_ptr<class IoStreamFile> IoStreamFileRef;
00213
00214 class IoStreamFile : public IoStream {
00215 public:
00217 static IoStreamFileRef createRef( FILE *file, bool ownsFile = true, int32_t defaultBufferSize = 2048 );
00218 ~IoStreamFile();
00219
00220 size_t readDataAvailable( void *dest, size_t maxSize );
00221
00222 void seekAbsolute( off_t absoluteOffset );
00223 void seekRelative( off_t relativeOffset );
00224 off_t tell() const;
00225 off_t size() const;
00226
00227 bool isEof() const;
00228
00229 FILE* getFILE() { return mFile; }
00230
00231 protected:
00232 IoStreamFile( FILE *aFile, bool aOwnsFile = true, int32_t aDefaultBufferSize = 2048 );
00233
00234 virtual void IORead( void *t, size_t size );
00235 virtual void IOWrite( const void *t, size_t size );
00236
00237 FILE *mFile;
00238 bool mOwnsFile;
00239 int32_t mBufferSize, mDefaultBufferSize;
00240 std::shared_ptr<uint8_t> mBuffer;
00241 off_t mBufferOffset;
00242 off_t mBufferFileOffset;
00243 mutable off_t mSize;
00244 mutable bool mSizeCached;
00245 };
00246
00247
00248 typedef std::shared_ptr<class IStreamMem> IStreamMemRef;
00249 class IStreamMem : public IStream {
00250 public:
00252 static IStreamMemRef createRef( const void *data, size_t size );
00253 ~IStreamMem();
00254
00255 size_t readDataAvailable( void *dest, size_t maxSize );
00256
00257 void seekAbsolute( off_t absoluteOffset );
00258 void seekRelative( off_t relativeOffset );
00260 off_t tell() const;
00262 off_t size() const { return static_cast<off_t>( mDataSize ); }
00263
00265 bool isEof() const;
00266
00268 const void* getData() { return reinterpret_cast<const void*>( mData ); }
00269
00270 protected:
00271 IStreamMem( const void *aData, size_t aDataSize );
00272
00273 virtual void IORead( void *t, size_t size );
00274
00275 const uint8_t *mData;
00276 size_t mDataSize;
00277 size_t mOffset;
00278 };
00279
00280
00281 typedef std::shared_ptr<class OStreamMem> OStreamMemRef;
00282
00283 class OStreamMem : public OStream {
00284 public:
00285 static OStreamMemRef createRef( size_t bufferSizeHint = 4096 ) { return std::shared_ptr<OStreamMem>( new OStreamMem( bufferSizeHint ) ); }
00286
00287 ~OStreamMem();
00288
00289 virtual off_t tell() const { return static_cast<off_t>( mOffset ); }
00290 virtual void seekAbsolute( off_t absoluteOffset );
00291 virtual void seekRelative( off_t relativeOffset );
00292
00293 void* getBuffer() { return mBuffer; }
00294
00295 protected:
00296 OStreamMem( size_t bufferSizeHint );
00297
00298 virtual void IOWrite( const void *t, size_t size );
00299
00300 void *mBuffer;
00301 size_t mDataSize;
00302 size_t mOffset;
00303 };
00304
00305
00306
00307 class IStreamStateRestore {
00308 public:
00309 IStreamStateRestore( IStream &aStream ) : mStream( aStream ), mOffset( aStream.tell() ) {}
00310 ~IStreamStateRestore() {
00311 mStream.seekAbsolute( mOffset );
00312 }
00313
00314 private:
00315 IStream &mStream;
00316 off_t mOffset;
00317 };
00318
00320 IStreamFileRef loadFileStream( const std::string &path );
00322 OStreamFileRef writeFileStream( const std::string &path, bool createParents = true );
00324 IoStreamFileRef readWriteFileStream( const std::string &path );
00325
00327 void loadStreamMemory( IStreamRef is, std::shared_ptr<uint8_t> *resultData, size_t *resultDataSize );
00329 Buffer loadStreamBuffer( IStreamRef is );
00330
00331
00332
00333 class StreamExc : public Exception {
00334 };
00335
00336 class StreamExcOutOfMemory : public StreamExc {
00337 };
00338
00339 #ifndef __OBJC__
00340 class cinder_stream_source {
00341 public:
00342 typedef char char_type;
00343 typedef boost::iostreams::source_tag category;
00344
00345 cinder_stream_source( cinder::IStreamRef aStream ) : mStream( aStream ) {}
00346
00347 std::streamsize read( char *s, std::streamsize n )
00348 {
00349 if( mStream->isEof() )
00350 return -1;
00351
00352 return (std::streamsize)mStream->readDataAvailable( s, (size_t)n );
00353 }
00354
00355 protected:
00356 IStreamRef mStream;
00357 };
00358
00359 typedef boost::iostreams::stream<cinder_stream_source> cinder_istream;
00360
00361 class cinder_stream_sink {
00362 public:
00363 typedef char char_type;
00364 typedef boost::iostreams::sink_tag category;
00365
00366 cinder_stream_sink( OStreamRef aStream ) : mStream( aStream ) {}
00367
00368 std::streamsize write( const char *s, std::streamsize n )
00369 {
00370 mStream->writeData( s, (size_t)n );
00371 return n;
00372 }
00373
00374 protected:
00375 OStreamRef mStream;
00376 };
00377
00378 typedef boost::iostreams::stream<cinder_stream_sink> cinder_ostream;
00379
00380 class cinder_stream_bidirectional_device {
00381 public:
00382 typedef char char_type;
00383 typedef boost::iostreams::seekable_device_tag category;
00384
00385 cinder_stream_bidirectional_device( cinder::IoStreamRef aStream ) : mStream( aStream ) {}
00386
00387 std::streamsize read( char *s, std::streamsize n )
00388 {
00389 return static_cast<std::streamsize>( mStream->readDataAvailable( s, (size_t)n ) );
00390 }
00391
00392 std::streamsize write( const char *s, std::streamsize n )
00393 {
00394 mStream->writeData( s, (size_t)n );
00395 return n;
00396 }
00397
00398 boost::iostreams::stream_offset seek( boost::iostreams::stream_offset off, std::ios_base::seekdir way)
00399 {
00400 if( way == std::ios_base::beg ) {
00401 mStream->seekAbsolute( (off_t)off );
00402 }
00403 else if( way == std::ios_base::cur ) {
00404 mStream->seekRelative( (off_t)off );
00405 }
00406 else {
00407 mStream->seekAbsolute( -(off_t)off );
00408 }
00409 return mStream->tell();
00410 }
00411
00412 protected:
00413 IoStreamRef mStream;
00414 };
00415
00416 typedef boost::iostreams::stream<cinder_stream_bidirectional_device> cinder_iostream;
00417
00418 #endif // ! __OBJC__
00419
00420 }