/src/qpdf/libqpdf/qpdf/Util.hh
Line | Count | Source |
1 | | #ifndef UTIL_HH |
2 | | #define UTIL_HH |
3 | | |
4 | | #include <qpdf/assert_debug.h> |
5 | | |
6 | | #include <concepts> |
7 | | #include <cstdint> |
8 | | #include <limits> |
9 | | #include <stdexcept> |
10 | | #include <string> |
11 | | #include <utility> |
12 | | |
13 | | using namespace std::literals; |
14 | | |
15 | | namespace qpdf::util |
16 | | { |
17 | | // qpdf::util is a collection of useful utility functions for qpdf internal use. It includes |
18 | | // inline functions, some of which are exposed as regular functions in QUtil. Implementations |
19 | | // are in QUtil.cc. |
20 | | |
21 | | // Throw a logic_error if 'cond' does not hold. |
22 | | // |
23 | | // DO NOT USE unless it is impractical or unnecessary to cover violations during CI Testing. |
24 | | template <typename T> |
25 | | inline void |
26 | | assertion(bool cond, T&& msg) |
27 | 2.09G | { |
28 | 2.09G | if (!cond) { |
29 | 0 | throw std::logic_error(std::forward<T>(msg)); |
30 | 0 | } |
31 | 2.09G | } void qpdf::util::assertion<char const (&) [56]>(bool, char const (&) [56]) Line | Count | Source | 27 | 10.8k | { | 28 | 10.8k | if (!cond) { | 29 | 0 | throw std::logic_error(std::forward<T>(msg)); | 30 | 0 | } | 31 | 10.8k | } |
void qpdf::util::assertion<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&) Line | Count | Source | 27 | 42.6M | { | 28 | 42.6M | if (!cond) { | 29 | 0 | throw std::logic_error(std::forward<T>(msg)); | 30 | 0 | } | 31 | 42.6M | } |
void qpdf::util::assertion<char const (&) [44]>(bool, char const (&) [44]) Line | Count | Source | 27 | 1.46M | { | 28 | 1.46M | if (!cond) { | 29 | 0 | throw std::logic_error(std::forward<T>(msg)); | 30 | 0 | } | 31 | 1.46M | } |
void qpdf::util::assertion<char const (&) [54]>(bool, char const (&) [54]) Line | Count | Source | 27 | 3.54M | { | 28 | 3.54M | if (!cond) { | 29 | 0 | throw std::logic_error(std::forward<T>(msg)); | 30 | 0 | } | 31 | 3.54M | } |
Unexecuted instantiation: void qpdf::util::assertion<char const (&) [71]>(bool, char const (&) [71]) void qpdf::util::assertion<char const (&) [57]>(bool, char const (&) [57]) Line | Count | Source | 27 | 35.2k | { | 28 | 35.2k | if (!cond) { | 29 | 0 | throw std::logic_error(std::forward<T>(msg)); | 30 | 0 | } | 31 | 35.2k | } |
void qpdf::util::assertion<char const (&) [51]>(bool, char const (&) [51]) Line | Count | Source | 27 | 15.8k | { | 28 | 15.8k | if (!cond) { | 29 | 0 | throw std::logic_error(std::forward<T>(msg)); | 30 | 0 | } | 31 | 15.8k | } |
void qpdf::util::assertion<char const (&) [41]>(bool, char const (&) [41]) Line | Count | Source | 27 | 38.1k | { | 28 | 38.1k | if (!cond) { | 29 | 0 | throw std::logic_error(std::forward<T>(msg)); | 30 | 0 | } | 31 | 38.1k | } |
void qpdf::util::assertion<char const (&) [40]>(bool, char const (&) [40]) Line | Count | Source | 27 | 52.0k | { | 28 | 52.0k | if (!cond) { | 29 | 0 | throw std::logic_error(std::forward<T>(msg)); | 30 | 0 | } | 31 | 52.0k | } |
void qpdf::util::assertion<char const (&) [46]>(bool, char const (&) [46]) Line | Count | Source | 27 | 220k | { | 28 | 220k | if (!cond) { | 29 | 0 | throw std::logic_error(std::forward<T>(msg)); | 30 | 0 | } | 31 | 220k | } |
void qpdf::util::assertion<char const (&) [25]>(bool, char const (&) [25]) Line | Count | Source | 27 | 275k | { | 28 | 275k | if (!cond) { | 29 | 0 | throw std::logic_error(std::forward<T>(msg)); | 30 | 0 | } | 31 | 275k | } |
void qpdf::util::assertion<char const (&) [42]>(bool, char const (&) [42]) Line | Count | Source | 27 | 30.9k | { | 28 | 30.9k | if (!cond) { | 29 | 0 | throw std::logic_error(std::forward<T>(msg)); | 30 | 0 | } | 31 | 30.9k | } |
void qpdf::util::assertion<char const (&) [34]>(bool, char const (&) [34]) Line | Count | Source | 27 | 11.9k | { | 28 | 11.9k | if (!cond) { | 29 | 0 | throw std::logic_error(std::forward<T>(msg)); | 30 | 0 | } | 31 | 11.9k | } |
void qpdf::util::assertion<char const (&) [72]>(bool, char const (&) [72]) Line | Count | Source | 27 | 244k | { | 28 | 244k | if (!cond) { | 29 | 0 | throw std::logic_error(std::forward<T>(msg)); | 30 | 0 | } | 31 | 244k | } |
void qpdf::util::assertion<char const (&) [45]>(bool, char const (&) [45]) Line | Count | Source | 27 | 19.7M | { | 28 | 19.7M | if (!cond) { | 29 | 0 | throw std::logic_error(std::forward<T>(msg)); | 30 | 0 | } | 31 | 19.7M | } |
void qpdf::util::assertion<char const (&) [53]>(bool, char const (&) [53]) Line | Count | Source | 27 | 459k | { | 28 | 459k | if (!cond) { | 29 | 0 | throw std::logic_error(std::forward<T>(msg)); | 30 | 0 | } | 31 | 459k | } |
void qpdf::util::assertion<char const (&) [35]>(bool, char const (&) [35]) Line | Count | Source | 27 | 82.5k | { | 28 | 82.5k | if (!cond) { | 29 | 0 | throw std::logic_error(std::forward<T>(msg)); | 30 | 0 | } | 31 | 82.5k | } |
void qpdf::util::assertion<char const (&) [68]>(bool, char const (&) [68]) Line | Count | Source | 27 | 72.9k | { | 28 | 72.9k | if (!cond) { | 29 | 0 | throw std::logic_error(std::forward<T>(msg)); | 30 | 0 | } | 31 | 72.9k | } |
Unexecuted instantiation: void qpdf::util::assertion<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&>(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&) void qpdf::util::assertion<char const (&) [83]>(bool, char const (&) [83]) Line | Count | Source | 27 | 1.09M | { | 28 | 1.09M | if (!cond) { | 29 | 0 | throw std::logic_error(std::forward<T>(msg)); | 30 | 0 | } | 31 | 1.09M | } |
void qpdf::util::assertion<char const (&) [50]>(bool, char const (&) [50]) Line | Count | Source | 27 | 14.2M | { | 28 | 14.2M | if (!cond) { | 29 | 0 | throw std::logic_error(std::forward<T>(msg)); | 30 | 0 | } | 31 | 14.2M | } |
void qpdf::util::assertion<char const (&) [43]>(bool, char const (&) [43]) Line | Count | Source | 27 | 206k | { | 28 | 206k | if (!cond) { | 29 | 0 | throw std::logic_error(std::forward<T>(msg)); | 30 | 0 | } | 31 | 206k | } |
void qpdf::util::assertion<char const (&) [52]>(bool, char const (&) [52]) Line | Count | Source | 27 | 2.00G | { | 28 | 2.00G | if (!cond) { | 29 | 0 | throw std::logic_error(std::forward<T>(msg)); | 30 | 0 | } | 31 | 2.00G | } |
void qpdf::util::assertion<char const (&) [58]>(bool, char const (&) [58]) Line | Count | Source | 27 | 23.1k | { | 28 | 23.1k | if (!cond) { | 29 | 0 | throw std::logic_error(std::forward<T>(msg)); | 30 | 0 | } | 31 | 23.1k | } |
void qpdf::util::assertion<char const (&) [48]>(bool, char const (&) [48]) Line | Count | Source | 27 | 509k | { | 28 | 509k | if (!cond) { | 29 | 0 | throw std::logic_error(std::forward<T>(msg)); | 30 | 0 | } | 31 | 509k | } |
void qpdf::util::assertion<char const (&) [49]>(bool, char const (&) [49]) Line | Count | Source | 27 | 33.1k | { | 28 | 33.1k | if (!cond) { | 29 | 0 | throw std::logic_error(std::forward<T>(msg)); | 30 | 0 | } | 31 | 33.1k | } |
void qpdf::util::assertion<char const (&) [47]>(bool, char const (&) [47]) Line | Count | Source | 27 | 6.93M | { | 28 | 6.93M | if (!cond) { | 29 | 0 | throw std::logic_error(std::forward<T>(msg)); | 30 | 0 | } | 31 | 6.93M | } |
void qpdf::util::assertion<char const (&) [65]>(bool, char const (&) [65]) Line | Count | Source | 27 | 11.0k | { | 28 | 11.0k | if (!cond) { | 29 | 0 | throw std::logic_error(std::forward<T>(msg)); | 30 | 0 | } | 31 | 11.0k | } |
void qpdf::util::assertion<char const (&) [121]>(bool, char const (&) [121]) Line | Count | Source | 27 | 1.96M | { | 28 | 1.96M | if (!cond) { | 29 | 0 | throw std::logic_error(std::forward<T>(msg)); | 30 | 0 | } | 31 | 1.96M | } |
Unexecuted instantiation: void qpdf::util::assertion<char const (&) [61]>(bool, char const (&) [61]) void qpdf::util::assertion<char const (&) [74]>(bool, char const (&) [74]) Line | Count | Source | 27 | 38.0k | { | 28 | 38.0k | if (!cond) { | 29 | 0 | throw std::logic_error(std::forward<T>(msg)); | 30 | 0 | } | 31 | 38.0k | } |
void qpdf::util::assertion<char const (&) [111]>(bool, char const (&) [111]) Line | Count | Source | 27 | 34.2k | { | 28 | 34.2k | if (!cond) { | 29 | 0 | throw std::logic_error(std::forward<T>(msg)); | 30 | 0 | } | 31 | 34.2k | } |
void qpdf::util::assertion<char const (&) [106]>(bool, char const (&) [106]) Line | Count | Source | 27 | 34.0k | { | 28 | 34.0k | if (!cond) { | 29 | 0 | throw std::logic_error(std::forward<T>(msg)); | 30 | 0 | } | 31 | 34.0k | } |
|
32 | | |
33 | | template <typename T> |
34 | | inline void |
35 | | internal_error_if(bool cond, T&& msg) |
36 | 112M | { |
37 | 112M | if (cond) { |
38 | 16 | throw std::logic_error("INTERNAL ERROR: "s.append(std::forward<T>(msg)) |
39 | 16 | .append( |
40 | 16 | "\nThis is a qpdf bug. Please report at " |
41 | 16 | "https://github.com/qpdf/qpdf/issues")); |
42 | 16 | } |
43 | 112M | } Unexecuted instantiation: void qpdf::util::internal_error_if<char const (&) [44]>(bool, char const (&) [44]) void qpdf::util::internal_error_if<char const (&) [29]>(bool, char const (&) [29]) Line | Count | Source | 36 | 33.2M | { | 37 | 33.2M | if (cond) { | 38 | 0 | throw std::logic_error("INTERNAL ERROR: "s.append(std::forward<T>(msg)) | 39 | 0 | .append( | 40 | 0 | "\nThis is a qpdf bug. Please report at " | 41 | 0 | "https://github.com/qpdf/qpdf/issues")); | 42 | 0 | } | 43 | 33.2M | } |
void qpdf::util::internal_error_if<char const (&) [28]>(bool, char const (&) [28]) Line | Count | Source | 36 | 38.3M | { | 37 | 38.3M | if (cond) { | 38 | 0 | throw std::logic_error("INTERNAL ERROR: "s.append(std::forward<T>(msg)) | 39 | 0 | .append( | 40 | 0 | "\nThis is a qpdf bug. Please report at " | 41 | 0 | "https://github.com/qpdf/qpdf/issues")); | 42 | 0 | } | 43 | 38.3M | } |
void qpdf::util::internal_error_if<char const (&) [34]>(bool, char const (&) [34]) Line | Count | Source | 36 | 40.6M | { | 37 | 40.6M | if (cond) { | 38 | 16 | throw std::logic_error("INTERNAL ERROR: "s.append(std::forward<T>(msg)) | 39 | 16 | .append( | 40 | 16 | "\nThis is a qpdf bug. Please report at " | 41 | 16 | "https://github.com/qpdf/qpdf/issues")); | 42 | 16 | } | 43 | 40.6M | } |
|
44 | | |
45 | | template <typename T> |
46 | | inline void |
47 | | no_ci_rt_error_if(bool cond, T&& msg) |
48 | 93.1M | { |
49 | 93.1M | if (cond) { |
50 | 4.71k | throw std::runtime_error(std::forward<T>(msg)); |
51 | 4.71k | } |
52 | 93.1M | } void qpdf::util::no_ci_rt_error_if<char const (&) [53]>(bool, char const (&) [53]) Line | Count | Source | 48 | 10.8k | { | 49 | 10.8k | if (cond) { | 50 | 79 | throw std::runtime_error(std::forward<T>(msg)); | 51 | 79 | } | 52 | 10.8k | } |
void qpdf::util::no_ci_rt_error_if<char const (&) [51]>(bool, char const (&) [51]) Line | Count | Source | 48 | 24.6M | { | 49 | 24.6M | if (cond) { | 50 | 307 | throw std::runtime_error(std::forward<T>(msg)); | 51 | 307 | } | 52 | 24.6M | } |
void qpdf::util::no_ci_rt_error_if<char const (&) [92]>(bool, char const (&) [92]) Line | Count | Source | 48 | 10.6k | { | 49 | 10.6k | if (cond) { | 50 | 0 | throw std::runtime_error(std::forward<T>(msg)); | 51 | 0 | } | 52 | 10.6k | } |
void qpdf::util::no_ci_rt_error_if<char const (&) [49]>(bool, char const (&) [49]) Line | Count | Source | 48 | 95.1k | { | 49 | 95.1k | if (cond) { | 50 | 104 | throw std::runtime_error(std::forward<T>(msg)); | 51 | 104 | } | 52 | 95.1k | } |
void qpdf::util::no_ci_rt_error_if<char const (&) [36]>(bool, char const (&) [36]) Line | Count | Source | 48 | 10.6k | { | 49 | 10.6k | if (cond) { | 50 | 147 | throw std::runtime_error(std::forward<T>(msg)); | 51 | 147 | } | 52 | 10.6k | } |
void qpdf::util::no_ci_rt_error_if<char const (&) [23]>(bool, char const (&) [23]) Line | Count | Source | 48 | 29.4M | { | 49 | 29.4M | if (cond) { | 50 | 1.03k | throw std::runtime_error(std::forward<T>(msg)); | 51 | 1.03k | } | 52 | 29.4M | } |
void qpdf::util::no_ci_rt_error_if<char const (&) [44]>(bool, char const (&) [44]) Line | Count | Source | 48 | 259k | { | 49 | 259k | if (cond) { | 50 | 487 | throw std::runtime_error(std::forward<T>(msg)); | 51 | 487 | } | 52 | 259k | } |
void qpdf::util::no_ci_rt_error_if<char const (&) [73]>(bool, char const (&) [73]) Line | Count | Source | 48 | 55.8k | { | 49 | 55.8k | if (cond) { | 50 | 0 | throw std::runtime_error(std::forward<T>(msg)); | 51 | 0 | } | 52 | 55.8k | } |
void qpdf::util::no_ci_rt_error_if<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(bool, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&) Line | Count | Source | 48 | 513k | { | 49 | 513k | if (cond) { | 50 | 0 | throw std::runtime_error(std::forward<T>(msg)); | 51 | 0 | } | 52 | 513k | } |
void qpdf::util::no_ci_rt_error_if<char const (&) [69]>(bool, char const (&) [69]) Line | Count | Source | 48 | 585k | { | 49 | 585k | if (cond) { | 50 | 295 | throw std::runtime_error(std::forward<T>(msg)); | 51 | 295 | } | 52 | 585k | } |
void qpdf::util::no_ci_rt_error_if<char const (&) [59]>(bool, char const (&) [59]) Line | Count | Source | 48 | 35.9M | { | 49 | 35.9M | if (cond) { | 50 | 0 | throw std::runtime_error(std::forward<T>(msg)); | 51 | 0 | } | 52 | 35.9M | } |
void qpdf::util::no_ci_rt_error_if<char const (&) [42]>(bool, char const (&) [42]) Line | Count | Source | 48 | 264k | { | 49 | 264k | if (cond) { | 50 | 0 | throw std::runtime_error(std::forward<T>(msg)); | 51 | 0 | } | 52 | 264k | } |
void qpdf::util::no_ci_rt_error_if<char const (&) [88]>(bool, char const (&) [88]) Line | Count | Source | 48 | 84.0k | { | 49 | 84.0k | if (cond) { | 50 | 0 | throw std::runtime_error(std::forward<T>(msg)); | 51 | 0 | } | 52 | 84.0k | } |
void qpdf::util::no_ci_rt_error_if<char const (&) [45]>(bool, char const (&) [45]) Line | Count | Source | 48 | 84.0k | { | 49 | 84.0k | if (cond) { | 50 | 14 | throw std::runtime_error(std::forward<T>(msg)); | 51 | 14 | } | 52 | 84.0k | } |
void qpdf::util::no_ci_rt_error_if<char const (&) [32]>(bool, char const (&) [32]) Line | Count | Source | 48 | 84.0k | { | 49 | 84.0k | if (cond) { | 50 | 120 | throw std::runtime_error(std::forward<T>(msg)); | 51 | 120 | } | 52 | 84.0k | } |
void qpdf::util::no_ci_rt_error_if<char const (&) [35]>(bool, char const (&) [35]) Line | Count | Source | 48 | 867k | { | 49 | 867k | if (cond) { | 50 | 328 | throw std::runtime_error(std::forward<T>(msg)); | 51 | 328 | } | 52 | 867k | } |
void qpdf::util::no_ci_rt_error_if<char const (&) [58]>(bool, char const (&) [58]) Line | Count | Source | 48 | 67.2k | { | 49 | 67.2k | if (cond) { | 50 | 1.79k | throw std::runtime_error(std::forward<T>(msg)); | 51 | 1.79k | } | 52 | 67.2k | } |
|
53 | | |
54 | | /// @brief Return true if `val` fits in `T` (predicate only). |
55 | | /// |
56 | | /// @tparam T integral target type |
57 | | /// @param val value to test |
58 | | /// @return true if `val` fits in `T` |
59 | | template <typename T> |
60 | | requires std::integral<T> |
61 | | bool |
62 | | fits(std::integral auto val) |
63 | 2.06M | { |
64 | | if constexpr (std::cmp_less( |
65 | | std::numeric_limits<decltype(val)>::min(), |
66 | 623k | std::numeric_limits<T>::min())) { |
67 | 623k | if (std::cmp_less(val, std::numeric_limits<T>::min())) { |
68 | 0 | return false; |
69 | 0 | } |
70 | 623k | } |
71 | | if constexpr (std::cmp_greater( |
72 | | std::numeric_limits<decltype(val)>::max(), |
73 | 1.74M | std::numeric_limits<T>::max())) { |
74 | 1.74M | if (std::cmp_greater(val, std::numeric_limits<T>::max())) { |
75 | 25 | return false; |
76 | 25 | } |
77 | 1.74M | } |
78 | 1.74M | return true; |
79 | 2.06M | } _ZN4qpdf4util4fitsIjTkNSt3__18integralEyQsr3stdE8integralIT_EEEbT0_ Line | Count | Source | 63 | 1.43M | { | 64 | | if constexpr (std::cmp_less( | 65 | | std::numeric_limits<decltype(val)>::min(), | 66 | | std::numeric_limits<T>::min())) { | 67 | | if (std::cmp_less(val, std::numeric_limits<T>::min())) { | 68 | | return false; | 69 | | } | 70 | | } | 71 | | if constexpr (std::cmp_greater( | 72 | | std::numeric_limits<decltype(val)>::max(), | 73 | 1.43M | std::numeric_limits<T>::max())) { | 74 | 1.43M | if (std::cmp_greater(val, std::numeric_limits<T>::max())) { | 75 | 25 | return false; | 76 | 25 | } | 77 | 1.43M | } | 78 | 1.43M | return true; | 79 | 1.43M | } |
_ZN4qpdf4util4fitsIjTkNSt3__18integralElQsr3stdE8integralIT_EEEbT0_ Line | Count | Source | 63 | 311k | { | 64 | | if constexpr (std::cmp_less( | 65 | | std::numeric_limits<decltype(val)>::min(), | 66 | 311k | std::numeric_limits<T>::min())) { | 67 | 311k | if (std::cmp_less(val, std::numeric_limits<T>::min())) { | 68 | 0 | return false; | 69 | 0 | } | 70 | 311k | } | 71 | | if constexpr (std::cmp_greater( | 72 | | std::numeric_limits<decltype(val)>::max(), | 73 | 311k | std::numeric_limits<T>::max())) { | 74 | 311k | if (std::cmp_greater(val, std::numeric_limits<T>::max())) { | 75 | 0 | return false; | 76 | 0 | } | 77 | 311k | } | 78 | 311k | return true; | 79 | 311k | } |
_ZN4qpdf4util4fitsIjTkNSt3__18integralEiQsr3stdE8integralIT_EEEbT0_ Line | Count | Source | 63 | 311k | { | 64 | | if constexpr (std::cmp_less( | 65 | | std::numeric_limits<decltype(val)>::min(), | 66 | 311k | std::numeric_limits<T>::min())) { | 67 | 311k | if (std::cmp_less(val, std::numeric_limits<T>::min())) { | 68 | 0 | return false; | 69 | 0 | } | 70 | 311k | } | 71 | | if constexpr (std::cmp_greater( | 72 | | std::numeric_limits<decltype(val)>::max(), | 73 | | std::numeric_limits<T>::max())) { | 74 | | if (std::cmp_greater(val, std::numeric_limits<T>::max())) { | 75 | | return false; | 76 | | } | 77 | | } | 78 | 311k | return true; | 79 | 311k | } |
Unexecuted instantiation: _ZN4qpdf4util4fitsIlTkNSt3__18integralEjQsr3stdE8integralIT_EEEbT0_ Unexecuted instantiation: _ZN4qpdf4util4fitsIiTkNSt3__18integralEjQsr3stdE8integralIT_EEEbT0_ |
80 | | |
81 | | /// @brief Convert `val` to `T`; throws std::range_error if out-of-range. |
82 | | /// |
83 | | /// @tparam T integral target type |
84 | | /// @param val value to convert |
85 | | /// @return Converted value as `T` |
86 | | template <typename T> |
87 | | requires std::integral<T> |
88 | | T |
89 | | to(std::integral auto val) |
90 | | { |
91 | | if (!fits<T>(val)) { |
92 | | throw std::range_error("out of range converting integral values"); |
93 | | } |
94 | | return static_cast<T>(val); |
95 | | } |
96 | | |
97 | | inline constexpr char |
98 | | hex_decode_char(char digit) |
99 | 170M | { |
100 | 170M | return digit <= '9' && digit >= '0' |
101 | 170M | ? char(digit - '0') |
102 | 170M | : (digit >= 'a' ? char(digit - 'a' + 10) |
103 | 27.4M | : (digit >= 'A' ? char(digit - 'A' + 10) : '\20')); |
104 | 170M | } |
105 | | |
106 | | inline constexpr bool |
107 | | is_hex_digit(char ch) |
108 | 54.4k | { |
109 | 54.4k | return hex_decode_char(ch) < '\20'; |
110 | 54.4k | } |
111 | | |
112 | | inline constexpr bool |
113 | | is_space(char ch) |
114 | 0 | { |
115 | 0 | return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t' || ch == '\f' || ch == '\v'; |
116 | 0 | } |
117 | | |
118 | | inline bool |
119 | | is_digit(char ch) |
120 | 196M | { |
121 | 196M | return (ch >= '0' && ch <= '9'); |
122 | 196M | } |
123 | | |
124 | | // Returns lower-case hex-encoded version of the char including a leading "#". |
125 | | inline std::string |
126 | | hex_encode_char(char c) |
127 | 292M | { |
128 | 292M | static auto constexpr hexchars = "0123456789abcdef"; |
129 | 292M | return {'#', hexchars[static_cast<unsigned char>(c) >> 4], hexchars[c & 0x0f]}; |
130 | 292M | } |
131 | | |
132 | | // Numerically increment a digit string. Ignore the last 'tail' characters. |
133 | | inline void |
134 | | increment(std::string& s, int tail = 0) |
135 | 1.00M | { |
136 | 1.00M | auto end = s.rend(); |
137 | 1.11M | for (auto it = s.rbegin() + tail; it != end; ++it) { |
138 | 1.10M | ++*it; |
139 | 1.10M | if (*it != ':') { |
140 | 993k | return; |
141 | 993k | } |
142 | 109k | *it = '0'; |
143 | 109k | } |
144 | 13.4k | s.insert(0, 1, '1'); |
145 | 13.4k | } |
146 | | |
147 | | inline bool |
148 | | is_utf16(std::string const& str) |
149 | 2.08M | { |
150 | 2.08M | return str.starts_with("\xfe\xff") || str.starts_with("\xff\xfe"); |
151 | 2.08M | } |
152 | | |
153 | | inline bool |
154 | | is_explicit_utf8(std::string const& str) |
155 | 1.82M | { |
156 | | // QPDF_String.cc knows that this is a 3-byte sequence. |
157 | 1.82M | return str.starts_with("\xef\xbb\xbf"); |
158 | 1.82M | } |
159 | | |
160 | | std::string random_string(size_t len); |
161 | | |
162 | | // Test helpers |
163 | | |
164 | | /// @brief Predicate: returns true if invoking `f()` throws an exception of type `E`. |
165 | | /// |
166 | | /// Internal test helper used by unit tests: call `throws<SomeException>([](){ ... })` and |
167 | | /// it returns true when the callable throws `SomeException` and false otherwise. |
168 | | /// The callable must be invocable with no arguments. |
169 | | template <typename E, typename F> |
170 | | requires std::invocable<F> |
171 | | inline bool |
172 | | throws(F&& f) |
173 | | { |
174 | | try { |
175 | | std::forward<F>(f)(); |
176 | | return false; |
177 | | } catch (E const&) { |
178 | | return true; |
179 | | } catch (...) { |
180 | | return false; |
181 | | } |
182 | | } |
183 | | |
184 | | } // namespace qpdf::util |
185 | | |
186 | | #endif // UTIL_HH |