summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libcamera/internal/meson.build1
-rw-r--r--include/libcamera/internal/yaml_emitter.h61
-rw-r--r--src/libcamera/meson.build1
-rw-r--r--src/libcamera/yaml_emitter.cpp187
4 files changed, 250 insertions, 0 deletions
diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build
index 1c5eef9c..7533b075 100644
--- a/include/libcamera/internal/meson.build
+++ b/include/libcamera/internal/meson.build
@@ -41,6 +41,7 @@ libcamera_internal_headers = files([
'v4l2_pixelformat.h',
'v4l2_subdevice.h',
'v4l2_videodevice.h',
+ 'yaml_emitter.h',
'yaml_parser.h',
])
diff --git a/include/libcamera/internal/yaml_emitter.h b/include/libcamera/internal/yaml_emitter.h
new file mode 100644
index 00000000..f8df5265
--- /dev/null
+++ b/include/libcamera/internal/yaml_emitter.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2024, Ideas On Board Oy
+ *
+ * libcamera YAML emitter helper
+ */
+
+#pragma once
+
+#include <map>
+#include <memory>
+#include <string>
+
+#include <libcamera/base/class.h>
+#include <libcamera/base/file.h>
+
+#include <yaml.h>
+
+namespace libcamera {
+
+class File;
+class YamlEvent;
+
+class YamlEmitter final
+{
+public:
+ ~YamlEmitter();
+
+ static std::unique_ptr<YamlEmitter> create(std::string &path);
+
+ int emit(std::map<std::string, std::string>);
+ int emit(const std::string &scalar);
+
+private:
+ LIBCAMERA_DISABLE_COPY(YamlEmitter);
+
+ class Emitter
+ {
+ public:
+ Emitter() = default;
+ ~Emitter();
+
+ void init(File *file);
+
+ int emit(YamlEvent *event);
+
+ private:
+ void logError();
+
+ yaml_emitter_t emitter_;
+ };
+
+ YamlEmitter() = default;
+
+ void init();
+
+ std::unique_ptr<File> file_;
+ Emitter emitter_;
+};
+
+} /* namespace libcamera */
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 */