SeqAn3 3.4.0-rc.1
The Modern C++ library for sequence analysis.
Loading...
Searching...
No Matches
predicate_detail.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2006-2024 Knut Reinert & Freie Universität Berlin
2// SPDX-FileCopyrightText: 2016-2024 Knut Reinert & MPI für molekulare Genetik
3// SPDX-License-Identifier: BSD-3-Clause
4
11#pragma once
12
13#include <array>
14#include <cctype>
15#include <concepts>
16#include <stdexcept>
17#include <string>
18
22
23namespace seqan3::detail
24{
25
26// ----------------------------------------------------------------------------
27// constexpr_pseudo_bitset (could be replaced with constexpr std::bitset or github.com/ClaasBontus/bitset2)
28// ----------------------------------------------------------------------------
29
34template <size_t N>
35class constexpr_pseudo_bitset : public std::array<bool, N>
36{
37private:
39 using base_t = std::array<bool, N>;
40
41public:
43 using base_t::base_t;
44
46 constexpr constexpr_pseudo_bitset operator|(constexpr_pseudo_bitset rhs) const noexcept
47 {
48 for (size_t i = 0; i < N; ++i)
49 rhs[i] = rhs[i] || base_t::operator[](i);
50
51 return rhs;
52 }
54 constexpr constexpr_pseudo_bitset operator~() const noexcept
55 {
56 constexpr_pseudo_bitset ret{};
57 for (size_t i = 0; i < N; ++i)
58 ret[i] = !base_t::operator[](i);
59
60 return ret;
61 }
62};
63
64// ----------------------------------------------------------------------------
65// condition_message_v
66// ----------------------------------------------------------------------------
67
76template <char op, typename condition_head_t, typename... condition_ts>
77inline std::string const condition_message_v{
78 std::string{"("}
79 + (condition_head_t::msg + ... + (std::string{" "} + std::string{{op, op}} + std::string{" "} + condition_ts::msg))
80 + std::string{")"}};
81
82// ----------------------------------------------------------------------------
83// char_predicate
84// ----------------------------------------------------------------------------
85
87template <typename condition_t>
88struct char_predicate_base;
90
101template <typename condition_t>
102concept char_predicate = requires {
103 requires std::predicate<std::remove_reference_t<condition_t>, char>;
104 requires std::is_base_of_v<char_predicate_base<std::remove_cvref_t<condition_t>>, std::remove_cvref_t<condition_t>>;
105
107
108 //The msg type can be added with a std::string.
109 {
111 } -> std::convertible_to<decltype(std::remove_reference_t<condition_t>::msg)>;
112};
114
134
135// ----------------------------------------------------------------------------
136// char_predicate
137// ----------------------------------------------------------------------------
138
140template <char_predicate... condition_ts>
141 requires (sizeof...(condition_ts) >= 2)
142struct char_predicate_disjunction;
143
144template <char_predicate condition_t>
145struct char_predicate_negator;
147
154template <typename derived_t>
155struct char_predicate_base
156{
158 using data_t = constexpr_pseudo_bitset<257>; // sizeof(char) plus EOF
159
165 template <char_predicate rhs_t>
166 constexpr auto operator||(rhs_t const &) const
167 {
168 return char_predicate_disjunction<derived_t, rhs_t>{};
169 }
170
172 constexpr auto operator!() const
173 {
174 return char_predicate_negator<derived_t>{};
175 }
177
182 template <std::integral value_t>
183 constexpr bool operator()(value_t const val) const noexcept
184 requires (sizeof(value_t) == 1)
185 {
186 return derived_t::data[static_cast<unsigned char>(val)];
187 }
188
190 template <std::integral value_t>
191 constexpr bool operator()(value_t const val) const noexcept
192 requires (sizeof(value_t) != 1)
193 {
194 // std::char_traits is only guaranteed to be defined for character types.
195 // libc++ deprecates other specialisations in llvm-17, and removes them in llvm-18.
196 // We map the non-character types to corresponding chracter types.
197 // For example, `seqan3::is_eof(EOF)` will call this function with `value_t == int`.
198 using char_value_t = std::conditional_t<
200 value_t,
202 std::same_as<value_t, std::char_traits<char>::int_type>,
203 char,
205 std::same_as<value_t, std::char_traits<wchar_t>::int_type>,
206 wchar_t,
208 std::same_as<value_t, std::char_traits<char8_t>::int_type>,
209 char8_t,
211 std::same_as<value_t, std::char_traits<char16_t>::int_type>,
212 char16_t,
214 char32_t,
215 void>>>>>>;
216 static_assert(!std::same_as<char_value_t, void>, "There is no valid character representation.");
217 using char_trait = std::char_traits<char_value_t>;
218 return (static_cast<std::make_unsigned_t<value_t>>(val) < 256) ? operator()(static_cast<uint8_t>(val))
219 : (char_trait::eq_int_type(val, char_trait::eof())) ? derived_t::data[256]
220 : false;
221 }
223
228 std::string message() const
229 {
230 return derived_t::msg;
231 }
233};
234
235// ----------------------------------------------------------------------------
236// char_predicate_disjunction
237// ----------------------------------------------------------------------------
238
245template <char_predicate... condition_ts>
246 requires (sizeof...(condition_ts) >= 2)
247struct char_predicate_disjunction : public char_predicate_base<char_predicate_disjunction<condition_ts...>>
248{
250 static inline std::string const msg = detail::condition_message_v<'|', condition_ts...>;
251
253 using base_t = char_predicate_base<char_predicate_disjunction<condition_ts...>>;
254
256 using typename base_t::data_t;
258 static constexpr data_t data = (condition_ts::data | ...);
259};
260
267template <char_predicate condition_t>
268struct char_predicate_negator : public char_predicate_base<char_predicate_negator<condition_t>>
269{
271 static inline std::string const msg = std::string{'!'} + condition_t::msg;
272
274 using base_t = char_predicate_base<char_predicate_negator<condition_t>>;
275
277 using typename base_t::data_t;
279 static constexpr data_t data = ~condition_t::data;
280};
281
282// ----------------------------------------------------------------------------
283// is_in_interval_type
284// ----------------------------------------------------------------------------
285
294template <uint8_t interval_first, uint8_t interval_last>
295 requires (interval_first <= interval_last)
296struct is_in_interval_type : public char_predicate_base<is_in_interval_type<interval_first, interval_last>>
297{
299 static inline std::string const msg = std::string{"is_in_interval<'"} + std::string{interval_first}
300 + std::string{"', '"} + std::string{interval_last} + std::string{"'>"};
301
303 using base_t = char_predicate_base<is_in_interval_type<interval_first, interval_last>>;
304
306 using typename base_t::data_t;
308 static constexpr data_t data = []() constexpr
309 {
310 data_t ret{};
311
312 for (size_t i = interval_first; i <= static_cast<size_t>(interval_last); ++i)
313 ret[i] = true;
314
315 return ret;
316 }();
317};
318
319// ----------------------------------------------------------------------------
320// is_char_type
321// ----------------------------------------------------------------------------
322
328template <int char_v>
329struct is_char_type : public char_predicate_base<is_char_type<char_v>>
330{
331 static_assert(char_v == EOF || static_cast<uint64_t>(char_v) < 256, "TODO");
332
334 static inline std::string const msg =
335 std::string{"is_char<'"} + ((char_v == EOF) ? std::string{"EOF"} : std::string{char_v}) + std::string{"'>"};
336
338 using base_t = char_predicate_base<is_char_type<char_v>>;
339
341 using typename base_t::data_t;
343 static constexpr data_t data = []() constexpr
344 {
345 data_t ret{};
346
347 if (char_v == EOF)
348 ret[256] = true;
349 else
350 ret[static_cast<uint8_t>(char_v)] = true;
351
352 return ret;
353 }();
354};
355
356} // namespace seqan3::detail
Provides various type traits on generic types.
A "pretty printer" for most SeqAn data structures and related types.
Definition debug_stream_type.hpp:79
T data(T... args)
auto operator|(validator1_type &&vali1, validator2_type &&vali2)
Enables the chaining of validators.
Definition validators.hpp:1117
Provides traits to inspect some information of a type, for example its name.
Provides concepts that do not have equivalents in C++20.
Hide me