diff --git a/czi-format/czi-parser/stream/buffered_binary_stream.cpp b/czi-format/czi-parser/stream/buffered_binary_stream.cpp index c91593a03e781199deab95002661ea78202fe21e..3da7987ca04ed5b5ff8e3e0ae53d46e2ee294625 100644 --- a/czi-format/czi-parser/stream/buffered_binary_stream.cpp +++ b/czi-format/czi-parser/stream/buffered_binary_stream.cpp @@ -1,284 +1,285 @@ -#include "buffered_binary_stream.h" - -BufferedBinaryStream::BufferedBinaryStream() -{ - this->isOpen = false; - this->underlayingSourceType = BufferSourceType_NoSource; -} - -BufferedBinaryStream::BufferedBinaryStream(ByteArray *bytes) -{ - this->isOpen = true; - this->underlayingSourceType = BufferSourceType_Memory; - this->memoryBuffer = bytes; - this->currentBufferPosition = 0; -} - -BufferedBinaryStream::BufferedBinaryStream(BinaryStreamBase *stream, const long streamBufferSize) -{ - this->isOpen = stream->is_open(); - this->underlayingSourceType = BufferSourceType_Stream; - this->streamBufferSize = streamBufferSize; - this->underlayingStream = stream; - this->currentBufferPosition = 0; -} - -BufferedBinaryStream::~BufferedBinaryStream() -{ - // Do we want to close stream / clear buffer? - // Probably not, because someone may want to use them later. - /* - switch (this->underlayingSourceType) - { - case BufferSourceType_Memory: - { - this->buffer.clear(); - } - break; - case BufferSourceType_Stream: - { - this->underlayingStream->close_stream(); - } - break; - } - */ -} - -long BufferedBinaryStream::get_size() const -{ - switch (this->underlayingSourceType) - { - case BufferSourceType_Memory: - { - return this->memoryBuffer->size(); - } - break; - case BufferSourceType_Stream: - { - return this->underlayingStream->get_size(); - } - break; - default: - always_assert(false && "Invalid BufferSourceType."); - break; - } - - return 0; -} - -long BufferedBinaryStream::get_position() -{ - switch (this->underlayingSourceType) - { - case BufferSourceType_Memory: - { - return this->currentBufferPosition; - } - break; - case BufferSourceType_Stream: - { - always_assert(this->currentBufferPosition <= this->streamBufferSize); - long pos = (this->readedFromSource > 0) ? this->readedFromSource - (this->streamBufferSize - this->currentBufferPosition) : 0; - return pos; - } - break; - default: - always_assert(false && "Invalid BufferSourceType."); - break; - } - - return 0; -} - -ulong BufferedBinaryStream::get_consume_size() -{ - - switch (this->underlayingSourceType) - { - case BufferSourceType_Memory: - { - always_assert(false && "This shouldn't be called ever."); - return 0; - } - break; - case BufferSourceType_Stream: - { - long totalSize = get_size(); - ulong currPos = this->underlayingStream->get_position(); - ulong avaible = totalSize - currPos; - ulong toConsume = (avaible > this->streamBufferSize) ? this->streamBufferSize : avaible; - return toConsume; - } - break; - default: - always_assert(false && "Invalid BufferSourceType."); - break; - } - return 0; -} - -void BufferedBinaryStream::move_to(const long position) -{ - always_assert(position < get_size()); - - switch (this->underlayingSourceType) - { - case BufferSourceType_Memory: - { - this->currentBufferPosition = position; - } - break; - case BufferSourceType_Stream: - { - - // move_to will always reload the buffer. - this->underlayingStream->move_to(position); - ulong toConsume = get_consume_size(); - this->streamBuffer = this->underlayingStream->consume_bytes(toConsume); - this->readedFromSource = this->underlayingStream->get_position(); - - // Just for sure. - //always_assert(this->readedFromSource == position + this->streamBufferSize); - - this->currentBufferPosition = 0; - } - break; - default: - always_assert(false && "Invalid BufferSourceType."); - break; - } -} - -void BufferedBinaryStream::move_to_beginning() -{ - switch (this->underlayingSourceType) - { - case BufferSourceType_Memory: - { - this->currentBufferPosition = 0; - } - break; - case BufferSourceType_Stream: - { - // move_to_beginning will always reload the buffer. - this->underlayingStream->move_to_beginning(); - this->streamBuffer = this->underlayingStream->consume_bytes(get_consume_size()); - this->readedFromSource = this->streamBufferSize; - this->currentBufferPosition = 0; - } - break; - default: - always_assert(false && "Invalid BufferSourceType."); - break; - } -} - -void BufferedBinaryStream::move_to_end() -{ - this->currentBufferPosition = get_size(); - switch (this->underlayingSourceType) - { - case BufferSourceType_Stream: - { - // move_to_beginning will always clear the buffer. - this->streamBuffer.clear(); - this->readedFromSource = this->currentBufferPosition; - this->currentBufferPosition = 0; - } - break; - default: - always_assert(false && "Invalid BufferSourceType."); - break; - } -} - -void BufferedBinaryStream::move_by(const long distance) -{ - always_assert((get_position() + distance) < get_size()); - - switch (this->underlayingSourceType) - { - case BufferSourceType_Memory: - { - always_assert((this->currentBufferPosition + distance) < this->memoryBuffer->size()); - this->currentBufferPosition += distance; - } - break; - case BufferSourceType_Stream: - { - // If atleast one byte can be read, just advance the buffer position. - if ((this->currentBufferPosition + distance + 1) < this->streamBufferSize) - { - this->currentBufferPosition += distance; - } - else - { - // If we are moving outside buffer, reload the buffer from desired location. - long currentPosInStreamRelativeToBufferPos = get_position(); - - always_assert((currentPosInStreamRelativeToBufferPos + distance) < this->underlayingStream->get_size()); - this->underlayingStream->move_to((currentPosInStreamRelativeToBufferPos + distance)); - - ulong toConsume = get_consume_size(); - this->streamBuffer = this->underlayingStream->consume_bytes(toConsume); - this->readedFromSource = this->underlayingStream->get_position(); - this->currentBufferPosition = 0; - } - } - break; - default: - always_assert(false && "Invalid BufferSourceType."); - break; - } -} - -ByteArray BufferedBinaryStream::consume_bytes(const ulong byteCount) -{ - if (this->streamBufferSize < byteCount) - { - printf(RED "To parse this file, you need buffer of size atleast: %lu\n" RESET, byteCount); - } - // We won't allow consuming more bytes than is buffer size. - always_assert(byteCount <= this->streamBufferSize && "Buffer is too small."); - - switch (this->underlayingSourceType) - { - case BufferSourceType_Memory: - { - // Check how many bytes are avaible in memory buffer. - ulong bytesAvaible = this->memoryBuffer->size() - this->currentBufferPosition; - always_assert(bytesAvaible <= byteCount); - - auto fromIt = this->memoryBuffer->begin() + this->currentBufferPosition; - auto toIt = fromIt + byteCount; - this->currentBufferPosition += byteCount; - - ByteArray result(fromIt, toIt); - return result; - } - break; - case BufferSourceType_Stream: - { - ulong bytesAvaible = this->streamBuffer.size() - this->currentBufferPosition; - if ((bytesAvaible == 0) || (byteCount > bytesAvaible)) - { - long currentPos = get_position(); - // Moving to current position will ensure, that streamBufferSize of data will be read into buffer. - move_to(currentPos); - } - - auto fromIt = this->streamBuffer.begin() + this->currentBufferPosition; - auto toIt = fromIt + byteCount; - this->currentBufferPosition += byteCount; - - ByteArray result(fromIt, toIt); - return result; - } - break; - default: - always_assert(false && "Invalid BufferSourceType."); - break; - } - - return ByteArray(); +#include "buffered_binary_stream.h" + +BufferedBinaryStream::BufferedBinaryStream() +{ + this->isOpen = false; + this->underlayingSourceType = BufferSourceType_NoSource; +} + +BufferedBinaryStream::BufferedBinaryStream(ByteArray *bytes) +{ + this->isOpen = true; + this->underlayingSourceType = BufferSourceType_Memory; + this->memoryBuffer = bytes; + this->currentBufferPosition = 0; +} + +BufferedBinaryStream::BufferedBinaryStream(BinaryStreamBase *stream, const long streamBufferSize) +{ + this->isOpen = stream->is_open(); + this->underlayingSourceType = BufferSourceType_Stream; + this->streamBufferSize = streamBufferSize; + this->underlayingStream = stream; + this->currentBufferPosition = 0; +} + +BufferedBinaryStream::~BufferedBinaryStream() +{ + // Do we want to close stream / clear buffer? + // Probably not, because someone may want to use them later. + /* + switch (this->underlayingSourceType) + { + case BufferSourceType_Memory: + { + this->buffer.clear(); + } + break; + case BufferSourceType_Stream: + { + this->underlayingStream->close_stream(); + } + break; + } + */ +} + +long BufferedBinaryStream::get_size() const +{ + switch (this->underlayingSourceType) + { + case BufferSourceType_Memory: + { + return this->memoryBuffer->size(); + } + break; + case BufferSourceType_Stream: + { + return this->underlayingStream->get_size(); + } + break; + default: + always_assert(false && "Invalid BufferSourceType."); + break; + } + + return 0; +} + +long BufferedBinaryStream::get_position() +{ + switch (this->underlayingSourceType) + { + case BufferSourceType_Memory: + { + return this->currentBufferPosition; + } + break; + case BufferSourceType_Stream: + { + always_assert(this->currentBufferPosition <= this->streamBufferSize); + long pos = (this->readedFromSource > 0) ? this->readedFromSource - (this->streamBufferSize - this->currentBufferPosition) : 0; + return pos; + } + break; + default: + always_assert(false && "Invalid BufferSourceType."); + break; + } + + return 0; +} + +ulong BufferedBinaryStream::get_consume_size() +{ + + switch (this->underlayingSourceType) + { + case BufferSourceType_Memory: + { + always_assert(false && "This shouldn't be called ever."); + return 0; + } + break; + case BufferSourceType_Stream: + { + long totalSize = get_size(); + ulong currPos = this->underlayingStream->get_position(); + ulong avaible = totalSize - currPos; + ulong toConsume = (avaible > this->streamBufferSize) ? this->streamBufferSize : avaible; + return toConsume; + } + break; + default: + always_assert(false && "Invalid BufferSourceType."); + break; + } + return 0; +} + +void BufferedBinaryStream::move_to(const long position) +{ + always_assert(position < get_size()); + + switch (this->underlayingSourceType) + { + case BufferSourceType_Memory: + { + this->currentBufferPosition = position; + } + break; + case BufferSourceType_Stream: + { + + // move_to will always reload the buffer. + this->underlayingStream->move_to(position); + ulong toConsume = get_consume_size(); + this->streamBuffer = this->underlayingStream->consume_bytes(toConsume); + this->readedFromSource = this->underlayingStream->get_position(); + + // Just for sure. + //always_assert(this->readedFromSource == position + this->streamBufferSize); + + this->currentBufferPosition = 0; + } + break; + default: + always_assert(false && "Invalid BufferSourceType."); + break; + } +} + +void BufferedBinaryStream::move_to_beginning() +{ + switch (this->underlayingSourceType) + { + case BufferSourceType_Memory: + { + this->currentBufferPosition = 0; + } + break; + case BufferSourceType_Stream: + { + // move_to_beginning will always reload the buffer. + this->underlayingStream->move_to_beginning(); + this->streamBuffer = this->underlayingStream->consume_bytes(get_consume_size()); + this->readedFromSource = this->streamBufferSize; + this->currentBufferPosition = 0; + } + break; + default: + always_assert(false && "Invalid BufferSourceType."); + break; + } +} + +void BufferedBinaryStream::move_to_end() +{ + this->currentBufferPosition = get_size(); + switch (this->underlayingSourceType) + { + case BufferSourceType_Stream: + { + // move_to_beginning will always clear the buffer. + this->streamBuffer.clear(); + this->readedFromSource = this->currentBufferPosition; + this->currentBufferPosition = 0; + } + break; + default: + always_assert(false && "Invalid BufferSourceType."); + break; + } +} + +void BufferedBinaryStream::move_by(const long distance) +{ + always_assert((get_position() + distance) < get_size()); + + switch (this->underlayingSourceType) + { + case BufferSourceType_Memory: + { + always_assert((this->currentBufferPosition + distance) < this->memoryBuffer->size()); + this->currentBufferPosition += distance; + } + break; + case BufferSourceType_Stream: + { + // If atleast one byte can be read, just advance the buffer position. + if ((this->currentBufferPosition + distance + 1) < this->streamBufferSize) + { + this->currentBufferPosition += distance; + } + else + { + // If we are moving outside buffer, reload the buffer from desired location. + long currentPosInStreamRelativeToBufferPos = get_position(); + + always_assert((currentPosInStreamRelativeToBufferPos + distance) < this->underlayingStream->get_size()); + this->underlayingStream->move_to((currentPosInStreamRelativeToBufferPos + distance)); + + ulong toConsume = get_consume_size(); + this->streamBuffer = this->underlayingStream->consume_bytes(toConsume); + this->readedFromSource = this->underlayingStream->get_position(); + this->currentBufferPosition = 0; + } + } + break; + default: + always_assert(false && "Invalid BufferSourceType."); + break; + } +} + +ByteArray BufferedBinaryStream::consume_bytes(const ulong byteCount) +{ + if (this->streamBufferSize < byteCount) + { + printf(RED "To parse this file, you need buffer of size atleast: %lu\n" RESET, byteCount); + } + // We won't allow consuming more bytes than is buffer size. + always_assert(byteCount <= this->streamBufferSize && "Buffer is too small."); + + switch (this->underlayingSourceType) + { + case BufferSourceType_Memory: + { + // Check how many bytes are avaible in memory buffer. + ulong bytesAvaible = this->memoryBuffer->size() - this->currentBufferPosition; + printf("BA: %lu\n", bytesAvaible); + always_assert(bytesAvaible >= byteCount); + + auto fromIt = this->memoryBuffer->begin() + this->currentBufferPosition; + auto toIt = fromIt + byteCount; + this->currentBufferPosition += byteCount; + + ByteArray result(fromIt, toIt); + return result; + } + break; + case BufferSourceType_Stream: + { + ulong bytesAvaible = this->streamBuffer.size() - this->currentBufferPosition; + if ((bytesAvaible == 0) || (byteCount > bytesAvaible)) + { + long currentPos = get_position(); + // Moving to current position will ensure, that streamBufferSize of data will be read into buffer. + move_to(currentPos); + } + + auto fromIt = this->streamBuffer.begin() + this->currentBufferPosition; + auto toIt = fromIt + byteCount; + this->currentBufferPosition += byteCount; + + ByteArray result(fromIt, toIt); + return result; + } + break; + default: + always_assert(false && "Invalid BufferSourceType."); + break; + } + + return ByteArray(); } \ No newline at end of file