feature(refactor): big update (#41)

This commit is contained in:
Xenxo Espasandín
2023-01-23 23:31:08 +01:00
committed by GitHub
parent 59e9ff458a
commit 775702323a
478 changed files with 82756 additions and 278117 deletions

76
src/utils/file.cpp Normal file
View File

@ -0,0 +1,76 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#include "stdinc.hpp"
#include "file.hpp"
namespace xsk::utils
{
auto file::read(std::filesystem::path const& file) -> std::vector<u8>
{
auto data = std::vector<u8>{};
auto stream = std::ifstream{ file, std::ios::binary };
if (!stream.good() && !stream.is_open())
{
throw std::runtime_error(fmt::format("couldn't open file {}", file.string()));
}
stream.seekg(0, std::ios::end);
std::streamsize size = stream.tellg();
stream.seekg(0, std::ios::beg);
if (size > -1)
{
data.resize(static_cast<uint32_t>(size));
stream.read(reinterpret_cast<char*>(data.data()), size);
}
stream.close();
return data;
}
auto file::save(std::filesystem::path const& file, std::vector<u8> const& data) -> void
{
return save(file, data.data(), data.size());
}
auto file::save(std::filesystem::path const& file, u8 const* data, usize size) -> void
{
auto path = file;
std::filesystem::create_directories(path.remove_filename());
auto stream = std::ofstream{ file, std::ios::binary | std::ofstream::out };
if (stream.is_open())
{
stream.write(reinterpret_cast<char const*>(data), size);
stream.close();
}
}
auto file::length(std::filesystem::path const& file) -> usize
{
auto stream = std::ifstream{ file, std::ios::binary };
if (stream.good())
{
stream.seekg(0, std::ios::end);
return static_cast<usize>(stream.tellg());
}
return 0;
}
auto file::exists(std::filesystem::path const& file) -> bool
{
return std::filesystem::exists(file);
}
} // namespace xsk::utils

21
src/utils/file.hpp Normal file
View File

@ -0,0 +1,21 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::utils
{
class file
{
public:
static auto read(std::filesystem::path const& file) -> std::vector<u8>;
static auto save(std::filesystem::path const& file, std::vector<u8> const& data) -> void;
static auto save(std::filesystem::path const& file, u8 const* data, usize size) -> void;
static auto length(std::filesystem::path const& file) -> usize;
static auto exists(std::filesystem::path const& file) -> bool;
};
} // namespace xsk::utils

256
src/utils/reader.cpp Normal file
View File

@ -0,0 +1,256 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#include "stdinc.hpp"
#include "reader.hpp"
namespace xsk::utils
{
reader::reader(bool swap) : data_{ nullptr }, size_ { 0 }, pos_{ 0 }, swap_{ swap }
{
}
reader::reader(std::vector<u8> const& data, bool swap) : data_{ data.data() }, size_{ static_cast<u32>(data.size()) }, pos_{ 0 }, swap_{ swap }
{
}
reader::reader(u8 const* data, u32 size, bool swap) : data_{ data }, size_{ size }, pos_{ 0 }, swap_{ swap }
{
}
template<> auto reader::read() -> i8
{
if (pos_ + 1 > size_) return i8{};
auto value = *reinterpret_cast<i8 const*>(data_ + pos_);
pos_ += 1;
return value;
}
template<> auto reader::read() -> u8
{
if (pos_ + 1 > size_) return u8{};
auto value = *reinterpret_cast<u8 const*>(data_ + pos_);
pos_ += 1;
return value;
}
template<> auto reader::read() -> i16
{
if (pos_ + 2 > size_) return i16{};
if (!swap_)
{
auto value = *reinterpret_cast<i16 const*>(data_ + pos_);
pos_ += 2;
return value;
}
auto bytes = std::array<u8, 2>{};
bytes[0] = (data_ + pos_)[1];
bytes[1] = (data_ + pos_)[0];
pos_ += 2;
return *reinterpret_cast<i16*>(bytes.data());
}
template<> auto reader::read() -> u16
{
if (pos_ + 2 > size_) return u16{};
if (!swap_)
{
auto value = *reinterpret_cast<u16 const*>(data_ + pos_);
pos_ += 2;
return value;
}
auto bytes = std::array<u8, 2>{};
bytes[0] = (data_ + pos_)[1];
bytes[1] = (data_ + pos_)[0];
pos_ += 2;
return *reinterpret_cast<u16*>(bytes.data());
}
template<> auto reader::read() -> i32
{
if (pos_ + 4 > size_) return i32{};
if (!swap_)
{
auto value = *reinterpret_cast<i32 const*>(data_ + pos_);
pos_ += 4;
return value;
}
auto bytes = std::array<u8, 4>{};
bytes[0] = (data_ + pos_)[3];
bytes[1] = (data_ + pos_)[2];
bytes[2] = (data_ + pos_)[1];
bytes[3] = (data_ + pos_)[0];
pos_ += 4;
return *reinterpret_cast<i32*>(bytes.data());
}
template<> auto reader::read() -> u32
{
if (pos_ + 4 > size_) return u32{};
if (!swap_)
{
auto value = *reinterpret_cast<u32 const*>(data_ + pos_);
pos_ += 4;
return value;
}
auto bytes = std::array<u8, 4>{};
bytes[0] = (data_ + pos_)[3];
bytes[1] = (data_ + pos_)[2];
bytes[2] = (data_ + pos_)[1];
bytes[3] = (data_ + pos_)[0];
pos_ += 4;
return *reinterpret_cast<u32*>(bytes.data());
}
template<> auto reader::read() -> i64
{
if (pos_ + 8 > size_) return i64{};
if (!swap_)
{
auto value = *reinterpret_cast<i64 const*>(data_ + pos_);
pos_ += 8;
return value;
}
auto bytes = std::array<u8, 8>{};
bytes[0] = (data_ + pos_)[7];
bytes[1] = (data_ + pos_)[6];
bytes[2] = (data_ + pos_)[5];
bytes[3] = (data_ + pos_)[4];
bytes[4] = (data_ + pos_)[3];
bytes[5] = (data_ + pos_)[2];
bytes[6] = (data_ + pos_)[1];
bytes[7] = (data_ + pos_)[0];
pos_ += 8;
return *reinterpret_cast<i64*>(bytes.data());
}
template<> auto reader::read() -> u64
{
if (pos_ + 8 > size_) return u64{};
if (!swap_)
{
auto value = *reinterpret_cast<u64 const*>(data_ + pos_);
pos_ += 8;
return value;
}
auto bytes = std::array<u8, 8>{};
bytes[0] = (data_ + pos_)[7];
bytes[1] = (data_ + pos_)[6];
bytes[2] = (data_ + pos_)[5];
bytes[3] = (data_ + pos_)[4];
bytes[4] = (data_ + pos_)[3];
bytes[5] = (data_ + pos_)[2];
bytes[6] = (data_ + pos_)[1];
bytes[7] = (data_ + pos_)[0];
pos_ += 8;
return *reinterpret_cast<u64*>(bytes.data());
}
template<> auto reader::read() -> f32
{
if (pos_ + 4 > size_) return f32{};
if (!swap_)
{
auto value = *reinterpret_cast<f32 const*>(data_ + pos_);
pos_ += 4;
return value;
}
auto bytes = std::array<u8, 4>{};
bytes[0] = (data_ + pos_)[3];
bytes[1] = (data_ + pos_)[2];
bytes[2] = (data_ + pos_)[1];
bytes[3] = (data_ + pos_)[0];
pos_ += 4;
return *reinterpret_cast<f32*>(bytes.data());
}
auto reader::read_cstr() -> std::string
{
auto ret = std::string{ reinterpret_cast<char const*>(data_ + pos_) };
pos_ += static_cast<u32>(ret.size() + 1);
return ret;
}
auto reader::read_bytes(u32 pos, u32 count) -> std::string
{
auto data = std::string{};
data.reserve(count * 3);
for (auto i = pos; i < pos + count; i++)
{
data += fmt::format("{:02X} ", *reinterpret_cast<u8 const*>(data_ + i));
}
data.pop_back();
return data;
}
auto reader::is_avail() -> bool
{
return (pos_ < size_) ? true : false;
}
auto reader::seek(u32 size) -> void
{
if (pos_ + size <= size_) pos_ += size;
}
auto reader::seek_neg(u32 size) -> void
{
if (pos_ - size >= 0) pos_ -= size;
}
auto reader::align(u32 size) -> u32
{
auto pos = pos_;
pos_ = (pos_ + (size - 1)) & ~(size - 1);
return pos_ - pos;
}
auto reader::data() -> u8 const*
{
return data_;
}
auto reader::size() -> u32
{
return size_;
}
auto reader::pos() -> u32
{
return pos_;
}
auto reader::pos(u32 pos) -> void
{
if (pos >= 0 && pos <= size_)
{
pos_ = pos;
}
}
} // namespace xsk::utils

40
src/utils/reader.hpp Normal file
View File

@ -0,0 +1,40 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::utils
{
class reader
{
public:
using ptr = std::unique_ptr<reader>;
private:
u8 const* data_;
u32 size_;
u32 pos_;
bool swap_;
public:
reader(bool swap = false);
reader(std::vector<u8> const& data, bool swap = false);
reader(u8 const* data, u32 size, bool swap = false);
template <typename T>
auto read() -> T;
auto read_cstr() -> std::string;
auto read_bytes(u32 pos, u32 count) -> std::string;
auto is_avail() -> bool;
auto seek(u32 size) -> void;
auto seek_neg(u32 size) -> void;
auto align(u32 size) -> u32;
auto data() -> u8 const*;
auto size() -> u32;
auto pos() -> u32;
auto pos(u32 pos) -> void;
};
} // namespace xsk::utils

View File

@ -1,6 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#include "stdafx.hpp"

View File

@ -1,28 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include <cstdio>
#include <algorithm>
#include <array>
#include <filesystem>
#include <fstream>
#include <functional>
#include <iostream>
#include <map>
#include <memory>
#include <regex>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <string>
#include <unordered_map>
#include <vector>
using namespace std::literals;
#include "xsk/utils.hpp"

View File

@ -1,29 +1,30 @@
// Copyright 2022 xensik. All rights reserved.
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#include "stdafx.hpp"
#include "stdinc.hpp"
#include "string.hpp"
namespace xsk::utils
{
auto string::oct_to_dec(const char* str) -> std::string
auto string::oct_to_dec(char const* str) -> std::string
{
return std::to_string(std::stoi(str, nullptr, 8));
}
auto string::bin_to_dec(const char* str) -> std::string
auto string::bin_to_dec(char const* str) -> std::string
{
return std::to_string(std::stoi(&str[2], nullptr, 2)); // str must prefix 0[bB]
}
auto string::hex_to_dec(const char* str) -> std::string
auto string::hex_to_dec(char const* str) -> std::string
{
return std::to_string(std::stoi(&str[2], nullptr, 16)); // str must prefix 0[xX]
}
auto string::iequals(const std::string& a, const std::string& b) -> bool
auto string::iequals(std::string const& a, std::string const& b) -> bool
{
return (a.size() == b.size()) && std::equal(a.begin(), a.end(), b.begin(), b.end(),
[](char a, char b)
@ -32,21 +33,21 @@ auto string::iequals(const std::string& a, const std::string& b) -> bool
});
}
auto string::is_number(const std::string& s) -> bool
auto string::is_number(std::string const& s) -> bool
{
return !s.empty() && std::all_of(s.begin(), s.end(), isdigit);
}
auto string::is_hex_number(const std::string& s) -> bool
auto string::is_hex_number(std::string const& s) -> bool
{
return !s.empty() && std::all_of(s.begin(), s.end(), isxdigit);
}
auto string::to_lower(const std::string& input) -> std::string
auto string::to_lower(std::string const& input) -> std::string
{
std::string data(input.begin(), input.end());
auto data = std::string{ input.begin(), input.end() };
for (std::size_t i = 0; i < data.size(); i++)
for (auto i = 0u; i < data.size(); i++)
{
data[i] = static_cast<char>(std::tolower(static_cast<unsigned char>(input[i])));
}
@ -54,10 +55,10 @@ auto string::to_lower(const std::string& input) -> std::string
return data;
}
auto string::to_code(const std::string& input) -> std::string
auto string::to_code(std::string const& input) -> std::string
{
std::string data = input.substr(1, input.size() - 2);
std::size_t pos;
auto data = input.substr(1, input.size() - 2);
auto pos = usize{ 0 };
while ((pos = data.find("\\n")) != std::string::npos)
{
@ -90,10 +91,10 @@ auto string::to_code(const std::string& input) -> std::string
return data;
}
auto string::to_literal(const std::string& input) -> std::string
auto string::to_literal(std::string const& input) -> std::string
{
std::string data(input.begin(), input.end());
std::size_t pos;
auto data = std::string{ input.begin(), input.end() };
auto pos = usize{ 0 };
while ((pos = data.find('\n')) != std::string::npos)
{
@ -133,11 +134,11 @@ auto string::to_literal(const std::string& input) -> std::string
return data;
}
auto string::fordslash(const std::string& s) -> std::string
auto string::fordslash(std::string const& s) -> std::string
{
std::string data(s.begin(), s.end());
auto data = std::string{ s.begin(), s.end() };
for (std::size_t i = 0; i < data.size(); i++)
for (auto i = 0u; i < data.size(); i++)
{
if (data[i] == '\\') data[i] = '/';
}
@ -145,11 +146,11 @@ auto string::fordslash(const std::string& s) -> std::string
return data;
}
auto string::backslash(const std::string& s) -> std::string
auto string::backslash(std::string const& s) -> std::string
{
std::string data(s.begin(), s.end());
auto data = std::string{ s.begin(), s.end() };
for (std::size_t i = 0; i < data.size(); i++)
for (auto i = 0u; i < data.size(); i++)
{
if (data[i] == '/') data[i] = '\\';
}
@ -157,9 +158,9 @@ auto string::backslash(const std::string& s) -> std::string
return data;
}
auto string::quote(const std::string& s, bool single) -> std::string
auto string::quote(std::string const& s, bool single) -> std::string
{
std::string data(s.begin(), s.end());
auto data = std::string{ s.begin(), s.end() };
if (single)
{
@ -175,7 +176,7 @@ auto string::quote(const std::string& s, bool single) -> std::string
return data;
}
auto string::unquote(const std::string& s) -> std::string
auto string::unquote(std::string const& s) -> std::string
{
if (s.at(0) == '\'' || s.at(0) == '\"')
return s.substr(1, s.size() - 2);
@ -185,9 +186,9 @@ auto string::unquote(const std::string& s) -> std::string
auto string::split(std::string& str, char delimiter) -> std::vector<std::string>
{
std::vector<std::string> tokens;
std::stringstream ss(str);
std::string tok;
auto tokens = std::vector<std::string>{};
auto ss = std::stringstream{ str };
auto tok = std::string{};
while (std::getline(ss, tok, delimiter))
{
@ -197,10 +198,10 @@ auto string::split(std::string& str, char delimiter) -> std::vector<std::string>
return tokens;
}
auto string::clean_buffer_lines(std::vector<std::uint8_t>& buffer) -> std::vector<std::string>
auto string::clean_buffer_lines(std::vector<u8>& buffer) -> std::vector<std::string>
{
std::string data = std::string(reinterpret_cast<char*>(buffer.data()), buffer.size());
std::size_t pos;
auto data = std::string{ reinterpret_cast<char*>(buffer.data()), buffer.size() };
auto pos = usize{ 0 };
while ((pos = data.find("\t")) != std::string::npos)
{
@ -212,9 +213,9 @@ auto string::clean_buffer_lines(std::vector<std::uint8_t>& buffer) -> std::vecto
data = data.replace(pos, 1, "");
}
std::vector<std::string> lines;
std::stringstream ss(data);
std::string tok;
auto lines = std::vector<std::string>{};
auto ss = std::stringstream{ data };
auto tok = std::string{};
while (std::getline(ss, tok, '\n'))
{
@ -226,10 +227,10 @@ auto string::clean_buffer_lines(std::vector<std::uint8_t>& buffer) -> std::vecto
auto string::parse_code(std::string& line) -> std::vector<std::string>
{
std::vector<std::string> data;
std::regex exp(R"(([_A-Za-z0-9\-]+|\"(?:\\.|[^\"])*?\"|\'(?:\\.|[^\'])*?\')(?:\s+|$))");
auto data = std::vector<std::string>{};
auto exp = std::regex{ R"(([_A-Za-z0-9\-]+|\"(?:\\.|[^\"])*?\"|\'(?:\\.|[^\'])*?\')(?:\s+|$))" };
for (auto i = std::sregex_iterator(line.begin(), line.end(), exp); i != std::sregex_iterator(); ++i)
for (auto i = std::sregex_iterator{ line.begin(), line.end(), exp }; i != std::sregex_iterator{}; ++i)
{
data.push_back(i->format("$1"));
}
@ -237,9 +238,9 @@ auto string::parse_code(std::string& line) -> std::vector<std::string>
return data;
}
auto string::float_string(float value) -> std::string
auto string::float_string(float value, bool toint) -> std::string
{
enum flags_t : std::uint8_t { none = 0, negative = 1, integer = 2, has_exp = 4, exp_neg = 8 };
enum flags_t : u8 { none = 0, negative = 1, integer = 2, has_exp = 4, exp_neg = 8 };
auto str = utils::string::va("%g", value);
@ -253,7 +254,7 @@ auto string::float_string(float value) -> std::string
}
if (!(flags & has_exp))
return str += (flags & integer) ? ".0" : "";
return str += ((flags & integer) && !toint) ? ".0" : "";
std::string p_int;
std::string p_dec;
@ -271,7 +272,7 @@ auto string::float_string(float value) -> std::string
while (i < str.size())
p_exp.push_back(str[i++]);
std::size_t offset = std::stoi(p_exp);
auto offset = usize{ std::stoul(p_exp) };
if ((flags & exp_neg))
offset -= p_int.size();
@ -303,7 +304,7 @@ auto string::float_string(float value) -> std::string
while (i < str.size())
p_exp.push_back(str[i++]);
std::size_t offset = std::stoi(p_exp);
auto offset = usize{ std::stoul(p_exp) };
offset -= (flags & exp_neg) ? p_int.size() : p_dec.size();

43
src/utils/string.hpp Normal file
View File

@ -0,0 +1,43 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::utils
{
class string
{
public:
template <typename ... Args>
static auto va(std::string const& format, Args ... args) -> std::string
{
usize size = snprintf(nullptr, 0, format.data(), args ...) + 1;
std::vector<char> buf;
buf.resize(size);
snprintf(buf.data(), size, format.data(), args ...);
return std::string(buf.data(), buf.data() + size - 1);
}
static auto oct_to_dec(char const* str) -> std::string;
static auto bin_to_dec(char const* str) -> std::string;
static auto hex_to_dec(char const* str) -> std::string;
static auto iequals(std::string const& a, std::string const& b) -> bool;
static auto is_number(std::string const& s) -> bool;
static auto is_hex_number(std::string const& s) -> bool;
static auto to_lower(std::string const& input) -> std::string;
static auto to_code(std::string const& input) -> std::string;
static auto to_literal(std::string const& input) -> std::string;
static auto fordslash(std::string const& s) -> std::string;
static auto backslash(std::string const& s) -> std::string;
static auto quote(std::string const& s, bool single = true) -> std::string;
static auto unquote(std::string const& s) -> std::string;
static auto split(std::string& str, char delimiter) -> std::vector<std::string>;
static auto clean_buffer_lines(std::vector<u8>& buffer) -> std::vector<std::string>;
static auto parse_code(std::string& line) -> std::vector<std::string>;
static auto float_string(float value, bool toint = false) -> std::string;
};
} // namespace xsk::utils

266
src/utils/writer.cpp Normal file
View File

@ -0,0 +1,266 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#include "stdinc.hpp"
#include "writer.hpp"
namespace xsk::utils
{
writer::writer(bool swap) : size_{ 0x100000 }, pos_{ 0 }, swap_{ swap }
{
data_ = reinterpret_cast<u8*>(std::malloc(size_));
std::memset(data_, 0, size_);
}
writer::writer(u32 size, bool swap) : size_{ size }, pos_{ 0 }, swap_{ swap }
{
data_ = reinterpret_cast<u8*>(std::malloc(size_));
std::memset(data_, 0, size_);
}
writer::~writer()
{
std::free(reinterpret_cast<void*>(data_));
}
auto writer::clear() -> void
{
std::memset(data_, 0, size_);
}
template<> auto writer::write(i8 data) -> void
{
if (pos_ + 1 > size_) return;
*reinterpret_cast<i8*>(data_ + pos_) = data;
pos_ += 1;
}
template<> auto writer::write(u8 data) -> void
{
if (pos_ + 1 > size_) return;
*reinterpret_cast<u8*>(data_ + pos_) = data;
pos_ += 1;
}
template<> auto writer::write(i16 data) -> void
{
if (pos_ + 2 > size_) return;
if (!swap_)
{
*reinterpret_cast<i16*>(data_ + pos_) = data;
}
else
{
(data_ + pos_)[0] = reinterpret_cast<u8*>(&data)[1];
(data_ + pos_)[1] = reinterpret_cast<u8*>(&data)[0];
}
pos_ += 2;
}
template<> auto writer::write(u16 data) -> void
{
if (pos_ + 2 > size_) return;
if (!swap_)
{
*reinterpret_cast<u16*>(data_ + pos_) = data;
}
else
{
(data_ + pos_)[0] = reinterpret_cast<u8*>(&data)[1];
(data_ + pos_)[1] = reinterpret_cast<u8*>(&data)[0];
}
pos_ += 2;
}
template<> auto writer::write(i32 data) -> void
{
if (pos_ + 4 > size_) return;
if (!swap_)
{
*reinterpret_cast<i32*>(data_ + pos_) = data;
}
else
{
(data_ + pos_)[0] = reinterpret_cast<u8*>(&data)[3];
(data_ + pos_)[1] = reinterpret_cast<u8*>(&data)[2];
(data_ + pos_)[2] = reinterpret_cast<u8*>(&data)[1];
(data_ + pos_)[3] = reinterpret_cast<u8*>(&data)[0];
}
pos_ += 4;
}
template<> auto writer::write(u32 data) -> void
{
if (pos_ + 4 > size_) return;
if (!swap_)
{
*reinterpret_cast<u32*>(data_ + pos_) = data;
}
else
{
(data_ + pos_)[0] = reinterpret_cast<u8*>(&data)[3];
(data_ + pos_)[1] = reinterpret_cast<u8*>(&data)[2];
(data_ + pos_)[2] = reinterpret_cast<u8*>(&data)[1];
(data_ + pos_)[3] = reinterpret_cast<u8*>(&data)[0];
}
pos_ += 4;
}
template<> auto writer::write(i64 data) -> void
{
if (pos_ + 8 > size_) return;
if (!swap_)
{
*reinterpret_cast<i64*>(data_ + pos_) = data;
}
else
{
(data_ + pos_)[0] = reinterpret_cast<u8*>(&data)[7];
(data_ + pos_)[1] = reinterpret_cast<u8*>(&data)[6];
(data_ + pos_)[2] = reinterpret_cast<u8*>(&data)[5];
(data_ + pos_)[3] = reinterpret_cast<u8*>(&data)[4];
(data_ + pos_)[4] = reinterpret_cast<u8*>(&data)[3];
(data_ + pos_)[5] = reinterpret_cast<u8*>(&data)[2];
(data_ + pos_)[6] = reinterpret_cast<u8*>(&data)[1];
(data_ + pos_)[7] = reinterpret_cast<u8*>(&data)[0];
}
pos_ += 8;
}
template<> auto writer::write(u64 data) -> void
{
if (pos_ + 8 > size_) return;
if (!swap_)
{
*reinterpret_cast<u64*>(data_ + pos_) = data;
}
else
{
(data_ + pos_)[0] = reinterpret_cast<u8*>(&data)[7];
(data_ + pos_)[1] = reinterpret_cast<u8*>(&data)[6];
(data_ + pos_)[2] = reinterpret_cast<u8*>(&data)[5];
(data_ + pos_)[3] = reinterpret_cast<u8*>(&data)[4];
(data_ + pos_)[4] = reinterpret_cast<u8*>(&data)[3];
(data_ + pos_)[5] = reinterpret_cast<u8*>(&data)[2];
(data_ + pos_)[6] = reinterpret_cast<u8*>(&data)[1];
(data_ + pos_)[7] = reinterpret_cast<u8*>(&data)[0];
}
pos_ += 8;
}
template<> auto writer::write(f32 data) -> void
{
if (pos_ + 4 > size_) return;
if (!swap_)
{
*reinterpret_cast<f32*>(data_ + pos_) = data;
}
else
{
(data_ + pos_)[0] = reinterpret_cast<u8*>(&data)[3];
(data_ + pos_)[1] = reinterpret_cast<u8*>(&data)[2];
(data_ + pos_)[2] = reinterpret_cast<u8*>(&data)[1];
(data_ + pos_)[3] = reinterpret_cast<u8*>(&data)[0];
}
pos_ += 4;
}
auto writer::write_string(std::string const& data) -> void
{
if (pos_ + data.size() > size_) return;
std::memcpy(reinterpret_cast<void*>(data_ + pos_), data.data(), data.size());
pos_ += static_cast<u32>(data.size());
}
auto writer::write_cstr(std::string const& data) -> void
{
if (pos_ + data.size() >= size_) return;
std::memcpy(reinterpret_cast<void*>(data_ + pos_), data.data(), data.size());
pos_ += static_cast<u32>(data.size() + 1);
}
auto writer::read_bytes(u32 pos, u32 count) -> std::string
{
auto data = std::string{};
data.reserve(count * 3);
for (auto i = pos; i < pos + count; i++)
{
data += fmt::format("{:02X} ", *reinterpret_cast<const u8*>(data_ + i));
}
data.pop_back();
return data;
}
auto writer::is_avail() -> bool
{
return (pos_ < size_) ? true : false;
}
auto writer::seek(u32 size) -> void
{
if (pos_ + size <= size_) pos_ += size;
}
auto writer::seek_neg(u32 size) -> void
{
if (pos_ - size >= 0) pos_ -= size;
}
auto writer::align(u32 size) -> u32
{
auto pos = pos_;
pos_ = (pos_ + (size - 1)) & ~(size - 1);
return pos_ - pos;
}
auto writer::data() -> const u8*
{
return data_;
}
auto writer::size() -> u32
{
return size_;
}
auto writer::pos() -> u32
{
return pos_;
}
auto writer::pos(u32 pos) -> void
{
if (pos >= 0 && pos <= size_)
{
pos_ = pos;
}
}
} // namespace xsk::utils

42
src/utils/writer.hpp Normal file
View File

@ -0,0 +1,42 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::utils
{
class writer
{
public:
using ptr = std::unique_ptr<writer>;
private:
u8* data_;
u32 size_;
u32 pos_;
bool swap_;
public:
writer(bool swap = false);
writer(u32 size, bool swap = false);
~writer();
auto clear() -> void;
template <typename T>
auto write(T data) -> void;
auto write_string(std::string const& data) -> void;
auto write_cstr(std::string const& data) -> void;
auto read_bytes(u32 pos, u32 count) -> std::string;
auto is_avail() -> bool;
auto seek(u32 size) -> void;
auto seek_neg(u32 size) -> void;
auto align(u32 size) -> u32;
auto data() -> u8 const*;
auto size() -> u32;
auto pos() -> u32;
auto pos(u32 pos) -> void;
};
} // namespace xsk::utils

View File

@ -1,25 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::arc
{
struct block
{
using ptr = std::unique_ptr<block>;
std::string loc_end;
std::string loc_break;
std::string loc_continue;
abort_t abort;
bool is_dev;
block() : abort(abort_t::abort_none), is_dev(false) {}
block(const std::string& lbreak, const std::string& lcont) : loc_break(lbreak), loc_continue(lcont), abort(abort_t::abort_none), is_dev(false) {}
};
} // namespace xsk::arc

View File

@ -1,22 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::arc
{
class assembler
{
public:
using ptr = std::unique_ptr<assembler>;
virtual ~assembler() = default;
virtual auto output() -> std::vector<std::uint8_t> = 0;
virtual void assemble(const std::string& file, std::vector<std::uint8_t>& data) = 0;
virtual void assemble(const std::string& file, assembly::ptr& data) = 0;
};
} // namespace xsk::arc

View File

@ -1,22 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::arc
{
class compiler
{
public:
using ptr = std::unique_ptr<compiler>;
virtual ~compiler() = default;
virtual auto output() -> assembly::ptr = 0;
virtual auto output_raw() -> std::vector<std::uint8_t> = 0;
virtual void compile(const std::string& file, std::vector<std::uint8_t>& data) = 0;
};
} // namespace xsk::arc

View File

@ -1,26 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::arc
{
class context
{
public:
using ptr = std::unique_ptr<context>;
virtual ~context() = default;
virtual void init(build mode, read_cb_type callback) = 0;
virtual void cleanup() = 0;
virtual auto assembler() -> assembler& = 0;
virtual auto disassembler() -> disassembler& = 0;
virtual auto compiler() -> compiler& = 0;
virtual auto decompiler() -> decompiler& = 0;
};
} // namespace xsk::arc

View File

@ -1,21 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::arc
{
class decompiler
{
public:
using ptr = std::unique_ptr<decompiler>;
virtual ~decompiler() = default;
virtual auto output() -> std::vector<std::uint8_t> = 0;
virtual void decompile(const std::string& file, const assembly::ptr& data) = 0;
};
} // namespace xsk::arc

View File

@ -1,22 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::arc
{
class disassembler
{
public:
using ptr = std::unique_ptr<disassembler>;
virtual ~disassembler() = default;
virtual auto output() -> assembly::ptr = 0;
virtual auto output_raw() -> std::vector<std::uint8_t> = 0;
virtual void disassemble(const std::string& file, std::vector<std::uint8_t>& data) = 0;
};
} // namespace xsk::arc

View File

@ -1,46 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::arc
{
class error : public std::runtime_error
{
public:
error(const std::string& what)
: std::runtime_error("[ERROR]: "s + what) {}
};
class asm_error : public std::runtime_error
{
public:
asm_error(const std::string& what)
: std::runtime_error("[ERROR]:assembler: "s + what) {}
};
class disasm_error : public std::runtime_error
{
public:
disasm_error(const std::string& what)
: std::runtime_error("[ERROR]:disassembler: "s + what) {}
};
class comp_error : public std::runtime_error
{
public:
comp_error(const location& loc, const std::string& what)
: std::runtime_error("[ERROR]:compiler:" + loc.print() + ": " + what) {}
};
class decomp_error : public std::runtime_error
{
public:
decomp_error(const std::string& what)
: std::runtime_error("[ERROR]:decompiler: "s + what) {}
};
} // namespace xsk::arc

View File

@ -1,229 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::arc
{
/// A point in a source file.
class position
{
public:
/// Type for file name.
typedef const std::string filename_type;
/// Type for line and column numbers.
typedef int counter_type;
/// Construct a position.
explicit position(filename_type *f = nullptr, counter_type l = 1, counter_type c = 1)
: filename(f), line(l), column(c) {}
/// Initialization.
void initialize(filename_type *fn = nullptr, counter_type l = 1, counter_type c = 1)
{
filename = fn;
line = l;
column = c;
}
/** \name Line and Column related manipulators
** \{ */
/// (line related) Advance to the COUNT next lines.
void lines(counter_type count = 1)
{
if (count)
{
column = 1;
line = add_(line, count, 1);
}
}
/// (column related) Advance to the COUNT next columns.
void columns(counter_type count = 1)
{
column = add_(column, count, 1);
}
/** \} */
/// File name to which this position refers.
filename_type *filename;
/// Current line number.
counter_type line;
/// Current column number.
counter_type column;
private:
/// Compute max (min, lhs+rhs).
static counter_type add_(counter_type lhs, counter_type rhs, counter_type min)
{
return lhs + rhs < min ? min : lhs + rhs;
}
};
/// Add \a width columns, in place.
inline position& operator+=(position &res, position::counter_type width)
{
res.columns(width);
return res;
}
/// Add \a width columns.
inline position operator+(position res, position::counter_type width)
{
return res += width;
}
/// Subtract \a width columns, in place.
inline position& operator-=(position &res, position::counter_type width)
{
return res += -width;
}
/// Subtract \a width columns.
inline position operator-(position res, position::counter_type width)
{
return res -= width;
}
/** \brief Intercept output stream redirection.
** \param ostr the destination output stream
** \param pos a reference to the position to redirect
*/
template <typename YYChar>
std::basic_ostream<YYChar>& operator<<(std::basic_ostream<YYChar> &ostr, const position &pos)
{
if (pos.filename)
ostr << *pos.filename << ':';
return ostr << pos.line << '.' << pos.column;
}
/// Two points in a source file.
class location
{
public:
/// Type for file name.
typedef position::filename_type filename_type;
/// Type for line and column numbers.
typedef position::counter_type counter_type;
/// Construct a location from \a b to \a e.
location(const position &b, const position &e)
: begin(b), end(e) {}
/// Construct a 0-width location in \a p.
explicit location(const position &p = position())
: begin(p), end(p) {}
/// Construct a 0-width location in \a f, \a l, \a c.
explicit location(filename_type *f, counter_type l = 1, counter_type c = 1)
: begin(f, l, c), end(f, l, c) {}
/// Initialization.
void initialize(filename_type *f = nullptr, counter_type l = 1, counter_type c = 1)
{
begin.initialize(f, l, c);
end = begin;
}
/** \name Line and Column related manipulators
** \{ */
public:
/// Reset initial location to final location.
void step()
{
begin = end;
}
/// Extend the current location to the COUNT next columns.
void columns(counter_type count = 1)
{
end += count;
}
/// Extend the current location to the COUNT next lines.
void lines(counter_type count = 1)
{
end.lines(count);
}
/** \} */
public:
auto print() const -> std::string
{
return *begin.filename + ":" + std::to_string(begin.line) + ":" + std::to_string(begin.column);
}
auto label() const -> std::string
{
return utils::string::va("loc_%X", begin.line);
}
public:
/// Beginning of the located region.
position begin;
/// End of the located region.
position end;
};
/// Join two locations, in place.
inline location& operator+=(location &res, const location &end)
{
res.end = end.end;
return res;
}
/// Join two locations.
inline location operator+(location res, const location &end)
{
return res += end;
}
/// Add \a width columns to the end position, in place.
inline location& operator+=(location &res, location::counter_type width)
{
res.columns(width);
return res;
}
/// Add \a width columns to the end position.
inline location operator+(location res, location::counter_type width)
{
return res += width;
}
/// Subtract \a width columns to the end position, in place.
inline location& operator-=(location &res, location::counter_type width)
{
return res += -width;
}
/// Subtract \a width columns to the end position.
inline location operator-(location res, location::counter_type width)
{
return res -= width;
}
/** \brief Intercept output stream redirection.
** \param ostr the destination output stream
** \param loc a reference to the location to redirect
**
** Avoid duplicate information.
*/
template <typename YYChar>
std::basic_ostream<YYChar>& operator<<(std::basic_ostream<YYChar> &ostr, const location &loc)
{
location::counter_type end_col = 0 < loc.end.column ? loc.end.column - 1 : 0;
ostr << loc.begin;
if (loc.end.filename && (!loc.begin.filename || *loc.begin.filename != *loc.end.filename))
ostr << '-' << loc.end.filename << ':' << loc.end.line << '.' << end_col;
else if (loc.begin.line < loc.end.line)
ostr << '-' << loc.end.line << '.' << end_col;
else if (loc.begin.column < end_col)
ostr << '-' << end_col;
return ostr;
}
} // namespace xsk::arc

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,181 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::arc
{
using read_cb_type = std::function<std::vector<std::uint8_t>(const std::string&)>;
enum class build
{
prod,
dev,
};
enum class abort_t
{
abort_none = 0,
abort_continue = 1,
abort_break = 2,
abort_return = 3,
};
struct include_t
{
std::string name;
std::vector<std::string> funcs;
include_t(const std::string& name, const std::vector<std::string>& funcs) : name(name), funcs(funcs) {}
};
struct animtree_t
{
std::string name;
bool loaded;
};
struct instruction
{
using ptr = std::unique_ptr<instruction>;
std::uint32_t index;
std::uint32_t size;
std::uint8_t opcode;
std::vector<std::string> data;
instruction() : index(0), size(0), opcode(0xFF) {}
};
struct function
{
using ptr = std::unique_ptr<function>;
std::uint32_t index;
std::uint32_t size;
std::uint8_t params;
std::uint8_t flags;
std::string name;
std::vector<instruction::ptr> instructions;
std::unordered_map<std::uint32_t, std::string> labels;
function() : index(0), size(0), params(0), flags(0) {}
};
struct animation_ref
{
using ptr = std::shared_ptr<animation_ref>;
std::string name;
std::uint32_t ref;
};
struct animtree_ref
{
using ptr = std::shared_ptr<animtree_ref>;
std::string name;
std::vector<std::uint32_t> refs;
std::vector<animation_ref> anims;
};
enum class string_type : std::uint8_t
{
literal = 0,
canonical = 1,
};
struct string_ref
{
using ptr = std::shared_ptr<string_ref>;
std::string name;
std::uint8_t type;
std::vector<std::uint32_t> refs;
};
enum class export_flags : std::uint8_t
{
export_none = 0x00,
export_public = 0x01,
export_autoexec = 0x02,
export_private = 0x04,
export_codecall = 0x08,
export_private2 = 0x10,
export_varargs = 0x20,
};
struct export_ref
{
using ptr = std::shared_ptr<export_ref>;
std::uint32_t checksum;
std::uint32_t offset;
std::string name;
std::string space;
std::uint8_t params;
std::uint8_t flags;
std::uint32_t size;
};
enum class import_flags : std::uint8_t
{
none = 0,
func_reference = 1,
func_call = 2,
func_call_thread = 3,
meth_call = 4,
meth_call_thread = 5,
developer = 0x10,
unk = 0x20, // T7, T8, T9
};
struct import_ref
{
using ptr = std::shared_ptr<import_ref>;
std::string space;
std::string name;
std::uint8_t params;
std::uint8_t flags;
std::vector<std::uint32_t> refs;
};
struct header
{
std::uint64_t magic;
std::uint32_t source_crc;
std::uint32_t include_offset;
std::uint32_t animtree_offset;
std::uint32_t cseg_offset;
std::uint32_t stringtablefixup_offset;
std::uint32_t exports_offset;
std::uint32_t imports_offset;
std::uint32_t fixup_offset;
std::uint32_t profile_offset;
std::uint32_t cseg_size;
std::uint16_t name;
std::uint16_t stringtablefixup_count;
std::uint16_t exports_count;
std::uint16_t imports_count;
std::uint16_t fixup_count;
std::uint16_t profile_count;
std::uint8_t include_count;
std::uint8_t animtree_count;
std::uint8_t flags;
// char[1] pad;
};
struct assembly
{
using ptr = std::unique_ptr<assembly>;
std::vector<function::ptr> functions;
std::vector<std::string> includes;
std::vector<animtree_ref> animtrees;
};
} // namespace xsk::arc

View File

@ -1,64 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#include "stdafx.hpp"
namespace xsk::gsc
{
auto asset::serialize() -> std::vector<std::uint8_t>
{
std::vector<std::uint8_t> data;
data.resize(name.size() + compressedLen + bytecodeLen + 13);
std::memset(data.data(), 0, data.size());
std::size_t pos = 0;
std::memcpy(&data[pos], name.data(), name.size() + 1);
pos += name.size() + 1;
*reinterpret_cast<std::uint32_t*>(&data[pos]) = compressedLen;
pos += 4;
*reinterpret_cast<std::uint32_t*>(&data[pos]) = len;
pos += 4;
*reinterpret_cast<std::uint32_t*>(&data[pos]) = bytecodeLen;
pos += 4;
std::memcpy(&data[pos], buffer.data(), buffer.size());
pos += buffer.size();
std::memcpy(&data[pos], bytecode.data(), bytecode.size());
return data;
}
void asset::deserialize(std::vector<std::uint8_t> data)
{
std::size_t pos = 0;
name = std::string(reinterpret_cast<const char*>(data.data()));
pos += name.size() + 1;
compressedLen = *reinterpret_cast<std::uint32_t*>(data.data() + pos);
pos += 4;
len = *reinterpret_cast<std::uint32_t*>(data.data() + pos);
pos += 4;
bytecodeLen = *reinterpret_cast<std::uint32_t*>(data.data() + pos);
pos += 4;
buffer.resize(compressedLen);
std::memcpy(buffer.data(), data.data() + pos, compressedLen);
pos += buffer.size();
bytecode.resize(bytecodeLen);
std::memcpy(bytecode.data(), data.data() + pos, bytecodeLen);
}
} // namespace xsk::gsc

View File

@ -1,26 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::gsc
{
struct asset
{
using ptr = std::unique_ptr<asset>;
std::string name;
std::uint32_t compressedLen;
std::uint32_t len;
std::uint32_t bytecodeLen;
std::vector<std::uint8_t> buffer;
std::vector<std::uint8_t> bytecode;
auto serialize() -> std::vector<std::uint8_t>;
void deserialize(std::vector<std::uint8_t> data);
};
} // namespace xsk::gsc

View File

@ -1,175 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#include "stdafx.hpp"
namespace xsk::gsc
{
block::block() : local_vars_create_count(0), local_vars_public_count(0),
abort(abort_t::abort_none), is_last(false) { }
void block::transfer(const block::ptr& child)
{
child->loc_break = this->loc_break;
child->loc_continue = this->loc_continue;
for (std::uint32_t i = 0; i < child->local_vars_public_count || i < this->local_vars_create_count; i++ )
{
auto pos = child->find_variable(i, this->local_vars.at(i).name);
if (pos < 0)
{
child->local_vars_public_count++;
child->local_vars.insert(child->local_vars.begin() + i, this->local_vars.at(i));
}
else
{
auto& v = child->local_vars;
if (pos > std::int32_t(i))
std::rotate(v.rend() - pos - 1, v.rend() - pos, v.rend() - i);
else
std::rotate(v.begin() + pos, v.begin() + pos + 1, v.begin() + i + 1);
child->local_vars.at(i).init = this->local_vars.at(i).init;
if (child->local_vars_public_count <= i)
child->local_vars_public_count++;
}
}
child->local_vars_create_count = this->local_vars_create_count;
child->abort = abort_t::abort_none;
}
void block::copy(const block::ptr& child)
{
child->local_vars = this->local_vars;
child->local_vars_create_count = this->local_vars_create_count;
child->local_vars_public_count = 0;
}
void block::append(const std::vector<block*>& childs)
{
bool glob = true;
if (childs.size() == 0) return;
for (std::size_t i = 0; i < childs.at(0)->local_vars.size(); i++ )
{
glob = true;
auto& var = childs.at(0)->local_vars.at(i);
if (this->find_variable(0, var.name) < 0)
{
for (std::size_t j = 1; j < childs.size(); j++ )
{
if (childs.at(j)->find_variable(0, var.name) < 0)
{
glob = false;
}
}
if (glob)
{
this->local_vars.push_back(var);
}
}
}
}
void block::merge(const std::vector<block*>& childs)
{
if (childs.size() == 0) return;
for (std::size_t childidx = 0; childidx < childs.size(); childidx++)
{
auto child = childs[childidx];
child->local_vars_public_count = static_cast<std::uint32_t>(this->local_vars.size());
for (std::size_t i = 0; i < this->local_vars.size(); i++ )
{
auto& name = this->local_vars.at(i).name;
auto pos = child->find_variable(i, name);
if (pos < 0)
{
child->local_vars.insert(child->local_vars.begin() + i, this->local_vars.at(i));
}
else if (pos > static_cast<std::int32_t>(i))
{
auto& v = child->local_vars;
std::rotate(v.rend() - pos - 1, v.rend() - pos, v.rend() - i);
}
}
}
}
void block::init_from_child(const std::vector<block*>& childs)
{
if (childs.size() == 0) return;
auto create_count = childs[0]->local_vars_public_count;
for (std::size_t i = 1; i < childs.size(); ++i )
{
auto child = childs[i];
if ( child->local_vars_public_count < create_count )
create_count = child->local_vars_public_count;
}
this->local_vars_create_count = create_count;
bool init = true;
for (std::uint32_t i = 0; i < create_count; i++ )
{
init = true;
if (!this->local_vars.at(i).init)
{
for (std::size_t j = 0; j < childs.size(); j++ )
{
auto child = childs[j];
if (!child->local_vars.at(i).init)
{
init = false;
}
}
if (init) this->local_vars.at(i).init = true;
}
}
}
auto block::find_variable(std::size_t start, const std::string& name) -> std::int32_t
{
for (std::size_t i = start; i < local_vars.size(); ++i )
{
if (local_vars.at(i).name == name)
return static_cast<std::int32_t>(i);
}
return -1;
}
void block::transfer_decompiler(const block::ptr& child)
{
for (std::uint32_t i = 0; i < this->local_vars.size(); i++ )
{
child->local_vars.push_back(this->local_vars.at(i));
}
child->local_vars_public_count = static_cast<std::uint32_t>(this->local_vars.size());
}
void block::append_decompiler(const block::ptr& child, bool all)
{
auto total = all ? child->local_vars.size() : child->local_vars_public_count;
for (auto i = this->local_vars.size(); i < total; i++ )
{
this->local_vars.push_back(child->local_vars.at(i));
}
}
} // namespace xsk::gsc

View File

@ -1,42 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::gsc
{
struct local_var
{
std::string name;
std::uint8_t create;
bool init;
};
struct block
{
using ptr = std::unique_ptr<block>;
std::string loc_end;
std::string loc_break;
std::string loc_continue;
std::vector<local_var> local_vars;
std::uint32_t local_vars_create_count;
std::uint32_t local_vars_public_count;
abort_t abort;
bool is_last;
block();
void transfer(const block::ptr& child);
void copy(const block::ptr& child);
void append(const std::vector<block*>& childs);
void merge(const std::vector<block*>& childs);
void init_from_child(const std::vector<block*>& childs);
auto find_variable(std::size_t start, const std::string& name) -> std::int32_t;
void transfer_decompiler(const block::ptr& child);
void append_decompiler(const block::ptr& child, bool all = false);
};
} // namespace xsk::gsc

View File

@ -1,23 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::gsc
{
class assembler
{
public:
using ptr = std::unique_ptr<assembler>;
virtual ~assembler() = default;
virtual auto output_script() -> std::vector<std::uint8_t> = 0;
virtual auto output_stack() -> std::vector<std::uint8_t> = 0;
virtual void assemble(const std::string& file, std::vector<std::uint8_t>& data) = 0;
virtual void assemble(const std::string& file, std::vector<gsc::function::ptr>& funcs) = 0;
};
} // namespace xsk::gsc

View File

@ -1,21 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::gsc
{
class compiler
{
public:
using ptr = std::unique_ptr<compiler>;
virtual ~compiler() = default;
virtual auto output() -> std::vector<gsc::function::ptr> = 0;
virtual void compile(const std::string& file, std::vector<std::uint8_t>& data) = 0;
};
} // namespace xsk::gsc

View File

@ -1,26 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::gsc
{
class context
{
public:
using ptr = std::unique_ptr<context>;
virtual ~context() = default;
virtual void init(build mode, read_cb_type callback) = 0;
virtual void cleanup() = 0;
virtual auto assembler() -> assembler& = 0;
virtual auto disassembler() -> disassembler& = 0;
virtual auto compiler() -> compiler& = 0;
virtual auto decompiler() -> decompiler& = 0;
};
} // namespace xsk::gsc

View File

@ -1,21 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::gsc
{
class decompiler
{
public:
using ptr = std::unique_ptr<decompiler>;
virtual ~decompiler() = default;
virtual auto output() -> std::vector<std::uint8_t> = 0;
virtual void decompile(const std::string& file, std::vector<gsc::function::ptr>& funcs) = 0;
};
} // namespace xsk::gsc

View File

@ -1,22 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::gsc
{
class disassembler
{
public:
using ptr = std::unique_ptr<disassembler>;
virtual ~disassembler() = default;
virtual auto output() -> std::vector<gsc::function::ptr> = 0;
virtual auto output_data() -> std::vector<std::uint8_t> = 0;
virtual void disassemble(const std::string& file, std::vector<std::uint8_t>& script, std::vector<std::uint8_t>& stack) = 0;
};
} // namespace xsk::gsc

View File

@ -1,46 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::gsc
{
class error : public std::runtime_error
{
public:
error(const std::string& what)
: std::runtime_error("[ERROR]: "s + what) {}
};
class asm_error : public std::runtime_error
{
public:
asm_error(const std::string& what)
: std::runtime_error("[ERROR]:assembler: "s + what) {}
};
class disasm_error : public std::runtime_error
{
public:
disasm_error(const std::string& what)
: std::runtime_error("[ERROR]:disassembler: "s + what) {}
};
class comp_error : public std::runtime_error
{
public:
comp_error(const gsc::location& loc, const std::string& what)
: std::runtime_error("[ERROR]:compiler:" + loc.print() + ": " + what) {}
};
class decomp_error : public std::runtime_error
{
public:
decomp_error(const std::string& what)
: std::runtime_error("[ERROR]:decompiler: "s + what) {}
};
} // namespace xsk::gsc

View File

@ -1,229 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::gsc
{
/// A point in a source file.
class position
{
public:
/// Type for file name.
typedef const std::string filename_type;
/// Type for line and column numbers.
typedef int counter_type;
/// Construct a position.
explicit position(filename_type *f = nullptr, counter_type l = 1, counter_type c = 1)
: filename(f), line(l), column(c) {}
/// Initialization.
void initialize(filename_type *fn = nullptr, counter_type l = 1, counter_type c = 1)
{
filename = fn;
line = l;
column = c;
}
/** \name Line and Column related manipulators
** \{ */
/// (line related) Advance to the COUNT next lines.
void lines(counter_type count = 1)
{
if (count)
{
column = 1;
line = add_(line, count, 1);
}
}
/// (column related) Advance to the COUNT next columns.
void columns(counter_type count = 1)
{
column = add_(column, count, 1);
}
/** \} */
/// File name to which this position refers.
filename_type *filename;
/// Current line number.
counter_type line;
/// Current column number.
counter_type column;
private:
/// Compute max (min, lhs+rhs).
static counter_type add_(counter_type lhs, counter_type rhs, counter_type min)
{
return lhs + rhs < min ? min : lhs + rhs;
}
};
/// Add \a width columns, in place.
inline position& operator+=(position &res, position::counter_type width)
{
res.columns(width);
return res;
}
/// Add \a width columns.
inline position operator+(position res, position::counter_type width)
{
return res += width;
}
/// Subtract \a width columns, in place.
inline position& operator-=(position &res, position::counter_type width)
{
return res += -width;
}
/// Subtract \a width columns.
inline position operator-(position res, position::counter_type width)
{
return res -= width;
}
/** \brief Intercept output stream redirection.
** \param ostr the destination output stream
** \param pos a reference to the position to redirect
*/
template <typename YYChar>
std::basic_ostream<YYChar>& operator<<(std::basic_ostream<YYChar> &ostr, const position &pos)
{
if (pos.filename)
ostr << *pos.filename << ':';
return ostr << pos.line << '.' << pos.column;
}
/// Two points in a source file.
class location
{
public:
/// Type for file name.
typedef position::filename_type filename_type;
/// Type for line and column numbers.
typedef position::counter_type counter_type;
/// Construct a location from \a b to \a e.
location(const position &b, const position &e)
: begin(b), end(e) {}
/// Construct a 0-width location in \a p.
explicit location(const position &p = position())
: begin(p), end(p) {}
/// Construct a 0-width location in \a f, \a l, \a c.
explicit location(filename_type *f, counter_type l = 1, counter_type c = 1)
: begin(f, l, c), end(f, l, c) {}
/// Initialization.
void initialize(filename_type *f = nullptr, counter_type l = 1, counter_type c = 1)
{
begin.initialize(f, l, c);
end = begin;
}
/** \name Line and Column related manipulators
** \{ */
public:
/// Reset initial location to final location.
void step()
{
begin = end;
}
/// Extend the current location to the COUNT next columns.
void columns(counter_type count = 1)
{
end += count;
}
/// Extend the current location to the COUNT next lines.
void lines(counter_type count = 1)
{
end.lines(count);
}
/** \} */
public:
auto print() const -> std::string
{
return *begin.filename + ":" + std::to_string(begin.line) + ":" + std::to_string(begin.column);
}
auto label() const -> std::string
{
return utils::string::va("loc_%X", begin.line);
}
public:
/// Beginning of the located region.
position begin;
/// End of the located region.
position end;
};
/// Join two locations, in place.
inline location& operator+=(location &res, const location &end)
{
res.end = end.end;
return res;
}
/// Join two locations.
inline location operator+(location res, const location &end)
{
return res += end;
}
/// Add \a width columns to the end position, in place.
inline location& operator+=(location &res, location::counter_type width)
{
res.columns(width);
return res;
}
/// Add \a width columns to the end position.
inline location operator+(location res, location::counter_type width)
{
return res += width;
}
/// Subtract \a width columns to the end position, in place.
inline location& operator-=(location &res, location::counter_type width)
{
return res += -width;
}
/// Subtract \a width columns to the end position.
inline location operator-(location res, location::counter_type width)
{
return res -= width;
}
/** \brief Intercept output stream redirection.
** \param ostr the destination output stream
** \param loc a reference to the location to redirect
**
** Avoid duplicate information.
*/
template <typename YYChar>
std::basic_ostream<YYChar>& operator<<(std::basic_ostream<YYChar> &ostr, const location &loc)
{
location::counter_type end_col = 0 < loc.end.column ? loc.end.column - 1 : 0;
ostr << loc.begin;
if (loc.end.filename && (!loc.begin.filename || *loc.begin.filename != *loc.end.filename))
ostr << '-' << loc.end.filename << ':' << loc.end.line << '.' << end_col;
else if (loc.begin.line < loc.end.line)
ostr << '-' << loc.end.line << '.' << end_col;
else if (loc.begin.column < end_col)
ostr << '-' << end_col;
return ostr;
}
} // namespace xsk::gsc

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#include "stdafx.hpp"
namespace xsk::gsc
{
} // namespace xsk::gsc

View File

@ -1,67 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::gsc
{
using read_cb_type = std::function<std::vector<std::uint8_t>(const std::string&)>;
enum class build
{
dev,
prod,
};
enum class abort_t
{
abort_none = 0,
abort_continue = 1,
abort_break = 2,
abort_return = 3,
};
struct include_t
{
std::string name;
std::vector<std::string> funcs;
include_t(const std::string& name, const std::vector<std::string>& funcs) : name(name), funcs(funcs) {}
};
struct animtree_t
{
std::string name;
bool loaded;
};
struct instruction
{
using ptr = std::unique_ptr<instruction>;
std::uint32_t index;
std::uint32_t size;
std::uint8_t opcode;
std::vector<std::string> data;
instruction() : index(0), size(0), opcode(0xFF) {}
};
struct function
{
using ptr = std::unique_ptr<function>;
std::uint32_t index;
std::uint32_t size;
std::uint32_t id;
std::string name;
std::vector<instruction::ptr> instructions;
std::unordered_map<std::uint32_t, std::string> labels;
function() : index(0), size(0), id(0) {}
};
} // namespace xsk::gsc

View File

@ -1,36 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
#include "utils/file.hpp"
#include "utils/string.hpp"
#include "utils/byte_buffer.hpp"
#include "utils/compression.hpp"
#include "gsc/location.hpp"
#include "gsc/types.hpp"
#include "gsc/asset.hpp"
#include "gsc/block.hpp"
#include "gsc/nodetree.hpp"
#include "gsc/interfaces/exception.hpp"
#include "gsc/interfaces/assembler.hpp"
#include "gsc/interfaces/disassembler.hpp"
#include "gsc/interfaces/compiler.hpp"
#include "gsc/interfaces/decompiler.hpp"
#include "gsc/interfaces/context.hpp"
#include "arc/location.hpp"
#include "arc/types.hpp"
#include "arc/block.hpp"
#include "arc/nodetree.hpp"
#include "arc/interfaces/exception.hpp"
#include "arc/interfaces/assembler.hpp"
#include "arc/interfaces/disassembler.hpp"
#include "arc/interfaces/compiler.hpp"
#include "arc/interfaces/decompiler.hpp"
#include "arc/interfaces/context.hpp"

View File

@ -1,123 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#include "stdafx.hpp"
namespace xsk::utils
{
byte_buffer::byte_buffer()
{
data_.resize(0x100000);
std::fill(data_.begin(), data_.end(), '\0');
size_ = static_cast<std::uint32_t>(data_.size());
pos_ = 0;
}
byte_buffer::byte_buffer(std::uint32_t size)
{
data_.resize(size);
std::fill(data_.begin(), data_.end(), '\0');
size_ = size;
pos_ = 0;
}
byte_buffer::byte_buffer(const std::vector<std::uint8_t>& data)
{
data_ = data;
size_ = static_cast<std::uint32_t>(data_.size());
pos_ = 0;
}
byte_buffer::~byte_buffer()
{
data_.clear();
size_ = 0;
pos_ = 0;
}
void byte_buffer::clear()
{
std::fill(data_.begin(), data_.end(), '\0');
}
auto byte_buffer::is_avail() -> bool
{
return (pos_ < size_) ? true : false;
}
void byte_buffer::seek(std::uint32_t count)
{
pos_ += count;
}
void byte_buffer::seek_neg(std::uint32_t count)
{
pos_ -= count;
}
void byte_buffer::write_string(const std::string& data)
{
if (pos_ + data.size() > size_) return;
std::memcpy(reinterpret_cast<void*>(data_.data() + pos_), data.data(), data.size());
pos_ += static_cast<std::uint32_t>(data.size());
}
void byte_buffer::write_c_string(const std::string& data)
{
if (pos_ + data.size() >= size_) return;
std::memcpy(reinterpret_cast<void*>(data_.data() + pos_), data.data(), data.size());
pos_ += static_cast<std::uint32_t>(data.size() + 1);
}
auto byte_buffer::read_c_string() -> std::string
{
auto ret = std::string(reinterpret_cast<const char*>(data_.data() + pos_));
pos_ += static_cast<std::uint32_t>(ret.size() + 1);
return ret;
}
auto byte_buffer::print_bytes(std::uint32_t pos, std::uint32_t count) -> std::string
{
std::string data {};
for (auto i = pos; i < pos + count; i++)
{
data = utils::string::va("%s %02X", data.data(), (*reinterpret_cast<std::uint8_t*>(data_.data() + i)));
}
return data;
}
auto byte_buffer::pos() -> std::uint32_t
{
return pos_;
}
void byte_buffer::pos(std::uint32_t pos)
{
if (pos >= 0 && pos <= size_)
{
pos_ = pos;
}
}
auto byte_buffer::align(std::uint32_t size) -> std::uint32_t
{
auto pos = pos_;
pos_ = (pos_ + (size - 1)) & ~(size - 1);
return pos_ - pos;
}
auto byte_buffer::buffer() -> std::vector<std::uint8_t>&
{
return data_;
}
} // namespace xsk::utils

View File

@ -1,93 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::utils
{
class byte_buffer
{
public:
using ptr = std::unique_ptr<byte_buffer>;
private:
std::vector<std::uint8_t> data_;
std::uint32_t size_;
std::uint32_t pos_;
public:
byte_buffer();
byte_buffer(std::uint32_t size);
byte_buffer(const std::vector<std::uint8_t>& data);
~byte_buffer();
template <typename T>
auto read() -> T
{
if (pos_ + sizeof(T) > size_) return T{};
auto ret = *reinterpret_cast<T*>(data_.data() + pos_);
pos_ += sizeof(T);
return ret;
}
template <typename T>
void write(T data)
{
if (pos_ + sizeof(T) > size_) return;
T* mem = reinterpret_cast<T*>(data_.data() + pos_);
std::memcpy(mem, &data, sizeof(T));
pos_ += sizeof(T);
}
template <typename T>
auto read_endian() -> T
{
if (pos_ + sizeof(T) > size_) return T{};
std::array<std::uint8_t, sizeof(T)> mem;
for (auto i = 0u; i < sizeof(T); i++)
{
mem[i] = reinterpret_cast<std::uint8_t*>(data_.data() + pos_)[sizeof(T) - 1 - i];
}
pos_ += sizeof(T);
return *reinterpret_cast<T*>(mem.data());
}
template <typename T>
void write_endian(T data)
{
if (pos_ + sizeof(T) > size_) return;
auto* mem = data_.data() + pos_;
for (auto i = 0u; i < sizeof(T); i++)
{
mem[i] = reinterpret_cast<std::uint8_t*>(&data)[sizeof(T) - 1 - i];
}
pos_ += sizeof(T);
}
void clear();
auto is_avail() -> bool;
void seek(std::uint32_t count);
void seek_neg(std::uint32_t count);
void write_string(const std::string& data);
void write_c_string(const std::string& data);
auto read_c_string() -> std::string;
auto print_bytes(std::uint32_t pos, std::uint32_t count) -> std::string;
auto pos() -> std::uint32_t;
void pos(std::uint32_t pos);
auto align(std::uint32_t size) -> std::uint32_t;
auto buffer() -> std::vector<std::uint8_t>&;
};
} // namespace xsk::utils

View File

@ -1,40 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#include "stdafx.hpp"
#include "zlib.h"
namespace xsk::utils
{
auto zlib::compress(const std::vector<std::uint8_t>& data) -> std::vector<std::uint8_t>
{
auto length = compressBound(static_cast<uLong>(data.size()));
std::vector<std::uint8_t> output;
output.resize(length);
auto result = compress2(reinterpret_cast<Bytef*>(output.data()), &length, reinterpret_cast<const Bytef*>(data.data()), static_cast<uLong>(data.size()), Z_BEST_COMPRESSION);
if (result != Z_OK) return {};
output.resize(length);
return output;
}
auto zlib::decompress(const std::vector<std::uint8_t>& data, std::uint32_t length) -> std::vector<std::uint8_t>
{
std::vector<std::uint8_t> output;
output.resize(length);
auto result = uncompress(reinterpret_cast<Bytef*>(output.data()), reinterpret_cast<uLong*>(&length), reinterpret_cast<const Bytef*>(data.data()), static_cast<uLong>(data.size()));
if (result != Z_OK) return {};
return output;
}
} // namespace xsk::uitls

View File

@ -1,18 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::utils
{
class zlib
{
public:
static auto compress(const std::vector<std::uint8_t>& data) -> std::vector<std::uint8_t>;
static auto decompress(const std::vector<std::uint8_t>& data, std::uint32_t length) -> std::vector<std::uint8_t>;
};
} // namespace xsk::utils

View File

@ -1,73 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#include "stdafx.hpp"
namespace xsk::utils
{
auto file::read(const std::string& file) -> std::vector<std::uint8_t>
{
std::vector<std::uint8_t> data;
std::ifstream stream(file, std::ios::binary);
if (!stream.good() && !stream.is_open())
{
throw std::runtime_error("Couldn't open file " + file);
}
stream.seekg(0, std::ios::end);
std::streamsize size = stream.tellg();
stream.seekg(0, std::ios::beg);
if (size > -1)
{
data.resize(static_cast<uint32_t>(size));
stream.read(reinterpret_cast<char*>(data.data()), size);
}
stream.close();
return data;
}
void file::save(const std::string& file, const std::vector<std::uint8_t>& data)
{
const auto pos = file.find_last_of("/\\");
if (pos != std::string::npos)
{
std::filesystem::create_directories(file.substr(0, pos));
}
std::ofstream stream(file, std::ios::binary | std::ofstream::out);
if (stream.is_open())
{
stream.write(reinterpret_cast<const char*>(data.data()), data.size());
stream.close();
}
}
auto file::length(const std::string& file) -> size_t
{
auto stream = std::ifstream(file, std::ios::binary);
if (stream.good())
{
stream.seekg(0, std::ios::end);
return static_cast<size_t>(stream.tellg());
}
return 0;
}
auto file::exists(const std::string& file) -> bool
{
return std::filesystem::exists(file);
}
} // namespace xsk::utils

View File

@ -1,20 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::utils
{
class file
{
public:
static auto read(const std::string& file) -> std::vector<std::uint8_t>;
static void save(const std::string& file, const std::vector<std::uint8_t>& data);
static auto length(const std::string& file) -> size_t;
static auto exists(const std::string& file) -> bool;
};
} // namespace xsk::utils

View File

@ -1,43 +0,0 @@
// Copyright 2022 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::utils
{
class string
{
public:
template <typename ... Args>
static auto va(const std::string& format, Args ... args) -> std::string
{
size_t size = snprintf(nullptr, 0, format.data(), args ...) + 1;
std::vector<char> buf;
buf.resize(size);
snprintf(buf.data(), size, format.data(), args ...);
return std::string(buf.data(), buf.data() + size - 1);
}
static auto oct_to_dec(const char* str) -> std::string;
static auto bin_to_dec(const char* str) -> std::string;
static auto hex_to_dec(const char* str) -> std::string;
static auto iequals(const std::string& a, const std::string& b) -> bool;
static auto is_number(const std::string& s) -> bool;
static auto is_hex_number(const std::string& s) -> bool;
static auto to_lower(const std::string& input) -> std::string;
static auto to_code(const std::string& input) -> std::string;
static auto to_literal(const std::string& input) -> std::string;
static auto fordslash(const std::string& s) -> std::string;
static auto backslash(const std::string& s) -> std::string;
static auto quote(const std::string& s, bool single = true) -> std::string;
static auto unquote(const std::string& s) -> std::string;
static auto split(std::string& str, char delimiter) -> std::vector<std::string>;
static auto clean_buffer_lines(std::vector<std::uint8_t>& buffer) -> std::vector<std::string>;
static auto parse_code(std::string& line) -> std::vector<std::string>;
static auto float_string(float value) -> std::string;
};
} // namespace xsk::utils

44
src/utils/zlib.cpp Normal file
View File

@ -0,0 +1,44 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#include "stdinc.hpp"
#include "zlib.hpp"
#include "zlib.h"
namespace xsk::utils
{
auto zlib::compress(std::vector<u8> const& data) -> std::vector<u8>
{
auto length = compressBound(static_cast<uLong>(data.size()));
auto output = std::vector<u8>{};
output.resize(length);
auto result = compress2(reinterpret_cast<Bytef*>(output.data()), &length, reinterpret_cast<const Bytef*>(data.data()), static_cast<uLong>(data.size()), Z_BEST_COMPRESSION);
if (result == Z_OK)
{
output.resize(length);
return output;
}
throw std::runtime_error(fmt::format("zlib compress error {}", result));
}
auto zlib::decompress(std::vector<u8> const& data, u32 length) -> std::vector<u8>
{
auto output = std::vector<u8>{};
output.resize(length);
auto result = uncompress(reinterpret_cast<Bytef*>(output.data()), reinterpret_cast<uLongf*>(&length), reinterpret_cast<const Bytef*>(data.data()), static_cast<uLong>(data.size()));
if (result == Z_OK)
return output;
throw std::runtime_error(fmt::format("zlib decompress error {}", result));
}
} // namespace xsk::uitls

18
src/utils/zlib.hpp Normal file
View File

@ -0,0 +1,18 @@
// Copyright 2023 xensik. All rights reserved.
//
// Use of this source code is governed by a GNU GPLv3 license
// that can be found in the LICENSE file.
#pragma once
namespace xsk::utils
{
class zlib
{
public:
static auto compress(std::vector<u8> const& data) -> std::vector<u8>;
static auto decompress(std::vector<u8> const& data, u32 length) -> std::vector<u8>;
};
} // namespace xsk::utils