Files
vr-poser/src/AppConfig.cpp
2026-03-15 21:16:36 -04:00

103 lines
3.5 KiB
C++

#include "AppConfig.h"
#include <fstream>
#include <sstream>
#include <iostream>
#include <filesystem>
#include <unistd.h>
#include <vector>
namespace fs = std::filesystem;
// ─────────────────────────────────────────────────────────────────────────────
static std::string trim(const std::string& s) {
const auto start = s.find_first_not_of(" \t\r\n");
if (start == std::string::npos) return {};
const auto end = s.find_last_not_of(" \t\r\n");
return s.substr(start, end - start + 1);
}
static std::string exeDir() {
char buf[4096] = {};
ssize_t n = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
if (n > 0)
return fs::path(std::string(buf, n)).parent_path().string();
return {};
}
// ─────────────────────────────────────────────────────────────────────────────
bool AppConfig::load() {
// Search order: next to exe, then cwd
std::vector<std::string> candidates;
std::string exe = exeDir();
if (!exe.empty())
candidates.push_back(exe + "/assets/config.ini");
candidates.push_back("assets/config.ini");
std::ifstream file;
std::string usedPath;
for (auto& p : candidates) {
file.open(p);
if (file.is_open()) { usedPath = p; break; }
}
if (!file.is_open()) {
std::cerr << "[config] No config.ini found — using defaults.\n";
return false;
}
std::cout << "[config] Loading: " << usedPath << "\n";
std::string section;
std::string line;
while (std::getline(file, line)) {
line = trim(line);
if (line.empty() || line[0] == '#') continue;
if (line.front() == '[' && line.back() == ']') {
section = line.substr(1, line.size() - 2);
continue;
}
auto eq = line.find('=');
if (eq == std::string::npos) continue;
std::string key = trim(line.substr(0, eq));
std::string val = trim(line.substr(eq + 1));
// Strip inline comments
auto hash = val.find('#');
if (hash != std::string::npos)
val = trim(val.substr(0, hash));
std::string fullKey = section.empty() ? key : section + "." + key;
m_values[fullKey] = val;
}
return true;
}
// ─────────────────────────────────────────────────────────────────────────────
std::string AppConfig::getString(const std::string& key,
const std::string& defaultVal) const {
auto it = m_values.find(key);
return it != m_values.end() && !it->second.empty()
? it->second : defaultVal;
}
float AppConfig::getFloat(const std::string& key, float defaultVal) const {
auto it = m_values.find(key);
if (it == m_values.end() || it->second.empty()) return defaultVal;
try { return std::stof(it->second); }
catch (...) { return defaultVal; }
}
int AppConfig::getInt(const std::string& key, int defaultVal) const {
auto it = m_values.find(key);
if (it == m_values.end() || it->second.empty()) return defaultVal;
try { return std::stoi(it->second); }
catch (...) { return defaultVal; }
}