Skip to content

Commit

Permalink
split BinaryReader
Browse files Browse the repository at this point in the history
  • Loading branch information
qnnnnez committed Jan 11, 2017
1 parent ef3bbc0 commit 0a7b9db
Show file tree
Hide file tree
Showing 6 changed files with 354 additions and 324 deletions.
263 changes: 263 additions & 0 deletions binaryio.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,263 @@
#include "binaryio.h"

namespace scpak
{
void BinaryReader::readBytes(int size, byte buf[])
{
for (int i = 0; i<size; ++i)
buf[i] = readByte();
}

int BinaryReader::readInt()
{
int value;
readBytes(4, reinterpret_cast<byte*>(&value));
return value;
}

float BinaryReader::readFloat()
{
float value;
readBytes(4, reinterpret_cast<byte*>(&value));
return value;
}

int BinaryReader::read7BitEncodedInt()
{
int value = 0;
int offset = 0;
while (offset != 35)
{
byte b = readByte();
value |= static_cast<int>(b & 127) << offset;
offset += 7;
if ((b & 128) == 0)
return value;
}
throw std::runtime_error("bad 7 bit encoded int32");
}

int BinaryReader::readUtf8Char()
{
byte first = readByte();
if ((first & 0b10000000) == 0)
// only one byte long, 0b0???????
return static_cast<int>(first);
if ((first & 0b11000000) == 0b11000000 && (first & 0b00100000) == 0)
{
// two bytes long, 0b110????? 0b10??????
int second = readByte();
int value = (first & 0b00011111) << 6;
value |= second & 0b00111111;
return value;
}
if ((first & 0b11100000) == 0b11100000 && (first & 0b00010000) == 0)
{
// three bytes long, 0b1110???? 0b10?????? 0b10??????
int second = readByte();
int third = readByte();
int value = (first & 0b00001111) << 12;
value |= (second & 0b00111111) << 6;
value |= third & 0b00111111;
return value;
}
if ((first & 0b11110000) == 0b11110000 && (first & 0b00001000) == 0)
{
// four bytes long, 0b11110??? 0b10?????? 0b10?????? 0b10??????
int second = readByte();
int third = readByte();
int fourth = readByte();
int value = (first & 0b00000111) << 18;
value |= (second & 0b00111111) << 12;
value |= (third & 0b00111111) << 6;
value |= fourth & 0b00111111;
return value;
}
throw std::runtime_error("utf-8 encoded unicode is too large");
}

bool BinaryReader::readBoolean()
{
return bool(readByte());
}

std::string BinaryReader::readString()
{
int length = read7BitEncodedInt();
std::string buffer;
buffer.resize(length);
for (int i = 0; i<length; ++i)
buffer[i] = static_cast<char>(readByte());
return buffer;
}

int BinaryReader::getUtf8CharCount(const std::string &value)
{
MemoryBinaryReader reader(reinterpret_cast<const byte*>(value.data()));
int count = 0;
while (reader.position < value.length())
{
int unicode = reader.readUtf8Char();
++count;
}
return count;
}


StreamBinaryReader::StreamBinaryReader(std::istream *stream)
{
m_stream = stream;
}

byte StreamBinaryReader::readByte()
{
if (!*m_stream)
throw std::runtime_error("bad stream");
char ch;
m_stream->get(ch);
return static_cast<byte>(ch);
}

MemoryBinaryReader::MemoryBinaryReader(const byte *buffer)
{
position = 0;
m_buffer = buffer;
}

byte MemoryBinaryReader::readByte()
{
return m_buffer[position++];
}

StreamBinaryWriter::StreamBinaryWriter(std::ostream *stream)
{
m_stream = stream;
}

void StreamBinaryWriter::writeByte(byte value)
{
if (!m_stream)
throw std::runtime_error("bad stream");
char ch = static_cast<char>(value);
m_stream->put(ch);
}

MemoryBinaryWriter::MemoryBinaryWriter(byte *buffer)
{
position = 0;
m_buffer = buffer;
}

void MemoryBinaryWriter::writeByte(byte value)
{
m_buffer[position++] = value;
}


void BinaryWriter::writeBytes(int size, const byte value[])
{
for (int i = 0; i<size; ++i)
writeByte(value[i]);
}

void BinaryWriter::writeInt(int value)
{
writeBytes(4, reinterpret_cast<byte*>(&value));
}

void BinaryWriter::writeFloat(float value)
{
writeBytes(4, reinterpret_cast<byte*>(&value));
}

int BinaryWriter::write7BitEncodedInt(int value)
{
int count = 0;
while (value > 127)
{
byte n = static_cast<byte>(value & 127);
n |= 128;
writeByte(n); ++count;
value >>= 7;
}
byte n = static_cast<byte>(value);
writeByte(n); ++count;
return count;
}

int BinaryWriter::writeUtf8Char(int value)
{
if (value <= 0x7f)
{
writeByte(static_cast<byte>(value));
return 1;
}
if (value <= 0x7ff)
{
byte first = value >> 6;
first &= 0b11011111;
first |= 0b11000000;
byte second = value & 0b00111111;
second &= 0b10111111;
second |= 0b10000000;
writeByte(first);
writeByte(second);
return 2;
}
if (value <= 0xffff)
{
byte first = value >> 12;
first &= 0b11101111;
first |= 0b11100000;

byte second = (value >> 6) & 0b00111111;
second &= 0b10111111;
second |= 0b10000000;

byte third = value & 0b00111111;
third &= 0b10111111;
third |= 0b10000000;

writeByte(first);
writeByte(second);
writeByte(third);
return 3;
}
if (value <= 0x10ffff)
{
byte first = value >> 18;
first &= 0b11110111;
first |= 0b11110000;

byte second = (value >> 12) & 0b00111111;
second &= 0b10111111;
second |= 0b10000000;

byte third = (value >> 6) & 0b00111111;
third &= 0b10111111;
third |= 0b10000000;

byte fourth = value & 0b00111111;
fourth &= 0b10111111;
fourth |= 0b10000000;

writeByte(first);
writeByte(second);
writeByte(third);
writeByte(fourth);
return 4;
}
throw std::runtime_error("unicode is too large");
}

void BinaryWriter::writeBoolean(bool value)
{
writeByte(byte(value));
}

void BinaryWriter::writeString(const std::string &value)
{
write7BitEncodedInt(value.length());
writeBytes(value.length(), reinterpret_cast<const byte*>(value.data()));
}
}
84 changes: 84 additions & 0 deletions binaryio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#pragma once
#include <string>
#include <istream>
#include <ostream>

