使用 yaml-cpp 更新 YAML 文档的节点和值
Updating node and values of YAML document with yaml-cpp
我需要用 C++ 解析一些 YAML(对 YAML 来说有点新)。我正在寻找使用 yaml-cpp。我的目标是:
- 创建一些 generic/reusable 实用函数来帮助解析此 YAML。
- 为了能够更新 YAML::Node and/or 添加缺失值(通过指定默认值)
如果我举一些 YAML 示例,它可能显示为:
...
comms:
messageBus:
remoteHost: "message-bus"
remotePort: 5672
甚至:
...
comms:
尽管如此,我希望能够更新反映默认值的 YAML。所以要阅读上面的 YAML,代码看起来像这样:
auto &nodeComms = get_yaml_node_field_or_insert(node, "comms");
auto &nodeMessageBus = get_yaml_node_field_or_insert(nodeComms , "comms");
auto strRemoteHost = get_yaml_string_field_or_default_and_update(nodeMessageBus, "remoteHost", "127.0.0.1");
auto nRemotePort = get_yaml_uint16_field_or_default_and_update(nodeMessageBus, "remotePort", uint16_t{5672});
因此,如果上面的代码在第二个示例中是 运行,则更新后的 YAML 现在将是:
...
comms:
messageBus:
remoteHost: "127.0.0.1"
remotePort: 5672
对于 get_yaml_string_field_or_default_and_update
和 get_yaml_uint16_field_or_default_and_update
,创建一个模板函数来处理读取不同的值类型并在必要时插入它们是相当简单的:
///////////////////////////////////////////////////////////////////////////
template <typename TYPE_IN, typename TYPE_RETURN>
TYPE_RETURN get_type_from_yaml_node_or_default_and_update(YAML::Node &node,
const char *pchFieldName,
TYPE_IN nValueDefault) noexcept
{
if (!node)
{
assert(false);
throw std::runtime_error("Invalid node");
}
if (!node[pchFieldName])
{
node[pchFieldName] = nValueDefault;
return nValueDefault;
}
try
{
return node[pchFieldName].as<TYPE_RETURN>();
}
catch (const std::exception &e)
{
node[pchFieldName] = nValueDefault;
return nValueDefault;
}
catch (...)
{
node[pchFieldName] = nValueDefault;
return nValueDefault;
}
}
我遇到的代码是 get_yaml_node_field_or_insert
:
///////////////////////////////////////////////////////////////////////////
YAML::Node &get_yaml_node_field_or_insert(YAML::Node &node, const char *pchFieldName) noexcept
{
if (!node)
{
assert(false);
throw std::runtime_error("Invalid node");
}
// TODO: Either 1) Return reference if it exists or 2) insert if it does not and return reference.
return node[pchFieldName];
}
根据 API,operator[] 似乎没有 return 引用。
// indexing
template <typename Key>
const Node operator[](const Key& key) const;
template <typename Key>
Node operator[](const Key& key);
任何 tips/suggestions 将不胜感激。
YAML::Node 已经是引用类型,因此从函数返回它不会进行深度复制。它也是可变的,因此您只需编辑它,更改就会更新根节点。
我需要用 C++ 解析一些 YAML(对 YAML 来说有点新)。我正在寻找使用 yaml-cpp。我的目标是:
- 创建一些 generic/reusable 实用函数来帮助解析此 YAML。
- 为了能够更新 YAML::Node and/or 添加缺失值(通过指定默认值)
如果我举一些 YAML 示例,它可能显示为:
...
comms:
messageBus:
remoteHost: "message-bus"
remotePort: 5672
甚至:
...
comms:
尽管如此,我希望能够更新反映默认值的 YAML。所以要阅读上面的 YAML,代码看起来像这样:
auto &nodeComms = get_yaml_node_field_or_insert(node, "comms");
auto &nodeMessageBus = get_yaml_node_field_or_insert(nodeComms , "comms");
auto strRemoteHost = get_yaml_string_field_or_default_and_update(nodeMessageBus, "remoteHost", "127.0.0.1");
auto nRemotePort = get_yaml_uint16_field_or_default_and_update(nodeMessageBus, "remotePort", uint16_t{5672});
因此,如果上面的代码在第二个示例中是 运行,则更新后的 YAML 现在将是:
...
comms:
messageBus:
remoteHost: "127.0.0.1"
remotePort: 5672
对于 get_yaml_string_field_or_default_and_update
和 get_yaml_uint16_field_or_default_and_update
,创建一个模板函数来处理读取不同的值类型并在必要时插入它们是相当简单的:
///////////////////////////////////////////////////////////////////////////
template <typename TYPE_IN, typename TYPE_RETURN>
TYPE_RETURN get_type_from_yaml_node_or_default_and_update(YAML::Node &node,
const char *pchFieldName,
TYPE_IN nValueDefault) noexcept
{
if (!node)
{
assert(false);
throw std::runtime_error("Invalid node");
}
if (!node[pchFieldName])
{
node[pchFieldName] = nValueDefault;
return nValueDefault;
}
try
{
return node[pchFieldName].as<TYPE_RETURN>();
}
catch (const std::exception &e)
{
node[pchFieldName] = nValueDefault;
return nValueDefault;
}
catch (...)
{
node[pchFieldName] = nValueDefault;
return nValueDefault;
}
}
我遇到的代码是 get_yaml_node_field_or_insert
:
///////////////////////////////////////////////////////////////////////////
YAML::Node &get_yaml_node_field_or_insert(YAML::Node &node, const char *pchFieldName) noexcept
{
if (!node)
{
assert(false);
throw std::runtime_error("Invalid node");
}
// TODO: Either 1) Return reference if it exists or 2) insert if it does not and return reference.
return node[pchFieldName];
}
根据 API,operator[] 似乎没有 return 引用。
// indexing
template <typename Key>
const Node operator[](const Key& key) const;
template <typename Key>
Node operator[](const Key& key);
任何 tips/suggestions 将不胜感激。
YAML::Node 已经是引用类型,因此从函数返回它不会进行深度复制。它也是可变的,因此您只需编辑它,更改就会更新根节点。