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 --- 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 +- 27 files changed, 509 insertions(+), 487 deletions(-) create mode 100644 src/libcamera/base/utils.cpp delete mode 100644 src/libcamera/utils.cpp (limited to 'src/libcamera') 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 -- cgit v1.2.1