libcamera v0.5.2
Supporting cameras in Linux since 2019
Loading...
Searching...
No Matches
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 * Miscellaneous utility functions
6 */
7
8#pragma once
9
10#include <algorithm>
11#include <chrono>
12#include <functional>
13#include <iterator>
14#include <ostream>
15#include <sstream>
16#include <stdint.h>
17#include <string.h>
18#include <string>
19#include <sys/time.h>
20#include <type_traits>
21#include <utility>
22#include <vector>
23
25#include <libcamera/base/private.h>
26
27#ifndef __DOXYGEN__
28
29/* uClibc and uClibc-ng don't provide O_TMPFILE */
30#ifndef O_TMPFILE
31#define O_TMPFILE (020000000 | O_DIRECTORY)
32#endif
33
34#endif
35
36namespace libcamera {
37
38namespace utils {
39
40const char *basename(const char *path);
41
42char *secure_getenv(const char *name);
43std::string dirname(const std::string &path);
44
45template<typename T>
46std::vector<typename T::key_type> map_keys(const T &map)
47{
48 std::vector<typename T::key_type> keys;
49 std::transform(map.begin(), map.end(), std::back_inserter(keys),
50 [](const auto &value) { return value.first; });
51 return keys;
52}
53
54template<class InputIt1, class InputIt2>
55unsigned int set_overlap(InputIt1 first1, InputIt1 last1,
56 InputIt2 first2, InputIt2 last2)
57{
58 unsigned int count = 0;
59
60 while (first1 != last1 && first2 != last2) {
61 if (*first1 < *first2) {
62 ++first1;
63 } else {
64 if (!(*first2 < *first1))
65 count++;
66 ++first2;
67 }
68 }
69
70 return count;
71}
72
73using clock = std::chrono::steady_clock;
74using duration = std::chrono::steady_clock::duration;
75using time_point = std::chrono::steady_clock::time_point;
76
77struct timespec duration_to_timespec(const duration &value);
78std::string time_point_to_string(const time_point &time);
79
80#ifndef __DOXYGEN__
81struct _hex {
82 uint64_t v;
83 unsigned int w;
84};
85
86std::basic_ostream<char, std::char_traits<char>> &
87operator<<(std::basic_ostream<char, std::char_traits<char>> &stream, const _hex &h);
88#endif
89
90template<typename T,
91 std::enable_if_t<std::is_integral<T>::value> * = nullptr>
92_hex hex(T value, unsigned int width = 0);
93
94#ifndef __DOXYGEN__
95template<>
96inline _hex hex<int8_t>(int8_t value, unsigned int width)
97{
98 return { static_cast<uint64_t>(value), width ? width : 2 };
99}
100
101template<>
102inline _hex hex<uint8_t>(uint8_t value, unsigned int width)
103{
104 return { static_cast<uint64_t>(value), width ? width : 2 };
105}
106
107template<>
108inline _hex hex<int16_t>(int16_t value, unsigned int width)
109{
110 return { static_cast<uint64_t>(value), width ? width : 4 };
111}
112
113template<>
114inline _hex hex<uint16_t>(uint16_t value, unsigned int width)
115{
116 return { static_cast<uint64_t>(value), width ? width : 4 };
117}
118
119template<>
120inline _hex hex<int32_t>(int32_t value, unsigned int width)
121{
122 return { static_cast<uint64_t>(value), width ? width : 8 };
123}
124
125template<>
126inline _hex hex<uint32_t>(uint32_t value, unsigned int width)
127{
128 return { static_cast<uint64_t>(value), width ? width : 8 };
129}
130
131template<>
132inline _hex hex<int64_t>(int64_t value, unsigned int width)
133{
134 return { static_cast<uint64_t>(value), width ? width : 16 };
135}
136
137template<>
138inline _hex hex<uint64_t>(uint64_t value, unsigned int width)
139{
140 return { static_cast<uint64_t>(value), width ? width : 16 };
141}
142#endif
143
144size_t strlcpy(char *dst, const char *src, size_t size);
145
146#ifndef __DOXYGEN__
147template<typename Container, typename UnaryOp>
148std::string join(const Container &items, const std::string &sep, UnaryOp op)
149{
150 std::ostringstream ss;
151 bool first = true;
152
153 for (typename Container::const_iterator it = std::begin(items);
154 it != std::end(items); ++it) {
155 if (!first)
156 ss << sep;
157 else
158 first = false;
159
160 ss << op(*it);
161 }
162
163 return ss.str();
164}
165
166template<typename Container>
167std::string join(const Container &items, const std::string &sep)
168{
169 std::ostringstream ss;
170 bool first = true;
171
172 for (typename Container::const_iterator it = std::begin(items);
173 it != std::end(items); ++it) {
174 if (!first)
175 ss << sep;
176 else
177 first = false;
178
179 ss << *it;
180 }
181
182 return ss.str();
183}
184#else
185template<typename Container, typename UnaryOp>
186std::string join(const Container &items, const std::string &sep, UnaryOp op = nullptr);
187#endif
188
189namespace details {
190
191class StringSplitter
192{
193public:
194 StringSplitter(const std::string &str, const std::string &delim);
195
196 class iterator
197 {
198 public:
199 using difference_type = std::size_t;
200 using value_type = std::string;
201 using pointer = value_type *;
202 using reference = value_type &;
203 using iterator_category = std::input_iterator_tag;
204
205 iterator(const StringSplitter *ss, std::string::size_type pos);
206
207 iterator &operator++();
208 std::string operator*() const;
209
210 bool operator==(const iterator &other) const
211 {
212 return pos_ == other.pos_;
213 }
214
215 bool operator!=(const iterator &other) const
216 {
217 return !(*this == other);
218 }
219
220 private:
221 const StringSplitter *ss_;
222 std::string::size_type pos_;
223 std::string::size_type next_;
224 };
225
226 iterator begin() const
227 {
228 return { this, 0 };
229 }
230
231 iterator end() const
232 {
233 return { this, std::string::npos };
234 }
235
236private:
237 std::string str_;
238 std::string delim_;
239};
240
241} /* namespace details */
242
243details::StringSplitter split(const std::string &str, const std::string &delim);
244
245std::string toAscii(const std::string &str);
246
247std::string libcameraBuildPath();
248std::string libcameraSourcePath();
249
250constexpr unsigned int alignDown(unsigned int value, unsigned int alignment)
251{
252 return value / alignment * alignment;
253}
254
255constexpr unsigned int alignUp(unsigned int value, unsigned int alignment)
256{
257 return (value + alignment - 1) / alignment * alignment;
258}
259
260namespace details {
261
262template<typename T>
263struct reverse_adapter {
264 T &iterable;
265};
266
267template<typename T>
268auto begin(reverse_adapter<T> r)
269{
270 return std::rbegin(r.iterable);
271}
272
273template<typename T>
274auto end(reverse_adapter<T> r)
275{
276 return std::rend(r.iterable);
277}
278
279} /* namespace details */
280
281template<typename T>
282details::reverse_adapter<T> reverse(T &&iterable)
283{
284 return { iterable };
285}
286
287namespace details {
288
289template<typename Base>
290class enumerate_iterator
291{
292private:
293 using base_reference = typename std::iterator_traits<Base>::reference;
294
295public:
296 using difference_type = typename std::iterator_traits<Base>::difference_type;
297 using value_type = std::pair<const std::size_t, base_reference>;
298 using pointer = value_type *;
299 using reference = value_type &;
300 using iterator_category = std::input_iterator_tag;
301
302 explicit enumerate_iterator(Base iter)
303 : current_(iter), pos_(0)
304 {
305 }
306
307 enumerate_iterator &operator++()
308 {
309 ++current_;
310 ++pos_;
311 return *this;
312 }
313
314 bool operator!=(const enumerate_iterator &other) const
315 {
316 return current_ != other.current_;
317 }
318
319 value_type operator*() const
320 {
321 return { pos_, *current_ };
322 }
323
324private:
325 Base current_;
326 std::size_t pos_;
327};
328
329template<typename Base>
330class enumerate_adapter
331{
332public:
333 using iterator = enumerate_iterator<Base>;
334
335 enumerate_adapter(Base begin, Base end)
336 : begin_(begin), end_(end)
337 {
338 }
339
340 iterator begin() const
341 {
342 return iterator{ begin_ };
343 }
344
345 iterator end() const
346 {
347 return iterator{ end_ };
348 }
349
350private:
351 const Base begin_;
352 const Base end_;
353};
354
355} /* namespace details */
356
357template<typename T>
358auto enumerate(T &iterable) -> details::enumerate_adapter<decltype(iterable.begin())>
359{
360 return { std::begin(iterable), std::end(iterable) };
361}
362
363#ifndef __DOXYGEN__
364template<typename T, size_t N>
365auto enumerate(T (&iterable)[N]) -> details::enumerate_adapter<T *>
366{
367 return { std::begin(iterable), std::end(iterable) };
368}
369#endif
370
371class Duration : public std::chrono::duration<double, std::nano>
372{
373 using BaseDuration = std::chrono::duration<double, std::nano>;
374
375public:
376 Duration() = default;
377
378 template<typename Rep>
379 constexpr explicit Duration(const Rep &r)
380 : BaseDuration(r)
381 {
382 }
383
384 template<typename Rep, typename Period>
385 constexpr Duration(const std::chrono::duration<Rep, Period> &d)
386 : BaseDuration(d)
387 {
388 }
389
390 template<typename Period>
391 double get() const
392 {
393 auto const c = std::chrono::duration_cast<std::chrono::duration<double, Period>>(*this);
394 return c.count();
395 }
396
397 explicit constexpr operator bool() const
398 {
399 return *this != BaseDuration::zero();
400 }
401};
402
403template<typename T>
404decltype(auto) abs_diff(const T &a, const T &b)
405{
406 if (a < b)
407 return b - a;
408 else
409 return a - b;
410}
411
412double strtod(const char *__restrict nptr, char **__restrict endptr);
413
414template<class Enum>
415constexpr std::underlying_type_t<Enum> to_underlying(Enum e) noexcept
416{
417 return static_cast<std::underlying_type_t<Enum>>(e);
418}
419
421{
422public:
424
425 void operator+=(std::function<void()> &&action);
426 void release();
427
428private:
429 std::vector<std::function<void()>> actions_;
430};
431
432#ifndef __DOXYGEN__
433template<typename EF>
434class scope_exit
435{
436public:
437 template<typename Fn,
438 std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Fn>>, scope_exit> &&
439 std::is_constructible_v<EF, Fn>> * = nullptr>
440 explicit scope_exit(Fn &&fn)
441 : exitFunction_(std::forward<Fn>(fn))
442 {
443 static_assert(std::is_nothrow_constructible_v<EF, Fn>);
444 }
445
446 ~scope_exit()
447 {
448 if (active_)
449 exitFunction_();
450 }
451
452 void release()
453 {
454 active_ = false;
455 }
456
457private:
459
460 EF exitFunction_;
461 bool active_ = true;
462};
463
464template<typename EF>
465scope_exit(EF) -> scope_exit<EF>;
466
467#endif /* __DOXYGEN__ */
468
469} /* namespace utils */
470
471#ifndef __DOXYGEN__
472template<class CharT, class Traits>
473std::basic_ostream<CharT, Traits> &operator<<(std::basic_ostream<CharT, Traits> &os,
474 const utils::Duration &d);
475#endif
476
477} /* namespace libcamera */
Utilities to help constructing class interfaces.
#define LIBCAMERA_DISABLE_COPY_AND_MOVE(klass)
Disable copy and move construction and assignment of the klass.
Definition class.h:29
constexpr Duration(const Rep &r)
Construct a Duration with r ticks.
Definition utils.h:379
double get() const
Retrieve the tick count, converted to the timebase provided by the template argument Period of type s...
Definition utils.h:391
constexpr Duration(const std::chrono::duration< Rep, Period > &d)
Construct a Duration by converting an arbitrary std::chrono::duration.
Definition utils.h:385
An object that performs actions upon destruction.
Definition utils.h:421
void release()
Remove all exit actions.
Definition utils.cpp:646
void operator+=(std::function< void()> &&action)
Add an exit action.
Definition utils.cpp:634
Top-level libcamera namespace.
Definition backtrace.h:17
std::ostream & operator<<(std::ostream &out, const Point &p)
Insert a text representation of a Point into an output stream.
Definition geometry.cpp:91
Matrix< U, Rows, Cols > operator*(T d, const Matrix< U, Rows, Cols > &m)
Multiply the matrix by a scalar.
Definition matrix.h:133
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:55
constexpr unsigned int alignUp(unsigned int value, unsigned int alignment)
Align value up to alignment.
Definition utils.h:255
std::chrono::steady_clock::duration duration
The libcamera duration related to libcamera::utils::clock.
Definition utils.h:74
const char * basename(const char *path)
Strip the directory prefix from the path.
Definition utils.cpp:37
details::StringSplitter split(const std::string &str, const std::string &delim)
Split a string based on a delimiter.
Definition utils.cpp:308
std::string time_point_to_string(const time_point &time)
Convert a time point to a string representation.
Definition utils.cpp:175
std::chrono::steady_clock::time_point time_point
The libcamera time point related to libcamera::utils::clock.
Definition utils.h:75
std::string join(const Container &items, const std::string &sep, UnaryOp op=nullptr)
Join elements of a container in a string with a separator.
_hex hex(T value, unsigned int width=0)
Write an hexadecimal value to an output string.
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:322
constexpr unsigned int alignDown(unsigned int value, unsigned int alignment)
Align value down to alignment.
Definition utils.h:250
size_t strlcpy(char *dst, const char *src, size_t size)
Copy a string with a size limit.
Definition utils.cpp:240
char * secure_getenv(const char *name)
Get an environment variable.
Definition utils.cpp:61
std::chrono::steady_clock clock
The libcamera clock (monotonic)
Definition utils.h:73
details::reverse_adapter< T > reverse(T &&iterable)
Wrap an iterable to reverse iteration in a range-based loop.
Definition utils.h:282
decltype(auto) abs_diff(const T &a, const T &b)
Calculates the absolute value of the difference between two elements.
Definition utils.h:404
std::vector< typename T::key_type > map_keys(const T &map)
Retrieve the keys of a std::map<>
Definition utils.h:46
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:161
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:358
constexpr std::underlying_type_t< Enum > to_underlying(Enum e) noexcept
Convert an enumeration to its underlygin type.
Definition utils.h:415
std::string dirname(const std::string &path)
Identify the dirname portion of a path.
Definition utils.cpp:83