libcamera v0.0.0+3240-f2a18172-dirty (2022-05-14T03:06:40+00:00)
Supporting cameras in Linux since 2019
utils.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: LGPL-2.1-or-later */
2/*
3 * Copyright (C) 2018, Google Inc.
4 *
5 * utils.h - Miscellaneous utility functions
6 */
7#ifndef __LIBCAMERA_BASE_UTILS_H__
8#define __LIBCAMERA_BASE_UTILS_H__
9
10#include <algorithm>
11#include <chrono>
12#include <iterator>
13#include <memory>
14#include <ostream>
15#include <sstream>
16#include <string>
17#include <string.h>
18#include <sys/time.h>
19#include <type_traits>
20#include <utility>
21#include <vector>
22
23#include <libcamera/base/private.h>
24
25#ifndef __DOXYGEN__
26
27/* uClibc and uClibc-ng don't provide O_TMPFILE */
28#ifndef O_TMPFILE
29#define O_TMPFILE (020000000 | O_DIRECTORY)
30#endif
31
32#endif
33
34namespace libcamera {
35
36namespace utils {
37
38const char *basename(const char *path);
39
40char *secure_getenv(const char *name);
41std::string dirname(const std::string &path);
42
43template<typename T>
44std::vector<typename T::key_type> map_keys(const T &map)
45{
46 std::vector<typename T::key_type> keys;
47 std::transform(map.begin(), map.end(), std::back_inserter(keys),
48 [](const auto &value) { return value.first; });
49 return keys;
50}
51
52template<class InputIt1, class InputIt2>
53unsigned int set_overlap(InputIt1 first1, InputIt1 last1,
54 InputIt2 first2, InputIt2 last2)
55{
56 unsigned int count = 0;
57
58 while (first1 != last1 && first2 != last2) {
59 if (*first1 < *first2) {
60 ++first1;
61 } else {
62 if (!(*first2 < *first1))
63 count++;
64 ++first2;
65 }
66 }
67
68 return count;
69}
70
71using clock = std::chrono::steady_clock;
72using duration = std::chrono::steady_clock::duration;
73using time_point = std::chrono::steady_clock::time_point;
74
75struct timespec duration_to_timespec(const duration &value);
76std::string time_point_to_string(const time_point &time);
77
78#ifndef __DOXYGEN__
79struct _hex {
80 uint64_t v;
81 unsigned int w;
82};
83
84std::basic_ostream<char, std::char_traits<char>> &
85operator<<(std::basic_ostream<char, std::char_traits<char>> &stream, const _hex &h);
86#endif
87
88template<typename T,
89 std::enable_if_t<std::is_integral<T>::value> * = nullptr>
90_hex hex(T value, unsigned int width = 0);
91
92#ifndef __DOXYGEN__
93template<>
94inline _hex hex<int32_t>(int32_t value, unsigned int width)
95{
96 return { static_cast<uint64_t>(value), width ? width : 8 };
97}
98
99template<>
100inline _hex hex<uint32_t>(uint32_t value, unsigned int width)
101{
102 return { static_cast<uint64_t>(value), width ? width : 8 };
103}
104
105template<>
106inline _hex hex<int64_t>(int64_t value, unsigned int width)
107{
108 return { static_cast<uint64_t>(value), width ? width : 16 };
109}
110
111template<>
112inline _hex hex<uint64_t>(uint64_t value, unsigned int width)
113{
114 return { static_cast<uint64_t>(value), width ? width : 16 };
115}
116#endif
117
118size_t strlcpy(char *dst, const char *src, size_t size);
119
120#ifndef __DOXYGEN__
121template<typename Container, typename UnaryOp>
122std::string join(const Container &items, const std::string &sep, UnaryOp op)
123{
124 std::ostringstream ss;
125 bool first = true;
126
127 for (typename Container::const_iterator it = std::begin(items);
128 it != std::end(items); ++it) {
129 if (!first)
130 ss << sep;
131 else
132 first = false;
133
134 ss << op(*it);
135 }
136
137 return ss.str();
138}
139
140template<typename Container>
141std::string join(const Container &items, const std::string &sep)
142{
143 std::ostringstream ss;
144 bool first = true;
145
146 for (typename Container::const_iterator it = std::begin(items);
147 it != std::end(items); ++it) {
148 if (!first)
149 ss << sep;
150 else
151 first = false;
152
153 ss << *it;
154 }
155
156 return ss.str();
157}
158#else
159template<typename Container, typename UnaryOp>
160std::string join(const Container &items, const std::string &sep, UnaryOp op = nullptr);
161#endif
162
163namespace details {
164
165class StringSplitter
166{
167public:
168 StringSplitter(const std::string &str, const std::string &delim);
169
170 class iterator
171 {
172 public:
173 iterator(const StringSplitter *ss, std::string::size_type pos);
174
175 iterator &operator++();
176 std::string operator*() const;
177 bool operator!=(const iterator &other) const;
178
179 private:
180 const StringSplitter *ss_;
181 std::string::size_type pos_;
182 std::string::size_type next_;
183 };
184
185 iterator begin() const;
186 iterator end() const;
187
188private:
189 std::string str_;
190 std::string delim_;
191};
192
193} /* namespace details */
194
195details::StringSplitter split(const std::string &str, const std::string &delim);
196
197std::string toAscii(const std::string &str);
198
199std::string libcameraBuildPath();
200std::string libcameraSourcePath();
201
202constexpr unsigned int alignDown(unsigned int value, unsigned int alignment)
203{
204 return value / alignment * alignment;
205}
206
207constexpr unsigned int alignUp(unsigned int value, unsigned int alignment)
208{
209 return (value + alignment - 1) / alignment * alignment;
210}
211
212namespace details {
213
214template<typename T>
215struct reverse_adapter {
216 T &iterable;
217};
218
219template<typename T>
220auto begin(reverse_adapter<T> r)
221{
222 return std::rbegin(r.iterable);
223}
224
225template<typename T>
226auto end(reverse_adapter<T> r)
227{
228 return std::rend(r.iterable);
229}
230
231} /* namespace details */
232
233template<typename T>
234details::reverse_adapter<T> reverse(T &&iterable)
235{
236 return { iterable };
237}
238
239namespace details {
240
241template<typename Base>
242class enumerate_iterator
243{
244private:
245 using base_reference = typename std::iterator_traits<Base>::reference;
246
247public:
248 using difference_type = typename std::iterator_traits<Base>::difference_type;
249 using value_type = std::pair<const std::size_t, base_reference>;
250 using pointer = value_type *;
251 using reference = value_type &;
252 using iterator_category = std::input_iterator_tag;
253
254 explicit enumerate_iterator(Base iter)
255 : current_(iter), pos_(0)
256 {
257 }
258
259 enumerate_iterator &operator++()
260 {
261 ++current_;
262 ++pos_;
263 return *this;
264 }
265
266 bool operator!=(const enumerate_iterator &other) const
267 {
268 return current_ != other.current_;
269 }
270
271 value_type operator*() const
272 {
273 return { pos_, *current_ };
274 }
275
276private:
277 Base current_;
278 std::size_t pos_;
279};
280
281template<typename Base>
282class enumerate_adapter
283{
284public:
285 using iterator = enumerate_iterator<Base>;
286
287 enumerate_adapter(Base begin, Base end)
288 : begin_(begin), end_(end)
289 {
290 }
291
292 iterator begin() const
293 {
294 return iterator{ begin_ };
295 }
296
297 iterator end() const
298 {
299 return iterator{ end_ };
300 }
301
302private:
303 const Base begin_;
304 const Base end_;
305};
306
307} /* namespace details */
308
309template<typename T>
310auto enumerate(T &iterable) -> details::enumerate_adapter<decltype(iterable.begin())>
311{
312 return { std::begin(iterable), std::end(iterable) };
313}
314
315#ifndef __DOXYGEN__
316template<typename T, size_t N>
317auto enumerate(T (&iterable)[N]) -> details::enumerate_adapter<T *>
318{
319 return { std::begin(iterable), std::end(iterable) };
320}
321#endif
322
323class Duration : public std::chrono::duration<double, std::nano>
324{
325 using BaseDuration = std::chrono::duration<double, std::nano>;
326
327public:
328 Duration() = default;
329
330 template<typename Rep, typename Period>
331 constexpr Duration(const std::chrono::duration<Rep, Period> &d)
332 : BaseDuration(d)
333 {
334 }
335
336 template<typename Period>
337 double get() const
338 {
339 auto const c = std::chrono::duration_cast<std::chrono::duration<double, Period>>(*this);
340 return c.count();
341 }
342
343 explicit constexpr operator bool() const
344 {
345 return *this != BaseDuration::zero();
346 }
347};
348
349} /* namespace utils */
350
351#ifndef __DOXYGEN__
352template<class CharT, class Traits>
353std::basic_ostream<CharT, Traits> &operator<<(std::basic_ostream<CharT, Traits> &os,
354 const utils::Duration &d);
355#endif
356
357} /* namespace libcamera */
358
359#endif /* __LIBCAMERA_BASE_UTILS_H__ */
Helper class from std::chrono::duration that represents a time duration in nanoseconds with double pr...
Definition: utils.h:324
double get() const
Retrieve the tick count, converted to the timebase provided by the template argument Period of type s...
Definition: utils.h:337
constexpr Duration(const std::chrono::duration< Rep, Period > &d)
Construct a Duration by converting an arbitrary std::chrono::duration.
Definition: utils.h:331
Top-level libcamera namespace.
Definition: backtrace.h:17
Transform operator*(Transform t0, Transform t1)
Compose two transforms together.
Definition: transform.cpp:207
const char * basename(const char *path)
Strip the directory prefix from the path.
Definition: utils.cpp:36
details::StringSplitter split(const std::string &str, const std::string &delim)
Split a string based on a delimiter.
Definition: utils.cpp:322
std::string time_point_to_string(const time_point &time)
Convert a time point to a string representation.
Definition: utils.cpp:174
constexpr unsigned int alignDown(unsigned int value, unsigned int alignment)
Align value down to alignment.
Definition: utils.h:202
std::string libcameraSourcePath()
Retrieve the path to the source directory.
Definition: source_paths.cpp:114
std::string toAscii(const std::string &str)
Remove any non-ASCII characters from a string.
Definition: utils.cpp:336
size_t strlcpy(char *dst, const char *src, size_t size)
Copy a string with a size limit.
Definition: utils.cpp:239
char * secure_getenv(const char *name)
Get an environment variable.
Definition: utils.cpp:60
std::chrono::steady_clock clock
The libcamera clock (monotonic)
Definition: utils.h:71
std::chrono::steady_clock::time_point time_point
The libcamera time point related to libcamera::utils::clock.
Definition: utils.h:73
unsigned int set_overlap(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2)
Count the number of elements in the intersection of two ranges.
Definition: utils.h:53
std::vector< typename T::key_type > map_keys(const T &map)
Retrieve the keys of a std::map<>
Definition: utils.h:44
constexpr unsigned int alignUp(unsigned int value, unsigned int alignment)
Align value up to alignment.
Definition: utils.h:207
std::string libcameraBuildPath()
Retrieve the path to the build directory.
Definition: source_paths.cpp:74
struct timespec duration_to_timespec(const duration &value)
Convert a duration to a timespec.
Definition: utils.cpp:160
auto enumerate(T &iterable) -> details::enumerate_adapter< decltype(iterable.begin())>
Wrap an iterable to enumerate index and value in a range-based loop.
Definition: utils.h:310
std::string join(const Container &items, const std::string &sep, UnaryOp op=nullptr)
Join elements of a container in a string with a separator.
std::chrono::steady_clock::duration duration
The libcamera duration related to libcamera::utils::clock.
Definition: utils.h:72
details::reverse_adapter< T > reverse(T &&iterable)
Wrap an iterable to reverse iteration in a range-based loop.
Definition: utils.h:234
_hex hex(T value, unsigned int width=0)
Write an hexadecimal value to an output string.
std::string dirname(const std::string &path)
Identify the dirname portion of a path.
Definition: utils.cpp:82