Files
korenkonder_ReDIVA/src/KKdLib/f2/pof.cpp
T

207 lines
4.9 KiB
C++

/*
by korenkonder
GitHub/GitLab: korenkonder
*/
#include "pof.hpp"
enum pof_value_type {
POF_VALUE_INVALID = 0x0,
POF_VALUE_INT8 = 0x1,
POF_VALUE_INT16 = 0x2,
POF_VALUE_INT32 = 0x3,
};
inline static bool pof_length_get_size(uint32_t* length, size_t val);
static size_t pof_read_offsets_count(stream& s);
inline static bool pof_write_packed_value(stream& s, size_t val);
pof::pof() {
}
pof::~pof() {
}
void pof::add(stream& s, int64_t offset) {
vec.push_back(s.get_position() + offset);
}
void pof::read(stream& s, bool shift_x) {
vec.clear();
size_t length = pof_read_offsets_count(s);
uint8_t bit_shift = (uint8_t)(shift_x ? 3 : 2);
size_t l = s.read_uint32_t() - 4ULL;
vec.reserve(length);
size_t i = 0;
size_t j = 0;
size_t offset = 0;
while (i < l) {
size_t v = s.read_uint8_t();
pof_value_type value = (pof_value_type)((v >> 6) & 0x03);
v &= 0x3F;
if (value == POF_VALUE_INT32) {
v = (((((v << 8) | s.read_uint8_t()) << 8) | s.read_uint8_t()) << 8) | s.read_uint8_t();
i += 3;
}
else if (value == POF_VALUE_INT16) {
v = (v << 8) | s.read_uint8_t();
i++;
}
else if (value == POF_VALUE_INVALID)
break;
offset += v;
vec.push_back(offset << bit_shift);
i++;
j++;
}
}
void pof::write(stream& s, bool shift_x) {
size_t j = 0;
size_t o = 0;
uint8_t bit_shift = (uint8_t)(shift_x ? 3 : 2);
size_t v = ((size_t)1 << bit_shift) - 1;
size_t l = length(shift_x);
if (shift_x)
s.write_uint32_t((uint32_t)l);
else
s.write_uint32_t((uint32_t)align_val(l, 4));
for (int64_t& i : vec) {
o = i;
if (o & v) {
pof_write_packed_value(s, 0x7FFFFFFF);
break;
}
size_t k = o - j;
if (&i != vec.data() && !k)
continue;
j = o;
o = k;
pof_write_packed_value(s, o >> bit_shift);
}
size_t pos = s.get_position();
for (size_t c = align_val(pos, 0x10) - pos; c > 0; c--)
s.write_uint8_t(0);
}
uint32_t pof::length(bool shift_x) {
uint32_t l = 4;
size_t j = 0;
uint8_t bit_shift = (uint8_t)(shift_x ? 3 : 2);
size_t v = ((size_t)1 << bit_shift) - 1;
for (int64_t& i : vec) {
size_t o = i;
if (o & v)
break;
else if (&i != vec.data()) {
size_t k = o - j;
if (!k)
continue;
j = o;
o = k;
}
else
j = o;
if (pof_length_get_size(&l, o >> bit_shift))
break;
}
return l;
}
inline void io_write_offset_pof_add(stream& s, int64_t val,
int32_t offset, bool is_x, pof* pof) {
if (!is_x) {
if (val)
val += offset;
pof->add(s, offset);
s.write_int32_t_reverse_endianness((int32_t)val);
}
else {
s.align_write(0x08);
pof->add(s, 0);
s.write_int64_t_reverse_endianness(val);
}
}
inline void io_write_offset_f2_pof_add(stream& s, int64_t val,
int32_t offset, pof* pof) {
if (val)
val += offset;
pof->add(s, offset);
s.write_int32_t_reverse_endianness((int32_t)val);
}
inline void io_write_offset_x_pof_add(stream& s, int64_t val, pof* pof) {
s.align_write(0x08);
pof->add(s, 0);
s.write_int64_t_reverse_endianness(val);
}
inline static bool pof_length_get_size(uint32_t* length, size_t val) {
*length += val < 0x40 ? 1 : val < 0x4000 ? 2 : val < 0x40000000 ? 4 : 1;
return val >= 0x40000000;
}
static size_t pof_read_offsets_count(stream& s) {
size_t pos = s.get_position();
size_t i, j, l;
pof_value_type val;
l = s.read_uint32_t() - 4ULL;
i = 0;
j = 0;
while (i < l) {
val = (pof_value_type)((s.read_uint8_t() >> 6) & 0x03);
if (val == POF_VALUE_INT32) {
s.read_uint8_t();
s.read_uint8_t();
s.read_uint8_t();
i += 3;
}
else if (val == POF_VALUE_INT16) {
s.read_uint8_t();
i++;
}
else if (val != POF_VALUE_INT8)
break;
i++;
j++;
}
s.set_position( pos, SEEK_SET);
return j;
}
static bool pof_write_packed_value(stream& s, size_t val) {
if (val < 0x40)
s.write_uint8_t((uint8_t)((POF_VALUE_INT8 << 6) | (val & 0x3F)));
else if (val < 0x4000) {
s.write_uint8_t((uint8_t)((POF_VALUE_INT16 << 6) | ((val >> 8) & 0x3F)));
s.write_uint8_t((uint8_t)val);
}
else if (val < 0x40000000) {
s.write_uint8_t((uint8_t)((POF_VALUE_INT32 << 6) | ((val >> 24) & 0x3F)));
s.write_uint8_t((uint8_t)(val >> 16));
s.write_uint8_t((uint8_t)(val >> 8));
s.write_uint8_t((uint8_t)val);
}
else {
s.write_uint8_t(POF_VALUE_INVALID << 6);
return true;
}
return false;
}