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// -----------------------------------------------------------------------------------------------------
2// Copyright (c) 2006-2023, Knut Reinert & Freie Universität Berlin
3// Copyright (c) 2016-2023, Knut Reinert & MPI für molekulare Genetik
4// This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
5// shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md
6// -----------------------------------------------------------------------------------------------------
7
14#pragma once
15
16#include <array>
17#include <cctype>
18#include <concepts>
19#include <stdexcept>
20#include <string>
21
25
26namespace seqan3::detail
27{
28
29// ----------------------------------------------------------------------------
30// constexpr_pseudo_bitset (could be replaced with constexpr std::bitset or github.com/ClaasBontus/bitset2)
31// ----------------------------------------------------------------------------
32
37template <size_t N>
38class constexpr_pseudo_bitset : public std::array<bool, N>
39{
40private:
42 using base_t = std::array<bool, N>;
43
44public:
46 using base_t::base_t;
47
49 constexpr constexpr_pseudo_bitset operator|(constexpr_pseudo_bitset rhs) const noexcept
50 {
51 for (size_t i = 0; i < N; ++i)
52 rhs[i] = rhs[i] || base_t::operator[](i);
53
54 return rhs;
55 }
57 constexpr constexpr_pseudo_bitset operator~() const noexcept
58 {
59 constexpr_pseudo_bitset ret{};
60 for (size_t i = 0; i < N; ++i)
61 ret[i] = !base_t::operator[](i);
62
63 return ret;
64 }
65};
66
67// ----------------------------------------------------------------------------
68// condition_message_v
69// ----------------------------------------------------------------------------
70
79template <char op, typename condition_head_t, typename... condition_ts>
80inline const std::string condition_message_v{
81 std::string{"("}
82 + (condition_head_t::msg + ... + (std::string{" "} + std::string{{op, op}} + std::string{" "} + condition_ts::msg))
83 + std::string{")"}};
84
85// ----------------------------------------------------------------------------
86// char_predicate
87// ----------------------------------------------------------------------------
88
90template <typename condition_t>
91struct char_predicate_base;
93
104template <typename condition_t>
105concept char_predicate = requires {
106 requires std::predicate<std::remove_reference_t<condition_t>, char>;
107 requires std::is_base_of_v<char_predicate_base<std::remove_cvref_t<condition_t>>,
109
111
112 //The msg type can be added with a std::string.
113 {
115 } -> std::convertible_to<decltype(std::remove_reference_t<condition_t>::msg)>;
116 };
118
138
139// ----------------------------------------------------------------------------
140// char_predicate
141// ----------------------------------------------------------------------------
142
144template <char_predicate... condition_ts>
145 requires (sizeof...(condition_ts) >= 2)
146struct char_predicate_disjunction;
147
148template <char_predicate condition_t>
149struct char_predicate_negator;
151
158template <typename derived_t>
159struct char_predicate_base
160{
162 using data_t = constexpr_pseudo_bitset<257>; // sizeof(char) plus EOF
163
169 template <char_predicate rhs_t>
170 constexpr auto operator||(rhs_t const &) const
171 {
172 return char_predicate_disjunction<derived_t, rhs_t>{};
173 }
174
176 constexpr auto operator!() const
177 {
178 return char_predicate_negator<derived_t>{};
179 }
181
186 template <std::integral value_t>
187 constexpr bool operator()(value_t const val) const noexcept
188 requires (sizeof(value_t) == 1)
189 {
190 return derived_t::data[static_cast<unsigned char>(val)];
191 }
192
194 template <std::integral value_t>
195 constexpr bool operator()(value_t const val) const noexcept
196 requires (sizeof(value_t) != 1)
197 {
198 // std::char_traits is only guaranteed to be defined for character types.
199 // libc++ deprecates other specialisations in llvm-17, and removes them in llvm-18.
200 // We map the non-character types to corresponding chracter types.
201 // For example, `seqan3::is_eof(EOF)` will call this function with `value_t == int`.
202 // clang-format off
203 using char_value_t = std::conditional_t<seqan3::builtin_character<value_t>, value_t,
209 void>>>>>>;
210 // clang-format on
211 static_assert(!std::same_as<char_value_t, void>, "There is no valid character representation.");
212 using char_trait = std::char_traits<char_value_t>;
213 return (static_cast<std::make_unsigned_t<value_t>>(val) < 256) ? operator()(static_cast<uint8_t>(val))
214 : (char_trait::eq_int_type(val, char_trait::eof())) ? derived_t::data[256]
215 : false;
216 }
218
223 std::string message() const
224 {
225 return derived_t::msg;
226 }
228};
229
230// ----------------------------------------------------------------------------
231// char_predicate_disjunction
232// ----------------------------------------------------------------------------
233
240template <char_predicate... condition_ts>
241 requires (sizeof...(condition_ts) >= 2)
242struct char_predicate_disjunction : public char_predicate_base<char_predicate_disjunction<condition_ts...>>
243{
245 static inline const std::string msg = detail::condition_message_v<'|', condition_ts...>;
246
248 using base_t = char_predicate_base<char_predicate_disjunction<condition_ts...>>;
249
251 using typename base_t::data_t;
253 static constexpr data_t data = (condition_ts::data | ...);
254};
255
262template <char_predicate condition_t>
263struct char_predicate_negator : public char_predicate_base<char_predicate_negator<condition_t>>
264{
266 static inline const std::string msg = std::string{'!'} + condition_t::msg;
267
269 using base_t = char_predicate_base<char_predicate_negator<condition_t>>;
270
272 using typename base_t::data_t;
274 static constexpr data_t data = ~condition_t::data;
275};
276
277// ----------------------------------------------------------------------------
278// is_in_interval_type
279// ----------------------------------------------------------------------------
280
289template <uint8_t interval_first, uint8_t interval_last>
290 requires (interval_first <= interval_last)
291struct is_in_interval_type : public char_predicate_base<is_in_interval_type<interval_first, interval_last>>
292{
294 static inline const std::string msg = std::string{"is_in_interval<'"} + std::string{interval_first}
295 + std::string{"', '"} + std::string{interval_last} + std::string{"'>"};
296
298 using base_t = char_predicate_base<is_in_interval_type<interval_first, interval_last>>;
299
301 using typename base_t::data_t;
303 static constexpr data_t data = []() constexpr
304 {
305 data_t ret{};
306
307 for (size_t i = interval_first; i <= static_cast<size_t>(interval_last); ++i)
308 ret[i] = true;
309
310 return ret;
311 }();
312};
313
314// ----------------------------------------------------------------------------
315// is_char_type
316// ----------------------------------------------------------------------------
317
323template <int char_v>
324struct is_char_type : public char_predicate_base<is_char_type<char_v>>
325{
326 static_assert(char_v == EOF || static_cast<uint64_t>(char_v) < 256, "TODO");
327
329 static inline const std::string msg =
330 std::string{"is_char<'"} + ((char_v == EOF) ? std::string{"EOF"} : std::string{char_v}) + std::string{"'>"};
331
333 using base_t = char_predicate_base<is_char_type<char_v>>;
334
336 using typename base_t::data_t;
338 static constexpr data_t data = []() constexpr
339 {
340 data_t ret{};
341
342 if (char_v == EOF)
343 ret[256] = true;
344 else
345 ret[static_cast<uint8_t>(char_v)] = true;
346
347 return ret;
348 }();
349};
350
351} // namespace seqan3::detail
Provides various type traits on generic types.
T data(T... args)
auto operator|(validator1_type &&vali1, validator2_type &&vali2)
Enables the chaining of validators.
Definition validators.hpp:1124
Provides traits to inspect some information of a type, for example its name.
Provides concepts that do not have equivalents in C++20.