SeqAn3 3.1.0
The Modern C++ library for sequence analysis.
predicate_detail.hpp
Go to the documentation of this file.
1// -----------------------------------------------------------------------------------------------------
2// Copyright (c) 2006-2021, Knut Reinert & Freie Universität Berlin
3// Copyright (c) 2016-2021, 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 <seqan3/std/concepts>
19#include <stdexcept>
20#include <string>
21
24
25namespace seqan3::detail
26{
27
28// ----------------------------------------------------------------------------
29// constexpr_pseudo_bitset (could be replaced with constexpr std::bitset or github.com/ClaasBontus/bitset2)
30// ----------------------------------------------------------------------------
31
36template <size_t N>
37class constexpr_pseudo_bitset : public std::array<bool, N>
38{
39private:
41 using base_t = std::array<bool, N>;
42public:
44 using base_t::base_t;
45
47 constexpr constexpr_pseudo_bitset operator|(constexpr_pseudo_bitset rhs) const noexcept
48 {
49 for (size_t i = 0; i < N; ++i)
50 rhs[i] = rhs[i] || base_t::operator[](i);
51
52 return rhs;
53 }
55 constexpr constexpr_pseudo_bitset operator~() const noexcept
56 {
57 constexpr_pseudo_bitset ret{};
58 for (size_t i = 0; i < N; ++i)
59 ret[i] = !base_t::operator[](i);
60
61 return ret;
62 }
63};
64
65// ----------------------------------------------------------------------------
66// condition_message_v
67// ----------------------------------------------------------------------------
68
77template <char op, typename condition_head_t, typename ...condition_ts>
78inline const std::string condition_message_v
79{
80 std::string{"("} +
81 (condition_head_t::msg + ... +
82 (std::string{" "} + std::string{{op, op}} + std::string{" "} + condition_ts::msg)) +
83 std::string{")"}
84};
85
86// ----------------------------------------------------------------------------
87// char_predicate
88// ----------------------------------------------------------------------------
89
91template <typename condition_t>
92struct char_predicate_base;
94
105template <typename condition_t>
106SEQAN3_CONCEPT char_predicate = requires
107{
108 requires std::predicate<std::remove_reference_t<condition_t>, char>;
109 requires std::is_base_of_v<char_predicate_base<std::remove_cvref_t<condition_t>>,
111
113
114 //The msg type can be added with a std::string.
116 std::convertible_to, decltype(std::remove_reference_t<condition_t>::msg));
117};
119
139
140// ----------------------------------------------------------------------------
141// char_predicate
142// ----------------------------------------------------------------------------
143
145template <char_predicate... condition_ts>
146 requires (sizeof...(condition_ts) >= 2)
147struct char_predicate_disjunction;
148
149template <char_predicate condition_t>
150struct char_predicate_negator;
152
159template <typename derived_t>
160struct char_predicate_base
161{
163 using data_t = constexpr_pseudo_bitset<257>; // sizeof(char) plus EOF
164
170 template <char_predicate rhs_t>
171 constexpr auto operator||(rhs_t const &) const
172 {
173 return char_predicate_disjunction<derived_t, rhs_t>{};
174 }
175
177 constexpr auto operator!() const
178 {
179 return char_predicate_negator<derived_t>{};
180 }
182
187 template <std::integral value_t>
188 constexpr bool operator()(value_t const val) const noexcept
190 requires (sizeof(value_t) == 1)
192 {
193 return derived_t::data[static_cast<unsigned char>(val)];
194 }
195
197 template <std::integral value_t>
198 constexpr bool operator()(value_t const val) const noexcept
200 requires (sizeof(value_t) != 1)
202 {
203 using char_trait = std::char_traits<value_t>;
204 return (static_cast<std::make_unsigned_t<value_t>>(val) < 256) ? operator()(static_cast<uint8_t>(val)) :
205 (char_trait::eq_int_type(val, char_trait::eof())) ? derived_t::data[256] : false;
206 }
208
213 std::string message() const
214 {
215 return derived_t::msg;
216 }
218};
219
220// ----------------------------------------------------------------------------
221// char_predicate_disjunction
222// ----------------------------------------------------------------------------
223
230template <char_predicate... condition_ts>
232 requires (sizeof...(condition_ts) >= 2)
234struct char_predicate_disjunction : public char_predicate_base<char_predicate_disjunction<condition_ts...>>
235{
237 inline static const std::string msg = detail::condition_message_v<'|', condition_ts...>;
238
240 using base_t = char_predicate_base<char_predicate_disjunction<condition_ts...>>;
241
243 using typename base_t::data_t;
245 static constexpr data_t data = (condition_ts::data | ...);
246};
247
254template <char_predicate condition_t>
255struct char_predicate_negator : public char_predicate_base<char_predicate_negator<condition_t>>
256{
258 inline static const std::string msg = std::string{'!'} + condition_t::msg;
259
261 using base_t = char_predicate_base<char_predicate_negator<condition_t>>;
262
264 using typename base_t::data_t;
266 static constexpr data_t data = ~condition_t::data;
267};
268
269// ----------------------------------------------------------------------------
270// is_in_interval_type
271// ----------------------------------------------------------------------------
272
281template <uint8_t interval_first, uint8_t interval_last>
283 requires (interval_first <= interval_last)
285struct is_in_interval_type : public char_predicate_base<is_in_interval_type<interval_first, interval_last>>
286{
288 inline static const std::string msg = std::string{"is_in_interval<'"} +
289 std::string{interval_first} +
290 std::string{"', '"} +
291 std::string{interval_last} +
292 std::string{"'>"};
293
295 using base_t = char_predicate_base<is_in_interval_type<interval_first, interval_last>>;
296
298 using typename base_t::data_t;
300 static constexpr data_t data = [] () constexpr
301 {
302 data_t ret{};
303
304 for (size_t i = interval_first; i <= static_cast<size_t>(interval_last); ++i)
305 ret[i] = true;
306
307 return ret;
308 }();
309};
310
311// ----------------------------------------------------------------------------
312// is_char_type
313// ----------------------------------------------------------------------------
314
320template <int char_v>
321struct is_char_type : public char_predicate_base<is_char_type<char_v>>
322{
323 static_assert(char_v == EOF || static_cast<uint64_t>(char_v) < 256, "TODO");
324
326 inline static const std::string msg = std::string{"is_char<'"} +
327 ((char_v == EOF) ? std::string{"EOF"} : std::string{char_v}) +
328 std::string{"'>"};
329
330
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.
The <concepts> header from C++20's standard library.
T data(T... args)
auto operator|(validator1_type &&vali1, validator2_type &&vali2)
Enables the chaining of validators.
Definition: validators.hpp:1120
#define SEQAN3_RETURN_TYPE_CONSTRAINT(expression, concept_name,...)
Same as writing {expression} -> concept_name<type1[, ...]> in a concept definition.
Definition: platform.hpp:57
Provides traits to inspect some information of a type, for example its name.