libcamera v0.4.0
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 <string.h>
17#include <string>
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<int8_t>(int8_t value, unsigned int width)
95{
96 return { static_cast<uint64_t>(value), width ? width : 2 };
97}
98
99template<>
100inline _hex hex<uint8_t>(uint8_t value, unsigned int width)
101{
102 return { static_cast<uint64_t>(value), width ? width : 2 };
103}
104
105template<>
106inline _hex hex<int16_t>(int16_t value, unsigned int width)
107{
108 return { static_cast<uint64_t>(value), width ? width : 4 };
109}
110
111template<>
112inline _hex hex<uint16_t>(uint16_t value, unsigned int width)
113{
114 return { static_cast<uint64_t>(value), width ? width : 4 };
115}
116
117template<>
118inline _hex hex<int32_t>(int32_t value, unsigned int width)
119{
120 return { static_cast<uint64_t>(value), width ? width : 8 };
121}
122
123template<>
124inline _hex hex<uint32_t>(uint32_t value, unsigned int width)
125{
126 return { static_cast<uint64_t>(value), width ? width : 8 };
127}
128
129template<>
130inline _hex hex<int64_t>(int64_t value, unsigned int width)
131{
132 return { static_cast<uint64_t>(value), width ? width : 16 };
133}
134
135template<>
136inline _hex hex<uint64_t>(uint64_t value, unsigned int width)
137{
138 return { static_cast<uint64_t>(value), width ? width : 16 };
139}
140#endif
141
142size_t strlcpy(char *dst, const char *src, size_t size);
143
144#ifndef __DOXYGEN__
145template<typename Container, typename UnaryOp>
146std::string join(const Container &items, const std::string &sep, UnaryOp op)
147{
148 std::ostringstream ss;
149 bool first = true;
150
151 for (typename Container::const_iterator it = std::begin(items);
152 it != std::end(items); ++it) {
153 if (!first)
154 ss << sep;
155 else
156 first = false;
157
158 ss << op(*it);
159 }
160
161 return ss.str();
162}
163
164template<typename Container>
165std::string join(const Container &items, const std::string &sep)
166{
167 std::ostringstream ss;
168 bool first = true;
169
170 for (typename Container::const_iterator it = std::begin(items);
171 it != std::end(items); ++it) {
172 if (!first)
173 ss << sep;
174 else
175 first = false;
176
177 ss << *it;
178 }
179
180 return ss.str();
181}
182#else
183template<typename Container, typename UnaryOp>
184std::string join(const Container &items, const std::string &sep, UnaryOp op = nullptr);
185#endif
186
187namespace details {
188
189class StringSplitter
190{
191public:
192 StringSplitter(const std::string &str, const std::string &delim);
193
194 class iterator
195 {
196 public:
197 using difference_type = std::size_t;
198 using value_type = std::string;
199 using pointer = value_type *;
200 using reference = value_type &;
201 using iterator_category = std::input_iterator_tag;
202
203 iterator(const StringSplitter *ss, std::string::size_type pos);
204
205 iterator &operator++();
206 std::string operator*() const;
207
208 bool operator==(const iterator &other) const
209 {
210 return pos_ == other.pos_;
211 }
212
213 bool operator!=(const iterator &other) const
214 {
215 return !(*this == other);
216 }
217
218 private:
219 const StringSplitter *ss_;
220 std::string::size_type pos_;
221 std::string::size_type next_;
222 };
223
224 iterator begin() const
225 {
226 return { this, 0 };
227 }
228
229 iterator end() const
230 {
231 return { this, std::string::npos };
232 }
233
234private:
235 std::string str_;
236 std::string delim_;
237};
238
239} /* namespace details */
240
241details::StringSplitter split(const std::string &str, const std::string &delim);
242
243std::string toAscii(const std::string &str);
244
245std::string libcameraBuildPath();
246std::string libcameraSourcePath();
247
248constexpr unsigned int alignDown(unsigned int value, unsigned int alignment)
249{
250 return value / alignment * alignment;
251}
252
253constexpr unsigned int alignUp(unsigned int value, unsigned int alignment)
254{
255 return (value + alignment - 1) / alignment * alignment;
256}
257
258namespace details {
259
260template<typename T>
261struct reverse_adapter {
262 T &iterable;
263};
264
265template<typename T>
266auto begin(reverse_adapter<T> r)
267{
268 return std::rbegin(r.iterable);
269}
270
271template<typename T>
272auto end(reverse_adapter<T> r)
273{
274 return std::rend(r.iterable);
275}
276
277} /* namespace details */
278
279template<typename T>
280details::reverse_adapter<T> reverse(T &&iterable)
281{
282 return { iterable };
283}
284
285namespace details {
286
287template<typename Base>
288class enumerate_iterator
289{
290private:
291 using base_reference = typename std::iterator_traits<Base>::reference;
292
293public:
294 using difference_type = typename std::iterator_traits<Base>::difference_type;
295 using value_type = std::pair<const std::size_t, base_reference>;
296 using pointer = value_type *;
297 using reference = value_type &;
298 using iterator_category = std::input_iterator_tag;
299
300 explicit enumerate_iterator(Base iter)
301 : current_(iter), pos_(0)
302 {
303 }
304
305 enumerate_iterator &operator++()
306 {
307 ++current_;
308 ++pos_;
309 return *this;
310 }
311
312 bool operator!=(const enumerate_iterator &other) const
313 {
314 return current_ != other.current_;
315 }
316
317 value_type operator*() const
318 {
319 return { pos_, *current_ };
320 }
321
322private:
323 Base current_;
324 std::size_t pos_;
325};
326
327template<typename Base>
328class enumerate_adapter
329{
330public:
331 using iterator = enumerate_iterator<Base>;
332
333 enumerate_adapter(Base begin, Base end)
334 : begin_(begin), end_(end)
335 {
336 }
337
338 iterator begin() const
339 {
340 return iterator{ begin_ };
341 }
342
343 iterator end() const
344 {
345 return iterator{ end_ };
346 }
347
348private:
349 const Base begin_;
350 const Base end_;
351};
352
353} /* namespace details */
354
355template<typename T>
356auto enumerate(T &iterable) -> details::enumerate_adapter<decltype(iterable.begin())>
357{
358 return { std::begin(iterable), std::end(iterable) };
359}
360
361#ifndef __DOXYGEN__
362template<typename T, size_t N>
363auto enumerate(T (&iterable)[N]) -> details::enumerate_adapter<T *>
364{
365 return { std::begin(iterable), std::end(iterable) };
366}
367#endif
368
369class Duration : public std::chrono::duration<double, std::nano>
370{
371 using BaseDuration = std::chrono::duration<double, std::nano>;
372
373public:
374 Duration() = default;
375
376 template<typename Rep>
377 constexpr explicit Duration(const Rep &r)
378 : BaseDuration(r)
379 {
380 }
381
382 template<typename Rep, typename Period>
383 constexpr Duration(const std::chrono::duration<Rep, Period> &d)
384 : BaseDuration(d)
385 {
386 }
387
388 template<typename Period>
389 double get() const
390 {
391 auto const c = std::chrono::duration_cast<std::chrono::duration<double, Period>>(*this);
392 return c.count();
393 }
394
395 explicit constexpr operator bool() const
396 {
397 return *this != BaseDuration::zero();
398 }
399};
400
401template<typename T>
402decltype(auto) abs_diff(const T &a, const T &b)
403{
404 if (a < b)
405 return b - a;
406 else
407 return a - b;
408}
409
410double strtod(const char *__restrict nptr, char **__restrict endptr);
411
412template<class Enum>
413constexpr std::underlying_type_t<Enum> to_underlying(Enum e) noexcept
414{
415 return static_cast<std::underlying_type_t<Enum>>(e);
416}
417
419{
420public:
422
423 void operator+=(std::function<void()> &&action);
424 void release();
425
426private:
427 std::vector<std::function<void()>> actions_;
428};
429
430} /* namespace utils */
431
432#ifndef __DOXYGEN__
433template<class CharT, class Traits>
434std::basic_ostream<CharT, Traits> &operator<<(std::basic_ostream<CharT, Traits> &os,
435 const utils::Duration &d);
436#endif
437
438} /* namespace libcamera */
Helper class from std::chrono::duration that represents a time duration in nanoseconds with double pr...
Definition utils.h:370
constexpr Duration(const Rep &r)
Construct a Duration with r ticks.
Definition utils.h:377
double get() const
Retrieve the tick count, converted to the timebase provided by the template argument Period of type s...
Definition utils.h:389
constexpr Duration(const std::chrono::duration< Rep, Period > &d)
Construct a Duration by converting an arbitrary std::chrono::duration.
Definition utils.h:383
An object that performs actions upon destruction.
Definition utils.h:419
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:101
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
constexpr unsigned int alignUp(unsigned int value, unsigned int alignment)
Align value up to alignment.
Definition utils.h:253
std::chrono::steady_clock::duration duration
The libcamera duration related to libcamera::utils::clock.
Definition utils.h:72
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:73
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:248
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:71
details::reverse_adapter< T > reverse(T &&iterable)
Wrap an iterable to reverse iteration in a range-based loop.
Definition utils.h:280
decltype(auto) abs_diff(const T &a, const T &b)
Calculates the absolute value of the difference between two elements.
Definition utils.h:402
std::vector< typename T::key_type > map_keys(const T &map)
Retrieve the keys of a std::map<>
Definition utils.h:44
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:356
constexpr std::underlying_type_t< Enum > to_underlying(Enum e) noexcept
Convert an enumeration to its underlygin type.
Definition utils.h:413
std::string dirname(const std::string &path)
Identify the dirname portion of a path.
Definition utils.cpp:83