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