new pack system

This commit is contained in:
d1str4ught
2025-09-21 05:28:55 +02:00
parent 775cb2f927
commit 5b1d3c6bce
100 changed files with 5269 additions and 5825 deletions

View File

@@ -0,0 +1,11 @@
file(GLOB_RECURSE FILE_SOURCES "*.h" "*.c" "*.cpp")
add_library(PackLib STATIC ${FILE_SOURCES})
target_link_libraries(PackLib
libzstd_static
cryptopp-static
mio
)
GroupSourcesByFolder(PackLib)

71
src/PackLib/Pack.cpp Normal file
View File

@@ -0,0 +1,71 @@
#include "Pack.h"
#include <zstd.h>
bool CPack::Open(const std::string& path, TPackFileMap& entries)
{
std::error_code ec;
m_file.map(path, ec);
if (ec) {
return false;
}
size_t file_size = m_file.size();
if (file_size < sizeof(TPackFileHeader)) {
return false;
}
memcpy(&m_header, m_file.data(), sizeof(TPackFileHeader));
m_decryption.SetKeyWithIV(PACK_KEY.data(), PACK_KEY.size(), m_header.iv, CryptoPP::Camellia::BLOCKSIZE);
if (file_size < sizeof(TPackFileHeader) + m_header.entry_num * sizeof(TPackFileEntry)) {
return false;
}
for (size_t i = 0; i < m_header.entry_num; i++) {
TPackFileEntry entry;
memcpy(&entry, m_file.data() + sizeof(TPackFileHeader) + i * sizeof(TPackFileEntry), sizeof(TPackFileEntry));
m_decryption.ProcessData((CryptoPP::byte*)&entry, (CryptoPP::byte*)&entry, sizeof(TPackFileEntry));
entries[entry.file_name] = std::make_pair(shared_from_this(), entry);
if (file_size < m_header.data_begin + entry.offset + entry.compressed_size) {
return false;
}
}
return true;
}
bool CPack::GetFile(const TPackFileEntry& entry, TPackFile& result)
{
result.resize(entry.file_size);
size_t offset = m_header.data_begin + entry.offset;
switch (entry.encryption)
{
case 0: {
size_t decompressed_size = ZSTD_decompress(result.data(), result.size(), m_file.data() + offset, entry.compressed_size);
if (decompressed_size != entry.file_size) {
return false;
}
} break;
case 1: {
std::vector<uint8_t> compressed_data(entry.compressed_size);
memcpy(compressed_data.data(), m_file.data() + offset, entry.compressed_size);
m_decryption.Resynchronize(entry.iv, sizeof(entry.iv));
m_decryption.ProcessData(compressed_data.data(), compressed_data.data(), entry.compressed_size);
size_t decompressed_size = ZSTD_decompress(result.data(), result.size(), compressed_data.data(), compressed_data.size());
if (decompressed_size != entry.file_size) {
return false;
}
} break;
default: return false;
}
return true;
}

21
src/PackLib/Pack.h Normal file
View File

@@ -0,0 +1,21 @@
#pragma once
#include <string>
#include <mio/mmap.hpp>
#include "config.h"
class CPack : public std::enable_shared_from_this<CPack>
{
public:
CPack() = default;
~CPack() = default;
bool Open(const std::string& path, TPackFileMap& entries);
bool GetFile(const TPackFileEntry& entry, TPackFile& result);
private:
TPackFileHeader m_header;
mio::mmap_source m_file;
CryptoPP::CTR_Mode<CryptoPP::Camellia>::Decryption m_decryption;
};

View File

@@ -0,0 +1,40 @@
#include "PackManager.h"
bool CPackManager::AddPack(const std::string& path)
{
std::shared_ptr<CPack> pack = std::make_shared<CPack>();
return pack->Open(path, m_entries);
}
bool CPackManager::GetFile(std::string_view path, TPackFile& result)
{
thread_local std::string buf;
NormalizePath(path, buf);
auto it = m_entries.find(buf);
if (it != m_entries.end()) {
return it->second.first->GetFile(it->second.second, result);
}
return false;
}
bool CPackManager::IsExist(std::string_view path) const
{
thread_local std::string buf;
NormalizePath(path, buf);
auto it = m_entries.find(buf);
return it != m_entries.end();
}
void CPackManager::NormalizePath(std::string_view in, std::string& out) const
{
out.resize(in.size());
for (std::size_t i = 0; i < out.size(); ++i) {
if (in[i] == '\\')
out[i] = '/';
else
out[i] = static_cast<char>(std::tolower(in[i]));
}
}

22
src/PackLib/PackManager.h Normal file
View File

@@ -0,0 +1,22 @@
#pragma once
#include <unordered_map>
#include "EterBase/Singleton.h"
#include "Pack.h"
class CPackManager : public CSingleton<CPackManager>
{
public:
CPackManager() = default;
virtual ~CPackManager() = default;
bool AddPack(const std::string& path);
bool GetFile(std::string_view path, TPackFile& result);
bool IsExist(std::string_view path) const;
private:
void NormalizePath(std::string_view in, std::string& out) const;
private:
TPackFileMap m_entries;
};

43
src/PackLib/config.h Normal file
View File

@@ -0,0 +1,43 @@
#pragma once
#include <cstdint>
#include <array>
#include <vector>
#include <string>
#include <memory>
#include <unordered_map>
#include <gcm.h>
#include <modes.h>
#include <osrng.h>
#include <secblock.h>
#include <camellia.h>
constexpr std::array<uint8_t, 32> PACK_KEY = {
0x00,0x11,0x22,0x33, 0x44,0x55,0x66,0x77,
0x88,0x99,0xAA,0xBB, 0xCC,0xDD,0xEE,0xFF,
0x01,0x23,0x45,0x67, 0x89,0xAB,0xCD,0xEF,
0xFE,0xDC,0xBA,0x98, 0x76,0x54,0x32,0x10
};
#pragma pack(push, 1)
struct TPackFileHeader
{
uint64_t entry_num;
uint64_t data_begin;
uint8_t iv[CryptoPP::Camellia::BLOCKSIZE];
};
struct TPackFileEntry
{
char file_name[FILENAME_MAX+1];
uint64_t offset;
uint64_t file_size;
uint64_t compressed_size;
uint8_t encryption;
uint8_t iv[CryptoPP::Camellia::BLOCKSIZE];
};
#pragma pack(pop)
class CPack;
using TPackFile = std::vector<uint8_t>;
using TPackFileMapEntry = std::pair<std::shared_ptr<CPack>, TPackFileEntry>;
using TPackFileMap = std::unordered_map<std::string, TPackFileMapEntry>;