Обновление узла и значений документа YAML с помощью yaml- cpp - PullRequest
0 голосов
/ 01 февраля 2020

Мне нужно проанализировать некоторые YAML в C ++ (вроде newi sh в YAML). Я ищу использовать yaml- cpp. Мои цели:

  • Создать несколько общих / многократно используемых утилит для помощи в разборе этого YAML.
  • Чтобы иметь возможность обновить YAML :: Node и / или добавить пропущенные значения (указав значения по умолчанию)

Если я возьму какой-нибудь пример 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.

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

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

Буду признателен за любые советы / предложения.

1 Ответ

1 голос
/ 01 февраля 2020

YAML :: Node уже является ссылочным типом, поэтому возвращение его из функции не делает глубокую копию. Он также изменчив, так что вы можете просто отредактировать его, и изменение обновит узел root.

...