toml++ pour C++ : guide complet avec exemples
1. Qu'est-ce que toml++ et pourquoi l'utiliser ?
TOML (Tom's Obvious Minimal Language) est un format de fichier de configuration conçu comme une alternative à INI, YAML et JSON. Il est pensé pour être extrêmement lisible par l'humain, se mapper sans ambiguïté en tables de hachage et être simple à analyser. Contrairement à YAML, TOML n'autorise aucune ambiguïté (notamment avec l'indentation ou les types de données), et contrairement à JSON, il ne nécessite pas de guillemets pour les clés et supporte les commentaires.
toml++ (également connu sous le nom tomlplusplus) est une bibliothèque moderne, header-only (uniquement des en-têtes) pour analyser et générer des fichiers TOML en C++17 et versions ultérieures. Elle ne nécessite aucune compilation : il suffit d'inclure le fichier d'en-tête pour bénéficier de toutes ses fonctionnalités. Cela en fait un choix idéal pour les projets où la simplicité d'intégration, les performances et le typage strict sont essentiels.
Pourquoi utiliser toml++ ? Premièrement, elle offre un support complet de la spécification TOML v1.0, y compris les tables imbriquées, les tableaux de tables, les dates, les heures et les dates locales. Deuxièmement, elle est conçue avec un fort accent sur la sécurité des types : vous obtenez des valeurs fortement typées (std::string, int64_t, double, bool, toml::date, etc.) et non un objet brut de type JSON. Troisièmement, elle est incroyablement rapide et possède un minimum de dépendances (seulement la bibliothèque standard C++17).
2. Installation
toml++ est une bibliothèque header-only. Cela signifie que vous n'avez pas besoin de la compiler séparément. Il suffit de copier les fichiers d'en-tête dans votre projet et de les inclure.
Méthode 1 : Vcpkg (recommandé pour Windows et Linux)
# Installation via vcpkg
vcpkg install tomlplusplus
# Intégration dans CMakeLists.txt
find_package(tomlplusplus CONFIG REQUIRED)
target_link_libraries(my_project PRIVATE tomlplusplus::tomlplusplus)
Méthode 2 : Conan
# Installation via Conan
conan install tomlplusplus/3.4.0@
# Dans conanfile.txt
[requires]
tomlplusplus/3.4.0
[generators]
CMakeDeps
Méthode 3 : Installation manuelle (la plus simple)
# Téléchargez la dernière version depuis GitHub
wget https://github.com/marzer/tomlplusplus/archive/refs/tags/v3.4.0.tar.gz
tar -xzf v3.4.0.tar.gz
# Copiez le dossier include/toml++ dans votre projet
cp -r tomlplusplus-3.4.0/include/toml++ /chemin/vers/votre/projet/include/
# Dans votre code, incluez simplement :
#include <toml++/toml.h>
Méthode 4 : CMake FetchContent (pour les projets CMake)
include(FetchContent)
FetchContent_Declare(
tomlplusplus
GIT_REPOSITORY https://github.com/marzer/tomlplusplus.git
GIT_TAG v3.4.0
)
FetchContent_MakeAvailable(tomlplusplus)
target_link_libraries(my_project PRIVATE tomlplusplus::tomlplusplus)
3. Démarrage rapide — exemple minimal fonctionnel
Créons un fichier config.toml :
# config.toml
title = "Exemple de configuration"
[server]
host = "localhost"
port = 8080
debug = true
[database]
name = "mydb"
user = "admin"
password = "secret123"
Écrivons maintenant le code C++ pour le lire :
#include <toml++/toml.h>
#include <iostream>
#include <filesystem>
int main() {
// 1. Analyse du fichier
auto config = toml::parse_file("config.toml");
// 2. Lecture des valeurs simples
std::string title = config["title"].value_or("default");
std::cout << "Titre : " << title << std::endl;
// 3. Lecture des tables imbriquées
auto server = config["server"];
std::string host = server["host"].value_or("localhost");
int port = server["port"].value_or(3000);
bool debug = server["debug"].value_or(false);
std::cout << "Serveur : " << host << ":" << port << std::endl;
std::cout << "Mode debug : " << (debug ? "activé" : "désactivé") << std::endl;
// 4. Lecture d'une autre table
auto database = config["database"];
std::string db_name = database["name"].value_or("inconnu");
std::string db_user = database["user"].value_or("inconnu");
std::cout << "Base de données : " << db_name << " (utilisateur : " << db_user << ")" << std::endl;
return 0;
}
Compilez avec :
g++ -std=c++17 -I include/ main.cpp -o programme
./programme
Résultat attendu :
Titre : Exemple de configuration
Serveur : localhost:8080
Mode debug : activé
Base de données : mydb (utilisateur : admin)
4. Méthodes principales de toml++
4.1. Analyse de fichiers
La méthode toml::parse_file() est la plus courante pour charger un fichier TOML :
auto config = toml::parse_file("chemin/vers/fichier.toml");
Pour analyser une chaîne de caractères directement :
std::string contenu = R"(
[exemple]
valeur = 42
)";
auto config = toml::parse(contenu);
4.2. Accès aux valeurs
Utilisez l'opérateur [] pour accéder aux clés. La méthode value_or() permet de fournir une valeur par défaut :
int port = config["serveur"]["port"].value_or(8080);
std::string nom = config["application"]["nom"].value_or("defaut");
bool actif = config["features"]["debug"].value_or(false);
4.3. Gestion des tableaux
Les tableaux TOML sont accessibles via toml::array :
auto& tableau = *config["liste_nombres"].as_array();
for (auto& element : tableau) {
int valeur = element.value_or(0);
std::cout << valeur << std::endl;
}
4.4. Tableaux de tables
Les tableaux de tables sont très utiles pour les listes d'objets :
auto& utilisateurs = *config["utilisateurs"].as_array();
for (auto& utilisateur : utilisateurs) {
std::string nom = utilisateur["nom"].value_or("");
int age = utilisateur["age"].value_or(0);
std::cout << "Utilisateur : " << nom << ", " << age << " ans" << std::endl;
}
4.5. Gestion des dates et heures
TOML supporte nativement les dates et heures. toml++ les mappe vers des types C++ standards :
auto date = config["date_evenement"].value<toml::date>();
auto heure = config["heure_evenement"].value<toml::time>();
auto date_heure = config["timestamp"].value<toml::date_time>();
if (date) {
std::cout << "Année : " << date->year << std::endl;
}
5. Exemple avancé : configuration d'application
Voici un exemple plus complet illustrant l'utilisation de toml++ dans une application réelle :
# app_config.toml
[application]
nom = "MonApp"
version = "2.1.0"
mode = "production"
[base_de_donnees]
hote = "db.example.com"
port = 5432
nom = "app_db"
utilisateur = "app_user"
mot_de_passe = "s3cr3t!"
pool_connexions = 10
[logging]
niveau = "info"
fichier = "/var/log/monapp.log"
rotation = "quotidienne"
[[serveurs]]
nom = "principal"
adresse = "192.168.1.10"
port = 443
ssl = true
[[serveurs]]
nom = "secondaire"
adresse = "192.168.1.11"
port = 80
ssl = false
#include <toml++/toml.h>
#include <iostream>
#include <vector>
#include <string>
struct Serveur {
std::string nom;
std::string adresse;
int port;
bool ssl;
};
int main() {
try {
auto config = toml::parse_file("app_config.toml");
// Configuration application
auto app = config["application"];
std::string nom_app = app["nom"].value_or("Inconnu");
std::string version = app["version"].value_or("0.0.0");
std::string mode = app["mode"].value_or("developpement");
std::cout << "Application : " << nom_app << " v" << version << " (" << mode << ")" << std::endl;
// Configuration base de données
auto db = config["base_de_donnees"];
std::string db_hote = db["hote"].value_or("localhost");
int db_port = db["port"].value_or(5432);
std::string db_nom = db["nom"].value_or("default");
int pool = db["pool_connexions"].value_or(5);
std::cout << "Base de données : " << db_hote << ":" << db_port << "/" << db_nom << " (pool: " << pool << ")" << std::endl;
// Liste des serveurs
std::vector<Serveur> serveurs;
auto& tableau_serveurs = *config["serveurs"].as_array();
for (auto& s : tableau_serveurs) {
Serveur serveur;
serveur.nom = s["nom"].value_or("");
serveur.adresse = s["adresse"].value_or("");
serveur.port = s["port"].value_or(80);
serveur.ssl = s["ssl"].value_or(false);
serveurs.push_back(serveur);
}
std::cout << "Serveurs configurés : " << serveurs.size() << std::endl;
for (const auto& s : serveurs) {
std::cout << " - " << s.nom << " : " << s.adresse << ":" << s.port;
if (s.ssl) std::cout << " (SSL)";
std::cout << std::endl;
}
} catch (const toml::parse_error& err) {
std::cerr << "Erreur d'analyse TOML : " << err << std::endl;
return 1;
}
return 0;
}
6. Bonnes pratiques et astuces
- Utilisez toujours
value_or()pour fournir des valeurs par défaut et éviter les erreurs d'exécution. - Structurez vos fichiers TOML avec des sections claires et des noms de clés explicites.
- Validez vos fichiers TOML avec des outils en ligne ou des validateurs avant de les utiliser dans votre code.
- Utilisez les commentaires dans vos fichiers TOML pour documenter les options de configuration.
- Préférez les tableaux de tables pour les listes d'objets plutôt que des tableaux de valeurs complexes.
- Testez vos configurations avec différents fichiers TOML pour vous assurer que votre code gère correctement les cas limites.
7. Conclusion
toml++ est une bibliothèque puissante, légère et facile à intégrer pour la gestion des fichiers de configuration TOML en C++. Sa nature header-only, son support complet de la spécification TOML v1.0 et son typage strict en font un excellent choix pour tout projet C++ moderne. Que vous développiez une petite application ou un système complexe, toml++ vous offre la flexibilité et la fiabilité nécessaires pour gérer vos configurations de manière élégante et efficace.
Pour aller plus loin, consultez la documentation officielle et le dépôt GitHub du projet.
Aussi dans la bibliothèque
ImageSharp C# (.NET) : guide complet avec exemples
Java Image I/O API : redimensionnement et recadrage d'images | Guide
Compose Multiplatform Kotlin : guide complet avec exemples
Surveillance des applications TypeScript : bibliothèques, outils et configuration