linter; manage_hiscore i resource_loader
This commit is contained in:
+112
-89
@@ -3,6 +3,7 @@
|
|||||||
#include <SDL3/SDL.h> // Para SDL_ReadIO, SDL_WriteIO, SDL_CloseIO, SDL_GetError, SDL_IOFromFile, SDL_LogError, SDL_LogCategory, SDL_LogInfo
|
#include <SDL3/SDL.h> // Para SDL_ReadIO, SDL_WriteIO, SDL_CloseIO, SDL_GetError, SDL_IOFromFile, SDL_LogError, SDL_LogCategory, SDL_LogInfo
|
||||||
|
|
||||||
#include <algorithm> // Para __sort_fn, sort
|
#include <algorithm> // Para __sort_fn, sort
|
||||||
|
#include <array> // Para array
|
||||||
#include <functional> // Para identity
|
#include <functional> // Para identity
|
||||||
#include <iterator> // Para distance
|
#include <iterator> // Para distance
|
||||||
#include <ranges> // Para __find_if_fn, find_if
|
#include <ranges> // Para __find_if_fn, find_if
|
||||||
@@ -109,117 +110,41 @@ auto ManageHiScoreTable::loadFromFile(const std::string& file_path) -> bool {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Table temp_table; // Tabla temporal para no corromper la actual si hay errores
|
// Validar header (magic number + version + table size)
|
||||||
bool success = true;
|
if (!validateMagicNumber(file, file_path)) {
|
||||||
|
|
||||||
// Validación 1: Verificar magic number "CCAE"
|
|
||||||
char magic[4];
|
|
||||||
if (SDL_ReadIO(file, magic, 4) != 4 || magic[0] != 'C' || magic[1] != 'C' || magic[2] != 'A' || magic[3] != 'E') {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Invalid magic number in %s - file may be corrupted or old format", getFileName(file_path).c_str());
|
|
||||||
SDL_CloseIO(file);
|
SDL_CloseIO(file);
|
||||||
clear();
|
clear();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validación 2: Verificar versión del formato
|
if (!validateVersion(file, file_path)) {
|
||||||
int version = 0;
|
|
||||||
if (SDL_ReadIO(file, &version, sizeof(int)) != sizeof(int)) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Cannot read version in %s", getFileName(file_path).c_str());
|
|
||||||
SDL_CloseIO(file);
|
SDL_CloseIO(file);
|
||||||
clear();
|
clear();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version != FILE_VERSION) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Unsupported file version %d in %s (expected %d)", version, getFileName(file_path).c_str(), FILE_VERSION);
|
|
||||||
SDL_CloseIO(file);
|
|
||||||
clear();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validación 3: Leer y validar tamaño de la tabla
|
|
||||||
int table_size = 0;
|
int table_size = 0;
|
||||||
if (SDL_ReadIO(file, &table_size, sizeof(int)) != sizeof(int)) {
|
if (!readTableSize(file, file_path, table_size)) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Cannot read table size in %s", getFileName(file_path).c_str());
|
|
||||||
SDL_CloseIO(file);
|
SDL_CloseIO(file);
|
||||||
clear();
|
clear();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (table_size < 0 || table_size > MAX_TABLE_SIZE) {
|
// Leer todas las entradas
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Invalid table size %d in %s (expected 0-%d)", table_size, getFileName(file_path).c_str(), MAX_TABLE_SIZE);
|
Table temp_table;
|
||||||
SDL_CloseIO(file);
|
bool success = true;
|
||||||
clear();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Leer cada entrada con validaciones
|
|
||||||
for (int i = 0; i < table_size; ++i) {
|
for (int i = 0; i < table_size; ++i) {
|
||||||
HiScoreEntry entry;
|
HiScoreEntry entry;
|
||||||
|
if (!readEntry(file, file_path, i, entry)) {
|
||||||
// Validación 4: Leer y validar puntuación
|
|
||||||
if (SDL_ReadIO(file, &entry.score, sizeof(int)) != sizeof(int)) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Cannot read score for entry %d in %s", i, getFileName(file_path).c_str());
|
|
||||||
success = false;
|
success = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry.score < 0 || entry.score > MAX_SCORE) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Invalid score %d for entry %d in %s", entry.score, i, getFileName(file_path).c_str());
|
|
||||||
success = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validación 5: Leer y validar tamaño del nombre
|
|
||||||
int name_size = 0;
|
|
||||||
if (SDL_ReadIO(file, &name_size, sizeof(int)) != sizeof(int)) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Cannot read name size for entry %d in %s", i, getFileName(file_path).c_str());
|
|
||||||
success = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name_size < 0 || name_size > MAX_NAME_SIZE) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Invalid name size %d for entry %d in %s", name_size, i, getFileName(file_path).c_str());
|
|
||||||
success = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Leer el nombre
|
|
||||||
std::vector<char> name_buffer(name_size + 1);
|
|
||||||
if (SDL_ReadIO(file, name_buffer.data(), name_size) != static_cast<size_t>(name_size)) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Cannot read name for entry %d in %s", i, getFileName(file_path).c_str());
|
|
||||||
success = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
name_buffer[name_size] = '\0';
|
|
||||||
entry.name = std::string(name_buffer.data());
|
|
||||||
|
|
||||||
// Validación 6: Leer one_credit_complete
|
|
||||||
int occ_value = 0;
|
|
||||||
if (SDL_ReadIO(file, &occ_value, sizeof(int)) != sizeof(int)) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Cannot read one_credit_complete for entry %d in %s", i, getFileName(file_path).c_str());
|
|
||||||
success = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
entry.one_credit_complete = (occ_value != 0);
|
|
||||||
|
|
||||||
temp_table.push_back(entry);
|
temp_table.push_back(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validación 7: Verificar checksum
|
// Verificar checksum
|
||||||
if (success) {
|
if (success) {
|
||||||
unsigned int stored_checksum = 0;
|
success = verifyChecksum(file, file_path, temp_table);
|
||||||
if (SDL_ReadIO(file, &stored_checksum, sizeof(unsigned int)) != sizeof(unsigned int)) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Cannot read checksum in %s", getFileName(file_path).c_str());
|
|
||||||
success = false;
|
|
||||||
} else {
|
|
||||||
unsigned int calculated_checksum = calculateChecksum(temp_table);
|
|
||||||
if (stored_checksum != calculated_checksum) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Checksum mismatch in %s (stored: 0x%08X, calculated: 0x%08X) - file is corrupted",
|
|
||||||
getFileName(file_path).c_str(), stored_checksum, calculated_checksum);
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_CloseIO(file);
|
SDL_CloseIO(file);
|
||||||
@@ -236,6 +161,104 @@ auto ManageHiScoreTable::loadFromFile(const std::string& file_path) -> bool {
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Métodos auxiliares privados para loadFromFile
|
||||||
|
|
||||||
|
auto ManageHiScoreTable::validateMagicNumber(SDL_IOStream* file, const std::string& file_path) -> bool {
|
||||||
|
std::array<char, 4> magic;
|
||||||
|
if (SDL_ReadIO(file, magic.data(), 4) != 4 || magic[0] != 'C' || magic[1] != 'C' || magic[2] != 'A' || magic[3] != 'E') {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Invalid magic number in %s - file may be corrupted or old format", getFileName(file_path).c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ManageHiScoreTable::validateVersion(SDL_IOStream* file, const std::string& file_path) -> bool {
|
||||||
|
int version = 0;
|
||||||
|
if (SDL_ReadIO(file, &version, sizeof(int)) != sizeof(int)) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Cannot read version in %s", getFileName(file_path).c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version != FILE_VERSION) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Unsupported file version %d in %s (expected %d)", version, getFileName(file_path).c_str(), FILE_VERSION);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ManageHiScoreTable::readTableSize(SDL_IOStream* file, const std::string& file_path, int& table_size) -> bool {
|
||||||
|
if (SDL_ReadIO(file, &table_size, sizeof(int)) != sizeof(int)) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Cannot read table size in %s", getFileName(file_path).c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (table_size < 0 || table_size > MAX_TABLE_SIZE) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Invalid table size %d in %s (expected 0-%d)", table_size, getFileName(file_path).c_str(), MAX_TABLE_SIZE);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ManageHiScoreTable::readEntry(SDL_IOStream* file, const std::string& file_path, int index, HiScoreEntry& entry) -> bool {
|
||||||
|
// Leer y validar puntuación
|
||||||
|
if (SDL_ReadIO(file, &entry.score, sizeof(int)) != sizeof(int)) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Cannot read score for entry %d in %s", index, getFileName(file_path).c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry.score < 0 || entry.score > MAX_SCORE) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Invalid score %d for entry %d in %s", entry.score, index, getFileName(file_path).c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Leer y validar tamaño del nombre
|
||||||
|
int name_size = 0;
|
||||||
|
if (SDL_ReadIO(file, &name_size, sizeof(int)) != sizeof(int)) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Cannot read name size for entry %d in %s", index, getFileName(file_path).c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name_size < 0 || name_size > MAX_NAME_SIZE) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Invalid name size %d for entry %d in %s", name_size, index, getFileName(file_path).c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Leer el nombre
|
||||||
|
std::vector<char> name_buffer(name_size + 1);
|
||||||
|
if (SDL_ReadIO(file, name_buffer.data(), name_size) != static_cast<size_t>(name_size)) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Cannot read name for entry %d in %s", index, getFileName(file_path).c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
name_buffer[name_size] = '\0';
|
||||||
|
entry.name = std::string(name_buffer.data());
|
||||||
|
|
||||||
|
// Leer one_credit_complete
|
||||||
|
int occ_value = 0;
|
||||||
|
if (SDL_ReadIO(file, &occ_value, sizeof(int)) != sizeof(int)) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Cannot read one_credit_complete for entry %d in %s", index, getFileName(file_path).c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
entry.one_credit_complete = (occ_value != 0);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ManageHiScoreTable::verifyChecksum(SDL_IOStream* file, const std::string& file_path, const Table& temp_table) -> bool {
|
||||||
|
unsigned int stored_checksum = 0;
|
||||||
|
if (SDL_ReadIO(file, &stored_checksum, sizeof(unsigned int)) != sizeof(unsigned int)) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Cannot read checksum in %s", getFileName(file_path).c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int calculated_checksum = calculateChecksum(temp_table);
|
||||||
|
if (stored_checksum != calculated_checksum) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Checksum mismatch in %s (stored: 0x%08X, calculated: 0x%08X) - file is corrupted",
|
||||||
|
getFileName(file_path).c_str(), stored_checksum, calculated_checksum);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Calcula checksum de la tabla
|
// Calcula checksum de la tabla
|
||||||
auto ManageHiScoreTable::calculateChecksum(const Table& table) -> unsigned int {
|
auto ManageHiScoreTable::calculateChecksum(const Table& table) -> unsigned int {
|
||||||
unsigned int checksum = 0x12345678; // Magic seed
|
unsigned int checksum = 0x12345678; // Magic seed
|
||||||
@@ -250,7 +273,7 @@ auto ManageHiScoreTable::calculateChecksum(const Table& table) -> unsigned int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Checksum de one_credit_complete
|
// Checksum de one_credit_complete
|
||||||
checksum = ((checksum << 5) + checksum) + (entry.one_credit_complete ? 1u : 0u);
|
checksum = ((checksum << 5) + checksum) + (entry.one_credit_complete ? 1U : 0U);
|
||||||
}
|
}
|
||||||
|
|
||||||
return checksum;
|
return checksum;
|
||||||
@@ -263,8 +286,8 @@ auto ManageHiScoreTable::saveToFile(const std::string& file_path) -> bool {
|
|||||||
|
|
||||||
if (file != nullptr) {
|
if (file != nullptr) {
|
||||||
// Escribe magic number "CCAE"
|
// Escribe magic number "CCAE"
|
||||||
const char magic[4] = {'C', 'C', 'A', 'E'};
|
constexpr std::array<char, 4> MAGIC = {'C', 'C', 'A', 'E'};
|
||||||
SDL_WriteIO(file, magic, 4);
|
SDL_WriteIO(file, MAGIC.data(), 4);
|
||||||
|
|
||||||
// Escribe versión del formato
|
// Escribe versión del formato
|
||||||
int version = FILE_VERSION;
|
int version = FILE_VERSION;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <SDL3/SDL.h> // Para SDL_IOStream
|
||||||
|
|
||||||
#include <string> // Para std::string
|
#include <string> // Para std::string
|
||||||
#include <vector> // Para std::vector
|
#include <vector> // Para std::vector
|
||||||
|
|
||||||
@@ -45,6 +47,13 @@ class ManageHiScoreTable {
|
|||||||
Table& table_; // Referencia a la tabla con los records
|
Table& table_; // Referencia a la tabla con los records
|
||||||
|
|
||||||
// --- Métodos privados ---
|
// --- Métodos privados ---
|
||||||
void sort(); // Ordena la tabla
|
void sort(); // Ordena la tabla
|
||||||
static auto calculateChecksum(const Table& table) -> unsigned int; // Calcula checksum de la tabla
|
static auto calculateChecksum(const Table& table) -> unsigned int; // Calcula checksum de la tabla
|
||||||
|
|
||||||
|
// Métodos auxiliares para loadFromFile
|
||||||
|
auto validateMagicNumber(SDL_IOStream* file, const std::string& file_path) -> bool;
|
||||||
|
auto validateVersion(SDL_IOStream* file, const std::string& file_path) -> bool;
|
||||||
|
auto readTableSize(SDL_IOStream* file, const std::string& file_path, int& table_size) -> bool;
|
||||||
|
auto readEntry(SDL_IOStream* file, const std::string& file_path, int index, HiScoreEntry& entry) -> bool;
|
||||||
|
auto verifyChecksum(SDL_IOStream* file, const std::string& file_path, const Table& temp_table) -> bool;
|
||||||
};
|
};
|
||||||
@@ -39,7 +39,7 @@ auto ResourceLoader::initialize(const std::string& pack_file, bool enable_fallba
|
|||||||
}
|
}
|
||||||
delete resource_pack_;
|
delete resource_pack_;
|
||||||
resource_pack_ = nullptr;
|
resource_pack_ = nullptr;
|
||||||
std::cerr << "Failed to load resource pack: " << pack_file << std::endl;
|
std::cerr << "Failed to load resource pack: " << pack_file << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fallback_to_files_) {
|
if (fallback_to_files_) {
|
||||||
|
|||||||
@@ -34,6 +34,6 @@ class ResourceLoader {
|
|||||||
[[nodiscard]] auto getAvailableResources() const -> std::vector<std::string>;
|
[[nodiscard]] auto getAvailableResources() const -> std::vector<std::string>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
auto loadFromFile(const std::string& filename) -> std::vector<uint8_t>;
|
static auto loadFromFile(const std::string& filename) -> std::vector<uint8_t>;
|
||||||
static auto getDataPath(const std::string& filename) -> std::string;
|
static auto getDataPath(const std::string& filename) -> std::string;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user