From cbdc93e9d1666010d49e06940158a37c61cc6fa7 Mon Sep 17 00:00:00 2001 From: Kieran Bingham Date: Tue, 15 Jun 2021 15:40:45 +0100 Subject: libcamera/base: Move utils to the base library Move the utils functionality to the libcamera/base library. Reviewed-by: Hirokazu Honda Reviewed-by: Paul Elder Reviewed-by: Laurent Pinchart Signed-off-by: Kieran Bingham --- include/libcamera/base/meson.build | 1 + include/libcamera/base/utils.h | 355 ++++++++++++++++ include/libcamera/internal/log.h | 2 +- include/libcamera/internal/meson.build | 1 - include/libcamera/internal/thread.h | 3 +- include/libcamera/internal/utils.h | 355 ---------------- src/android/camera_device.cpp | 3 +- src/android/jpeg/exif.cpp | 3 +- src/ipa/ipu3/ipu3_agc.h | 4 +- src/ipa/raspberrypi/cam_helper.hpp | 3 +- src/ipa/raspberrypi/controller/agc_algorithm.hpp | 3 +- src/ipa/raspberrypi/controller/agc_status.h | 2 +- src/ipa/raspberrypi/controller/camera_mode.h | 2 +- src/ipa/raspberrypi/controller/device_status.h | 2 +- src/ipa/raspberrypi/controller/rpi/agc.hpp | 2 +- src/ipa/raspberrypi/controller/rpi/lux.hpp | 2 +- src/libcamera/base/meson.build | 1 + src/libcamera/base/utils.cpp | 463 +++++++++++++++++++++ src/libcamera/camera_manager.cpp | 3 +- src/libcamera/camera_sensor.cpp | 3 +- src/libcamera/controls.cpp | 3 +- src/libcamera/event_dispatcher_poll.cpp | 3 +- src/libcamera/ipa_manager.cpp | 3 +- src/libcamera/ipa_module.cpp | 3 +- src/libcamera/ipa_proxy.cpp | 3 +- src/libcamera/log.cpp | 3 +- src/libcamera/meson.build | 1 - src/libcamera/object.cpp | 3 +- src/libcamera/pipeline/ipu3/imgu.cpp | 3 +- src/libcamera/pipeline/ipu3/ipu3.cpp | 3 +- src/libcamera/pipeline/raspberrypi/raspberrypi.cpp | 3 +- src/libcamera/pipeline/rkisp1/rkisp1.cpp | 3 +- src/libcamera/pipeline/simple/converter.cpp | 3 +- src/libcamera/pipeline/uvcvideo/uvcvideo.cpp | 3 +- src/libcamera/pipeline/vimc/vimc.cpp | 3 +- src/libcamera/pipeline_handler.cpp | 3 +- src/libcamera/process.cpp | 3 +- src/libcamera/source_paths.cpp | 2 +- src/libcamera/stream.cpp | 3 +- src/libcamera/timer.cpp | 3 +- src/libcamera/utils.cpp | 463 --------------------- src/libcamera/v4l2_device.cpp | 3 +- src/libcamera/v4l2_subdevice.cpp | 3 +- src/v4l2/v4l2_camera_proxy.cpp | 3 +- src/v4l2/v4l2_compat_manager.cpp | 3 +- test/camera-sensor.cpp | 3 +- test/file-descriptor.cpp | 2 +- test/ipc/unixsocket_ipc.cpp | 3 +- test/log/log_process.cpp | 3 +- test/pixel-format.cpp | 2 +- test/process/process_test.cpp | 3 +- test/signal-threads.cpp | 3 +- test/utils.cpp | 2 +- test/v4l2_subdevice/list_formats.cpp | 3 +- test/v4l2_videodevice/formats.cpp | 3 +- 55 files changed, 904 insertions(+), 868 deletions(-) create mode 100644 include/libcamera/base/utils.h delete mode 100644 include/libcamera/internal/utils.h create mode 100644 src/libcamera/base/utils.cpp delete mode 100644 src/libcamera/utils.cpp diff --git a/include/libcamera/base/meson.build b/include/libcamera/base/meson.build index 0a7a57b8..9f0ba6b0 100644 --- a/include/libcamera/base/meson.build +++ b/include/libcamera/base/meson.build @@ -3,6 +3,7 @@ libcamera_base_include_dir = libcamera_include_dir / 'base' libcamera_base_headers = files([ + 'utils.h', ]) install_headers(libcamera_base_headers, diff --git a/include/libcamera/base/utils.h b/include/libcamera/base/utils.h new file mode 100644 index 00000000..d1aaff65 --- /dev/null +++ b/include/libcamera/base/utils.h @@ -0,0 +1,355 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2018, Google Inc. + * + * utils.h - Miscellaneous utility functions + */ +#ifndef __LIBCAMERA_BASE_UTILS_H__ +#define __LIBCAMERA_BASE_UTILS_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef __DOXYGEN__ + +/* uClibc and uClibc-ng don't provide O_TMPFILE */ +#ifndef O_TMPFILE +#define O_TMPFILE (020000000 | O_DIRECTORY) +#endif + +#endif + +namespace libcamera { + +namespace utils { + +const char *basename(const char *path); + +char *secure_getenv(const char *name); +std::string dirname(const std::string &path); + +template +std::vector map_keys(const T &map) +{ + std::vector keys; + std::transform(map.begin(), map.end(), std::back_inserter(keys), + [](const auto &value) { return value.first; }); + return keys; +} + +template +unsigned int set_overlap(InputIt1 first1, InputIt1 last1, + InputIt2 first2, InputIt2 last2) +{ + unsigned int count = 0; + + while (first1 != last1 && first2 != last2) { + if (*first1 < *first2) { + ++first1; + } else { + if (!(*first2 < *first1)) + count++; + ++first2; + } + } + + return count; +} + +using clock = std::chrono::steady_clock; +using duration = std::chrono::steady_clock::duration; +using time_point = std::chrono::steady_clock::time_point; + +struct timespec duration_to_timespec(const duration &value); +std::string time_point_to_string(const time_point &time); + +#ifndef __DOXYGEN__ +struct _hex { + uint64_t v; + unsigned int w; +}; + +std::basic_ostream> & +operator<<(std::basic_ostream> &stream, const _hex &h); +#endif + +template +_hex hex(T value, unsigned int width = 0); + +#ifndef __DOXYGEN__ +template<> +inline _hex hex(int32_t value, unsigned int width) +{ + return { static_cast(value), width ? width : 8 }; +} + +template<> +inline _hex hex(uint32_t value, unsigned int width) +{ + return { static_cast(value), width ? width : 8 }; +} + +template<> +inline _hex hex(int64_t value, unsigned int width) +{ + return { static_cast(value), width ? width : 16 }; +} + +template<> +inline _hex hex(uint64_t value, unsigned int width) +{ + return { static_cast(value), width ? width : 16 }; +} +#endif + +size_t strlcpy(char *dst, const char *src, size_t size); + +#ifndef __DOXYGEN__ +template +std::string join(const Container &items, const std::string &sep, UnaryOp op) +{ + std::ostringstream ss; + bool first = true; + + for (typename Container::const_iterator it = std::begin(items); + it != std::end(items); ++it) { + if (!first) + ss << sep; + else + first = false; + + ss << op(*it); + } + + return ss.str(); +} + +template +std::string join(const Container &items, const std::string &sep) +{ + std::ostringstream ss; + bool first = true; + + for (typename Container::const_iterator it = std::begin(items); + it != std::end(items); ++it) { + if (!first) + ss << sep; + else + first = false; + + ss << *it; + } + + return ss.str(); +} +#else +template +std::string join(const Container &items, const std::string &sep, UnaryOp op = nullptr); +#endif + +namespace details { + +class StringSplitter +{ +public: + StringSplitter(const std::string &str, const std::string &delim); + + class iterator + { + public: + iterator(const StringSplitter *ss, std::string::size_type pos); + + iterator &operator++(); + std::string operator*() const; + bool operator!=(const iterator &other) const; + + private: + const StringSplitter *ss_; + std::string::size_type pos_; + std::string::size_type next_; + }; + + iterator begin() const; + iterator end() const; + +private: + std::string str_; + std::string delim_; +}; + +} /* namespace details */ + +details::StringSplitter split(const std::string &str, const std::string &delim); + +std::string toAscii(const std::string &str); + +std::string libcameraBuildPath(); +std::string libcameraSourcePath(); + +constexpr unsigned int alignDown(unsigned int value, unsigned int alignment) +{ + return value / alignment * alignment; +} + +constexpr unsigned int alignUp(unsigned int value, unsigned int alignment) +{ + return (value + alignment - 1) / alignment * alignment; +} + +namespace details { + +template +struct reverse_adapter { + T &iterable; +}; + +template +auto begin(reverse_adapter r) +{ + return std::rbegin(r.iterable); +} + +template +auto end(reverse_adapter r) +{ + return std::rend(r.iterable); +} + +} /* namespace details */ + +template +details::reverse_adapter reverse(T &&iterable) +{ + return { iterable }; +} + +namespace details { + +template +class enumerate_iterator +{ +private: + using base_reference = typename std::iterator_traits::reference; + +public: + using difference_type = typename std::iterator_traits::difference_type; + using value_type = std::pair; + using pointer = value_type *; + using reference = value_type &; + using iterator_category = std::input_iterator_tag; + + explicit enumerate_iterator(Base iter) + : current_(iter), pos_(0) + { + } + + enumerate_iterator &operator++() + { + ++current_; + ++pos_; + return *this; + } + + bool operator!=(const enumerate_iterator &other) const + { + return current_ != other.current_; + } + + value_type operator*() const + { + return { pos_, *current_ }; + } + +private: + Base current_; + difference_type pos_; +}; + +template +class enumerate_adapter +{ +public: + using iterator = enumerate_iterator; + + enumerate_adapter(Base begin, Base end) + : begin_(begin), end_(end) + { + } + + iterator begin() const + { + return iterator{ begin_ }; + } + + iterator end() const + { + return iterator{ end_ }; + } + +private: + const Base begin_; + const Base end_; +}; + +} /* namespace details */ + +template +auto enumerate(T &iterable) -> details::enumerate_adapter +{ + return { std::begin(iterable), std::end(iterable) }; +} + +#ifndef __DOXYGEN__ +template +auto enumerate(T (&iterable)[N]) -> details::enumerate_adapter +{ + return { std::begin(iterable), std::end(iterable) }; +} +#endif + +class Duration : public std::chrono::duration +{ + using BaseDuration = std::chrono::duration; + +public: + Duration() = default; + + template + constexpr Duration(const std::chrono::duration &d) + : BaseDuration(d) + { + } + + template + double get() const + { + auto const c = std::chrono::duration_cast>(*this); + return c.count(); + } + + explicit constexpr operator bool() const + { + return *this != BaseDuration::zero(); + } +}; + +} /* namespace utils */ + +#ifndef __DOXYGEN__ +template +std::basic_ostream &operator<<(std::basic_ostream &os, + const utils::Duration &d); +#endif + +} /* namespace libcamera */ + +#endif /* __LIBCAMERA_BASE_UTILS_H__ */ diff --git a/include/libcamera/internal/log.h b/include/libcamera/internal/log.h index b8efb161..9c2beab6 100644 --- a/include/libcamera/internal/log.h +++ b/include/libcamera/internal/log.h @@ -12,7 +12,7 @@ #include -#include "libcamera/internal/utils.h" +#include namespace libcamera { diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build index 205b36a9..1348e926 100644 --- a/include/libcamera/internal/meson.build +++ b/include/libcamera/internal/meson.build @@ -43,7 +43,6 @@ libcamera_internal_headers = files([ 'sysfs.h', 'thread.h', 'timer.h', - 'utils.h', 'v4l2_device.h', 'v4l2_pixelformat.h', 'v4l2_subdevice.h', diff --git a/include/libcamera/internal/thread.h b/include/libcamera/internal/thread.h index 25d0308d..9662e28b 100644 --- a/include/libcamera/internal/thread.h +++ b/include/libcamera/internal/thread.h @@ -14,8 +14,9 @@ #include +#include + #include "libcamera/internal/message.h" -#include "libcamera/internal/utils.h" namespace libcamera { diff --git a/include/libcamera/internal/utils.h b/include/libcamera/internal/utils.h deleted file mode 100644 index 15beb0f4..00000000 --- a/include/libcamera/internal/utils.h +++ /dev/null @@ -1,355 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2018, Google Inc. - * - * utils.h - Miscellaneous utility functions - */ -#ifndef __LIBCAMERA_INTERNAL_UTILS_H__ -#define __LIBCAMERA_INTERNAL_UTILS_H__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef __DOXYGEN__ - -/* uClibc and uClibc-ng don't provide O_TMPFILE */ -#ifndef O_TMPFILE -#define O_TMPFILE (020000000 | O_DIRECTORY) -#endif - -#endif - -namespace libcamera { - -namespace utils { - -const char *basename(const char *path); - -char *secure_getenv(const char *name); -std::string dirname(const std::string &path); - -template -std::vector map_keys(const T &map) -{ - std::vector keys; - std::transform(map.begin(), map.end(), std::back_inserter(keys), - [](const auto &value) { return value.first; }); - return keys; -} - -template -unsigned int set_overlap(InputIt1 first1, InputIt1 last1, - InputIt2 first2, InputIt2 last2) -{ - unsigned int count = 0; - - while (first1 != last1 && first2 != last2) { - if (*first1 < *first2) { - ++first1; - } else { - if (!(*first2 < *first1)) - count++; - ++first2; - } - } - - return count; -} - -using clock = std::chrono::steady_clock; -using duration = std::chrono::steady_clock::duration; -using time_point = std::chrono::steady_clock::time_point; - -struct timespec duration_to_timespec(const duration &value); -std::string time_point_to_string(const time_point &time); - -#ifndef __DOXYGEN__ -struct _hex { - uint64_t v; - unsigned int w; -}; - -std::basic_ostream> & -operator<<(std::basic_ostream> &stream, const _hex &h); -#endif - -template -_hex hex(T value, unsigned int width = 0); - -#ifndef __DOXYGEN__ -template<> -inline _hex hex(int32_t value, unsigned int width) -{ - return { static_cast(value), width ? width : 8 }; -} - -template<> -inline _hex hex(uint32_t value, unsigned int width) -{ - return { static_cast(value), width ? width : 8 }; -} - -template<> -inline _hex hex(int64_t value, unsigned int width) -{ - return { static_cast(value), width ? width : 16 }; -} - -template<> -inline _hex hex(uint64_t value, unsigned int width) -{ - return { static_cast(value), width ? width : 16 }; -} -#endif - -size_t strlcpy(char *dst, const char *src, size_t size); - -#ifndef __DOXYGEN__ -template -std::string join(const Container &items, const std::string &sep, UnaryOp op) -{ - std::ostringstream ss; - bool first = true; - - for (typename Container::const_iterator it = std::begin(items); - it != std::end(items); ++it) { - if (!first) - ss << sep; - else - first = false; - - ss << op(*it); - } - - return ss.str(); -} - -template -std::string join(const Container &items, const std::string &sep) -{ - std::ostringstream ss; - bool first = true; - - for (typename Container::const_iterator it = std::begin(items); - it != std::end(items); ++it) { - if (!first) - ss << sep; - else - first = false; - - ss << *it; - } - - return ss.str(); -} -#else -template -std::string join(const Container &items, const std::string &sep, UnaryOp op = nullptr); -#endif - -namespace details { - -class StringSplitter -{ -public: - StringSplitter(const std::string &str, const std::string &delim); - - class iterator - { - public: - iterator(const StringSplitter *ss, std::string::size_type pos); - - iterator &operator++(); - std::string operator*() const; - bool operator!=(const iterator &other) const; - - private: - const StringSplitter *ss_; - std::string::size_type pos_; - std::string::size_type next_; - }; - - iterator begin() const; - iterator end() const; - -private: - std::string str_; - std::string delim_; -}; - -} /* namespace details */ - -details::StringSplitter split(const std::string &str, const std::string &delim); - -std::string toAscii(const std::string &str); - -std::string libcameraBuildPath(); -std::string libcameraSourcePath(); - -constexpr unsigned int alignDown(unsigned int value, unsigned int alignment) -{ - return value / alignment * alignment; -} - -constexpr unsigned int alignUp(unsigned int value, unsigned int alignment) -{ - return (value + alignment - 1) / alignment * alignment; -} - -namespace details { - -template -struct reverse_adapter { - T &iterable; -}; - -template -auto begin(reverse_adapter r) -{ - return std::rbegin(r.iterable); -} - -template -auto end(reverse_adapter r) -{ - return std::rend(r.iterable); -} - -} /* namespace details */ - -template -details::reverse_adapter reverse(T &&iterable) -{ - return { iterable }; -} - -namespace details { - -template -class enumerate_iterator -{ -private: - using base_reference = typename std::iterator_traits::reference; - -public: - using difference_type = typename std::iterator_traits::difference_type; - using value_type = std::pair; - using pointer = value_type *; - using reference = value_type &; - using iterator_category = std::input_iterator_tag; - - explicit enumerate_iterator(Base iter) - : current_(iter), pos_(0) - { - } - - enumerate_iterator &operator++() - { - ++current_; - ++pos_; - return *this; - } - - bool operator!=(const enumerate_iterator &other) const - { - return current_ != other.current_; - } - - value_type operator*() const - { - return { pos_, *current_ }; - } - -private: - Base current_; - difference_type pos_; -}; - -template -class enumerate_adapter -{ -public: - using iterator = enumerate_iterator; - - enumerate_adapter(Base begin, Base end) - : begin_(begin), end_(end) - { - } - - iterator begin() const - { - return iterator{ begin_ }; - } - - iterator end() const - { - return iterator{ end_ }; - } - -private: - const Base begin_; - const Base end_; -}; - -} /* namespace details */ - -template -auto enumerate(T &iterable) -> details::enumerate_adapter -{ - return { std::begin(iterable), std::end(iterable) }; -} - -#ifndef __DOXYGEN__ -template -auto enumerate(T (&iterable)[N]) -> details::enumerate_adapter -{ - return { std::begin(iterable), std::end(iterable) }; -} -#endif - -class Duration : public std::chrono::duration -{ - using BaseDuration = std::chrono::duration; - -public: - Duration() = default; - - template - constexpr Duration(const std::chrono::duration &d) - : BaseDuration(d) - { - } - - template - double get() const - { - auto const c = std::chrono::duration_cast>(*this); - return c.count(); - } - - explicit constexpr operator bool() const - { - return *this != BaseDuration::zero(); - } -}; - -} /* namespace utils */ - -#ifndef __DOXYGEN__ -template -std::basic_ostream &operator<<(std::basic_ostream &os, - const utils::Duration &d); -#endif - -} /* namespace libcamera */ - -#endif /* __LIBCAMERA_INTERNAL_UTILS_H__ */ diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp index 4bd125d7..6243c07e 100644 --- a/src/android/camera_device.cpp +++ b/src/android/camera_device.cpp @@ -20,9 +20,10 @@ #include #include +#include + #include "libcamera/internal/log.h" #include "libcamera/internal/thread.h" -#include "libcamera/internal/utils.h" #include "system/graphics.h" diff --git a/src/android/jpeg/exif.cpp b/src/android/jpeg/exif.cpp index 922086cd..747f1cfa 100644 --- a/src/android/jpeg/exif.cpp +++ b/src/android/jpeg/exif.cpp @@ -14,8 +14,9 @@ #include #include +#include + #include "libcamera/internal/log.h" -#include "libcamera/internal/utils.h" using namespace libcamera; diff --git a/src/ipa/ipu3/ipu3_agc.h b/src/ipa/ipu3/ipu3_agc.h index a5a78233..60c7a84f 100644 --- a/src/ipa/ipu3/ipu3_agc.h +++ b/src/ipa/ipu3/ipu3_agc.h @@ -12,9 +12,9 @@ #include -#include +#include -#include "libcamera/internal/utils.h" +#include #include "libipa/algorithm.h" diff --git a/src/ipa/raspberrypi/cam_helper.hpp b/src/ipa/raspberrypi/cam_helper.hpp index f53f5c39..221898ce 100644 --- a/src/ipa/raspberrypi/cam_helper.hpp +++ b/src/ipa/raspberrypi/cam_helper.hpp @@ -15,7 +15,8 @@ #include "controller/metadata.hpp" #include "md_parser.hpp" -#include "libcamera/internal/utils.h" +#include + #include "libcamera/internal/v4l2_videodevice.h" namespace RPiController { diff --git a/src/ipa/raspberrypi/controller/agc_algorithm.hpp b/src/ipa/raspberrypi/controller/agc_algorithm.hpp index 134bbcda..61595ea2 100644 --- a/src/ipa/raspberrypi/controller/agc_algorithm.hpp +++ b/src/ipa/raspberrypi/controller/agc_algorithm.hpp @@ -6,7 +6,8 @@ */ #pragma once -#include "libcamera/internal/utils.h" +#include + #include "algorithm.hpp" namespace RPiController { diff --git a/src/ipa/raspberrypi/controller/agc_status.h b/src/ipa/raspberrypi/controller/agc_status.h index 5d50e177..20cb1b62 100644 --- a/src/ipa/raspberrypi/controller/agc_status.h +++ b/src/ipa/raspberrypi/controller/agc_status.h @@ -6,7 +6,7 @@ */ #pragma once -#include "libcamera/internal/utils.h" +#include // The AGC algorithm should post the following structure into the image's // "agc.status" metadata. diff --git a/src/ipa/raspberrypi/controller/camera_mode.h b/src/ipa/raspberrypi/controller/camera_mode.h index 2aa2335d..65888230 100644 --- a/src/ipa/raspberrypi/controller/camera_mode.h +++ b/src/ipa/raspberrypi/controller/camera_mode.h @@ -8,7 +8,7 @@ #include -#include "libcamera/internal/utils.h" +#include // Description of a "camera mode", holding enough information for control // algorithms to adapt their behaviour to the different modes of the camera, diff --git a/src/ipa/raspberrypi/controller/device_status.h b/src/ipa/raspberrypi/controller/device_status.h index 131b4cd3..f7423524 100644 --- a/src/ipa/raspberrypi/controller/device_status.h +++ b/src/ipa/raspberrypi/controller/device_status.h @@ -6,7 +6,7 @@ */ #pragma once -#include "libcamera/internal/utils.h" +#include // Definition of "device metadata" which stores things like shutter time and // analogue gain that downstream control algorithms will want to know. diff --git a/src/ipa/raspberrypi/controller/rpi/agc.hpp b/src/ipa/raspberrypi/controller/rpi/agc.hpp index 75078948..85067dc6 100644 --- a/src/ipa/raspberrypi/controller/rpi/agc.hpp +++ b/src/ipa/raspberrypi/controller/rpi/agc.hpp @@ -9,7 +9,7 @@ #include #include -#include "libcamera/internal/utils.h" +#include #include "../agc_algorithm.hpp" #include "../agc_status.h" diff --git a/src/ipa/raspberrypi/controller/rpi/lux.hpp b/src/ipa/raspberrypi/controller/rpi/lux.hpp index 45c84439..3ebd35d1 100644 --- a/src/ipa/raspberrypi/controller/rpi/lux.hpp +++ b/src/ipa/raspberrypi/controller/rpi/lux.hpp @@ -8,7 +8,7 @@ #include -#include "libcamera/internal/utils.h" +#include #include "../lux_status.h" #include "../algorithm.hpp" diff --git a/src/libcamera/base/meson.build b/src/libcamera/base/meson.build index e8384602..6d9ec374 100644 --- a/src/libcamera/base/meson.build +++ b/src/libcamera/base/meson.build @@ -1,6 +1,7 @@ # SPDX-License-Identifier: CC0-1.0 libcamera_base_sources = files([ + 'utils.cpp', ]) libcamera_base_deps = [ diff --git a/src/libcamera/base/utils.cpp b/src/libcamera/base/utils.cpp new file mode 100644 index 00000000..45b92b67 --- /dev/null +++ b/src/libcamera/base/utils.cpp @@ -0,0 +1,463 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * utils.cpp - Miscellaneous utility functions + */ + +#include + +#include +#include +#include +#include +#include + +/** + * \file base/utils.h + * \brief Miscellaneous utility functions + */ + +namespace libcamera { + +namespace utils { + +/** + * \brief Strip the directory prefix from the path + * \param[in] path The path to process + * + * basename is implemented differently across different C libraries. This + * implementation matches the one provided by the GNU libc, and does not + * modify its input parameter. + * + * \return A pointer within the given path without any leading directory + * components. + */ +const char *basename(const char *path) +{ + const char *base = strrchr(path, '/'); + return base ? base + 1 : path; +} + +/** + * \brief Get an environment variable + * \param[in] name The name of the variable to return + * + * The environment list is searched to find the variable 'name', and the + * corresponding string is returned. + * + * If 'secure execution' is required then this function always returns NULL to + * avoid vulnerabilities that could occur if set-user-ID or set-group-ID + * programs accidentally trust the environment. + * + * \note Not all platforms may support the features required to implement the + * secure execution check, in which case this function behaves as getenv(). A + * notable example of this is Android. + * + * \return A pointer to the value in the environment or NULL if the requested + * environment variable doesn't exist or if secure execution is required. + */ +char *secure_getenv(const char *name) +{ +#if HAVE_SECURE_GETENV + return ::secure_getenv(name); +#else +#if HAVE_ISSETUGID + if (issetugid()) + return NULL; +#endif + return getenv(name); +#endif +} + +/** + * \brief Identify the dirname portion of a path + * \param[in] path The full path to parse + * + * This function conforms with the behaviour of the %dirname() function as + * defined by POSIX. + * + * \return A string of the directory component of the path + */ +std::string dirname(const std::string &path) +{ + if (path.empty()) + return "."; + + /* + * Skip all trailing slashes. If the path is only made of slashes, + * return "/". + */ + size_t pos = path.size() - 1; + while (path[pos] == '/') { + if (!pos) + return "/"; + pos--; + } + + /* + * Find the previous slash. If the path contains no non-trailing slash, + * return ".". + */ + while (path[pos] != '/') { + if (!pos) + return "."; + pos--; + } + + /* + * Return the directory name up to (but not including) any trailing + * slash. If this would result in an empty string, return "/". + */ + while (path[pos] == '/') { + if (!pos) + return "/"; + pos--; + } + + return path.substr(0, pos + 1); +} + +/** + * \fn std::vector map_keys(const T &map) + * \brief Retrieve the keys of a std::map<> + * \param[in] map The map whose keys to retrieve + * \return A std::vector<> containing the keys of \a map + */ + +/** + * \fn libcamera::utils::set_overlap(InputIt1 first1, InputIt1 last1, + * InputIt2 first2, InputIt2 last2) + * \brief Count the number of elements in the intersection of two ranges + * + * Count the number of elements in the intersection of the sorted ranges [\a + * first1, \a last1) and [\a first1, \a last2). Elements are compared using + * operator< and the ranges must be sorted with respect to the same. + * + * \return The number of elements in the intersection of the two ranges + */ + +/** + * \typedef clock + * \brief The libcamera clock (monotonic) + */ + +/** + * \typedef duration + * \brief The libcamera duration related to libcamera::utils::clock + */ + +/** + * \typedef time_point + * \brief The libcamera time point related to libcamera::utils::clock + */ + +/** + * \brief Convert a duration to a timespec + * \param[in] value The duration + * \return A timespec expressing the duration + */ +struct timespec duration_to_timespec(const duration &value) +{ + uint64_t nsecs = std::chrono::duration_cast(value).count(); + struct timespec ts; + ts.tv_sec = nsecs / 1000000000ULL; + ts.tv_nsec = nsecs % 1000000000ULL; + return ts; +} + +/** + * \brief Convert a time point to a string representation + * \param[in] time The time point + * \return A string representing the time point in hh:mm:ss.nanoseconds format + */ +std::string time_point_to_string(const time_point &time) +{ + uint64_t nsecs = std::chrono::duration_cast(time.time_since_epoch()).count(); + unsigned int secs = nsecs / 1000000000ULL; + + std::ostringstream ossTimestamp; + ossTimestamp.fill('0'); + ossTimestamp << secs / (60 * 60) << ":" + << std::setw(2) << (secs / 60) % 60 << ":" + << std::setw(2) << secs % 60 << "." + << std::setw(9) << nsecs % 1000000000ULL; + return ossTimestamp.str(); +} + +std::basic_ostream> & +operator<<(std::basic_ostream> &stream, const _hex &h) +{ + stream << "0x"; + + std::ostream::fmtflags flags = stream.setf(std::ios_base::hex, + std::ios_base::basefield); + std::streamsize width = stream.width(h.w); + char fill = stream.fill('0'); + + stream << h.v; + + stream.flags(flags); + stream.width(width); + stream.fill(fill); + + return stream; +} + +/** + * \fn hex(T value, unsigned int width) + * \brief Write an hexadecimal value to an output string + * \param value The value + * \param width The width + * + * Return an object of unspecified type such that, if \a os is the name of an + * output stream of type std::ostream, and T is an integer type, then the + * expression + * + * \code{.cpp} + * os << utils::hex(value) + * \endcode + * + * will output the \a value to the stream in hexadecimal form with the base + * prefix and the filling character set to '0'. The field width is set to \a + * width if specified to a non-zero value, or to the native width of type T + * otherwise. The \a os stream configuration is not modified. + */ + +/** + * \brief Copy a string with a size limit + * \param[in] dst The destination string + * \param[in] src The source string + * \param[in] size The size of the destination string + * + * This function copies the null-terminated string \a src to \a dst with a limit + * of \a size - 1 characters, and null-terminates the result if \a size is + * larger than 0. If \a src is larger than \a size - 1, \a dst is truncated. + * + * \return The size of \a src + */ +size_t strlcpy(char *dst, const char *src, size_t size) +{ + if (size) { + strncpy(dst, src, size); + dst[size - 1] = '\0'; + } + + return strlen(src); +} + +details::StringSplitter::StringSplitter(const std::string &str, const std::string &delim) + : str_(str), delim_(delim) +{ +} + +details::StringSplitter::iterator::iterator(const details::StringSplitter *ss, std::string::size_type pos) + : ss_(ss), pos_(pos) +{ + next_ = ss_->str_.find(ss_->delim_, pos_); +} + +details::StringSplitter::iterator &details::StringSplitter::iterator::operator++() +{ + pos_ = next_; + if (pos_ != std::string::npos) { + pos_ += ss_->delim_.length(); + next_ = ss_->str_.find(ss_->delim_, pos_); + } + + return *this; +} + +std::string details::StringSplitter::iterator::operator*() const +{ + std::string::size_type count; + count = next_ != std::string::npos ? next_ - pos_ : next_; + return ss_->str_.substr(pos_, count); +} + +bool details::StringSplitter::iterator::operator!=(const details::StringSplitter::iterator &other) const +{ + return pos_ != other.pos_; +} + +details::StringSplitter::iterator details::StringSplitter::begin() const +{ + return iterator(this, 0); +} + +details::StringSplitter::iterator details::StringSplitter::end() const +{ + return iterator(this, std::string::npos); +} + +/** + * \fn template \ + * std::string utils::join(const Container &items, const std::string &sep, UnaryOp op) + * \brief Join elements of a container in a string with a separator + * \param[in] items The container + * \param[in] sep The separator to add between elements + * \param[in] op A function that converts individual elements to strings + * + * This function joins all elements in the \a items container into a string and + * returns it. The \a sep separator is added between elements. If the container + * elements are not implicitly convertible to std::string, the \a op function + * shall be provided to perform conversion of elements to std::string. + * + * \return A string that concatenates all elements in the container + */ + +/** + * \fn split(const std::string &str, const std::string &delim) + * \brief Split a string based on a delimiter + * \param[in] str The string to split + * \param[in] delim The delimiter string + * + * This function splits the string \a str into substrings based on the + * delimiter \a delim. It returns an object of unspecified type that can be + * used in a range-based for loop and yields the substrings in sequence. + * + * \return An object that can be used in a range-based for loop to iterate over + * the substrings + */ +details::StringSplitter split(const std::string &str, const std::string &delim) +{ + /** \todo Try to avoid copies of str and delim */ + return details::StringSplitter(str, delim); +} + +/** + * \brief Remove any non-ASCII characters from a string + * \param[in] str The string to strip + * + * Remove all non-ASCII characters from a string. + * + * \return A string equal to \a str stripped out of all non-ASCII characters + */ +std::string toAscii(const std::string &str) +{ + std::string ret; + for (const char &c : str) + if (!(c & 0x80)) + ret += c; + return ret; +} + +/** + * \fn alignDown(unsigned int value, unsigned int alignment) + * \brief Align \a value down to \a alignment + * \param[in] value The value to align + * \param[in] alignment The alignment + * \return The value rounded down to the nearest multiple of \a alignment + */ + +/** + * \fn alignUp(unsigned int value, unsigned int alignment) + * \brief Align \a value up to \a alignment + * \param[in] value The value to align + * \param[in] alignment The alignment + * \return The value rounded up to the nearest multiple of \a alignment + */ + +/** + * \fn reverse(T &&iterable) + * \brief Wrap an iterable to reverse iteration in a range-based loop + * \param[in] iterable The iterable + * \return A value of unspecified type that, when used in a range-based for + * loop, will cause the loop to iterate over the \a iterable in reverse order + */ + +/** + * \fn enumerate(T &iterable) + * \brief Wrap an iterable to enumerate index and value in a range-based loop + * \param[in] iterable The iterable + * + * Range-based for loops are handy and widely preferred in C++, but are limited + * in their ability to replace for loops that require access to a loop counter. + * The enumerate() function solves this problem by wrapping the \a iterable in + * an adapter that, when used as a range-expression, will provide iterators + * whose value_type is a pair of index and value reference. + * + * The iterable must support std::begin() and std::end(). This includes all + * containers provided by the standard C++ library, as well as C-style arrays. + * + * A typical usage pattern would use structured binding to store the index and + * value in two separate variables: + * + * \code{.cpp} + * std::vector values = ...; + * + * for (auto [index, value] : utils::enumerate(values)) { + * ... + * } + * \endcode + * + * Note that the argument to enumerate() has to be an lvalue, as the lifetime + * of any rvalue would not be extended to the whole for loop. The compiler will + * complain if an rvalue is passed to the function, in which case it should be + * stored in a local variable before the loop. + * + * \return A value of unspecified type that, when used in a range-based for + * loop, iterates over an indexed view of the \a iterable + */ + +/** + * \class Duration + * \brief Helper class from std::chrono::duration that represents a time + * duration in nanoseconds with double precision + */ + +/** + * \fn Duration::Duration(const std::chrono::duration &d) + * \brief Construct a Duration by converting an arbitrary std::chrono::duration + * \param[in] d The std::chrono::duration object to convert from + * + * The constructed \a Duration object is internally represented in double + * precision with nanoseconds ticks. + */ + +/** + * \fn Duration::get() + * \brief Retrieve the tick count, converted to the timebase provided by the + * template argument Period of type \a std::ratio + * + * A typical usage example is given below: + * + * \code{.cpp} + * utils::Duration d = 5s; + * double d_in_ms = d.get(); + * \endcode + * + * \return The tick count of the Duration expressed in \a Period + */ + +/** + * \fn Duration::operator bool() + * \brief Boolean operator to test if a \a Duration holds a non-zero time value + * + * \return True if \a Duration is a non-zero time value, False otherwise + */ + +} /* namespace utils */ + +#ifndef __DOXYGEN__ +template +std::basic_ostream &operator<<(std::basic_ostream &os, + const utils::Duration &d) +{ + std::basic_ostringstream s; + + s.flags(os.flags()); + s.imbue(os.getloc()); + s.setf(std::ios_base::fixed, std::ios_base::floatfield); + s.precision(2); + s << d.get() << "us"; + return os << s.str(); +} + +template +std::basic_ostream> & +operator<< >(std::basic_ostream> &os, + const utils::Duration &d); +#endif + +} /* namespace libcamera */ diff --git a/src/libcamera/camera_manager.cpp b/src/libcamera/camera_manager.cpp index 1ecf2b07..a3784db6 100644 --- a/src/libcamera/camera_manager.cpp +++ b/src/libcamera/camera_manager.cpp @@ -12,13 +12,14 @@ #include +#include + #include "libcamera/internal/device_enumerator.h" #include "libcamera/internal/ipa_manager.h" #include "libcamera/internal/log.h" #include "libcamera/internal/pipeline_handler.h" #include "libcamera/internal/process.h" #include "libcamera/internal/thread.h" -#include "libcamera/internal/utils.h" /** * \file camera_manager.h diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp index 3e135353..94dcf4f9 100644 --- a/src/libcamera/camera_sensor.cpp +++ b/src/libcamera/camera_sensor.cpp @@ -18,11 +18,12 @@ #include +#include + #include "libcamera/internal/bayer_format.h" #include "libcamera/internal/camera_sensor_properties.h" #include "libcamera/internal/formats.h" #include "libcamera/internal/sysfs.h" -#include "libcamera/internal/utils.h" /** * \file camera_sensor.h diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp index 5aef4e71..7df372ad 100644 --- a/src/libcamera/controls.cpp +++ b/src/libcamera/controls.cpp @@ -12,9 +12,10 @@ #include #include +#include + #include "libcamera/internal/control_validator.h" #include "libcamera/internal/log.h" -#include "libcamera/internal/utils.h" /** * \file controls.h diff --git a/src/libcamera/event_dispatcher_poll.cpp b/src/libcamera/event_dispatcher_poll.cpp index 456c6def..0b6aee18 100644 --- a/src/libcamera/event_dispatcher_poll.cpp +++ b/src/libcamera/event_dispatcher_poll.cpp @@ -16,11 +16,12 @@ #include #include +#include + #include "libcamera/internal/event_notifier.h" #include "libcamera/internal/log.h" #include "libcamera/internal/thread.h" #include "libcamera/internal/timer.h" -#include "libcamera/internal/utils.h" /** * \file event_dispatcher_poll.h diff --git a/src/libcamera/ipa_manager.cpp b/src/libcamera/ipa_manager.cpp index 93d02d94..263cacd6 100644 --- a/src/libcamera/ipa_manager.cpp +++ b/src/libcamera/ipa_manager.cpp @@ -12,12 +12,13 @@ #include #include +#include + #include "libcamera/internal/file.h" #include "libcamera/internal/ipa_module.h" #include "libcamera/internal/ipa_proxy.h" #include "libcamera/internal/log.h" #include "libcamera/internal/pipeline_handler.h" -#include "libcamera/internal/utils.h" /** * \file ipa_manager.h diff --git a/src/libcamera/ipa_module.cpp b/src/libcamera/ipa_module.cpp index f53e529b..a4e7fb86 100644 --- a/src/libcamera/ipa_module.cpp +++ b/src/libcamera/ipa_module.cpp @@ -23,10 +23,11 @@ #include +#include + #include "libcamera/internal/file.h" #include "libcamera/internal/log.h" #include "libcamera/internal/pipeline_handler.h" -#include "libcamera/internal/utils.h" /** * \file ipa_module.h diff --git a/src/libcamera/ipa_proxy.cpp b/src/libcamera/ipa_proxy.cpp index b70fde58..ca980ec7 100644 --- a/src/libcamera/ipa_proxy.cpp +++ b/src/libcamera/ipa_proxy.cpp @@ -12,9 +12,10 @@ #include #include +#include + #include "libcamera/internal/ipa_module.h" #include "libcamera/internal/log.h" -#include "libcamera/internal/utils.h" /** * \file ipa_proxy.h diff --git a/src/libcamera/log.cpp b/src/libcamera/log.cpp index 74829a56..5ff0e901 100644 --- a/src/libcamera/log.cpp +++ b/src/libcamera/log.cpp @@ -23,8 +23,9 @@ #include +#include + #include "libcamera/internal/thread.h" -#include "libcamera/internal/utils.h" /** * \file log.h diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 655c0c16..b70688d8 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -52,7 +52,6 @@ libcamera_sources = files([ 'thread.cpp', 'timer.cpp', 'transform.cpp', - 'utils.cpp', 'v4l2_device.cpp', 'v4l2_pixelformat.cpp', 'v4l2_subdevice.cpp', diff --git a/src/libcamera/object.cpp b/src/libcamera/object.cpp index 5e6b73f9..51cac64e 100644 --- a/src/libcamera/object.cpp +++ b/src/libcamera/object.cpp @@ -11,11 +11,12 @@ #include +#include + #include "libcamera/internal/log.h" #include "libcamera/internal/message.h" #include "libcamera/internal/semaphore.h" #include "libcamera/internal/thread.h" -#include "libcamera/internal/utils.h" /** * \file object.h diff --git a/src/libcamera/pipeline/ipu3/imgu.cpp b/src/libcamera/pipeline/ipu3/imgu.cpp index 4eb3f7b7..32d143a8 100644 --- a/src/libcamera/pipeline/ipu3/imgu.cpp +++ b/src/libcamera/pipeline/ipu3/imgu.cpp @@ -16,9 +16,10 @@ #include #include +#include + #include "libcamera/internal/log.h" #include "libcamera/internal/media_device.h" -#include "libcamera/internal/utils.h" namespace libcamera { diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 6c93bc6d..6b43ad2f 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -20,6 +20,8 @@ #include #include +#include + #include "libcamera/internal/camera_sensor.h" #include "libcamera/internal/delayed_controls.h" #include "libcamera/internal/device_enumerator.h" @@ -27,7 +29,6 @@ #include "libcamera/internal/log.h" #include "libcamera/internal/media_device.h" #include "libcamera/internal/pipeline_handler.h" -#include "libcamera/internal/utils.h" #include "cio2.h" #include "frames.h" diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index 4e26a193..082eb1ee 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -24,6 +24,8 @@ #include #include +#include + #include #include @@ -35,7 +37,6 @@ #include "libcamera/internal/ipa_manager.h" #include "libcamera/internal/media_device.h" #include "libcamera/internal/pipeline_handler.h" -#include "libcamera/internal/utils.h" #include "libcamera/internal/v4l2_videodevice.h" #include "dma_heaps.h" diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index 6699839c..c625d724 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -24,6 +24,8 @@ #include #include +#include + #include "libcamera/internal/camera_sensor.h" #include "libcamera/internal/delayed_controls.h" #include "libcamera/internal/device_enumerator.h" @@ -31,7 +33,6 @@ #include "libcamera/internal/log.h" #include "libcamera/internal/media_device.h" #include "libcamera/internal/pipeline_handler.h" -#include "libcamera/internal/utils.h" #include "libcamera/internal/v4l2_subdevice.h" #include "libcamera/internal/v4l2_videodevice.h" diff --git a/src/libcamera/pipeline/simple/converter.cpp b/src/libcamera/pipeline/simple/converter.cpp index 68644ef6..589f185b 100644 --- a/src/libcamera/pipeline/simple/converter.cpp +++ b/src/libcamera/pipeline/simple/converter.cpp @@ -15,9 +15,10 @@ #include #include +#include + #include "libcamera/internal/log.h" #include "libcamera/internal/media_device.h" -#include "libcamera/internal/utils.h" #include "libcamera/internal/v4l2_videodevice.h" namespace libcamera { diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp index 12a85b24..d8c17dcc 100644 --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp @@ -19,12 +19,13 @@ #include #include +#include + #include "libcamera/internal/device_enumerator.h" #include "libcamera/internal/log.h" #include "libcamera/internal/media_device.h" #include "libcamera/internal/pipeline_handler.h" #include "libcamera/internal/sysfs.h" -#include "libcamera/internal/utils.h" #include "libcamera/internal/v4l2_videodevice.h" namespace libcamera { diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp index 8bbac008..025ca562 100644 --- a/src/libcamera/pipeline/vimc/vimc.cpp +++ b/src/libcamera/pipeline/vimc/vimc.cpp @@ -23,13 +23,14 @@ #include #include +#include + #include "libcamera/internal/camera_sensor.h" #include "libcamera/internal/device_enumerator.h" #include "libcamera/internal/ipa_manager.h" #include "libcamera/internal/log.h" #include "libcamera/internal/media_device.h" #include "libcamera/internal/pipeline_handler.h" -#include "libcamera/internal/utils.h" #include "libcamera/internal/v4l2_subdevice.h" #include "libcamera/internal/v4l2_videodevice.h" diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp index e507a8bb..6fb2a743 100644 --- a/src/libcamera/pipeline_handler.cpp +++ b/src/libcamera/pipeline_handler.cpp @@ -13,11 +13,12 @@ #include #include +#include + #include "libcamera/internal/device_enumerator.h" #include "libcamera/internal/log.h" #include "libcamera/internal/media_device.h" #include "libcamera/internal/tracepoints.h" -#include "libcamera/internal/utils.h" /** * \file pipeline_handler.h diff --git a/src/libcamera/process.cpp b/src/libcamera/process.cpp index 40a434a6..35091f60 100644 --- a/src/libcamera/process.cpp +++ b/src/libcamera/process.cpp @@ -20,9 +20,10 @@ #include #include +#include + #include "libcamera/internal/event_notifier.h" #include "libcamera/internal/log.h" -#include "libcamera/internal/utils.h" /** * \file process.h diff --git a/src/libcamera/source_paths.cpp b/src/libcamera/source_paths.cpp index 834b698f..19689585 100644 --- a/src/libcamera/source_paths.cpp +++ b/src/libcamera/source_paths.cpp @@ -14,7 +14,7 @@ #include #include -#include "libcamera/internal/utils.h" +#include /** * \file source_paths.h diff --git a/src/libcamera/stream.cpp b/src/libcamera/stream.cpp index f7bafcf8..d5d68427 100644 --- a/src/libcamera/stream.cpp +++ b/src/libcamera/stream.cpp @@ -15,8 +15,9 @@ #include +#include + #include "libcamera/internal/log.h" -#include "libcamera/internal/utils.h" /** * \file stream.h diff --git a/src/libcamera/timer.cpp b/src/libcamera/timer.cpp index c242113a..9496671e 100644 --- a/src/libcamera/timer.cpp +++ b/src/libcamera/timer.cpp @@ -11,11 +11,12 @@ #include +#include + #include "libcamera/internal/event_dispatcher.h" #include "libcamera/internal/log.h" #include "libcamera/internal/message.h" #include "libcamera/internal/thread.h" -#include "libcamera/internal/utils.h" /** * \file timer.h diff --git a/src/libcamera/utils.cpp b/src/libcamera/utils.cpp deleted file mode 100644 index c7ebef68..00000000 --- a/src/libcamera/utils.cpp +++ /dev/null @@ -1,463 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2019, Google Inc. - * - * utils.cpp - Miscellaneous utility functions - */ - -#include "libcamera/internal/utils.h" - -#include -#include -#include -#include -#include - -/** - * \file utils.h - * \brief Miscellaneous utility functions - */ - -namespace libcamera { - -namespace utils { - -/** - * \brief Strip the directory prefix from the path - * \param[in] path The path to process - * - * basename is implemented differently across different C libraries. This - * implementation matches the one provided by the GNU libc, and does not - * modify its input parameter. - * - * \return A pointer within the given path without any leading directory - * components. - */ -const char *basename(const char *path) -{ - const char *base = strrchr(path, '/'); - return base ? base + 1 : path; -} - -/** - * \brief Get an environment variable - * \param[in] name The name of the variable to return - * - * The environment list is searched to find the variable 'name', and the - * corresponding string is returned. - * - * If 'secure execution' is required then this function always returns NULL to - * avoid vulnerabilities that could occur if set-user-ID or set-group-ID - * programs accidentally trust the environment. - * - * \note Not all platforms may support the features required to implement the - * secure execution check, in which case this function behaves as getenv(). A - * notable example of this is Android. - * - * \return A pointer to the value in the environment or NULL if the requested - * environment variable doesn't exist or if secure execution is required. - */ -char *secure_getenv(const char *name) -{ -#if HAVE_SECURE_GETENV - return ::secure_getenv(name); -#else -#if HAVE_ISSETUGID - if (issetugid()) - return NULL; -#endif - return getenv(name); -#endif -} - -/** - * \brief Identify the dirname portion of a path - * \param[in] path The full path to parse - * - * This function conforms with the behaviour of the %dirname() function as - * defined by POSIX. - * - * \return A string of the directory component of the path - */ -std::string dirname(const std::string &path) -{ - if (path.empty()) - return "."; - - /* - * Skip all trailing slashes. If the path is only made of slashes, - * return "/". - */ - size_t pos = path.size() - 1; - while (path[pos] == '/') { - if (!pos) - return "/"; - pos--; - } - - /* - * Find the previous slash. If the path contains no non-trailing slash, - * return ".". - */ - while (path[pos] != '/') { - if (!pos) - return "."; - pos--; - } - - /* - * Return the directory name up to (but not including) any trailing - * slash. If this would result in an empty string, return "/". - */ - while (path[pos] == '/') { - if (!pos) - return "/"; - pos--; - } - - return path.substr(0, pos + 1); -} - -/** - * \fn std::vector map_keys(const T &map) - * \brief Retrieve the keys of a std::map<> - * \param[in] map The map whose keys to retrieve - * \return A std::vector<> containing the keys of \a map - */ - -/** - * \fn libcamera::utils::set_overlap(InputIt1 first1, InputIt1 last1, - * InputIt2 first2, InputIt2 last2) - * \brief Count the number of elements in the intersection of two ranges - * - * Count the number of elements in the intersection of the sorted ranges [\a - * first1, \a last1) and [\a first1, \a last2). Elements are compared using - * operator< and the ranges must be sorted with respect to the same. - * - * \return The number of elements in the intersection of the two ranges - */ - -/** - * \typedef clock - * \brief The libcamera clock (monotonic) - */ - -/** - * \typedef duration - * \brief The libcamera duration related to libcamera::utils::clock - */ - -/** - * \typedef time_point - * \brief The libcamera time point related to libcamera::utils::clock - */ - -/** - * \brief Convert a duration to a timespec - * \param[in] value The duration - * \return A timespec expressing the duration - */ -struct timespec duration_to_timespec(const duration &value) -{ - uint64_t nsecs = std::chrono::duration_cast(value).count(); - struct timespec ts; - ts.tv_sec = nsecs / 1000000000ULL; - ts.tv_nsec = nsecs % 1000000000ULL; - return ts; -} - -/** - * \brief Convert a time point to a string representation - * \param[in] time The time point - * \return A string representing the time point in hh:mm:ss.nanoseconds format - */ -std::string time_point_to_string(const time_point &time) -{ - uint64_t nsecs = std::chrono::duration_cast(time.time_since_epoch()).count(); - unsigned int secs = nsecs / 1000000000ULL; - - std::ostringstream ossTimestamp; - ossTimestamp.fill('0'); - ossTimestamp << secs / (60 * 60) << ":" - << std::setw(2) << (secs / 60) % 60 << ":" - << std::setw(2) << secs % 60 << "." - << std::setw(9) << nsecs % 1000000000ULL; - return ossTimestamp.str(); -} - -std::basic_ostream> & -operator<<(std::basic_ostream> &stream, const _hex &h) -{ - stream << "0x"; - - std::ostream::fmtflags flags = stream.setf(std::ios_base::hex, - std::ios_base::basefield); - std::streamsize width = stream.width(h.w); - char fill = stream.fill('0'); - - stream << h.v; - - stream.flags(flags); - stream.width(width); - stream.fill(fill); - - return stream; -} - -/** - * \fn hex(T value, unsigned int width) - * \brief Write an hexadecimal value to an output string - * \param value The value - * \param width The width - * - * Return an object of unspecified type such that, if \a os is the name of an - * output stream of type std::ostream, and T is an integer type, then the - * expression - * - * \code{.cpp} - * os << utils::hex(value) - * \endcode - * - * will output the \a value to the stream in hexadecimal form with the base - * prefix and the filling character set to '0'. The field width is set to \a - * width if specified to a non-zero value, or to the native width of type T - * otherwise. The \a os stream configuration is not modified. - */ - -/** - * \brief Copy a string with a size limit - * \param[in] dst The destination string - * \param[in] src The source string - * \param[in] size The size of the destination string - * - * This function copies the null-terminated string \a src to \a dst with a limit - * of \a size - 1 characters, and null-terminates the result if \a size is - * larger than 0. If \a src is larger than \a size - 1, \a dst is truncated. - * - * \return The size of \a src - */ -size_t strlcpy(char *dst, const char *src, size_t size) -{ - if (size) { - strncpy(dst, src, size); - dst[size - 1] = '\0'; - } - - return strlen(src); -} - -details::StringSplitter::StringSplitter(const std::string &str, const std::string &delim) - : str_(str), delim_(delim) -{ -} - -details::StringSplitter::iterator::iterator(const details::StringSplitter *ss, std::string::size_type pos) - : ss_(ss), pos_(pos) -{ - next_ = ss_->str_.find(ss_->delim_, pos_); -} - -details::StringSplitter::iterator &details::StringSplitter::iterator::operator++() -{ - pos_ = next_; - if (pos_ != std::string::npos) { - pos_ += ss_->delim_.length(); - next_ = ss_->str_.find(ss_->delim_, pos_); - } - - return *this; -} - -std::string details::StringSplitter::iterator::operator*() const -{ - std::string::size_type count; - count = next_ != std::string::npos ? next_ - pos_ : next_; - return ss_->str_.substr(pos_, count); -} - -bool details::StringSplitter::iterator::operator!=(const details::StringSplitter::iterator &other) const -{ - return pos_ != other.pos_; -} - -details::StringSplitter::iterator details::StringSplitter::begin() const -{ - return iterator(this, 0); -} - -details::StringSplitter::iterator details::StringSplitter::end() const -{ - return iterator(this, std::string::npos); -} - -/** - * \fn template \ - * std::string utils::join(const Container &items, const std::string &sep, UnaryOp op) - * \brief Join elements of a container in a string with a separator - * \param[in] items The container - * \param[in] sep The separator to add between elements - * \param[in] op A function that converts individual elements to strings - * - * This function joins all elements in the \a items container into a string and - * returns it. The \a sep separator is added between elements. If the container - * elements are not implicitly convertible to std::string, the \a op function - * shall be provided to perform conversion of elements to std::string. - * - * \return A string that concatenates all elements in the container - */ - -/** - * \fn split(const std::string &str, const std::string &delim) - * \brief Split a string based on a delimiter - * \param[in] str The string to split - * \param[in] delim The delimiter string - * - * This function splits the string \a str into substrings based on the - * delimiter \a delim. It returns an object of unspecified type that can be - * used in a range-based for loop and yields the substrings in sequence. - * - * \return An object that can be used in a range-based for loop to iterate over - * the substrings - */ -details::StringSplitter split(const std::string &str, const std::string &delim) -{ - /** \todo Try to avoid copies of str and delim */ - return details::StringSplitter(str, delim); -} - -/** - * \brief Remove any non-ASCII characters from a string - * \param[in] str The string to strip - * - * Remove all non-ASCII characters from a string. - * - * \return A string equal to \a str stripped out of all non-ASCII characters - */ -std::string toAscii(const std::string &str) -{ - std::string ret; - for (const char &c : str) - if (!(c & 0x80)) - ret += c; - return ret; -} - -/** - * \fn alignDown(unsigned int value, unsigned int alignment) - * \brief Align \a value down to \a alignment - * \param[in] value The value to align - * \param[in] alignment The alignment - * \return The value rounded down to the nearest multiple of \a alignment - */ - -/** - * \fn alignUp(unsigned int value, unsigned int alignment) - * \brief Align \a value up to \a alignment - * \param[in] value The value to align - * \param[in] alignment The alignment - * \return The value rounded up to the nearest multiple of \a alignment - */ - -/** - * \fn reverse(T &&iterable) - * \brief Wrap an iterable to reverse iteration in a range-based loop - * \param[in] iterable The iterable - * \return A value of unspecified type that, when used in a range-based for - * loop, will cause the loop to iterate over the \a iterable in reverse order - */ - -/** - * \fn enumerate(T &iterable) - * \brief Wrap an iterable to enumerate index and value in a range-based loop - * \param[in] iterable The iterable - * - * Range-based for loops are handy and widely preferred in C++, but are limited - * in their ability to replace for loops that require access to a loop counter. - * The enumerate() function solves this problem by wrapping the \a iterable in - * an adapter that, when used as a range-expression, will provide iterators - * whose value_type is a pair of index and value reference. - * - * The iterable must support std::begin() and std::end(). This includes all - * containers provided by the standard C++ library, as well as C-style arrays. - * - * A typical usage pattern would use structured binding to store the index and - * value in two separate variables: - * - * \code{.cpp} - * std::vector values = ...; - * - * for (auto [index, value] : utils::enumerate(values)) { - * ... - * } - * \endcode - * - * Note that the argument to enumerate() has to be an lvalue, as the lifetime - * of any rvalue would not be extended to the whole for loop. The compiler will - * complain if an rvalue is passed to the function, in which case it should be - * stored in a local variable before the loop. - * - * \return A value of unspecified type that, when used in a range-based for - * loop, iterates over an indexed view of the \a iterable - */ - -/** - * \class Duration - * \brief Helper class from std::chrono::duration that represents a time - * duration in nanoseconds with double precision - */ - -/** - * \fn Duration::Duration(const std::chrono::duration &d) - * \brief Construct a Duration by converting an arbitrary std::chrono::duration - * \param[in] d The std::chrono::duration object to convert from - * - * The constructed \a Duration object is internally represented in double - * precision with nanoseconds ticks. - */ - -/** - * \fn Duration::get() - * \brief Retrieve the tick count, converted to the timebase provided by the - * template argument Period of type \a std::ratio - * - * A typical usage example is given below: - * - * \code{.cpp} - * utils::Duration d = 5s; - * double d_in_ms = d.get(); - * \endcode - * - * \return The tick count of the Duration expressed in \a Period - */ - -/** - * \fn Duration::operator bool() - * \brief Boolean operator to test if a \a Duration holds a non-zero time value - * - * \return True if \a Duration is a non-zero time value, False otherwise - */ - -} /* namespace utils */ - -#ifndef __DOXYGEN__ -template -std::basic_ostream &operator<<(std::basic_ostream &os, - const utils::Duration &d) -{ - std::basic_ostringstream s; - - s.flags(os.flags()); - s.imbue(os.getloc()); - s.setf(std::ios_base::fixed, std::ios_base::floatfield); - s.precision(2); - s << d.get() << "us"; - return os << s.str(); -} - -template -std::basic_ostream> & -operator<< >(std::basic_ostream> &os, - const utils::Duration &d); -#endif - -} /* namespace libcamera */ diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 5660e6ea..facb53e1 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -16,10 +16,11 @@ #include #include +#include + #include "libcamera/internal/event_notifier.h" #include "libcamera/internal/log.h" #include "libcamera/internal/sysfs.h" -#include "libcamera/internal/utils.h" /** * \file v4l2_device.h diff --git a/src/libcamera/v4l2_subdevice.cpp b/src/libcamera/v4l2_subdevice.cpp index 721ff5a9..2c56cfaf 100644 --- a/src/libcamera/v4l2_subdevice.cpp +++ b/src/libcamera/v4l2_subdevice.cpp @@ -19,10 +19,11 @@ #include +#include + #include "libcamera/internal/log.h" #include "libcamera/internal/media_device.h" #include "libcamera/internal/media_object.h" -#include "libcamera/internal/utils.h" /** * \file v4l2_subdevice.h diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index f8bfe595..a5a25507 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -20,9 +20,10 @@ #include #include +#include + #include "libcamera/internal/formats.h" #include "libcamera/internal/log.h" -#include "libcamera/internal/utils.h" #include "v4l2_camera.h" #include "v4l2_camera_file.h" diff --git a/src/v4l2/v4l2_compat_manager.cpp b/src/v4l2/v4l2_compat_manager.cpp index 96dbcdf2..27de6c50 100644 --- a/src/v4l2/v4l2_compat_manager.cpp +++ b/src/v4l2/v4l2_compat_manager.cpp @@ -22,8 +22,9 @@ #include #include +#include + #include "libcamera/internal/log.h" -#include "libcamera/internal/utils.h" #include "v4l2_camera_file.h" diff --git a/test/camera-sensor.cpp b/test/camera-sensor.cpp index 8c7fd1d2..a8dcad82 100644 --- a/test/camera-sensor.cpp +++ b/test/camera-sensor.cpp @@ -10,10 +10,11 @@ #include +#include + #include "libcamera/internal/camera_sensor.h" #include "libcamera/internal/device_enumerator.h" #include "libcamera/internal/media_device.h" -#include "libcamera/internal/utils.h" #include "libcamera/internal/v4l2_subdevice.h" #include "test.h" diff --git a/test/file-descriptor.cpp b/test/file-descriptor.cpp index aa3c896f..85b077a2 100644 --- a/test/file-descriptor.cpp +++ b/test/file-descriptor.cpp @@ -13,7 +13,7 @@ #include -#include "libcamera/internal/utils.h" +#include #include "test.h" diff --git a/test/ipc/unixsocket_ipc.cpp b/test/ipc/unixsocket_ipc.cpp index 3049eaa8..161d09b9 100644 --- a/test/ipc/unixsocket_ipc.cpp +++ b/test/ipc/unixsocket_ipc.cpp @@ -15,6 +15,8 @@ #include #include +#include + #include "libcamera/internal/event_dispatcher.h" #include "libcamera/internal/ipa_data_serializer.h" #include "libcamera/internal/ipc_pipe.h" @@ -22,7 +24,6 @@ #include "libcamera/internal/process.h" #include "libcamera/internal/thread.h" #include "libcamera/internal/timer.h" -#include "libcamera/internal/utils.h" #include "test.h" diff --git a/test/log/log_process.cpp b/test/log/log_process.cpp index c0a1a012..413d9207 100644 --- a/test/log/log_process.cpp +++ b/test/log/log_process.cpp @@ -16,12 +16,13 @@ #include +#include + #include "libcamera/internal/event_dispatcher.h" #include "libcamera/internal/log.h" #include "libcamera/internal/process.h" #include "libcamera/internal/thread.h" #include "libcamera/internal/timer.h" -#include "libcamera/internal/utils.h" #include "test.h" diff --git a/test/pixel-format.cpp b/test/pixel-format.cpp index c4a08f46..0f364f83 100644 --- a/test/pixel-format.cpp +++ b/test/pixel-format.cpp @@ -10,7 +10,7 @@ #include #include -#include "libcamera/internal/utils.h" +#include #include "test.h" diff --git a/test/process/process_test.cpp b/test/process/process_test.cpp index 1279d8c1..a5155bae 100644 --- a/test/process/process_test.cpp +++ b/test/process/process_test.cpp @@ -9,11 +9,12 @@ #include #include +#include + #include "libcamera/internal/event_dispatcher.h" #include "libcamera/internal/process.h" #include "libcamera/internal/thread.h" #include "libcamera/internal/timer.h" -#include "libcamera/internal/utils.h" #include "test.h" diff --git a/test/signal-threads.cpp b/test/signal-threads.cpp index 3c5f3792..8a96b5d2 100644 --- a/test/signal-threads.cpp +++ b/test/signal-threads.cpp @@ -9,9 +9,10 @@ #include #include +#include + #include "libcamera/internal/message.h" #include "libcamera/internal/thread.h" -#include "libcamera/internal/utils.h" #include "test.h" diff --git a/test/utils.cpp b/test/utils.cpp index f170ae4c..9cd2cd07 100644 --- a/test/utils.cpp +++ b/test/utils.cpp @@ -14,7 +14,7 @@ #include #include -#include "libcamera/internal/utils.h" +#include #include "test.h" diff --git a/test/v4l2_subdevice/list_formats.cpp b/test/v4l2_subdevice/list_formats.cpp index 74ec81a8..9cbd7b94 100644 --- a/test/v4l2_subdevice/list_formats.cpp +++ b/test/v4l2_subdevice/list_formats.cpp @@ -10,7 +10,8 @@ #include -#include "libcamera/internal/utils.h" +#include + #include "libcamera/internal/v4l2_subdevice.h" #include "v4l2_subdevice_test.h" diff --git a/test/v4l2_videodevice/formats.cpp b/test/v4l2_videodevice/formats.cpp index 255446fe..6c052622 100644 --- a/test/v4l2_videodevice/formats.cpp +++ b/test/v4l2_videodevice/formats.cpp @@ -8,7 +8,8 @@ #include #include -#include "libcamera/internal/utils.h" +#include + #include "libcamera/internal/v4l2_videodevice.h" #include "v4l2_videodevice_test.h" -- cgit v1.2.1