blob: ff33829ad4efd3ae8bfdfc7b26e70f6f992f91ef [file] [log] [blame] [edit]
/* Copyright 2023 The ChromiumOS Authors
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* Specialised YamlNode, representing a YAML mapping.
*
* This is equivalent to maps/dictionaries in programming languages.
*
* Keys are always strings in this implementation.
* (YAML itself allows any node to be a key).
*/
#include "tools/mctk/yaml_tree.h"
#include <linux/types.h>
#include <yaml.h>
#include <memory> /* std::unique_ptr */
#include <string>
#include <utility> /* std::move, std::pair */
#include <vector>
#include "tools/mctk/debug.h"
/* Caller is responsible for deleting the event passed in */
std::unique_ptr<YamlMap> YamlMap::FromParserEvent(yaml_parser_t& parser,
yaml_event_t& start_event) {
MCTK_ASSERT_EQ(start_event.type, YAML_MAPPING_START_EVENT);
auto new_map = std::make_unique<YamlMap>();
if (!new_map)
return NULL;
/* Store YAML formatting style for debugging purposes */
new_map->implicit_ = start_event.data.mapping_start.implicit;
new_map->style_ = start_event.data.mapping_start.style;
while (true) {
yaml_event_t event;
if (!yaml_parser_parse(&parser, &event))
goto error;
if (event.type == YAML_MAPPING_END_EVENT) {
yaml_event_delete(&event);
return new_map;
}
/* Part 1: We expect a scalar as a key */
if (event.type != YAML_SCALAR_EVENT) {
yaml_event_delete(&event);
goto error;
}
std::string key((const char*)event.data.scalar.value,
event.data.scalar.length);
yaml_event_delete(&event);
/* Part 2: Parse any node type as a value */
auto value = YamlNode::FromParser(parser);
if (!value)
goto error;
new_map->map_.push_back(YamlMapPair(key, std::move(value)));
}
error:
return NULL;
}
bool YamlMap::Emit(yaml_emitter_t& emitter) {
yaml_event_t event;
if (!yaml_mapping_start_event_initialize(
&event, NULL, reinterpret_cast<const yaml_char_t*>(YAML_MAP_TAG),
implicit_, style_))
return false;
if (!yaml_emitter_emit(&emitter, &event))
return false;
for (YamlMapPair& pair : this->map_) {
if (!yaml_scalar_event_initialize(
&event, NULL, NULL,
reinterpret_cast<const yaml_char_t*>(pair.first.c_str()), -1, 1, 1,
YAML_ANY_SCALAR_STYLE))
return false;
if (!yaml_emitter_emit(&emitter, &event))
return false;
pair.second->Emit(emitter);
}
if (!yaml_mapping_end_event_initialize(&event))
return false;
if (!yaml_emitter_emit(&emitter, &event))
return false;
return true;
}