Files
libsst/Include/ZUtil/ZBinaryReader.hpp
2026-04-03 00:22:39 -05:00

750 lines
22 KiB
C++

/*
ZBinaryReader.hpp
Author: Patrick Baggett <ptbaggett@762studios.com
Created: 3/6/2013
Purpose:
Binary stream reader interface
License:
TODO
*/
#pragma once
#ifndef _ZBINARYREADER_HPP
#define _ZBINARYREADER_HPP
#include <pstdint.h>
#include <SST/SST_Endian.h>
class ZBinaryReader
{
public:
ZBinaryReader(SST_ByteOrder streamOrder) :
streamByteOrder(streamOrder)
{
}
//SINGLE ELEMENT READ
/*
virtual public ZBinaryReader::ReadU8
Reads a single unsigned 8-bit value from the stream.
No validation is performed.
@return (uint8_t) - value read from the stream
*/
virtual uint8_t ReadU8() = 0;
/*
virtual public ZBinaryReader::ReadU16
Reads a single unsigned 16-bit value from the stream.
No validation is performed.
@return (uint16_t) - value read from the stream
*/
virtual uint16_t ReadU16() = 0;
/*
virtual public ZBinaryReader::ReadU32
Reads a single unsigned 32-bit value from the stream.
No validation is performed.
@return (uint32_t) - value read from the stream
*/
virtual uint32_t ReadU32() = 0;
/*
virtual public ZBinaryReader::ReadU64
Reads a single unsigned 64-bit value from the stream.
No validation is performed.
@return (uint64_t) - value read from the stream
*/
virtual uint64_t ReadU64() = 0;
/*
public ZBinaryReader::ReadF32
Reads a single 32-bit floating point value from the stream.
No validation is performed.
@return (float) - value read from the stream
*/
float ReadF32() { return cast_i2f(ReadU32()); }
/*
public ZBinaryReader::ReadF64
Reads a single 64-bit floating point value from the stream.
No validation is performed.
@return (double) - value read from the stream
*/
double ReadF64() { return cast_i2d(ReadU64()); }
//=====================================================================
//ARRAY READ
//=====================================================================
/*
virtual public ZBinaryReader::ReadU8Array
Reads an array of 8-bit unsigned values from the stream.
No validation is performed.
@param ptr - The base of the array
@param count - Number of elements to read
@return (void)
*/
virtual void ReadU8Array(uint8_t* ptr, size_t count) = 0;
/*
virtual public ZBinaryReader::ReadU16Array
Reads an array of 16-bit unsigned values from the stream.
No validation is performed.
@param ptr - The base of the array
@param count - Number of elements to read
@return (void)
*/
virtual void ReadU16Array(uint16_t* ptr, size_t count) = 0;
/*
virtual public ZBinaryReader::ReadU32Array
Reads an array of 32-bit unsigned values from the stream.
No validation is performed.
@param ptr - The base of the array
@param count - Number of elements to read
@return (void)
*/
virtual void ReadU32Array(uint32_t* ptr, size_t count) = 0;
/*
virtual public ZBinaryReader::ReadU64Array
Reads an array of 64-bit unsigned values from the stream.
No validation is performed.
@param ptr - The base of the array
@param count - Number of elements to read
@return (void)
*/
virtual void ReadU64Array(uint64_t* ptr, size_t count) = 0;
/*
public ZBinaryReader::ReadF32Array
Reads an array of 32-bit floating point values from the stream.
No validation is performed.
@param ptr - The base of the array
@param count - Number of elements to read
@return (void)
*/
void ReadF32Array(float* ptr, size_t count) { ReadU32Array((uint32_t*)ptr, count); }
/*
public ZBinaryReader::ReadF64Array
Reads an array of 64-bit floating point values from the stream.
No validation is performed.
@param ptr - The base of the array
@param count - Number of elements to read
@return (void)
*/
void ReadF64Array(double* ptr, size_t count) { ReadU64Array((uint64_t*)ptr, count); }
//=====================================================================
//STREAM SEEKING / POSITIONING
//=====================================================================
/*
virtual public ZBinaryReader::GetLength
Gets the total length of the stream in bytes.
@return (size_t) - The total length of the stream
*/
virtual size_t GetLength() const = 0;
/*
virtual public ZBinaryReader::GetOffset
Gets the current (zero-based) offset into the stream from which the next read will
be performed.
@return (size_t) - The offset.
*/
virtual size_t GetOffset() const = 0;
/*
public ZBinaryReader::SeekForward
Advances the offset into the stream by the given number of bytes.
No validation is performed.
@param amount - The amount of seek forward by.
@return (void)
*/
void SeekForward(size_t amount) { SeekTo(GetOffset() + amount); }
/*
public ZBinaryReader::SeekBackward
Rewinds the offset into the stream by the given number of bytes.
No validation is performed.
@param amount - The amount of seek backward by.
@return (void)
*/
void SeekBackward(size_t amount) { SeekTo(GetOffset() - amount); }
/*
virtual public ZBinaryReader::SeekTo
Directly sets the offset into the stream from which reads will occur.
No validation is performed.
@param offset - The new offset
@return (void)
*/
virtual void SeekTo(size_t offset) = 0;
/*
public ZBinaryReader::Rewind
Sets the offset to the start of the stream
@param offset - The new offset
@return (void)
*/
void Rewind() { SeekTo(0); }
/*
public ZBinaryReader::CanRead
Checks if the given number of bytes can be read
@param bytes - The number of bytes that wish to be read
@return (void)
*/
bool CanRead(size_t bytes) const { return (GetLength() - GetOffset() >= bytes); }
//=====================================================================
//SAFE SEEK FUNCTIONS
//=====================================================================
/*
public ZBinaryReader::SafeSeekForward
Attempts to advance the offset into the stream by the given number of bytes. If
this would produce an out-of-bounds result, then false is returned and the offset
is not adjusted, otherwise, the offset is adjusted and true is returned.
@param amount - The amount to seek forward by
@return (bool) - True if the seek operation succeeded, false if the value was invalid
*/
bool SafeSeekForward(size_t amount)
{
bool ok = (GetLength() - GetOffset() > amount); //i.e. length > offset + amount
if(ok)
SeekTo(GetOffset() + amount);
return ok;
}
/*
public ZBinaryReader::SafeSeekBackward
Attempts to rewind the offset into the stream by the given number of bytes. If
this would produce an out-of-bounds result, then false is returned and the offset
is not adjusted, otherwise, the offset is adjusted and true is returned.
@param amount - The amount to seek backward by
@return (bool) - True if the seek operation succeeded, false if the value was invalid
*/
bool SafeSeekBackward(size_t amount)
{
bool ok = (GetOffset() >= amount); //i.e. offset - amount >= 0
if(ok)
SeekTo(GetOffset() - amount);
return ok;
}
/*
public ZBinaryReader::SafeSeekTo
Attempts to set the offset into the stream directly. If the new offset is
out-of-bounds, then false is returned and the offset is not adjusted,
otherwise, the offset is adjusted and true is returned.
@return (bool) - True if the seek operation succeeded, false if the value was invalid
*/
bool SafeSeekTo(size_t offset)
{
bool ok = (offset < GetLength());
if(ok) SeekTo(offset);
return ok;
}
//=====================================================================
//SAFE READ FUNCTIONS
//=====================================================================
/*
public ZBinaryReader::SafeReadU8
Attempt to reads a single unsigned 8-bit value from the stream. If this would
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
the value is read and stored at *ptr and true is returned.
No validation is performed.
@param ptr - The address to store the read value at
@return (bool) - If the value was successfully read
*/
bool SafeReadU8(uint8_t* ptr)
{
bool ok = CanRead(sizeof(uint8_t));
if(ok) *ptr = ReadU8();
return ok;
}
/*
public ZBinaryReader::SafeReadU16
Attempt to reads a single unsigned 16-bit value from the stream. If this would
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
the value is read and stored at *ptr and true is returned.
No validation is performed.
@param ptr - The address to store the read value at
@return (bool) - If the value was successfully read
*/
bool SafeReadU16(uint16_t* ptr)
{
bool ok = CanRead(sizeof(uint16_t));
if(ok) *ptr = ReadU16();
return ok;
}
/*
public ZBinaryReader::SafeReadU32
Attempt to reads a single unsigned 32-bit value from the stream. If this would
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
the value is read and stored at *ptr and true is returned.
No validation is performed.
@param ptr - The address to store the read value at
@return (bool) - If the value was successfully read
*/
bool SafeReadU32(uint32_t* ptr)
{
bool ok = CanRead(sizeof(uint32_t));
if(ok) *ptr = ReadU32();
return ok;
}
/*
public ZBinaryReader::SafeReadU64
Attempt to reads a single unsigned 64-bit value from the stream. If this would
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
the value is read and stored at *ptr and true is returned.
No validation is performed.
@param ptr - The address to store the read value at
@return (bool) - If the value was successfully read
*/
bool SafeReadU64(uint64_t* ptr)
{
bool ok = CanRead(sizeof(uint64_t));
if(ok) *ptr = ReadU64();
return ok;
}
/*
public ZBinaryReader::SafeReadF32
Attempt to reads a single 32-bit floating point value from the stream. If this would
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
the value is read and stored at *ptr and true is returned.
No validation is performed.
@param ptr - The address to store the read value at
@return (bool) - If the value was successfully read
*/
bool SafeReadF32(float* ptr)
{
bool ok = CanRead(sizeof(float));
if(ok) *ptr = ReadF32();
return ok;
}
/*
public ZBinaryReader::SafeReadF64
Attempt to reads a single 64-bit floating point value from the stream. If this would
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
the value is read and stored at *ptr and true is returned.
No validation is performed.
@param ptr - The address to store the read value at
@return (bool) - If the value was successfully read
*/
bool SafeReadF64(double* ptr)
{
bool ok = CanRead(sizeof(double));
if(ok) *ptr = ReadF64();
return ok;
}
/*
public ZBinaryReader::SafeReadU8Array
Attempt to reads an array of unsigned 8-bit values from the stream. If this would
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
the values are read and stored at *ptr and true is returned.
No validation is performed.
@param ptr - The address to store the values
@param count - The number of values to read
@return (bool) - If the array was successfully read
*/
bool SafeReadU8Array(uint8_t* ptr, size_t count)
{
bool ok = CanRead(count);
if(ok) ReadU8Array(ptr, count);
return ok;
}
/*
public ZBinaryReader::SafeReadU16Array
Attempt to reads an array of unsigned 16-bit values from the stream. If this would
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
the values are read and stored at *ptr and true is returned.
No validation is performed.
@param ptr - The address to store the values
@param count - The number of values to read
@return (bool) - If the array was successfully read
*/
bool SafeReadU16Array(uint16_t* ptr, size_t count)
{
bool ok = (SIZE_MAX / count > sizeof(uint16_t)); //i.e. SIZE_MAX > count * size
ok = ok && CanRead(count * sizeof(uint16_t));
if(ok) ReadU16Array(ptr, count);
return ok;
}
/*
public ZBinaryReader::SafeReadU32Array
Attempt to reads an array of unsigned 32-bit values from the stream. If this would
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
the values are read and stored at *ptr and true is returned.
No validation is performed.
@param ptr - The address to store the values
@param count - The number of values to read
@return (bool) - If the array was successfully read
*/
bool SafeReadU32Array(uint32_t* ptr, size_t count)
{
bool ok = (SIZE_MAX / count > sizeof(uint32_t)); //i.e. SIZE_MAX > count * size
ok = ok && CanRead(count * sizeof(uint32_t));
if(ok) ReadU32Array(ptr, count);
return ok;
}
/*
public ZBinaryReader::SafeReadU64Array
Attempt to reads an array of unsigned 64-bit values from the stream. If this would
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
the values are read and stored at *ptr and true is returned.
No validation is performed.
@param ptr - The address to store the values
@param count - The number of values to read
@return (bool) - If the array was successfully read
*/
bool SafeReadU64Array(uint64_t* ptr, size_t count)
{
bool ok = (SIZE_MAX / count > sizeof(uint64_t)); //i.e. SIZE_MAX > count * size
ok = ok && CanRead(count * sizeof(uint64_t));
if(ok) ReadU64Array(ptr, count);
return ok;
}
/*
public ZBinaryReader::SafeReadF32Array
Attempt to reads an array of 32-bit floating point values from the stream. If this would
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
the values are read and stored at *ptr and true is returned.
No validation is performed.
@param ptr - The address to store the values
@param count - The number of values to read
@return (bool) - If the array was successfully read
*/
bool SafeReadF32Array(float* ptr, size_t count) { return SafeReadU32Array((uint32_t*)ptr, count); }
/*
public ZBinaryReader::SafeReadF64Array
Attempt to reads an array of 64-bit floating point values from the stream. If this would
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
the values are read and stored at *ptr and true is returned.
No validation is performed.
@param ptr - The address to store the values
@param count - The number of values to read
@return (bool) - If the array was successfully read
*/
bool SafeReadF64Array(double* ptr, size_t count) { return SafeReadU64Array((uint64_t*)ptr, count); }
//=====================================================================
//TYPED ALIASES
//=====================================================================
/*
public ZBinaryReader::ReadI8
Reads a single signed 8-bit value from the stream.
No validation is performed.
@return (int8_t) - value read from the stream
*/
int8_t ReadI8() { return (int8_t)ReadU8(); }
/*
public ZBinaryReader::ReadI16
Reads a single signed 16-bit value from the stream.
No validation is performed.
@return (int16_t) - value read from the stream
*/
int16_t ReadI16() { return (int16_t)ReadU16(); }
/*
public ZBinaryReader::ReadI32
Reads a single signed 32-bit value from the stream.
No validation is performed.
@return (int32_t) - value read from the stream
*/
int32_t ReadI32() { return (int32_t)ReadU32(); }
/*
public ZBinaryReader::ReadI64
Reads a single signed 64-bit value from the stream.
No validation is performed.
@return (int64_t) - value read from the stream
*/
int64_t ReadI64() { return (int64_t)ReadU64(); }
/*
public ZBinaryReader::ReadI8Array
Reads an array of 8-bit signed values from the stream.
No validation is performed.
@param ptr - The base of the array
@param count - Number of elements to read
@return (void)
*/
void ReadI8Array(int8_t* ptr, size_t count) { return ReadU8Array((uint8_t*)ptr, count); }
/*
public ZBinaryReader::ReadI16Array
Reads an array of 16-bit signed values from the stream.
No validation is performed.
@param ptr - The base of the array
@param count - Number of elements to read
@return (void)
*/
void ReadI16Array(int16_t* ptr, size_t count) { return ReadU16Array((uint16_t*)ptr, count); }
/*
public ZBinaryReader::ReadI32Array
Reads an array of 32-bit signed values from the stream.
No validation is performed.
@param ptr - The base of the array
@param count - Number of elements to read
@return (void)
*/
void ReadI32Array(int32_t* ptr, size_t count) { return ReadU32Array((uint32_t*)ptr, count); }
/*
public ZBinaryReader::ReadI64Array
Reads an array of 64-bit signed values from the stream.
No validation is performed.
@param ptr - The base of the array
@param count - Number of elements to read
@return (void)
*/
void ReadI64Array(int64_t* ptr, size_t count) { return ReadU64Array((uint64_t*)ptr, count); }
/*
public ZBinaryReader::SafeReadI8
Attempt to reads a single signed 8-bit value from the stream. If this would
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
the value is read and stored at *ptr and true is returned.
No validation is performed.
@param ptr - The address to store the read value at
@return (bool) - If the value was successfully read
*/
bool SafeReadI8(int8_t* ptr) { return SafeReadU8((uint8_t*)ptr); }
/*
public ZBinaryReader::SafeReadI16
Attempt to reads a single signed 16-bit value from the stream. If this would
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
the value is read and stored at *ptr and true is returned.
No validation is performed.
@param ptr - The address to store the read value at
@return (bool) - If the value was successfully read
*/
bool SafeReadI16(int16_t* ptr) { return SafeReadU16((uint16_t*)ptr); }
/*
public ZBinaryReader::SafeReadI32
Attempt to reads a single signed 32-bit value from the stream. If this would
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
the value is read and stored at *ptr and true is returned.
No validation is performed.
@param ptr - The address to store the read value at
@return (bool) - If the value was successfully read
*/
bool SafeReadI32(int32_t* ptr) { return SafeReadU32((uint32_t*)ptr); }
/*
public ZBinaryReader::SafeReadI64
Attempt to reads a single signed 64-bit value from the stream. If this would
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
the value is read and stored at *ptr and true is returned.
No validation is performed.
@param ptr - The address to store the read value at
@return (bool) - If the value was successfully read
*/
bool SafeReadI64(int64_t* ptr) { return SafeReadU64((uint64_t*)ptr); }
/*
public ZBinaryReader::SafeReadI8Array
Attempt to reads an array of signed 8-bit values from the stream. If this would
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
the values are read and stored at *ptr and true is returned.
No validation is performed.
@param ptr - The address to store the values
@param count - The number of values to read
@return (bool) - If the array was successfully read
*/
bool SafeReadI8Array(int8_t* ptr, size_t count) { return SafeReadU8Array((uint8_t*)ptr, count); }
/*
public ZBinaryReader::SafeReadI16Array
Attempt to reads an array of signed 16-bit values from the stream. If this would
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
the values are read and stored at *ptr and true is returned.
No validation is performed.
@param ptr - The address to store the values
@param count - The number of values to read
@return (bool) - If the array was successfully read
*/
bool SafeReadI16Array(int16_t* ptr, size_t count) { return SafeReadU16Array((uint16_t*)ptr, count); }
/*
public ZBinaryReader::SafeReadI32Array
Attempt to reads an array of signed 32-bit values from the stream. If this would
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
the values are read and stored at *ptr and true is returned.
No validation is performed.
@param ptr - The address to store the values
@param count - The number of values to read
@return (bool) - If the array was successfully read
*/
bool SafeReadI32Array(int32_t* ptr, size_t count) { return SafeReadU32Array((uint32_t*)ptr, count); }
/*
public ZBinaryReader::SafeReadI64Array
Attempt to reads an array of signed 64-bit values from the stream. If this would
result in reading out of bounds, false is returned and *ptr is unmodified, otherwise
the values are read and stored at *ptr and true is returned.
No validation is performed.
@param ptr - The address to store the values
@param count - The number of values to read
@return (bool) - If the array was successfully read
*/
bool SafeReadI64Array(int64_t* ptr, size_t count) { return SafeReadU64Array((uint64_t*)ptr, count); }
//=====================================================================
//GETTERS / SETTERS
//=====================================================================
/*
public ZBinaryReader::GetStreamByteOrder
Gets the byte order in which the stream (source data) is read as.
@return (SST_ByteOrder) - The byte order
*/
SST_ByteOrder GetStreamByteOrder() const { return streamByteOrder; }
/*
public ZBinaryReader::SetStreamByteOrder
Sets the byte order in which the stream (source data) is read as.
@param newOrder - The new byte order
@return (void)
*/
void SetStreamByteOrder(SST_ByteOrder newOrder) { streamByteOrder = newOrder; }
private:
SST_ByteOrder streamByteOrder; //The current byte order the stream is being read in.
};
#endif