libcamera  v0.4.0
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 <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 
34 namespace libcamera {
35 
36 namespace utils {
37 
38 const char *basename(const char *path);
39 
40 char *secure_getenv(const char *name);
41 std::string dirname(const std::string &path);
42 
43 template<typename T>
44 std::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 
52 template<class InputIt1, class InputIt2>
53 unsigned 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 
71 using clock = std::chrono::steady_clock;
72 using duration = std::chrono::steady_clock::duration;
73 using time_point = std::chrono::steady_clock::time_point;
74 
75 struct timespec duration_to_timespec(const duration &value);
76 std::string time_point_to_string(const time_point &time);
77 
78 #ifndef __DOXYGEN__
79 struct _hex {
80  uint64_t v;
81  unsigned int w;
82 };
83 
84 std::basic_ostream<char, std::char_traits<char>> &
85 operator<<(std::basic_ostream<char, std::char_traits<char>> &stream, const _hex &h);
86 #endif
87 
88 template<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__
93 template<>
94 inline _hex hex<int8_t>(int8_t value, unsigned int width)
95 {
96  return { static_cast<uint64_t>(value), width ? width : 2 };
97 }
98 
99 template<>
100 inline _hex hex<uint8_t>(uint8_t value, unsigned int width)
101 {
102  return { static_cast<uint64_t>(value), width ? width : 2 };
103 }
104 
105 template<>
106 inline _hex hex<int16_t>(int16_t value, unsigned int width)
107 {
108  return { static_cast<uint64_t>(value), width ? width : 4 };
109 }
110 
111 template<>
112 inline _hex hex<uint16_t>(uint16_t value, unsigned int width)
113 {
114  return { static_cast<uint64_t>(value), width ? width : 4 };
115 }
116 
117 template<>
118 inline _hex hex<int32_t>(int32_t value, unsigned int width)
119 {
120  return { static_cast<uint64_t>(value), width ? width : 8 };
121 }
122 
123 template<>
124 inline _hex hex<uint32_t>(uint32_t value, unsigned int width)
125 {
126  return { static_cast<uint64_t>(value), width ? width : 8 };
127 }
128 
129 template<>
130 inline _hex hex<int64_t>(int64_t value, unsigned int width)
131 {
132  return { static_cast<uint64_t>(value), width ? width : 16 };
133 }
134 
135 template<>
136 inline _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 
142 size_t strlcpy(char *dst, const char *src, size_t size);
143 
144 #ifndef __DOXYGEN__
145 template<typename Container, typename UnaryOp>
146 std::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 
164 template<typename Container>
165 std::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
183 template<typename Container, typename UnaryOp>
184 std::string join(const Container &items, const std::string &sep, UnaryOp op = nullptr);
185 #endif
186 
187 namespace details {
188 
189 class StringSplitter
190 {
191 public:
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 
234 private:
235  std::string str_;
236  std::string delim_;
237 };
238 
239 } /* namespace details */
240 
241 details::StringSplitter split(const std::string &str, const std::string &delim);
242 
243 std::string toAscii(const std::string &str);
244 
245 std::string libcameraBuildPath();
246 std::string libcameraSourcePath();
247 
248 constexpr unsigned int alignDown(unsigned int value, unsigned int alignment)
249 {
250  return value / alignment * alignment;
251 }
252 
253 constexpr unsigned int alignUp(unsigned int value, unsigned int alignment)
254 {
255  return (value + alignment - 1) / alignment * alignment;
256 }
257 
258 namespace details {
259 
260 template<typename T>
261 struct reverse_adapter {
262  T &iterable;
263 };
264 
265 template<typename T>
266 auto begin(reverse_adapter<T> r)
267 {
268  return std::rbegin(r.iterable);
269 }
270 
271 template<typename T>
272 auto end(reverse_adapter<T> r)
273 {
274  return std::rend(r.iterable);
275 }
276 
277 } /* namespace details */
278 
279 template<typename T>
280 details::reverse_adapter<T> reverse(T &&iterable)
281 {
282  return { iterable };
283 }
284 
285 namespace details {
286 
287 template<typename Base>
288 class enumerate_iterator
289 {
290 private:
291  using base_reference = typename std::iterator_traits<Base>::reference;
292 
293 public:
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 
322 private:
323  Base current_;
324  std::size_t pos_;
325 };
326 
327 template<typename Base>
328 class enumerate_adapter
329 {
330 public:
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 
348 private:
349  const Base begin_;
350  const Base end_;
351 };
352 
353 } /* namespace details */
354 
355 template<typename T>
356 auto enumerate(T &iterable) -> details::enumerate_adapter<decltype(iterable.begin())>
357 {
358  return { std::begin(iterable), std::end(iterable) };
359 }
360 
361 #ifndef __DOXYGEN__
362 template<typename T, size_t N>
363 auto enumerate(T (&iterable)[N]) -> details::enumerate_adapter<T *>
364 {
365  return { std::begin(iterable), std::end(iterable) };
366 }
367 #endif
368 
369 class Duration : public std::chrono::duration<double, std::nano>
370 {
371  using BaseDuration = std::chrono::duration<double, std::nano>;
372 
373 public:
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 
401 template<typename T>
402 decltype(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 
410 double strtod(const char *__restrict nptr, char **__restrict endptr);
411 
412 template<class Enum>
413 constexpr std::underlying_type_t<Enum> to_underlying(Enum e) noexcept
414 {
415  return static_cast<std::underlying_type_t<Enum>>(e);
416 }
417 
419 {
420 public:
421  ~ScopeExitActions();
422 
423  void operator+=(std::function<void()> &&action);
424  void release();
425 
426 private:
427  std::vector<std::function<void()>> actions_;
428 };
429 
430 } /* namespace utils */
431 
432 #ifndef __DOXYGEN__
433 template<class CharT, class Traits>
434 std::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
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
constexpr Duration(const Rep &r)
Construct a Duration with r ticks.
Definition: utils.h:377
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
bool operator!=(const Vector< T, Rows > &lhs, const Vector< T, Rows > &rhs)
Compare vectors for inequality.
Definition: vector.h:323
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
bool operator==(const ColorSpace &lhs, const ColorSpace &rhs)
Compare color spaces for equality.
Definition: color_space.cpp:506
Matrix< U, Rows, Cols > operator*(T d, const Matrix< U, Rows, Cols > &m)
Multiply the matrix by a scalar.
Definition: matrix.h:101
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
constexpr unsigned int alignDown(unsigned int value, unsigned int alignment)
Align value down to alignment.
Definition: utils.h:248
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 std::underlying_type_t< Enum > to_underlying(Enum e) noexcept
Convert an enumeration to its underlygin type.
Definition: utils.h:413
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
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:253
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
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:280
_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:83