libcamera  v0.4.0+58-f63f4d71
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  * 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 
35 namespace libcamera {
36 
37 namespace utils {
38 
39 const char *basename(const char *path);
40 
41 char *secure_getenv(const char *name);
42 std::string dirname(const std::string &path);
43 
44 template<typename T>
45 std::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 
53 template<class InputIt1, class InputIt2>
54 unsigned 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 
72 using clock = std::chrono::steady_clock;
73 using duration = std::chrono::steady_clock::duration;
74 using time_point = std::chrono::steady_clock::time_point;
75 
76 struct timespec duration_to_timespec(const duration &value);
77 std::string time_point_to_string(const time_point &time);
78 
79 #ifndef __DOXYGEN__
80 struct _hex {
81  uint64_t v;
82  unsigned int w;
83 };
84 
85 std::basic_ostream<char, std::char_traits<char>> &
86 operator<<(std::basic_ostream<char, std::char_traits<char>> &stream, const _hex &h);
87 #endif
88 
89 template<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__
94 template<>
95 inline _hex hex<int8_t>(int8_t value, unsigned int width)
96 {
97  return { static_cast<uint64_t>(value), width ? width : 2 };
98 }
99 
100 template<>
101 inline _hex hex<uint8_t>(uint8_t value, unsigned int width)
102 {
103  return { static_cast<uint64_t>(value), width ? width : 2 };
104 }
105 
106 template<>
107 inline _hex hex<int16_t>(int16_t value, unsigned int width)
108 {
109  return { static_cast<uint64_t>(value), width ? width : 4 };
110 }
111 
112 template<>
113 inline _hex hex<uint16_t>(uint16_t value, unsigned int width)
114 {
115  return { static_cast<uint64_t>(value), width ? width : 4 };
116 }
117 
118 template<>
119 inline _hex hex<int32_t>(int32_t value, unsigned int width)
120 {
121  return { static_cast<uint64_t>(value), width ? width : 8 };
122 }
123 
124 template<>
125 inline _hex hex<uint32_t>(uint32_t value, unsigned int width)
126 {
127  return { static_cast<uint64_t>(value), width ? width : 8 };
128 }
129 
130 template<>
131 inline _hex hex<int64_t>(int64_t value, unsigned int width)
132 {
133  return { static_cast<uint64_t>(value), width ? width : 16 };
134 }
135 
136 template<>
137 inline _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 
143 size_t strlcpy(char *dst, const char *src, size_t size);
144 
145 #ifndef __DOXYGEN__
146 template<typename Container, typename UnaryOp>
147 std::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 
165 template<typename Container>
166 std::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
184 template<typename Container, typename UnaryOp>
185 std::string join(const Container &items, const std::string &sep, UnaryOp op = nullptr);
186 #endif
187 
188 namespace details {
189 
190 class StringSplitter
191 {
192 public:
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 
235 private:
236  std::string str_;
237  std::string delim_;
238 };
239 
240 } /* namespace details */
241 
242 details::StringSplitter split(const std::string &str, const std::string &delim);
243 
244 std::string toAscii(const std::string &str);
245 
246 std::string libcameraBuildPath();
247 std::string libcameraSourcePath();
248 
249 constexpr unsigned int alignDown(unsigned int value, unsigned int alignment)
250 {
251  return value / alignment * alignment;
252 }
253 
254 constexpr unsigned int alignUp(unsigned int value, unsigned int alignment)
255 {
256  return (value + alignment - 1) / alignment * alignment;
257 }
258 
259 namespace details {
260 
261 template<typename T>
262 struct reverse_adapter {
263  T &iterable;
264 };
265 
266 template<typename T>
267 auto begin(reverse_adapter<T> r)
268 {
269  return std::rbegin(r.iterable);
270 }
271 
272 template<typename T>
273 auto end(reverse_adapter<T> r)
274 {
275  return std::rend(r.iterable);
276 }
277 
278 } /* namespace details */
279 
280 template<typename T>
281 details::reverse_adapter<T> reverse(T &&iterable)
282 {
283  return { iterable };
284 }
285 
286 namespace details {
287 
288 template<typename Base>
289 class enumerate_iterator
290 {
291 private:
292  using base_reference = typename std::iterator_traits<Base>::reference;
293 
294 public:
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 
323 private:
324  Base current_;
325  std::size_t pos_;
326 };
327 
328 template<typename Base>
329 class enumerate_adapter
330 {
331 public:
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 
349 private:
350  const Base begin_;
351  const Base end_;
352 };
353 
354 } /* namespace details */
355 
356 template<typename T>
357 auto enumerate(T &iterable) -> details::enumerate_adapter<decltype(iterable.begin())>
358 {
359  return { std::begin(iterable), std::end(iterable) };
360 }
361 
362 #ifndef __DOXYGEN__
363 template<typename T, size_t N>
364 auto enumerate(T (&iterable)[N]) -> details::enumerate_adapter<T *>
365 {
366  return { std::begin(iterable), std::end(iterable) };
367 }
368 #endif
369 
370 class Duration : public std::chrono::duration<double, std::nano>
371 {
372  using BaseDuration = std::chrono::duration<double, std::nano>;
373 
374 public:
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 
402 template<typename T>
403 decltype(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 
411 double strtod(const char *__restrict nptr, char **__restrict endptr);
412 
413 template<class Enum>
414 constexpr std::underlying_type_t<Enum> to_underlying(Enum e) noexcept
415 {
416  return static_cast<std::underlying_type_t<Enum>>(e);
417 }
418 
420 {
421 public:
422  ~ScopeExitActions();
423 
424  void operator+=(std::function<void()> &&action);
425  void release();
426 
427 private:
428  std::vector<std::function<void()>> actions_;
429 };
430 
431 } /* namespace utils */
432 
433 #ifndef __DOXYGEN__
434 template<class CharT, class Traits>
435 std::basic_ostream<CharT, Traits> &operator<<(std::basic_ostream<CharT, Traits> &os,
436  const utils::Duration &d);
437 #endif
438 
439 } /* namespace libcamera */
bool operator==(const ColorSpace &lhs, const ColorSpace &rhs)
Compare color spaces for equality.
Definition: color_space.cpp:506
std::string libcameraSourcePath()
Retrieve the path to the source directory.
Definition: source_paths.cpp:114
const char * basename(const char *path)
Strip the directory prefix from the path.
Definition: utils.cpp:37
struct timespec duration_to_timespec(const duration &value)
Convert a duration to a timespec.
Definition: utils.cpp:161
Top-level libcamera namespace.
Definition: backtrace.h:17
std::chrono::steady_clock clock
The libcamera clock (monotonic)
Definition: utils.h:72
An object that performs actions upon destruction.
Definition: utils.h:419
std::vector< typename T::key_type > map_keys(const T &map)
Retrieve the keys of a std::map<>
Definition: utils.h:45
std::string dirname(const std::string &path)
Identify the dirname portion of a path.
Definition: utils.cpp:83
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
std::chrono::steady_clock::time_point time_point
The libcamera time point related to libcamera::utils::clock.
Definition: utils.h:74
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
Matrix< U, Rows, Cols > operator*(T d, const Matrix< U, Rows, Cols > &m)
Multiply the matrix by a scalar.
Definition: matrix.h:103
std::string time_point_to_string(const time_point &time)
Convert a time point to a string representation.
Definition: utils.cpp:175
double strtod(const char *__restrict nptr, char **__restrict endptr)
Convert a string to a double independently of the current locale.
Definition: utils.cpp:496
char * secure_getenv(const char *name)
Get an environment variable.
Definition: utils.cpp:61
std::string libcameraBuildPath()
Retrieve the path to the build directory.
Definition: source_paths.cpp:74
constexpr Duration(const Rep &r)
Construct a Duration with r ticks.
Definition: utils.h:378
constexpr unsigned int alignDown(unsigned int value, unsigned int alignment)
Align value down to alignment.
Definition: utils.h:249
std::chrono::steady_clock::duration duration
The libcamera duration related to libcamera::utils::clock.
Definition: utils.h:73
details::StringSplitter split(const std::string &str, const std::string &delim)
Split a string based on a delimiter.
Definition: utils.cpp:308
_hex hex(T value, unsigned int width=0)
Write an hexadecimal value to an output string.
Helper class from std::chrono::duration that represents a time duration in nanoseconds with double pr...
Definition: utils.h:370
size_t strlcpy(char *dst, const char *src, size_t size)
Copy a string with a size limit.
Definition: utils.cpp:240
constexpr std::underlying_type_t< Enum > to_underlying(Enum e) noexcept
Convert an enumeration to its underlygin type.
Definition: utils.h:414
std::string join(const Container &items, const std::string &sep, UnaryOp op=nullptr)
Join elements of a container in a string with a separator.
constexpr unsigned int alignUp(unsigned int value, unsigned int alignment)
Align value up to alignment.
Definition: utils.h:254
std::string toAscii(const std::string &str)
Remove any non-ASCII characters from a string.
Definition: utils.cpp:322
details::reverse_adapter< T > reverse(T &&iterable)
Wrap an iterable to reverse iteration in a range-based loop.
Definition: utils.h:281
constexpr Duration(const std::chrono::duration< Rep, Period > &d)
Construct a Duration by converting an arbitrary std::chrono::duration.
Definition: utils.h:384