mirror of
https://github.com/MacPaw/XADMaster.git
synced 2025-08-29 19:43:47 +02:00
222 lines
6.1 KiB
Objective-C
222 lines
6.1 KiB
Objective-C
/*
|
|
* CSInputBuffer.h
|
|
*
|
|
* Copyright (c) 2017-present, MacPaw Inc. All rights reserved.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
* MA 02110-1301 USA
|
|
*/
|
|
#import <Foundation/Foundation.h>
|
|
#import "CSHandle.h"
|
|
|
|
typedef struct CSInputBuffer
|
|
{
|
|
CSHandle *parent;
|
|
off_t startoffs;
|
|
BOOL eof;
|
|
|
|
uint8_t *buffer;
|
|
unsigned int bufsize,bufbytes,currbyte;
|
|
|
|
uint32_t bits;
|
|
unsigned int numbits;
|
|
} CSInputBuffer;
|
|
|
|
|
|
|
|
// Allocation and management
|
|
|
|
CSInputBuffer *CSInputBufferAlloc(CSHandle *parent,int size);
|
|
CSInputBuffer *CSInputBufferAllocWithBuffer(const uint8_t *buffer,int length,off_t startoffs);
|
|
CSInputBuffer *CSInputBufferAllocEmpty(void);
|
|
void CSInputBufferFree(CSInputBuffer *self);
|
|
|
|
void CSInputSetMemoryBuffer(CSInputBuffer *self,uint8_t *buffer,int length,off_t startoffs);
|
|
|
|
static inline CSHandle *CSInputHandle(CSInputBuffer *self)
|
|
{
|
|
return self->parent;
|
|
}
|
|
|
|
|
|
|
|
// Buffer and file positioning
|
|
|
|
void CSInputRestart(CSInputBuffer *self);
|
|
void CSInputFlush(CSInputBuffer *self);
|
|
|
|
void CSInputSynchronizeFileOffset(CSInputBuffer *self);
|
|
void CSInputSeekToFileOffset(CSInputBuffer *self,off_t offset);
|
|
void CSInputSeekToBufferOffset(CSInputBuffer *self,off_t offset);
|
|
void CSInputSetStartOffset(CSInputBuffer *self,off_t offset);
|
|
off_t CSInputBufferOffset(CSInputBuffer *self);
|
|
off_t CSInputFileOffset(CSInputBuffer *self);
|
|
off_t CSInputBufferBitOffset(CSInputBuffer *self);
|
|
|
|
void _CSInputFillBuffer(CSInputBuffer *self);
|
|
|
|
|
|
|
|
|
|
// Byte reading
|
|
|
|
#define CSInputBufferLookAhead 4
|
|
|
|
static inline void _CSInputBufferRaiseEOF(CSInputBuffer *self)
|
|
{
|
|
if(self->parent) [self->parent _raiseEOF];
|
|
else [NSException raise:CSEndOfFileException
|
|
format:@"Attempted to read past the end of memory buffer."];
|
|
}
|
|
|
|
static inline int _CSInputBytesLeftInBuffer(CSInputBuffer *self)
|
|
{
|
|
return self->bufbytes-self->currbyte;
|
|
}
|
|
|
|
static inline void _CSInputCheckAndFillBuffer(CSInputBuffer *self)
|
|
{
|
|
if(!self->eof&&_CSInputBytesLeftInBuffer(self)<=CSInputBufferLookAhead) _CSInputFillBuffer(self);
|
|
}
|
|
|
|
static inline void CSInputSkipBytes(CSInputBuffer *self,int num)
|
|
{
|
|
self->currbyte+=num;
|
|
}
|
|
|
|
static inline int _CSInputPeekByteWithoutEOF(CSInputBuffer *self,int offs)
|
|
{
|
|
return self->buffer[self->currbyte+offs];
|
|
}
|
|
|
|
static inline int CSInputPeekByte(CSInputBuffer *self,int offs)
|
|
{
|
|
_CSInputCheckAndFillBuffer(self);
|
|
if(offs>=_CSInputBytesLeftInBuffer(self)) _CSInputBufferRaiseEOF(self);
|
|
return _CSInputPeekByteWithoutEOF(self,offs);
|
|
}
|
|
|
|
static inline int CSInputNextByte(CSInputBuffer *self)
|
|
{
|
|
int byte=CSInputPeekByte(self,0);
|
|
CSInputSkipBytes(self,1);
|
|
return byte;
|
|
}
|
|
|
|
static inline BOOL CSInputAtEOF(CSInputBuffer *self)
|
|
{
|
|
_CSInputCheckAndFillBuffer(self);
|
|
return _CSInputBytesLeftInBuffer(self)<=0;
|
|
}
|
|
|
|
|
|
|
|
|
|
// Bitstream reading
|
|
|
|
void _CSInputFillBits(CSInputBuffer *self);
|
|
void _CSInputFillBitsLE(CSInputBuffer *self);
|
|
|
|
unsigned int CSInputNextBit(CSInputBuffer *self);
|
|
unsigned int CSInputNextBitLE(CSInputBuffer *self);
|
|
unsigned int CSInputNextBitString(CSInputBuffer *self,int numbits);
|
|
unsigned int CSInputNextBitStringLE(CSInputBuffer *self,int numbits);
|
|
unsigned int CSInputNextLongBitString(CSInputBuffer *self,int numbits);
|
|
unsigned int CSInputNextLongBitStringLE(CSInputBuffer *self,int numbits);
|
|
|
|
void CSInputSkipBits(CSInputBuffer *self,int numbits);
|
|
void CSInputSkipBitsLE(CSInputBuffer *self,int numbits);
|
|
BOOL CSInputOnByteBoundary(CSInputBuffer *self);
|
|
void CSInputSkipToByteBoundary(CSInputBuffer *self);
|
|
void CSInputSkipTo16BitBoundary(CSInputBuffer *self);
|
|
|
|
static inline unsigned int CSInputBitsLeftInBuffer(CSInputBuffer *self)
|
|
{
|
|
_CSInputCheckAndFillBuffer(self);
|
|
return _CSInputBytesLeftInBuffer(self)*8+(self->numbits&7);
|
|
}
|
|
|
|
static inline void _CSInputCheckAndFillBits(CSInputBuffer *self,int numbits)
|
|
{
|
|
if(numbits>self->numbits) _CSInputFillBits(self);
|
|
}
|
|
|
|
static inline void _CSInputCheckAndFillBitsLE(CSInputBuffer *self,int numbits)
|
|
{
|
|
if(numbits>self->numbits) _CSInputFillBitsLE(self);
|
|
}
|
|
|
|
static inline unsigned int CSInputPeekBitString(CSInputBuffer *self,int numbits)
|
|
{
|
|
if(numbits==0) return 0;
|
|
_CSInputCheckAndFillBits(self,numbits);
|
|
return self->bits>>(32-numbits);
|
|
}
|
|
|
|
static inline unsigned int CSInputPeekBitStringLE(CSInputBuffer *self,int numbits)
|
|
{
|
|
if(numbits==0) return 0;
|
|
_CSInputCheckAndFillBitsLE(self,numbits);
|
|
return self->bits&((1<<numbits)-1);
|
|
}
|
|
|
|
static inline void CSInputSkipPeekedBits(CSInputBuffer *self,int numbits)
|
|
{
|
|
int numbytes=(numbits-(self->numbits&7)+7)>>3;
|
|
CSInputSkipBytes(self,numbytes);
|
|
|
|
if(_CSInputBytesLeftInBuffer(self)<0) _CSInputBufferRaiseEOF(self);
|
|
|
|
self->bits<<=numbits;
|
|
self->numbits-=numbits;
|
|
}
|
|
|
|
static inline void CSInputSkipPeekedBitsLE(CSInputBuffer *self,int numbits)
|
|
{
|
|
int numbytes=(numbits-(self->numbits&7)+7)>>3;
|
|
CSInputSkipBytes(self,numbytes);
|
|
|
|
if(_CSInputBytesLeftInBuffer(self)<0) _CSInputBufferRaiseEOF(self);
|
|
|
|
self->bits>>=numbits;
|
|
self->numbits-=numbits;
|
|
}
|
|
|
|
|
|
|
|
|
|
// Multibyte reading
|
|
|
|
#define CSInputNextValueImpl(type,name,conv) \
|
|
static inline type name(CSInputBuffer *self) \
|
|
{ \
|
|
_CSInputCheckAndFillBuffer(self); \
|
|
type val=conv(self->buffer+self->currbyte); \
|
|
CSInputSkipBytes(self,sizeof(type)); \
|
|
return val; \
|
|
}
|
|
|
|
CSInputNextValueImpl(int16_t,CSInputNextInt16LE,CSInt16LE)
|
|
CSInputNextValueImpl(int32_t,CSInputNextInt32LE,CSInt32LE)
|
|
CSInputNextValueImpl(uint16_t,CSInputNextUInt16LE,CSUInt16LE)
|
|
CSInputNextValueImpl(uint32_t,CSInputNextUInt32LE,CSUInt32LE)
|
|
CSInputNextValueImpl(int16_t,CSInputNextInt16BE,CSInt16BE)
|
|
CSInputNextValueImpl(int32_t,CSInputNextInt32BE,CSInt32BE)
|
|
CSInputNextValueImpl(uint16_t,CSInputNextUInt16BE,CSUInt16BE)
|
|
CSInputNextValueImpl(uint32_t,CSInputNextUInt32BE,CSUInt32BE)
|
|
|
|
|
|
|
|
|