基于C++的配置文件解析器/编码器——toml库

在平常的软件开发过程中,配置文件是重要的一环,使用配置文件在软件开发过程中具有以下好处和必要性:

  • 灵活性:配置文件允许在不修改代码的情况下更改应用程序的行为,通过修改配置文件,可以调整应用程序的参数、设置和选项,以满足不同的需求和环境。
  • 可维护性:将配置信息从代码中分离出来,使得维护和管理变得更加容易,当需要修改配置时,只需修改配置文件,而不需要重新编译和部署整个应用程序。
  • 可扩展性:配置文件可以用于支持应用程序的扩展。通过添加新的配置项,可以轻松地引入新的功能或模块,而无需修改现有的代码。
  • 跨环境部署 :使用配置文件可以轻松地在不同的环境中部署应用程序,例如开发、测试和生产环境,通过切换不同的配置文件,可以适应不同环境的需求。
    总之,配置文件在软件开发中起到了关键的作用,它们提供了一种灵活、可维护和可扩展的方式来管理应用程序的行为和设置。

虽然写配置文件本身是一个简单的事情,但很容易出错,且容易因为规范不一导致解析出错,自从使用了TOML库,发现是真香!

1.关于toml

toml11是一个C++的库,用于解析和生成 TOML(Tom's Obvious, Minimal Language)格式的配置文件。TOML是一种易于阅读和编写的配置文件格式,被广泛用于各种应用程序的配置文件中。主要作用是提供了一种简单、高效的方式来读取和写入TOML格式的配置文件。

源码:
https://github.com/marzer/tomlplusplus
https://github.com/ToruNiina/toml11

https://gitee.com/boss-dog/tomlplusplus
https://gitee.com/boss-dog/toml11

toml11和tomlplusplus都是C++的库,用于解析和生成TOML格式的配置文件。

toml11是一个轻量级的TOML库,可以直接包含在项目中使用,无需额外的依赖,代码量较小,功能相对较少,但足以满足大多数简单的TOML文件解析和生成需求。

tomlplusplus是一个更为全面和功能丰富的TOML库,它是基于toml11的基础上进行扩展和改进的,支持更多的TOML语法特性,提供了更灵活的配置选项和更强大的错误处理机制。

总的来说,toml11适用于简单的TOML文件解析和生成需求,它轻量、易用、快速。而tomlplusplus则适用于更复杂的TOML文件操作,提供了更多的功能和选项,并具有更好的性能。选择使用哪个库取决于具体的需求和项目的规模。

1.1 安装toml

  • 1.从toml11的仓库下载源代码
bash 复制代码
git clone https://gitee.com/boss-dog/toml11.git
  • 2.将下载的源代码放置在项目目录中的合适位置。

  • 3.在CMakeLists.txt文件中添加以下内容,以引入toml11库:

powershell 复制代码
# 设置toml11库的路径
set(TOML11_INCLUDE_DIR /path/to/toml11)

# 添加toml11库的头文件路径
include_directories(${TOML11_INCLUDE_DIR})

# 添加toml11库的源文件
add_library(toml11 INTERFACE)
target_include_directories(toml11 INTERFACE ${TOML11_INCLUDE_DIR})

请确保将/path/to/toml11替换为实际的toml11库的路径。

  • 在项目中可以使用#include "toml.hpp"来包含toml11库的头文件,并使用toml::前缀来访问toml11库的功能

2.示例:使用toml库编写对配置文件的解析

dog_roster.conf

xml 复制代码
num_dog = 3
version = '1.1.2'

[[Zhou]]
name = 'BuDing'
adopted = true
age = 4
weight = 15.6
height = 30.0

    [Zhou.options]
    pose = [0.1,0.2,0.3]


[[Zhou]]
name = 'DuoDuo'
adopted = true
age = 3.5
weight = 15.6
height = 29.8

    [Zhou.options]
    pose = [1.1,1.2,1.3]

[[Zhou]]
name = 'PaoPao'
adopted = false
age = 6
weight = 28.2
height = 50.1

    [Zhou.options]
    pose = [0.01,0.02,0.03]

CMakeLists.txt

powershell 复制代码
cmake_minimum_required(VERSION 3.16)
project(MyDemo)

# 设置C++标准
set(CMAKE_CXX_STANDARD 17)

# 设置toml11库的路径
set(TOML11_INCLUDE_DIR toml11)

# 添加toml11库的头文件路径
include_directories(${TOML11_INCLUDE_DIR})

# 添加可执行文件
add_executable(test_toml
    test_toml.cpp
)

# 添加toml11库的源文件
add_library(toml11 INTERFACE)
target_include_directories(test_toml INTERFACE ${TOML11_INCLUDE_DIR})

test_toml.cpp

cpp 复制代码
#include <iostream>
#include "toml.hpp"

int main()
{
    // 解析配置文件
    std::ifstream config_file("../dog_roster.conf");

    if (!config_file.is_open()) {
        std::cerr << "Failed to open config file!" << std::endl;
        return -1;
    }
    const auto data = toml::parse(config_file);

    // 获取num_dog和version的值
    const int num_dog = toml::find<int>(data, "num_dog");
    const std::string version = toml::find<std::string>(data, "version");

    std::cout << "num_dog: " << num_dog << std::endl;
    std::cout << "version: " << version << std::endl;

    try {
        // 遍历每个狗的信息
        const auto &dogs = toml::find(data, "Zhou");
        for (const auto &dog : dogs.as_array()) {
            const std::string name = toml::find<std::string>(dog, "name");
            const bool adopted = toml::find<bool>(dog, "adopted");

            int age = -1;
            if (dog.at("age").is_integer()) {
                age = toml::find<int>(dog, "age");
            } else if (dog.at("age").is_floating()) {
                age = toml::find<double>(dog, "age");
            }

            const double weight = toml::find<double>(dog, "weight");
            const double height = toml::find<double>(dog, "height");

            std::cout << "name: " << name << std::endl;
            std::cout << "adopted: " << (adopted ? "true" : "false")
                      << std::endl;
            std::cout << "age: " << age << std::endl;
            std::cout << "weight: " << weight << std::endl;
            std::cout << "height: " << height << std::endl;

            // 获取pose选项的值
            const auto &options = toml::find(dog, "options");
            const auto pose = toml::find<std::vector<double>>(options, "pose");

            std::cout << "pose: [";
            for (const auto &p : pose) {
                std::cout << p << ", ";
            }
            std::cout << "]" << std::endl;
        }
    } catch (const toml::syntax_error &e) {
        std::cerr << "Syntax error in configuration file: " << e.what()
                  << std::endl;
    } catch (const std::exception &e) {
        std::cerr << "Error occurred: " << e.what() << std::endl;
    }

    std::cout << "Finished!" << std::endl;
    return 0;
}
相关推荐
诚丞成1 小时前
计算世界之安生:C++继承的文水和智慧(上)
开发语言·c++
东风吹柳2 小时前
观察者模式(sigslot in C++)
c++·观察者模式·信号槽·sigslot
A懿轩A2 小时前
C/C++ 数据结构与算法【栈和队列】 栈+队列详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·栈和队列
大胆飞猪3 小时前
C++9--前置++和后置++重载,const,日期类的实现(对前几篇知识点的应用)
c++
1 9 J3 小时前
数据结构 C/C++(实验五:图)
c语言·数据结构·c++·学习·算法
夕泠爱吃糖3 小时前
C++中如何实现序列化和反序列化?
服务器·数据库·c++
长潇若雪3 小时前
《类和对象:基础原理全解析(上篇)》
开发语言·c++·经验分享·类和对象
染指11105 小时前
50.第二阶段x86游戏实战2-lua获取本地寻路,跨地图寻路和获取当前地图id
c++·windows·lua·游戏安全·反游戏外挂·游戏逆向·luastudio
Code out the future6 小时前
【C++——临时对象,const T&】
开发语言·c++
sam-zy6 小时前
MFC用List Control 和Picture控件实现界面切换效果
c++·mfc