#include "CSInputBuffer.h" #include "IFileReader.h" #include #include // Allocation and management CSInputBuffer *CSInputBufferAlloc(IFileReader *parent, int size) { CSInputBuffer *self = static_cast(malloc(sizeof(CSInputBuffer) + size)); if (!self) return NULL; self->parent = parent; self->startoffs = parent->GetPosition(); self->eof = false; self->buffer = (uint8_t *)&self[1]; self->bufsize = size; self->bufbytes = 0; self->currbyte = 0; self->bits = 0; self->numbits = 0; return self; } CSInputBuffer *CSInputBufferAllocWithBuffer(const uint8_t *buffer, int length, IFileReader::FilePos_t startoffs) { CSInputBuffer *self = static_cast(malloc(sizeof(CSInputBuffer))); if (!self) return NULL; self->parent = NULL; self->startoffs = -startoffs; self->eof = true; self->buffer = (uint8_t *)buffer; // Since eof is set, the buffer won't be written to. self->bufsize = length; self->bufbytes = length; self->currbyte = 0; self->bits = 0; self->numbits = 0; return self; } CSInputBuffer *CSInputBufferAllocEmpty() { CSInputBuffer *self = static_cast(malloc(sizeof(CSInputBuffer))); if (!self) return NULL; self->parent = NULL; self->startoffs = 0; self->eof = true; self->buffer = NULL; self->bufsize = 0; self->bufbytes = 0; self->currbyte = 0; self->bits = 0; self->numbits = 0; return self; } void CSInputBufferFree(CSInputBuffer *self) { free(self); } void CSInputSetMemoryBuffer(CSInputBuffer *self, uint8_t *buffer, int length, IFileReader::FilePos_t startoffs) { self->eof = true; self->startoffs = -startoffs; self->buffer = buffer; self->bufsize = length; self->bufbytes = length; self->currbyte = 0; self->bits = 0; self->numbits = 0; } // Buffer and file positioning void CSInputRestart(CSInputBuffer *self) { CSInputSeekToFileOffset(self, self->startoffs); } void CSInputFlush(CSInputBuffer *self) { self->currbyte = self->bufbytes = 0; self->bits = 0; self->numbits = 0; } void CSInputSynchronizeFileOffset(CSInputBuffer *self) { CSInputSeekToFileOffset(self, CSInputFileOffset(self)); } void CSInputSeekToFileOffset(CSInputBuffer *self, IFileReader::FilePos_t offset) { self->parent->SeekStart(offset); self->eof = false; CSInputFlush(self); } void CSInputSeekToBufferOffset(CSInputBuffer *self, IFileReader::FilePos_t offset) { CSInputSeekToFileOffset(self, offset + self->startoffs); } void CSInputSetStartOffset(CSInputBuffer *self, IFileReader::FilePos_t offset) { self->startoffs = offset; } IFileReader::FilePos_t CSInputBufferOffset(CSInputBuffer *self) { return CSInputFileOffset(self) - self->startoffs; } IFileReader::FilePos_t CSInputFileOffset(CSInputBuffer *self) { if (self->parent) return self->parent->GetPosition() - self->bufbytes + self->currbyte; else return self->currbyte; } IFileReader::FilePos_t CSInputBufferBitOffset(CSInputBuffer *self) { return CSInputBufferOffset(self) * 8 - (self->numbits & 7); } // Byte reading void _CSInputFillBuffer(CSInputBuffer *self) { int left = _CSInputBytesLeftInBuffer(self); if (left >= 0) memmove(self->buffer, self->buffer + self->currbyte, left); else { self->parent->SeekCurrent(-left); left = 0; } int actual = self->parent->Read(self->buffer + left, self->bufsize - left); if (actual == 0) self->eof = true; self->bufbytes = left + actual; self->currbyte = 0; } // Bitstream reading // TODO: clean up and/or make faster bool _CSInputFillBits(CSInputBuffer *self) { _CSInputCheckAndFillBuffer(self); int numbytes = (32 - self->numbits) >> 3; int left = _CSInputBytesLeftInBuffer(self); if (numbytes > left) numbytes = left; int startoffset = self->numbits >> 3; // int shift=24-self->numbits; // for(int i=0;ibits|=_CSInputPeekByteWithoutEOF(self,i+startoffset)<bits = (_CSInputPeekByteWithoutEOF(self, startoffset) << 24) | (_CSInputPeekByteWithoutEOF(self, startoffset + 1) << 16) | (_CSInputPeekByteWithoutEOF(self, startoffset + 2) << 8) | _CSInputPeekByteWithoutEOF(self, startoffset + 3); break; case 3: self->bits |= ( (_CSInputPeekByteWithoutEOF(self, startoffset) << 16) | (_CSInputPeekByteWithoutEOF(self, startoffset + 1) << 8) | (_CSInputPeekByteWithoutEOF(self, startoffset + 2) << 0) ) << (8 - self->numbits); break; case 2: self->bits |= ( (_CSInputPeekByteWithoutEOF(self, startoffset) << 8) | (_CSInputPeekByteWithoutEOF(self, startoffset + 1) << 0) ) << (16 - self->numbits); break; case 1: self->bits |= _CSInputPeekByteWithoutEOF(self, startoffset) << (24 - self->numbits); break; } self->numbits += numbytes * 8; return true; } bool _CSInputFillBitsLE(CSInputBuffer *self) { _CSInputCheckAndFillBuffer(self); int numbytes = (32 - self->numbits) >> 3; int left = _CSInputBytesLeftInBuffer(self); if (numbytes > left) numbytes = left; int startoffset = self->numbits >> 3; for (int i = 0; i < numbytes; i++) { self->bits |= _CSInputPeekByteWithoutEOF(self, i + startoffset) << self->numbits; self->numbits += 8; } return true; } bool CSInputNextBit(CSInputBuffer *self, unsigned int &bit) { if (!CSInputPeekBitString(self, 1, bit)) return false; return CSInputSkipPeekedBits(self, 1); } bool CSInputNextBitLE(CSInputBuffer *self, unsigned int &bit) { if (!CSInputPeekBitStringLE(self, 1, bit)) return false; return CSInputSkipPeekedBitsLE(self, 1); } bool CSInputNextBitString(CSInputBuffer *self, int numbits, unsigned int &bits) { if (numbits == 0) { bits = 0; return true; } if (!CSInputPeekBitString(self, numbits, bits)) return false; return CSInputSkipPeekedBits(self, numbits); } bool CSInputNextBitStringLE(CSInputBuffer *self, int numbits, unsigned int &bits) { if (numbits == 0) { bits = 0; return true; } if (!CSInputPeekBitStringLE(self, numbits, bits)) return false; if (!CSInputSkipPeekedBitsLE(self, numbits)) return false; return true; } bool CSInputNextLongBitString(CSInputBuffer *self, int numbits, unsigned int &bits) { if (numbits <= 25) return CSInputNextBitString(self, numbits, bits); else { int rest = numbits - 25; unsigned int readBits; if (!CSInputNextBitString(self, 25, readBits)) return false; readBits <<= rest; unsigned int moreBits; if (!CSInputNextBitString(self, rest, moreBits)) return false; bits = (readBits | moreBits); return true; } } bool CSInputNextLongBitStringLE(CSInputBuffer *self, int numbits, unsigned int &bits) { if (numbits <= 25) return CSInputNextBitStringLE(self, numbits, bits); else { int rest = numbits - 25; unsigned int readBits; if (!CSInputNextBitStringLE(self, 25, readBits)) return false; unsigned int moreBits; if (!CSInputNextBitStringLE(self, rest, moreBits)) return false; bits = (readBits | (moreBits << 25)); return true; } } bool CSInputSkipBits(CSInputBuffer *self, int numbits) { if (numbits <= self->numbits) return CSInputSkipPeekedBits(self, numbits); else { int skipbits = numbits - (self->numbits & 7); CSInputSkipToByteBoundary(self); CSInputSkipBytes(self, skipbits >> 3); if (skipbits & 7) { unsigned int scratch; if (!CSInputNextBitString(self, skipbits & 7, scratch)) return false; } return true; } } bool CSInputSkipBitsLE(CSInputBuffer *self, int numbits) { if (numbits <= self->numbits) return CSInputSkipPeekedBitsLE(self, numbits); else { int skipbits = numbits - (self->numbits & 7); CSInputSkipToByteBoundary(self); CSInputSkipBytes(self, skipbits >> 3); if (skipbits & 7) { unsigned int scratch; if (!CSInputNextBitStringLE(self, skipbits & 7, scratch)) return false; } return true; } } bool CSInputOnByteBoundary(CSInputBuffer *self) { return (self->numbits & 7) == 0; } bool CSInputSkipToByteBoundary(CSInputBuffer *self) { self->bits = 0; self->numbits = 0; return true; } bool CSInputSkipTo16BitBoundary(CSInputBuffer *self) { if (!CSInputSkipToByteBoundary(self)) return false; if (CSInputBufferOffset(self) & 1) { if (!CSInputSkipBytes(self, 1)) return false; } return true; }