File ConfigParser.cpp
File List > benchmark > ConfigParser.cpp
Go to the documentation of this file
// ConfigParser.cpp
//
// Lit un JSON et le met "en ligne" sous forme d'argv pour CLI11.
//
// Regles :
// - cle "input" ou "output" -> --key value(s)
// - cle "parameters" (a tout niveau) -> cle ignoree, chaque cle du premier
// niveau devient --key, suivie des
// valeurs feuilles de son sous-arbre
// (cles internes ignorees)
// - autre cle scalaire (hors mode parameters) -> juste la valeur
// - autre objet -> cle ignoree, on recurse
//
// Forward-declaration a coller dans main.cpp :
//
// #include <string>
// #include <vector>
// std::vector<char*> getConfigJSON(const std::string& filepath);
//
#include <nlohmann/json.hpp>
#include <fstream>
#include <stdexcept>
#include <string>
#include <vector>
using json = nlohmann::ordered_json;
namespace {
// Storage statique : les char* retournes pointent ici.
static std::vector<std::string> g_argsStorage;
std::string toFlag(const std::string& key) {
return key.size() == 1 ? "-" + key : "--" + key;
}
std::string toString(const json& v) {
if (v.is_string()) return v.get<std::string>();
return v.dump(); // nombres, booleens, etc.
}
void appendLeafValues(const json& v, std::vector<std::string>& out) {
if (v.is_null()) return;
if (v.is_array()) {
for (const auto& item : v) appendLeafValues(item, out);
return;
}
if (v.is_object()) {
for (auto it = v.begin(); it != v.end(); ++it) {
appendLeafValues(it.value(), out);
}
return;
}
out.push_back(toString(v));
}
// Aplatit recursivement le JSON dans `out`.
void flatten(const json& v, std::vector<std::string>& out) {
if (!v.is_object()) return;
for (auto it = v.begin(); it != v.end(); ++it) {
const std::string& key = it.key();
const json& val = it.value();
if (val.is_null()) continue;
// Cas special : "input" / "output" -> toujours --key value(s)
if (key == "input" || key == "output") {
out.push_back(toFlag(key));
if (val.is_array()) {
for (const auto& x : val) out.push_back(toString(x));
}
else if (!val.is_object()) {
out.push_back(toString(val));
}
continue;
}
// Cas special : "parameters" -> cle ignoree, mode parameters active
if (key == "parameters") {
if (val.is_object()) {
for (auto paramIt = val.begin(); paramIt != val.end(); ++paramIt) {
out.push_back(toFlag(paramIt.key()));
appendLeafValues(paramIt.value(), out);
}
}
else if (val.is_array()) {
for (const auto& item : val) {
if (!item.is_object()) continue;
for (auto paramIt = item.begin(); paramIt != item.end(); ++paramIt) {
out.push_back(toFlag(paramIt.key()));
appendLeafValues(paramIt.value(), out);
}
}
}
continue;
}
// Cas general
if (val.is_object()) {
// On saute la cle parente, on aplatit le contenu.
flatten(val, out);
}
else if (val.is_array()) {
if (!val.empty() && val.front().is_object()) {
// Tableau d'objets : on aplatit chaque objet.
for (const auto& item : val) flatten(item, out);
}
else {
// Tableau de scalaires.
for (const auto& x : val) out.push_back(toString(x));
}
}
else {
// Scalaire.
out.push_back(toString(val));
}
}
}
}
std::vector<char*> getConfigJSON(const std::string& filepath) {
std::ifstream file(filepath);
if (!file.is_open()) {
throw std::runtime_error("Cannot open config file: " + filepath);
}
json data;
file >> data;
g_argsStorage.clear();
g_argsStorage.push_back("argos_benchmark"); // argv[0]
flatten(data, g_argsStorage);
std::vector<char*> argv;
argv.reserve(g_argsStorage.size());
for (auto& s : g_argsStorage) argv.push_back(s.data());
return argv;
}