[v6,04/16] config: Add configuration retrieval helpers
diff mbox series

Message ID 20241206171148.1189292-5-mzamazal@redhat.com
State New
Headers show
Series
  • Add global configuration file
Related show

Commit Message

Milan Zamazal Dec. 6, 2024, 5:11 p.m. UTC
They make accessing simple configuration values simpler.

GlobalConfiguration::option must check for the key presence before
retrieving the value using operator[] because if the key is not present
then YamlObject::empty may be returned as a regular value.

Signed-off-by: Milan Zamazal <mzamazal@redhat.com>
---
 .../libcamera/internal/global_configuration.h |  6 +++
 src/libcamera/base/global_configuration.cpp   | 52 ++++++++++++++++++-
 src/libcamera/base/log.cpp                    | 13 ++---
 3 files changed, 62 insertions(+), 9 deletions(-)

Patch
diff mbox series

diff --git a/include/libcamera/internal/global_configuration.h b/include/libcamera/internal/global_configuration.h
index bed88279..07062145 100644
--- a/include/libcamera/internal/global_configuration.h
+++ b/include/libcamera/internal/global_configuration.h
@@ -7,6 +7,9 @@ 
 
 #pragma once
 
+#include <optional>
+#include <string>
+
 #include "libcamera/internal/yaml_parser.h"
 
 namespace libcamera {
@@ -19,6 +22,9 @@  void initialize();
 
 unsigned int version();
 Configuration configuration();
+std::optional<std::string> option(const std::string &confPath);
+std::optional<std::string> envOption(const char *const envVariable,
+				     const std::string &confPath);
 
 } /* namespace GlobalConfiguration */
 
diff --git a/src/libcamera/base/global_configuration.cpp b/src/libcamera/base/global_configuration.cpp
index 8d823b98..84821f26 100644
--- a/src/libcamera/base/global_configuration.cpp
+++ b/src/libcamera/base/global_configuration.cpp
@@ -8,6 +8,8 @@ 
 #include "libcamera/internal/global_configuration.h"
 
 #include <filesystem>
+#include <memory>
+#include <string>
 #include <sys/types.h>
 
 #include <libcamera/base/file.h>
@@ -126,7 +128,10 @@  void initialize()
  * configuration files exist then only the first one found is used and no
  * configuration merging is performed.
  *
- * The configuration can be accessed using GlobalConfiguration::configuration().
+ * The configuration can be accessed using the provided helpers. Namely
+ * GlobalConfiguration::option() or GlobalConfiguration::envOption() to access
+ * individual options or GlobalConfiguration::configuration() to access the
+ * whole configuration.
  */
 
 /**
@@ -137,6 +142,51 @@  void initialize()
  * the underlying type.
  */
 
+/**
+ * \brief Return value of the configuration option identified by \a confPath
+ * \param[in] confPath Sequence of the YAML section names (excluding
+ * `configuration') leading to the requested option separated by dots
+ * \return A value if an item corresponding to \a confPath exists in the
+ * configuration file, no value otherwise
+ */
+std::optional<std::string> option(const std::string &confPath)
+{
+	const YamlObject *c = &configuration();
+	for (auto part : utils::split(confPath, ".")) {
+		c = &(*c)[part];
+		if (!*c)
+			return {};
+	}
+	return c->get<std::string>();
+}
+
+/**
+ * \brief Return value of the configuration option from a file or environment
+ * \param[in] envVariable Environment variable to get the value from
+ * \param[in] confPath The same as in GlobalConfiguration::option
+ *
+ * This helper looks first at the given environment variable and if it is
+ * defined then it returns its value (even if it is empty). Otherwise it looks
+ * for \a confPath the same way as in GlobalConfiguration::option. Only string
+ * values are supported.
+ *
+ * \note Support for using environment variables to configure libcamera behavior
+ * is provided here mostly for backward compatibility reasons. Introducing new
+ * configuration environment variables is discouraged.
+ *
+ * \return A value retrieved from the given environment option or configuration
+ * file or no value if not found
+ */
+std::optional<std::string> envOption(
+	const char *const envVariable,
+	const std::string &confPath)
+{
+	const char *envValue = utils::secure_getenv(envVariable);
+	if (envValue)
+		return std::optional{ std::string{ envValue } };
+	return option(confPath);
+}
+
 /**
  * \brief Return configuration version
  *
diff --git a/src/libcamera/base/log.cpp b/src/libcamera/base/log.cpp
index 0f676710..891b4ae9 100644
--- a/src/libcamera/base/log.cpp
+++ b/src/libcamera/base/log.cpp
@@ -628,14 +628,11 @@  void Logger::parseLogFile()
  */
 void Logger::parseLogLevels()
 {
-	const char *debug = utils::secure_getenv("LIBCAMERA_LOG_LEVELS");
-	if (!debug) {
-		const std::optional<std::string> confDebug =
-			GlobalConfiguration::configuration()["log"]["levels"].get<std::string>();
-		if (!confDebug.has_value())
-			return;
-		debug = confDebug.value().c_str();
-	}
+	const std::optional<std::string> confDebug =
+		GlobalConfiguration::envOption("LIBCAMERA_LOG_LEVELS", "log.levels");
+	if (!confDebug.has_value())
+		return;
+	const char *debug = confDebug.value().c_str();
 
 	for (const char *pair = debug; *debug != '\0'; pair = debug) {
 		const char *comma = strchrnul(debug, ',');