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
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;
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;
00169 off_t mBufferFileOffset;
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;
00230 off_t mBufferFileOffset;
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
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
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;
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 {
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 }