#include "scpak.h"


namespace scpak
{
class BinaryReader
{
public:
virtual byte readByte() = 0;
void readBytes(int size, byte buf[]);
int readInt();
float readFloat();
int read7BitEncodedInt();
int readUtf8Char();
bool readBoolean();
std::string readString();

static int getUtf8CharCount(const std::string &value);
private:
std::istream *m_stream;
};

class StreamBinaryReader : public BinaryReader
{
public:
StreamBinaryReader(std::istream *stream);

byte readByte();
private:
std::istream *m_stream;
};

class MemoryBinaryReader : public BinaryReader
{
public:
MemoryBinaryReader(const byte *buffer);
unsigned position;

byte readByte();
private:
const byte *m_buffer;
};

class BinaryWriter
{
public:
virtual void writeByte(byte value) = 0;
void writeBytes(int size, const byte value[]);
void writeInt(int value);
void writeFloat(float value);
int write7BitEncodedInt(int value);
int writeUtf8Char(int value);
void writeBoolean(bool value);
void writeString(const std::string &value);
private:
std::ostream *m_stream;
};

class StreamBinaryWriter : public BinaryWriter
{
public:
StreamBinaryWriter(std::ostream *stream);

void writeByte(byte value);
private:
std::ostream *m_stream;
};

class MemoryBinaryWriter : public BinaryWriter
{
public:
MemoryBinaryWriter(byte *buffer);
unsigned position;

void writeByte(byte value);
private:
byte *m_buffer;
};
}
1 change: 1 addition & 0 deletions main.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "pakfile.h"
#include "process.h"
#include "native.h"
#include <iostream>
#include <sstream>
#include <fstream>

Expand Down
Loading

0 comments on commit 0a7b9db

Please sign in to comment.