1

I need to parse some YAML in C++ (sort of newish to YAML). I'm looking to use yaml-cpp. My objectives are:

  • To create some generic/reusable utility functions to help parsing of this YAML.
  • To be able to update a YAML::Node and/or add missing values (by specifying default values)

If I take some example YAML, it might appear as:

...
  comms:
    messageBus:
      remoteHost: "message-bus"
      remotePort: 5672

or even:

...
  comms:

Nonetheless, I want to be able to update YAML reflecting default values. So to read the above YAML, the code would look something like:

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});

so that if the above code is run on the second example, the updated YAML would now be:

...
  comms:
    messageBus:
      remoteHost: "127.0.0.1"
      remotePort: 5672

For both get_yaml_string_field_or_default_and_update and get_yaml_uint16_field_or_default_and_update, it's fairly trivial to create a templated function to handle reading different value types and inserting them if necessary:

///////////////////////////////////////////////////////////////////////////
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;
    }
}

The code I'm struggling with is 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];
}

It looks as if the operator[] does not return a reference according to API.

// indexing
template <typename Key>
const Node operator[](const Key& key) const;

template <typename Key>
Node operator[](const Key& key);

Any tips/suggestions would be greatly appreciated.

1 Answer 1

1

YAML::Node is a reference type already, so returning it from a function doesn’t make a deep copy. It’s also mutable, so you can just edit it and the change will update the root node.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! I hadn't appreciated the subtlety.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.