resource_list: loadFromString delega a parsers en namespace anònim
This commit is contained in:
@@ -16,6 +16,71 @@
|
||||
|
||||
namespace Resource {
|
||||
|
||||
namespace {
|
||||
// Un item del format modern: pot ser string (path) o mapping ({path, required?, absolute?})
|
||||
void parseAssetItem(List& list, const fkyaml::node& item, List::Type type, const std::string& prefix, const std::string& system_folder, const std::string& category, const std::string& type_str) {
|
||||
try {
|
||||
if (item.is_string()) {
|
||||
auto path = List::replaceVariables(item.get_value<std::string>(), prefix, system_folder);
|
||||
list.add(path, type, true, false);
|
||||
return;
|
||||
}
|
||||
if (item.is_mapping() && item.contains("path")) {
|
||||
auto path = List::replaceVariables(item["path"].get_value<std::string>(), prefix, system_folder);
|
||||
const bool REQUIRED = !item.contains("required") || item["required"].get_value<bool>();
|
||||
const bool ABSOLUTE = item.contains("absolute") && item["absolute"].get_value<bool>();
|
||||
list.add(path, type, REQUIRED, ABSOLUTE);
|
||||
return;
|
||||
}
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Warning: Invalid item in type '%s', category '%s', skipping", type_str.c_str(), category.c_str());
|
||||
} catch (const std::exception& e) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error parsing asset in category '%s', type '%s': %s", category.c_str(), type_str.c_str(), e.what());
|
||||
}
|
||||
}
|
||||
|
||||
// (TIPO: [items...]) del format modern. Itera els items i delega a parseAssetItem.
|
||||
void parseModernType(List& list, const fkyaml::node& items_node, List::Type type, const std::string& type_str, const std::string& category, const std::string& prefix, const std::string& system_folder) {
|
||||
if (!items_node.is_sequence()) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Warning: Type '%s' in category '%s' is not a sequence, skipping", type_str.c_str(), category.c_str());
|
||||
return;
|
||||
}
|
||||
for (const auto& item : items_node) {
|
||||
parseAssetItem(list, item, type, prefix, system_folder, category, type_str);
|
||||
}
|
||||
}
|
||||
|
||||
// {type, path, required?, absolute?} del format antic
|
||||
void parseLegacyAsset(List& list, const fkyaml::node& asset, const std::string& category, const std::string& prefix, const std::string& system_folder) {
|
||||
try {
|
||||
if (!asset.contains("type") || !asset.contains("path")) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Warning: Asset in category '%s' missing 'type' or 'path', skipping", category.c_str());
|
||||
return;
|
||||
}
|
||||
auto type_str = asset["type"].get_value<std::string>();
|
||||
auto path = asset["path"].get_value<std::string>();
|
||||
const bool REQUIRED = !asset.contains("required") || asset["required"].get_value<bool>();
|
||||
const bool ABSOLUTE = asset.contains("absolute") && asset["absolute"].get_value<bool>();
|
||||
path = List::replaceVariables(path, prefix, system_folder);
|
||||
list.add(path, List::parseAssetType(type_str), REQUIRED, ABSOLUTE);
|
||||
} catch (const std::exception& e) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error parsing asset in category '%s': %s", category.c_str(), e.what());
|
||||
}
|
||||
}
|
||||
|
||||
// Categoria amb format modern (TIPO → [items]). Itera els tipus.
|
||||
void parseModernCategory(List& list, const fkyaml::node& category_assets, const std::string& category, const std::string& prefix, const std::string& system_folder) {
|
||||
for (auto type_it = category_assets.begin(); type_it != category_assets.end(); ++type_it) {
|
||||
try {
|
||||
auto type_str = type_it.key().get_value<std::string>();
|
||||
const List::Type TYPE = List::parseAssetType(type_str);
|
||||
parseModernType(list, type_it.value(), TYPE, type_str, category, prefix, system_folder);
|
||||
} catch (const std::exception& e) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error parsing type in category '%s': %s", category.c_str(), e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// Singleton
|
||||
List* List::instance = nullptr;
|
||||
|
||||
@@ -160,17 +225,13 @@ namespace Resource {
|
||||
}
|
||||
|
||||
// Carga recursos desde un string de configuración (para release con pack)
|
||||
void List::loadFromString(const std::string& config_content, const std::string& prefix, const std::string& system_folder) { // NOLINT(readability-function-cognitive-complexity)
|
||||
void List::loadFromString(const std::string& config_content, const std::string& prefix, const std::string& system_folder) {
|
||||
try {
|
||||
// Parsear YAML
|
||||
auto yaml = fkyaml::node::deserialize(config_content);
|
||||
|
||||
// Verificar estructura básica
|
||||
if (!yaml.contains("assets")) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Invalid assets.yaml format - missing 'assets' key");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& assets = yaml["assets"];
|
||||
|
||||
// Iterar sobre cada categoría (fonts, palettes, etc.)
|
||||
@@ -179,105 +240,19 @@ namespace Resource {
|
||||
const auto& category_assets = it.value();
|
||||
|
||||
if (category_assets.is_mapping()) {
|
||||
// Nuevo formato: categoría → { TIPO: [paths...], TIPO2: [paths...] }
|
||||
for (auto type_it = category_assets.begin(); type_it != category_assets.end(); ++type_it) {
|
||||
try {
|
||||
auto type_str = type_it.key().get_value<std::string>();
|
||||
Type type = parseAssetType(type_str);
|
||||
const auto& items = type_it.value();
|
||||
|
||||
if (!items.is_sequence()) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Warning: Type '%s' in category '%s' is not a sequence, skipping",
|
||||
type_str.c_str(),
|
||||
category.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const auto& item : items) {
|
||||
try {
|
||||
if (item.is_string()) {
|
||||
// Formato simple: solo el path
|
||||
auto path = replaceVariables(item.get_value<std::string>(), prefix, system_folder);
|
||||
addToMap(path, type, true, false);
|
||||
} else if (item.is_mapping() && item.contains("path")) {
|
||||
// Formato expandido: { path, required?, absolute? }
|
||||
auto path = replaceVariables(item["path"].get_value<std::string>(), prefix, system_folder);
|
||||
bool required = !item.contains("required") || item["required"].get_value<bool>();
|
||||
bool absolute = item.contains("absolute") && item["absolute"].get_value<bool>();
|
||||
addToMap(path, type, required, absolute);
|
||||
} else {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Warning: Invalid item in type '%s', category '%s', skipping",
|
||||
type_str.c_str(),
|
||||
category.c_str());
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Error parsing asset in category '%s', type '%s': %s",
|
||||
category.c_str(),
|
||||
type_str.c_str(),
|
||||
e.what());
|
||||
}
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Error parsing type in category '%s': %s",
|
||||
category.c_str(),
|
||||
e.what());
|
||||
}
|
||||
}
|
||||
parseModernCategory(*this, category_assets, category, prefix, system_folder);
|
||||
} else if (category_assets.is_sequence()) {
|
||||
// Formato antiguo (retrocompatibilidad): categoría → [{type, path}, ...]
|
||||
for (const auto& asset : category_assets) {
|
||||
try {
|
||||
if (!asset.contains("type") || !asset.contains("path")) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Warning: Asset in category '%s' missing 'type' or 'path', skipping",
|
||||
category.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
auto type_str = asset["type"].get_value<std::string>();
|
||||
auto path = asset["path"].get_value<std::string>();
|
||||
bool required = true;
|
||||
bool absolute = false;
|
||||
|
||||
if (asset.contains("required")) {
|
||||
required = asset["required"].get_value<bool>();
|
||||
}
|
||||
if (asset.contains("absolute")) {
|
||||
absolute = asset["absolute"].get_value<bool>();
|
||||
}
|
||||
|
||||
path = replaceVariables(path, prefix, system_folder);
|
||||
Type type = parseAssetType(type_str);
|
||||
addToMap(path, type, required, absolute);
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Error parsing asset in category '%s': %s",
|
||||
category.c_str(),
|
||||
e.what());
|
||||
}
|
||||
}
|
||||
for (const auto& asset : category_assets) { parseLegacyAsset(*this, asset, category, prefix, system_folder); }
|
||||
} else {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Warning: Category '%s' has invalid format, skipping",
|
||||
category.c_str());
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Warning: Category '%s' has invalid format, skipping", category.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Loaded " << file_list_.size() << " assets from YAML config" << '\n';
|
||||
|
||||
} catch (const fkyaml::exception& e) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"YAML parsing error: %s",
|
||||
e.what());
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "YAML parsing error: %s", e.what());
|
||||
} catch (const std::exception& e) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Error loading assets: %s",
|
||||
e.what());
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error loading assets: %s", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,10 @@ namespace Resource {
|
||||
[[nodiscard]] auto getListByType(Type type) const -> std::vector<std::string>;
|
||||
[[nodiscard]] auto exists(const std::string& filename) const -> bool; // Verifica si un asset existe
|
||||
|
||||
// --- Helpers static (públics perquè els fan servir parsers externs del .cpp) ---
|
||||
[[nodiscard]] static auto parseAssetType(const std::string& type_str) -> Type; // Convierte string a tipo
|
||||
[[nodiscard]] static auto replaceVariables(const std::string& path, const std::string& prefix, const std::string& system_folder) -> std::string; // Reemplaza variables en la ruta
|
||||
|
||||
private:
|
||||
// --- Estructuras privadas ---
|
||||
struct Item {
|
||||
@@ -62,11 +66,9 @@ namespace Resource {
|
||||
std::string prefix_; // Prefijo para rutas (${PREFIX})
|
||||
|
||||
// --- Métodos internos ---
|
||||
[[nodiscard]] static auto getTypeName(Type type) -> std::string; // Obtiene el nombre del tipo
|
||||
[[nodiscard]] static auto parseAssetType(const std::string& type_str) -> Type; // Convierte string a tipo
|
||||
void addToMap(const std::string& file_path, Type type, bool required, bool absolute); // Añade archivo al mapa
|
||||
[[nodiscard]] static auto replaceVariables(const std::string& path, const std::string& prefix, const std::string& system_folder) -> std::string; // Reemplaza variables en la ruta
|
||||
static auto parseOptions(const std::string& options, bool& required, bool& absolute) -> void; // Parsea opciones
|
||||
[[nodiscard]] static auto getTypeName(Type type) -> std::string; // Obtiene el nombre del tipo
|
||||
void addToMap(const std::string& file_path, Type type, bool required, bool absolute); // Añade archivo al mapa
|
||||
static auto parseOptions(const std::string& options, bool& required, bool& absolute) -> void; // Parsea opciones
|
||||
|
||||
// --- Constructores y destructor privados (singleton) ---
|
||||
explicit List(std::string executable_path) // Constructor privado
|
||||
|
||||
Reference in New Issue
Block a user