Line | Branch | Exec | Source |
---|---|---|---|
1 | // SPDX-FileCopyrightText: 2022-2023 Dennis Gläser <dennis.glaeser@iws.uni-stuttgart.de> | ||
2 | // SPDX-License-Identifier: MIT | ||
3 | /*! | ||
4 | * \file | ||
5 | * \ingroup Common | ||
6 | * \copydoc GridFormat::ReservedString | ||
7 | */ | ||
8 | #ifndef GRIDFORMAT_COMMON_RESERVED_STRING_HPP_ | ||
9 | #define GRIDFORMAT_COMMON_RESERVED_STRING_HPP_ | ||
10 | |||
11 | #include <cmath> | ||
12 | #include <string_view> | ||
13 | #include <algorithm> | ||
14 | #include <ostream> | ||
15 | |||
16 | #if __has_include(<format>) | ||
17 | #include <format> | ||
18 | #endif | ||
19 | |||
20 | #include <gridformat/common/exceptions.hpp> | ||
21 | |||
22 | namespace GridFormat { | ||
23 | |||
24 | /*! | ||
25 | * \ingroup Common | ||
26 | * \brief String with a fixed maximum size of characters it can hold. | ||
27 | * We need to construct constexpr variables of strings in some places, | ||
28 | * which is not possible with std::string. This implementation currently | ||
29 | * only exposes the minimum interface that we need. | ||
30 | * \note Does not support dynamic allocation to more characters than max_size. | ||
31 | */ | ||
32 | template<std::size_t max_size = 30> | ||
33 | class ReservedString { | ||
34 | public: | ||
35 | 3 | ReservedString() = default; | |
36 | |||
37 | template<std::size_t N> | ||
38 | 206192 | constexpr ReservedString(const char (&input)[N]) { | |
39 | static_assert(N - 1 <= max_size, "Given string literal is too long"); | ||
40 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 103096 times.
|
206192 | if (input[N-1] != '\0') |
41 |
1/2✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
2 | throw ValueError("Expected null terminator character at the end of string literal"); |
42 | 206190 | _copy_from(input, N-1); | |
43 | 206190 | } | |
44 | |||
45 | 14738 | constexpr ReservedString(std::string_view s) { | |
46 | 14738 | _check_size(s.size()); | |
47 |
1/2✓ Branch 3 taken 14730 times.
✗ Branch 4 not taken.
|
14734 | _copy_from(s.begin(), s.size()); |
48 | 14734 | } | |
49 | |||
50 | 14732 | constexpr ReservedString(const std::string& s) | |
51 | 14732 | : ReservedString(std::string_view{s}) | |
52 | 14730 | {} | |
53 | |||
54 | 29455 | friend constexpr bool operator==(const ReservedString& a, const ReservedString& b) { | |
55 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 29453 times.
|
29455 | if (a._size != b._size) |
56 | 2 | return false; | |
57 | 29453 | return std::equal(a._text, a._text + a._size, b._text); | |
58 | } | ||
59 | |||
60 | friend std::ostream& operator<<(std::ostream& s, const ReservedString& str) { | ||
61 | std::for_each_n(str._text, str._size, [&] (const auto& character) { | ||
62 | s.put(character); | ||
63 | }); | ||
64 | return s; | ||
65 | } | ||
66 | |||
67 | 1351354 | constexpr operator std::string_view() const { | |
68 | 1351354 | return std::string_view{_text, _text + _size}; | |
69 | } | ||
70 | |||
71 | 14 | constexpr std::size_t size() const { return _size; } | |
72 | constexpr auto begin() const { return _text; } | ||
73 | constexpr auto end() const { return _text + _size; } | ||
74 | |||
75 | private: | ||
76 | template<typename IT> | ||
77 | 235650 | constexpr void _copy_from(IT&& iterator, std::size_t n) { | |
78 |
1/2✓ Branch 3 taken 117826 times.
✗ Branch 4 not taken.
|
235650 | std::copy_n(std::forward<IT>(iterator), std::min(n, max_size), _text); |
79 | 235650 | _size = n; | |
80 | 235650 | } | |
81 | |||
82 | 14738 | void _check_size(std::size_t n) { | |
83 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14730 times.
|
14738 | if (n >= max_size) |
84 |
1/2✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
|
8 | throw SizeError( |
85 |
3/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
|
8 | "Given character sequence exceeds maximum of " + std::to_string(max_size) + " characters " |
86 |
4/8✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
|
16 | + "(has" + std::to_string(n) + " characters). Input will be cropped." |
87 | ); | ||
88 | 14734 | } | |
89 | |||
90 | char _text[max_size]; | ||
91 | unsigned int _size{0}; | ||
92 | }; | ||
93 | |||
94 | template<std::size_t N> | ||
95 | ReservedString(const char (&input)[N]) -> ReservedString<N-1>; | ||
96 | |||
97 | } // namespace GridFormat | ||
98 | |||
99 | #if __cpp_lib_format | ||
100 | // specialize std::formatter for GridFormat::ReservedString | ||
101 | template <std::size_t n> | ||
102 | struct std::formatter<GridFormat::ReservedString<n>> : std::formatter<std::string_view> { | ||
103 | 1351340 | auto format(const GridFormat::ReservedString<n>& s, std::format_context& ctx) const { | |
104 | 1351340 | return std::formatter<std::string_view>::format(static_cast<std::string_view>(s), ctx); | |
105 | } | ||
106 | }; | ||
107 | #endif | ||
108 | |||
109 | #endif // GRIDFORMAT_COMMON_RESERVED_STRING_HPP_ | ||
110 |