Files
panopainter/src/binary_stream.cpp

361 lines
7.5 KiB
C++

#include "pch.h"
#include "binary_stream.h"
#include "asset.h"
BinaryStreamReader::~BinaryStreamReader()
{
m_ptr = m_cur = nullptr;
m_size = 0;
}
void BinaryStreamReader::init(uint8_t* data_ptr, size_t size, ByteOrder byte_order /*= ByteOrder::Host*/)
{
m_ptr = m_cur = data_ptr;
m_size = size;
m_byte_order = byte_order;
m_swap = byte_order == ByteOrder::Host ? false : byte_order != sys_order();
}
bool BinaryStreamReader::load(const std::string& path, ByteOrder byte_order /*= ByteOrder::Host*/)
{
if (m_asset.open(path.c_str()))
{
m_asset.read_all();
init(m_asset.m_data, m_asset.m_len, byte_order);
return true;
}
return false;
}
size_t BinaryStreamReader::pos()
{
return std::distance(m_ptr, m_cur);
}
void BinaryStreamReader::skip(size_t bytes)
{
m_cur += bytes;
}
void BinaryStreamReader::snap()
{
if ((size_t)m_cur % 4 != 0) m_cur += 4 - (size_t)m_cur % 4;
}
bool BinaryStreamReader::eof()
{
return std::distance(m_ptr, m_cur) >= m_size;
}
bool BinaryStreamReader::has_data(size_t sz)
{
return std::distance(m_ptr, m_cur + sz) <= m_size;
}
uint8_t BinaryStreamReader::ru8()
{
return read<uint8_t>();
}
uint16_t BinaryStreamReader::ru16()
{
return m_swap ? swap(read<uint16_t>()) : read<uint16_t>();
}
uint32_t BinaryStreamReader::ru32()
{
return m_swap ? swap(read<uint32_t>()) : read<uint32_t>();
}
uint64_t BinaryStreamReader::ru64()
{
return m_swap ? swap(read<uint64_t>()) : read<uint64_t>();
}
int8_t BinaryStreamReader::ri8()
{
return read<int8_t>();
}
int16_t BinaryStreamReader::ri16()
{
return m_swap ? swap(read<int16_t>()) : read<int16_t>();
}
int32_t BinaryStreamReader::ri32()
{
return m_swap ? swap(read<int32_t>()) : read<int32_t>();
}
int64_t BinaryStreamReader::ri64()
{
return m_swap ? swap(read<int64_t>()) : read<int64_t>();
}
float BinaryStreamReader::rflt()
{
return m_swap ? swap(read<float>()) : read<float>();
}
double BinaryStreamReader::rdbl()
{
return m_swap ? swap(read<double>()) : read<double>();
}
std::string BinaryStreamReader::pick(size_t chars)
{
return { (char*)m_cur, chars };
}
std::string BinaryStreamReader::rstring(size_t len)
{
return { advance<char>(len), len };
}
std::string BinaryStreamReader::rstring()
{
auto len = ru32();
return { advance<char>(len), len };
}
std::wstring BinaryStreamReader::rwstring(size_t len)
{
auto ptr = advance<char>(len * 2);
//for (int i = 0; i < len; i++)
// std::swap(ptr[i * 2], ptr[i * 2 + 1]);
// right trim trailing zeroes
if (len > 0)
{
auto wptr = (uint16_t*)ptr;
for (int i = (int)len - 1; i >= 0; i--)
if (wptr[i] == 0) len--;
}
// wide to UTF-16le
std::wstring_convert<std::codecvt_utf16<wchar_t, 0x10ffff>> converter;
return converter.from_bytes(ptr, ptr + len * 2);
}
std::wstring BinaryStreamReader::rwstring()
{
auto len = ru32();
return rwstring(len);
}
std::string BinaryStreamReader::rpascal()
{
auto len = ru8();
return rstring(len);
}
std::vector<glm::uint8_t> BinaryStreamReader::rraw(size_t bytes)
{
std::vector<uint8_t> ret(bytes);
std::copy_n(m_cur, bytes, ret.data());
skip(bytes);
return ret;
}
std::vector<glm::uint8_t> BinaryStreamReader::rraw()
{
auto size = ru32();
return rraw(size);
}
std::vector<glm::uint8_t> BinaryStreamReader::rrle(size_t encoded_bytes)
{
std::vector<uint8_t> data;
int32_t n;
for (int j = 0; j < encoded_bytes;)
{
n = ri8();
j++;
// copy the following char -n + 1 times
if (n < 0)
{
// NOP
if (n == -128)
continue;
n = -n + 1;
j++;
auto ch = ru8();
for (int c = 0; c < n; c++)
data.push_back(ch);
}
else
{
// read the following n + 1 chars (no compr)
for (int c = 0; c < n + 1; c++, j++)
data.push_back(ru8());
}
}
return data;
}
std::string BinaryStreamReader::rkey_or_string()
{
auto len = ru32();
if (len == 0)
len = 4;
return rstring(len);
}
void BinaryStreamWriter::init(ByteOrder byte_order /*= ByteOrder::Host*/)
{
m_byte_order = byte_order;
m_swap = byte_order == ByteOrder::Host ? false : byte_order != sys_order();
}
bool BinaryStreamWriter::save(const std::string& path) const
{
std::ofstream f(path, std::ios::binary);
if (f.good())
{
f.write((char*)m_data.data(), m_data.size());
return true;
}
return false;
}
void BinaryStreamWriter::skip(size_t bytes, uint8_t fill /*= 0*/)
{
m_data.resize(m_data.size() + bytes);
}
void BinaryStreamWriter::snap()
{
if ((size_t)m_data.size() % 4 != 0) m_data.resize(m_data.size() + 4 - (size_t)m_data.size() % 4);
}
void BinaryStreamWriter::wu8(uint8_t v)
{
return write<uint8_t>(v);
}
void BinaryStreamWriter::wu16(uint16_t v)
{
return m_swap ? write(swap(v)) : write(v);
}
void BinaryStreamWriter::wu32(uint32_t v)
{
return m_swap ? write(swap(v)) : write(v);
}
void BinaryStreamWriter::wu64(uint64_t v)
{
return m_swap ? write(swap(v)) : write(v);
}
void BinaryStreamWriter::wi8(int8_t v)
{
return write<int8_t>(v);
}
void BinaryStreamWriter::wi16(int16_t v)
{
return m_swap ? write(swap(v)) : write(v);
}
void BinaryStreamWriter::wi32(int32_t v)
{
return m_swap ? write(swap(v)) : write(v);
}
void BinaryStreamWriter::wi64(int64_t v)
{
return m_swap ? write(swap(v)) : write(v);
}
void BinaryStreamWriter::wflt(float v)
{
return m_swap ? write(swap(v)) : write(v);
}
void BinaryStreamWriter::wdbl(double v)
{
return m_swap ? write(swap(v)) : write(v);
}
void BinaryStreamWriter::wstring(std::string s)
{
wu32((uint32_t)s.size());
write(s.data(), s.size());
}
void BinaryStreamWriter::wstring_raw(std::string s)
{
write(s.data(), s.size());
}
void BinaryStreamWriter::wwstring(std::wstring s)
{
wu32((uint32_t)s.size());
std::wstring_convert<std::codecvt_utf16<wchar_t, 0x10ffff>> converter;
wstring_raw(converter.to_bytes(s));
}
void BinaryStreamWriter::wwstring_raw(std::wstring s)
{
std::wstring_convert<std::codecvt_utf16<wchar_t, 0x10ffff>> converter;
wstring(converter.to_bytes(s));
}
void BinaryStreamWriter::wpascal(std::string s)
{
wu8((uint8_t)s.size());
write(s.data(), s.size());
}
void BinaryStreamWriter::wraw(std::vector<uint8_t> raw)
{
wu32((uint32_t)raw.size());
write(raw.data(), raw.size());
}
void BinaryStreamWriter::wrle(std::vector<uint8_t> data)
{
size_t idx = 0;
auto ptr = data.data();
// find the next sequence and return the position
auto next_seq = [&]() -> std::pair<size_t, size_t> {
size_t i = idx;
while (i < data.size() - 1)
{
size_t count = 0;
for (size_t j = i + 1; j < data.size() && data[i] == data[j]; j++)
count++;
if (count > 0)
return { i, count + 1 };
i++;
}
return { i + 1, 0 };
};
while (idx < data.size())
{
auto seq = next_seq();
// non sequence chars
if (seq.first - idx > 0)
{
wi8(seq.first - idx - 1);
write(ptr + idx, seq.first - idx);
}
if (seq.second > 0)
{
wi8(-(int8_t)(seq.second - 1));
write(ptr[seq.first]);
}
idx = seq.first + seq.second;
}
}
void BinaryStreamWriter::wkey_or_string(std::string s)
{
assert(s.size() > 0);
wstring(s);
}