00001
00004
00005
00006
00007
00008 #ifndef _cel_stream_h_
00009 #define _cel_stream_h_
00010
00011 #include "cel_types.h"
00012 #include "cel_referable.h"
00013 #include "cel_string.h"
00014 #include "cel_datatraits.h"
00015 #include "cel_exception.h"
00016 #include "cel_lockable.h"
00017
00018 namespace Celartem
00019 {
00030 typedef void (*DuplicateStreamCallback)(
00031 void* inContext,
00032 size_t inBytesCopied,
00033 size_t inMaximumBytesToCopy);
00034
00035
00041 class Stream : public Referable, public Lockable
00042 {
00043 public:
00066 virtual size_t readBytes(
00067 void *buffer, size_t inSize, bool wouldBlock = false) = 0;
00068
00080 virtual void writeBytes(const void *buffer, size_t inSize) = 0;
00081
00086 virtual void flushBuffer() = 0;
00087
00095 virtual bool isEof() const = 0;
00096
00113 virtual size_t duplicateStream(
00114 Stream *inStream,
00115 size_t inBufferSize = 1024,
00116 DuplicateStreamCallback inCallback = NULL,
00117 void* inCallbackContext = NULL);
00118
00139 virtual size_t duplicateStreamBytes(
00140 Stream *inStream,
00141 size_t inMaximumByteSize,
00142 size_t inBufferSize = 1024,
00143 DuplicateStreamCallback inCallback = NULL,
00144 void* inCallbackContext = NULL);
00145 };
00146
00147
00154 template<typename T, StoragePolicy storagePolicy>
00155 struct WriteData
00156 {
00157 static void writeData(
00158 Stream *inStream, const T& n, Endian inEndian = endianHost);
00159 };
00160
00166 template<typename T>
00167 struct WriteData<T, notToBeStored>
00168 {
00169 static void writeData(
00170 Stream *inStream, const T& n, Endian inEndian = endianHost)
00171 {
00172 celThrow2(
00173 errNotPermitted,
00174 "The object should not be stored in the storage or it might lack DataTraits implementation for the type.");
00175 }
00176 };
00177
00183 template<typename T>
00184 struct WriteData<T, byCopyBytes>
00185 {
00186 static void writeData(
00187 Stream *inStream, const T& n, Endian inEndian = endianHost)
00188 {
00189 inStream->writeBytes(&n, sizeof(T));
00190 }
00191 };
00192
00199 template<typename T>
00200 struct WriteData<T, bySwapCopyBytes>
00201 {
00202 static void writeData(
00203 Stream *inStream, const T& n, Endian inEndian = endianHost)
00204 {
00205 u8 buffer[sizeof(T)];
00206 write<T>(buffer, n, inEndian);
00207 inStream->writeBytes(buffer, sizeof(T));
00208 }
00209 };
00210
00225 template<typename T>
00226 struct WriteData<T, byClassMethods>
00227 {
00228 static void writeData(
00229 Stream *inStream, const T& n, Endian inEndian = endianHost)
00230 {
00231 n.serialize(inStream, 0, inEndian);
00232 }
00233 };
00234
00235
00242 template<typename T, StoragePolicy storagePolicy>
00243 struct ReadData
00244 {
00245 static T readData(Stream *inStream, Endian inEndian = endianHost);
00246 };
00247
00253 template<typename T>
00254 struct ReadData<T, notToBeStored>
00255 {
00256 static T readData(
00257 Stream *inStream, Endian inEndian = endianHost)
00258 {
00259 celThrow2(
00260 errNotPermitted,
00261 "The object should not be load from the storage.");
00262 return T();
00263 }
00264 };
00265
00271 template<typename T>
00272 struct ReadData<T, byCopyBytes>
00273 {
00274 static T readData(
00275 Stream *inStream, Endian inEndian = endianHost)
00276 {
00277 T tmp;
00278 inStream->readBytes(&tmp, sizeof(T), true);
00279 return tmp;
00280 }
00281 };
00282
00289 template<typename T>
00290 struct ReadData<T, bySwapCopyBytes>
00291 {
00292 static T readData(
00293 Stream *inStream, Endian inEndian = endianHost)
00294 {
00295 u8 buffer[sizeof(T)];
00296 inStream->readBytes(buffer, sizeof(T), true);
00297 return read<T>(buffer, inEndian);
00298 }
00299 };
00300
00314 template<typename T>
00315 struct ReadData<T, byClassMethods>
00316 {
00317 static T readData(
00318 Stream *inStream, Endian inEndian = endianHost)
00319 {
00320 T t;
00321 t.deserialize(inStream, 0, inEndian);
00322 return t;
00323 }
00324 };
00325
00326
00349 template<typename T>
00350 void write(
00351 Stream *inStream, const T& n, Endian inEndian )
00352 {
00353 WriteData<T, DataTraits<T>::storagePolicy>::writeData(
00354 inStream, n, inEndian);
00355 }
00356
00377 template<typename T>
00378 T read(
00379 Stream *inStream, Endian inEndian )
00380 {
00381 return ReadData<T, DataTraits<T>::storagePolicy>::readData(
00382 inStream, inEndian);
00383 }
00384
00385
00390 class NullStream : public Stream
00391 {
00392 public:
00396 static AutoPtr<NullStream> create()
00397 {
00398 return new NullStream();
00399 }
00400
00401 virtual size_t readBytes(
00402 void *buffer, size_t inSize, bool wouldBlock = false)
00403 {
00404 celThrow2(errNotImplemented,
00405 "NullStream::readBytes should not be called.");
00406 }
00407
00408 virtual void writeBytes(const void *buffer, size_t inSize)
00409 {
00410
00411 }
00412
00413 virtual void flushBuffer()
00414 {
00415
00416 }
00417
00418 virtual bool isEof() const
00419 {
00420
00421 return true;
00422 }
00423
00424 virtual void lock() const {}
00425 virtual void unlock() const {}
00426
00427 private:
00428 NullStream() {}
00429 };
00430
00431
00436 class ByteCounterStream : public Stream
00437 {
00438 public:
00444 static AutoPtr<ByteCounterStream> create(Stream* inStream)
00445 {
00446 return new ByteCounterStream(inStream);
00447 }
00448
00454 size_t getNumOfBytesRead() const {return m_bytesRead;}
00455
00461 size_t getNumOfBytesWritten() const {return m_bytesWritten;}
00462
00466 void resetByteRead() {m_bytesRead = 0;}
00467
00471 void resetByteWritten() {m_bytesWritten = 0;}
00472
00473 virtual size_t readBytes(
00474 void *buffer, size_t inSize, bool wouldBlock = false)
00475 {
00476 size_t sizeRead = m_stream->readBytes(buffer, inSize, wouldBlock);
00477 m_bytesRead += sizeRead;
00478 return sizeRead;
00479 }
00480 virtual void writeBytes(const void *buffer, size_t inSize)
00481 {
00482 m_stream->writeBytes(buffer, inSize);
00483 m_bytesWritten += inSize;
00484 }
00485
00486 virtual void flushBuffer() {m_stream->flushBuffer();}
00487
00488 virtual bool isEof() const {return m_stream->isEof();}
00489
00490 virtual void lock() const {m_stream->lock();}
00491
00492 virtual void unlock() const {m_stream->unlock();}
00493
00494 private:
00495
00496 ByteCounterStream(Stream* inStream)
00497 : m_stream(inStream), m_bytesRead(0), m_bytesWritten(0)
00498 {}
00499 ByteCounterStream();
00500 ByteCounterStream(ByteCounterStream& inRef);
00501 ByteCounterStream& operator=(ByteCounterStream& inRef);
00502
00503 AutoPtr<Stream> m_stream;
00504 size_t m_bytesRead;
00505 size_t m_bytesWritten;
00506 };
00507
00508
00512 class PartialStream : public Stream
00513 {
00514 public:
00522 static AutoPtr<PartialStream> create(Stream* inStream, uint64_t inSize)
00523 {
00524 return new PartialStream(inStream, inSize);
00525 }
00526
00527 virtual size_t readBytes(
00528 void *buffer, size_t inSize, bool wouldBlock = false)
00529 {
00530 uint64_t bytes = m_bytesProcessed + inSize;
00531 if(bytes > m_size)
00532 {
00533 if(wouldBlock)
00534 celThrow2(errReadFailed, "Cannot read so many bytes!");
00535 inSize = (size_t)(m_size - m_bytesProcessed);
00536 }
00537 size_t sizeRead = m_stream->readBytes(buffer, inSize, wouldBlock);
00538 m_bytesProcessed += sizeRead;
00539 return sizeRead;
00540 }
00541
00542 virtual void writeBytes(const void *buffer, size_t inSize)
00543 {
00544 if(m_bytesProcessed + inSize > m_size)
00545 celThrow2(errReadFailed, "Cannot write so many bytes!");
00546 m_stream->writeBytes(buffer, inSize);
00547 m_bytesProcessed += inSize;
00548 }
00549
00550 virtual void flushBuffer()
00551 {
00552 m_stream->flushBuffer();
00553 }
00554
00555 virtual bool isEof() const
00556 {
00557 if(m_bytesProcessed >= m_size)
00558 return true;
00559 return m_stream->isEof();
00560 }
00561
00562 virtual void lock() const {m_stream->lock();}
00563
00564 virtual void unlock() const {m_stream->unlock();}
00565
00566 private:
00567
00568 PartialStream(Stream* inStream, uint64_t inSize)
00569 : m_stream(inStream), m_size(inSize), m_bytesProcessed(0)
00570 {}
00571 PartialStream();
00572 PartialStream(PartialStream& inRef);
00573 PartialStream& operator=(PartialStream& inRef);
00574
00575 AutoPtr<Stream> m_stream;
00576 uint64_t m_size;
00577 uint64_t m_bytesProcessed;
00578 };
00579
00580 }
00581
00582 #endif // _cel_stream_h_