Skip to content

Instantly share code, notes, and snippets.

@dtalley
Created March 29, 2012 08:01
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save dtalley/2234745 to your computer and use it in GitHub Desktop.
Save dtalley/2234745 to your computer and use it in GitHub Desktop.
Small C++ utility for reading binary data from a byte array
#include "ByteReader.h"
using namespace Orionark::Utility;
ByteReader::ByteReader(char *data)
: data(data),
pointer(0)
{
if( O32_HOST_ORDER == O32_LITTLE_ENDIAN )
{
endian = LITTLE_ENDIAN;
}
else if( O32_HOST_ORDER == O32_BIG_ENDIAN )
{
endian = BIG_ENDIAN;
}
else
{
endian = POP_ENDIAN;
}
}
ByteReader::~ByteReader()
{
}
void ByteReader::SetEndian(ByteEndianness end)
{
endian = end;
}
long unsigned int ByteReader::Tell()
{
return pointer;
}
void ByteReader::Seek(long unsigned int target)
{
pointer = target;
}
char ByteReader::ReadByte()
{
return ReadAny<char>();
}
float ByteReader::ReadSingle()
{
return ReadAny<float>();
}
double ByteReader::ReadDouble()
{
return ReadAny<double>();
}
short ByteReader::ReadInt16()
{
return ReadAny<short>();
}
unsigned short ByteReader::ReadUInt16()
{
return ReadAny<unsigned short>();
}
int ByteReader::ReadInt32()
{
return ReadAny<int>();
}
unsigned int ByteReader::ReadUInt32()
{
return ReadAny<unsigned int>();
}
long long int ByteReader::ReadInt64()
{
return ReadAny<long int>();
}
long long unsigned int ByteReader::ReadUInt64()
{
return ReadAny<long long unsigned int>();
}
std::string ByteReader::ReadString(unsigned int length)
{
std::string ret((char*)(data+pointer), length);
pointer += length;
return ret;
}
template<class T> T ByteReader::ReadAny()
{
T ret;
char *dst = (char *)&ret;
char *src = (char *)&(data[pointer]);
StoreBytes(src,dst,sizeof(T));
pointer += sizeof(T);
return ret;
}
void ByteReader::StoreBytes(
char *src,
char *dst,
size_t size
)
{
for( size_t i = 0; i < size; i++ )
{
if( O32_HOST_ORDER == O32_LITTLE_ENDIAN )
{
if( endian == LITTLE_ENDIAN )
dst[i] = src[i];
else if( endian == BIG_ENDIAN )
dst[i] = src[(size-i-1)];
else if( endian == POP_ENDIAN )
dst[i] = src[(i%2==0?(size-i-2):(size-i))];
}
else if( O32_HOST_ORDER == O32_BIG_ENDIAN )
{
if( endian == BIG_ENDIAN )
dst[i] = src[i];
else if( endian == LITTLE_ENDIAN )
dst[i] = src[(size-i-1)];
else if( endian == POP_ENDIAN )
dst[i] = src[(i%2==0?(i+1):(i-1))];
}
else
{
if( endian == POP_ENDIAN )
dst[i] = src[i];
else if( endian == LITTLE_ENDIAN )
dst[i] = src[(i%2==0?(size-i-2):(size-i))];
else if( endian == BIG_ENDIAN )
dst[i] = src[(i%2==0?(i+1):(i-1))];
}
}
}
#ifndef __ORIONARK_BYTE_READER__
#define __ORIONARK_BYTE_READER__
#include <limits.h>
#include <stdint.h>
#include <string>
#if CHAR_BIT != 8
#error "unsupported char size"
#endif
enum
{
O32_LITTLE_ENDIAN = 0x03020100ul,
O32_BIG_ENDIAN = 0x00010203ul,
O32_POP_ENDIAN = 001000302ul
};
static const union
{
unsigned char bytes[4];
uint32_t value;
}
o32_host_order = { { 0, 1, 2, 3 } };
#define O32_HOST_ORDER (o32_host_order.value)
namespace Orionark
{
namespace Utility
{
enum ByteEndianness
{
LITTLE_ENDIAN,
BIG_ENDIAN,
POP_ENDIAN
};
class ByteReader
{
public:
ByteReader(char*);
~ByteReader();
void SetEndian(ByteEndianness);
long long unsigned int ReadUInt64();
long long int ReadInt64();
unsigned int ReadUInt32();
int ReadInt32();
unsigned short ReadUInt16();
short ReadInt16();
double ReadDouble();
float ReadSingle();
char ReadByte();
std::string ReadString(unsigned int);
void StoreBytes(char *, char *, size_t);
long unsigned int Tell();
void Seek(long unsigned int);
private:
const char *data;
ByteEndianness endian;
template<class T> T ReadAny();
long unsigned int pointer;
};
}
}
#endif //__ORIONARK_BYTE_READER__
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment