[C++]-yml库yaml-cpp简介

2023-05-16

文章目录

  • YAML
    • 基本语法
    • 数据类型
      • 对象
      • 数组
      • 标量
      • 引用
  • yaml-cpp库
    • 生成器Emitter
    • 节点Node
      • 数组
      • 对象
      • 创建
      • 解析

yaml-cpp是一个yml操作库。

YAML

YAML (YAML Ain’t a Markup Language,YAML不是一种标记语言)通常以.yml为后缀,是一种直观的能够被电脑识别的数据序列化格式,并且容易被人类阅读。

基本语法

yaml语法简单,适合做配置文件:

  • 大小写敏感;
  • 使用缩进表示层级关系;
    • 缩进不允许使用tab,只允许空格
    • 缩进的空格数不重要,只要相同层级的元素左对齐即可
  • '#'表示注释;

数据类型

YAML支持以下几种数据类型:

  • 对象:键值对的集合,又称为映射(mapping)/哈希(hashes)/字典(dictionary);
  • 数组:一组按次序排列的值,又称为序列(sequence)/列表(list);
  • 标量(scalars):单个的、不可再分的值;

对象

对象键值对使用冒号结构表示 key: value,冒号后面要加一个空格

多层对象可表示为:

key: {key1: value1, key2: value2}

或者

key:
  key1: value1
  key2: value2

对于复杂的对象,可使用问号加一个空格代表一个复杂的 key,配合一个冒号加一个空格代表一个 value。以键为[complexkey1,complexkey2],值为 [complexvalue1,complexvalue2]为例:

?  
    - complexkey1
    - complexkey2
:
    - complexvalue1
    - complexvalue2

数组

- 开头的行表示构成一个数组,以一个数组对象为例:

companies:
    -
        id: 1
        name: company1
        price: 200W
    -
        id: 2
        name: company2
        price: 500W

也可以下方式表示:

companies: [{id: 1,name: company1,price: 200W},{id: 2,name: company2,price: 500W}]

标量

标量是最基本的,不可再分的值,包括:

  • 字符串:有特殊字符(如空格等),可用单引号或双引号括起来;否则不需要;字符串可以拆成多行,换行符会转换为空格。
  • 布尔值:TRUE/true/True或FALSE/false/False;
  • 整数
  • 浮点数
  • Null:使用**~**表示null;
  • 日期、时间:必须是ISO 8601格式的;

引用

& 用来建立锚点(defaults),<< 表示合并到当前数据,***** 用来引用锚点。

合并数据示例:

defaults: &defaults
  adapter:  postgres
  host:     localhost

development:
  database: myapp_development
  <<: *defaults

等价于:

defaults:
  adapter:  postgres
  host:     localhost

development:
  database: myapp_development
  adapter:  postgres
  host:     localhost

单纯引用示例:

localhost: 
	host: &host 127.0.0.1
	
user:
	host: *host
	db: users

等价于:

localhost: 
	host: 127.0.0.1
	
user:
	host: 127.0.0.1
	db: users

yaml-cpp库

