@@ -8,6 +8,11 @@
#pragma once
#include <filesystem>
+#include <optional>
+#include <string>
+#include <string_view>
+
+#include <libcamera/base/utils.h>
#include "libcamera/internal/yaml_parser.h"
@@ -23,6 +28,29 @@ public:
unsigned int version() const;
Configuration configuration() const;
+ template<typename T>
+ std::optional<T> option(
+ const std::initializer_list<std::string_view> confPath) const
+ {
+ const YamlObject *c = &configuration();
+ for (auto part : confPath) {
+ c = &(*c)[part];
+ if (!*c)
+ return {};
+ }
+ return c->get<T>();
+ }
+
+ std::optional<std::vector<std::string>> listOption(
+ const std::initializer_list<std::string_view> confPath) const;
+ std::optional<std::string> envOption(
+ const char *const envVariable,
+ const std::initializer_list<std::string_view> confPath) const;
+ std::optional<std::vector<std::string>> envListOption(
+ const char *const envVariable,
+ const std::initializer_list<std::string_view> confPath,
+ const std::string delimiter = ":") const;
+
private:
bool loadFile(const std::filesystem::path &fileName);
void load();
@@ -8,8 +8,12 @@
#include "libcamera/internal/global_configuration.h"
#include <filesystem>
+#include <memory>
+#include <optional>
+#include <string>
#include <string_view>
#include <sys/types.h>
+#include <vector>
#include <libcamera/base/file.h>
#include <libcamera/base/log.h>
@@ -43,6 +47,12 @@ LOG_DEFINE_CATEGORY(Configuration)
* If the first found configuration file cannot be opened or parsed, an error is
* reported and no configuration file is used. This is to prevent libcamera from
* using an unintended configuration file.
+ *
+ * The configuration can be accessed using the provided helpers. Namely
+ * GlobalConfiguration::option(), GlobalConfiguration::envOption(),
+ * GlobalConfiguration::listOption(), and GlobalConfiguration::envListOption()
+ * to access individual options, or GlobalConfiguration::configuration() to
+ * access the whole configuration.
*/
bool GlobalConfiguration::loadFile(const std::filesystem::path &fileName)
@@ -110,6 +120,95 @@ GlobalConfiguration::GlobalConfiguration()
* the underlying type.
*/
+/**
+ * \fn std::optional<T> GlobalConfiguration::option(const std::initializer_list<std::string_view> &confPath) const
+ * \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
+ * \return The value of the configuration item corresponding to \a confPath if
+ * it exists in the configuration file, or no value otherwise
+ */
+
+/**
+ * \brief Return values of the configuration option identified by \a confPath
+ * \tparam T The type of the retrieved configuration value
+ * \param[in] confPath Sequence of the YAML section names (excluding
+ * `configuration') leading to the requested list option, separated by dots
+ * \return A vector of strings or no value if not found
+ */
+std::optional<std::vector<std::string>> GlobalConfiguration::listOption(
+ const std::initializer_list<std::string_view> confPath) const
+{
+ const YamlObject *c = &configuration();
+ for (auto part : confPath) {
+ c = &(*c)[part];
+ if (!*c)
+ return {};
+ }
+ return c->getList<std::string>();
+}
+
+/**
+ * \brief Return value of environment variable with a fallback on the configuration file
+ * \param[in] envVariable Environment variable to get the value from
+ * \param[in] confPath The sequence of YAML section names to fall back on when
+ * \a envVariable is unavailable
+ *
+ * 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 The value retrieved from the given environment if it is set,
+ * otherwise the value from the configuration file if it exists, or no value if
+ * it does not
+ */
+std::optional<std::string> GlobalConfiguration::envOption(
+ const char *envVariable,
+ const std::initializer_list<std::string_view> confPath) const
+{
+ const char *envValue = utils::secure_getenv(envVariable);
+ if (envValue)
+ return std::optional{ std::string{ envValue } };
+ return option<std::string>(confPath);
+}
+
+/**
+ * \brief Return values 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
+ * \param[in] delimiter Items separator in the environment variable
+ *
+ * This helper looks first at the given environment variable and if it is
+ * defined (even if it is empty) then it splits its value by semicolons and
+ * returns the resulting list of strings. Otherwise it looks for \a confPath the
+ * same way as in GlobalConfiguration::option, value of which must be a list of
+ * strings.
+ *
+ * \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 vector of strings retrieved from the given environment option or
+ * configuration file or no value if not found; the vector may be empty
+ */
+std::optional<std::vector<std::string>> GlobalConfiguration::envListOption(
+ const char *const envVariable,
+ const std::initializer_list<std::string_view> confPath,
+ const std::string delimiter) const
+{
+ const char *envValue = utils::secure_getenv(envVariable);
+ if (envValue) {
+ auto items = utils::split(envValue, delimiter);
+ return std::vector<std::string>(items.begin(), items.end());
+ }
+ return listOption(confPath);
+}
+
/**
* \brief Return configuration version
*