diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libcamera/meson.build | 1 | ||||
-rw-r--r-- | src/libcamera/yaml_emitter.cpp | 187 |
2 files changed, 188 insertions, 0 deletions
diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index aa9ab029..5b8af410 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -51,6 +51,7 @@ libcamera_internal_sources = files([ 'v4l2_pixelformat.cpp', 'v4l2_subdevice.cpp', 'v4l2_videodevice.cpp', + 'yaml_emitter.cpp', 'yaml_parser.cpp', ]) diff --git a/src/libcamera/yaml_emitter.cpp b/src/libcamera/yaml_emitter.cpp new file mode 100644 index 00000000..5683d1d4 --- /dev/null +++ b/src/libcamera/yaml_emitter.cpp @@ -0,0 +1,187 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Ideas On Board Oy + * + * libcamera YAML emitter helper + */ + +#include "libcamera/internal/yaml_emitter.h" + +#include <libcamera/base/log.h> +#include <libcamera/base/span.h> + +/** + * \file yaml_emitter.h + * \brief A YAML emitter helper + */ + +namespace libcamera { + +LOG_DEFINE_CATEGORY(YamlEmitter) + +namespace { + +int yamlWrite(void *data, unsigned char *buffer, size_t size) +{ + File *file = static_cast<File *>(data); + + Span<unsigned char> buf{ buffer, size }; + ssize_t ret = file->write(buf); + if (ret < 0) + return 0; + + return 1; +} + +} /* namespace */ + +class YamlEvent +{ +public: + static std::unique_ptr<YamlEvent> create(); + + const yaml_event_t *event() const + { + return &event_; + } + + yaml_event_t *event() + { + return &event_; + } + +private: + YamlEvent() = default; + + yaml_event_t event_; +}; + +std::unique_ptr<YamlEvent> YamlEvent::create() +{ + struct Deleter : std::default_delete<YamlEvent> { + void operator()(YamlEvent *yamlEvent) + { + yaml_event_delete(yamlEvent->event()); + } + }; + + return std::unique_ptr<YamlEvent>(new YamlEvent(), Deleter()); +} + +YamlEmitter::Emitter::~Emitter() +{ + yaml_emitter_delete(&emitter_); +} + +void YamlEmitter::Emitter::init(File *file) +{ + yaml_emitter_initialize(&emitter_); + yaml_emitter_set_output(&emitter_, yamlWrite, file); +} + +void YamlEmitter::Emitter::logError() +{ + switch (emitter_.error) { + case YAML_MEMORY_ERROR: + LOG(YamlEmitter, Error) + << "Memory error: Not enough memory for emitting"; + break; + + case YAML_WRITER_ERROR: + LOG(YamlEmitter, Error) + << "Writer error: " << emitter_.problem; + break; + + case YAML_EMITTER_ERROR: + LOG(YamlEmitter, Error) + << "Emitter error: " << emitter_.problem; + break; + + default: + LOG(YamlEmitter, Error) << "Internal problem"; + break; + } +} + +int YamlEmitter::Emitter::emit(YamlEvent *event) +{ + int ret = yaml_emitter_emit(&emitter_, event->event()); + if (!ret) { + logError(); + return -EINVAL; + } + + return 0; +} + +YamlEmitter::~YamlEmitter() +{ + std::unique_ptr<YamlEvent> event = YamlEvent::create(); + + yaml_document_end_event_initialize(event->event(), 0); + emitter_.emit(event.get()); + + yaml_stream_end_event_initialize(event->event()); + emitter_.emit(event.get()); +} + +void YamlEmitter::init() +{ + emitter_.init(file_.get()); + + std::unique_ptr<YamlEvent> event = YamlEvent::create(); + + yaml_stream_start_event_initialize(event->event(), YAML_UTF8_ENCODING); + emitter_.emit(event.get()); + + yaml_document_start_event_initialize(event->event(), NULL, NULL, + NULL, 0); + emitter_.emit(event.get()); +} + +std::unique_ptr<YamlEmitter> YamlEmitter::create(std::string &path) +{ + YamlEmitter *emitter = new YamlEmitter(); + + emitter->file_ = std::make_unique<File>(path); + emitter->file_->open(File::OpenModeFlag::WriteOnly); + + emitter->init(); + + return std::unique_ptr<YamlEmitter>(emitter); +} + +int YamlEmitter::emit(std::map<std::string, std::string> map) +{ + std::unique_ptr<YamlEvent> event = YamlEvent::create(); + + auto iter = map.begin(); + + yaml_mapping_start_event_initialize(event->event(), NULL, NULL, + true, YAML_BLOCK_MAPPING_STYLE); + emitter_.emit(event.get()); + + emit(iter->first); + emit(iter->second); + + yaml_mapping_end_event_initialize(event->event()); + emitter_.emit(event.get()); + + return 0; +} + +int YamlEmitter::emit(const std::string &scalar) +{ + const unsigned char *value = reinterpret_cast<const unsigned char *> + (scalar.c_str()); + std::unique_ptr<YamlEvent> event = YamlEvent::create(); + + yaml_scalar_event_initialize(event->event(), NULL, NULL, value, + scalar.length(), true, false, + YAML_PLAIN_SCALAR_STYLE); + emitter_.emit(event.get()); + + return 0; +} + +} /* namespace libcamera */ |