yaml-cpp是C++的开源库(https://github.com/jbeder/yaml-cpp);

生成器Emitter

YAML::Emitter可用于生成YAML格式文本,通过c_str()获取对应字符串:

  • YAML::BeginSeq ... YAML::EndSeq:生成数组序列,其中间的内容即为数组元素;通过YAML::Flow可控制显示方式;
  • YAML::BeginMap ... YAML::EndMap:生成对象:
    • YAML::Key:用于输入键;
    • YAML::Value:用于输入值;
  • YAML::Anchor("AnchorName") ... YAML::Alias("AnchorName"):分别用于生成锚点,和引用锚点。

Emitter还可直接输入容器(如vector作为数组)。

void buildYAML() {
    YAML::Emitter out;
    out << YAML::BeginMap;
    out << YAML::Key << "name" << YAML::Value << "orchard";
    out << YAML::Key << "fruits";
    out << YAML::Value << YAML::BeginSeq << "apple" << "banana" << "pear" << YAML::EndSeq;

    std::vector<int> vec{10, 20, 30};
    out << YAML::Key << "weight" << YAML::Value << YAML::Flow << vec ;

    std::map<std::string, int> others;
    out << YAML::Key << "extra" << YAML::Value  << YAML::Block;
    others["pear"] = 10;
    others["peach"] = 20;
    out << others;

    out << YAML::EndMap;
    std::cout << out.c_str() << std::endl;
}
// name: orchard
// fruits:
//   - apple
//   - banana
//   - pear
// weight: [10, 20, 30]
// extra:
//   peach: 20
//   pear: 10

节点Node

Node是yaml-cpp中核心概念,用于存储解析后的yaml信息:

  • Node LoadFile(const std::string& filename):从文件中加载;
  • Node Load(...):从字符串或输入流中加载;

Node是一个类map结构,可通过operator["name"]来获取子项(可级联,且不存在时不会出错):

  • .IsDefined():判断是否存在。
  • .as<type>():获取对应值。
  • .Type():获取对应的类型({ Undefined, Null, Scalar, Sequence, Map });

数组

数组可像STL中的列表一样访问:

YAML::Node primes = YAML::Load("[2, 3, 5, 7, 11]");
for (std::size_t i=0;i<primes.size();i++) {
  std::cout << primes[i].as<int>() << "\n";
}
// or:
for (YAML::const_iterator it=primes.begin();it!=primes.end();++it) {
  std::cout << it->as<int>() << "\n";
}
// or:
for (auto num : primes) {
  std::cout << num.as<int>() << "\n";
}

对象

对象可像STL中的map一样访问:

YAML::Node lineup = YAML::Load("{1B: Prince Fielder, 2B: Rickie Weeks, LF: Ryan Braun}");
for(YAML::const_iterator it=lineup.begin();it!=lineup.end();++it) {
  std::cout << "Playing at " << it->first.as<std::string>() << " is " << it->second.as<std::string>() << "\n";
}
// or:
for(auto ln : lineup){
	std::cout << "Playing at " << ln.first.as<std::string>() << " is " << ln.second.as<std::string>() << "\n";
}

创建

通过Node也可方便地创建yaml:

void buildByNode() {
    YAML::Node node;  // starts out as null
    node["key"] = "value";  // it now is a map node
    node["seq"].push_back("first element");  // node["seq"] automatically becomes a sequence
    node["seq"].push_back("second element");

    node["mirror"] = node["seq"][0];  // this creates an alias

    auto strOut = YAML::Dump(node);
    std::cout<<strOut<<std::endl;
}

// key: value
// seq:
//   - &1 first element
//   - second element
// mirror: *1

解析

以读取config.yml为例:

common:
  logLevel: 1
  logPath: './logs'
  
  abilities:
    -
      name: motion
      ability: [run]
    -
      name: study
      ability: [math, english]
	  
plugin:
  file: ./plugin/fast.so
  param: 
    param1: value1
    p2: v2
    p3: test	

读取代码:

void loadConfigs() {
    YAML::Node root;
    try {
        root = YAML::LoadFile("./.config.yml");
    } catch (YAML::ParserException &ex) {
        std::cerr << "!! config parse failed: " << ex.what() << std::endl;
        exit(-1);
    } catch (YAML::BadFile &ex) {
        std::cerr << "!! config load failed: " << ex.what() << std::endl;
        exit(-1);
    }
    
    // common node:
    auto nodeCommon = root["common"];
    if (!nodeCommon.IsDefined()) {
        std::cerr << "Node [common] not found, use default log-config" << std::endl;
        return;
    }
    if (nodeCommon["logLevel"].IsDefined()) {
        std::cout << "LogLevel: " << nodeCommon["logLevel"].as<int>() << std::endl;
    }
    if (nodeCommon["logPath"].IsDefined()) {
         std::cout << "LogPath: " << nodeCommon["logPath"].as<std::string>() << std::endl;
    }
    
    // loadAbility(nodeCommon, ...)
    // loadPlugin(root["plugin"], ...)
}

读取ability:

void loadAbility(const YAML::Node &nodeCommon, std::vector<CommonAbility> &allAbility) {
    if (!nodeCommon["abilities"].IsDefined()) {
        std::cerr << "Node [engine/abilities] not found") << std::endl;
        return;
    }

    auto nodeAbility = nodeCommon["abilities"];
    allAbility.reserve(nodeAbility.size());
    for (auto eg : nodeAbility) {
        auto subAbility = eg["ability"];
        std::vector<std::string> vecAbility;
        vecAbility.reserve(subAbility.size());
        for (auto ab : subAbility) {
            vecAbility.emplace_back(ab.as<std::string>());
        }

        allAbility.emplace_back(CommonAbility{name:eg["name"].as<std::string>(), abilities:vecAbility});
    }
}

读取plugin:

void loadPlugins(const YAML::Node &plug, PluginInfo &config) {
    if (!plug["file"].IsDefined()) {
        std::cerr << "file of plugin [{}] not found!!", pl);
        return;
    }
    plInfo.file = plug["file"].as<std::string>();

    auto param = plug["param"];
    if (param.IsDefined()) {
        for (auto it = param.begin(); it != param.end(); ++it) {
            plInfo.param[it->first.as<std::string>()] = it->second.as<std::string>();
        }
    }
}

通过iterator枚举对象时,first为键,second为值。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

[C++]-yml库yaml-cpp简介 的相关文章

随机推荐

  • ubuntu解决github访问速度慢的一个小tip

    一 通过设置hosts来解决 xff1a 登录http tool chinaz com dns 查询以下域名映射 并分别取访问速度较快的一个ip xff0c 比如我的 github span class token punctuation
  • 搞SLAM装完一个新的ubuntu系统后需要的环境配置

    所有的文件上传百度云 xff1a 链接 https pan baidu com s 1xheyHxPwaD8Tb9QJ6SAHUA 提取码 gmt9 一个搞SLAM的小白 xff0c 新装完ubuntu系统后应该配置这些内容 1 换源2 安
  • 四元数、变换矩阵、欧拉角转换关系

    四元数to变换矩阵 Eigen span class token double colon punctuation span Quaterniond span class token function quaternion span spa
  • 队列queue最简单的复制拷贝方式

    span class token macro property span class token directive hash span span class token directive keyword include span spa
  • 影单:分享一下最近在看的一些电影

    1 千与千寻 电影讲的是少女千寻随爸爸妈妈搬去新的城市 xff0c 开车迷路 xff0c 进入了一个神秘隧道 xff0c 隧道另一边有个风情小镇 xff0c 爸爸妈妈没抵制得了食物的诱惑 xff0c 大吃特吃变成了猪 那是个妖怪的世界 xf
  • conda相关

    安装 ubuntu 18 04 安装conda环境 及 创建虚拟环境 创建虚拟环境 conda create span class token operator span n your env name python span class
  • 几种PCL点云显示方式

    注意添加头文件 xff1a span class token macro property span class token directive hash span span class token directive keyword in
  • 复盘一下slam中常用的几种点云类型

    使用livox雷达常涉及至少3种点云格式 xff0c 一个是livox官方定义的custom格式 xff0c 另外两个就是激光 视觉常用的pcl类型和ros类型 之前总结过Livox雷达驱动程序发布点云格式CustomMsg和pcl Poi
  • [Python]-使用Requests模拟登录

    文章目录 登录说明session操作data序列化 示例代码登录流程验证 在 使用Requests进行HTTP请求与文件上传下载 中介绍了requests库的常用方法 xff0c 本章介绍如何使用request进行用户登录 登录说明 一般页
  • mloam

    以读 pcd xff1a 读取4个激光雷达数据 xff0c input estimator span class token punctuation span span class token function inputCloud spa
  • ROS 工作空间下编译库文件,安装库头文件到devel文件夹

    Hello xff0c 欢迎来到我的博客 我们在ROS工作空间下编程时 xff0c 可能会出现这一种情况 xff1a 我们在一个package下写了一个库 xff0c 而在另一个package要引用这个库 这个时候该怎么处理呢 xff1f
  • js打开新页面的两种方式

    1 点击某一个链接之后跳转到新页面显示 window open http www baidu com blank 2 需要刷新当前页面或者覆盖当前页面 window open http www baidu com self
  • ROS入门教程的学习与总结

    ROS入门教程的学习与总结 1 安装ROS环境2 创建ROS空间3 创建ROS package4 catkin清除命令5 待续 1 安装ROS环境 ROS官网安装参考链接 Linux版本如果是16 04 安装ROS Kinect版本 ava
  • vins-fusion 怎么输出文件? vio_global,vio.txt,vio.csv内容与位置的修改

    提示 xff1a 文章写完后 xff0c 目录可以自动生成 xff0c 如何生成可参考右边的帮助文档 目录 vins fusion 怎么输出文件 xff1f vio global vio txt vio csv内容与位置的修改1 vio g
  • ubuntu18.04安装、使用evo

    ubuntu18 04安装evo 1 切换python版本2 安装pip33 安装evo4 自带test测试5 evo工具介绍6 evo使用6 针对不同数据集的格式以及evo命令 官方连接 xff1a https github com Mi
  • RTKLIB源码及介绍

    目录 1 官网翻译 2 文件下载 1 官网翻译 RTKLIB xff1a 用于 GNSS 定位的开源程序包 下载 版本 日期 适用于 Windows 的二进制 AP 包 带有源程序的完整包 0 2 0 2006 12 16 rtklib 0
  • KITTI数据集基准、转换成tum以及十个groundtruth对应图

    KITTI数据集基准 转换成tum以及十个groundtruth对应图 时间戳的位置gt的位置利用evo进行转换生成kitti基准带时间的tum格式十个路径展示 xff1a 跑vins fusion的时候 xff0c 不知道使用的kitti
  • 【国产可编程逻辑控制器plc调研】

    国产可编程逻辑控制器plc调研 1 高性能PLC xff08 ACxxx系列 xff09 2 中型PLC xff08 AMx00系列 xff09 3 小型PLC xff08 HxU HxS xff09 4 小型紧凑型PLC xff08 Ea
  • 【工业相机接口配置】万兆网口、Camera Link接口、CXP接口

    工业相机接口配置 xff08 万兆网口 Camera Link接口 CXP接口 xff09 万兆网口Camera Link接口CXP接口 目前接触到的工业相机主要有万兆网口 Camera Link接口 CXP接口等不同的接口 另外更常用的是
  • [C++]-yml库yaml-cpp简介

    文章目录 YAML基本语法数据类型对象数组标量引用 yaml cpp库生成器Emitter节点Node数组对象创建解析 yaml cpp是一个yml操作库 YAML YAML YAML Ain t a Markup Language xff