SeqAn3  3.2.0
The Modern C++ library for sequence analysis.
predicate_detail.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2022, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2022, 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 
24 
25 namespace seqan3::detail
26 {
27 
28 // ----------------------------------------------------------------------------
29 // constexpr_pseudo_bitset (could be replaced with constexpr std::bitset or github.com/ClaasBontus/bitset2)
30 // ----------------------------------------------------------------------------
31 
36 template <size_t N>
37 class constexpr_pseudo_bitset : public std::array<bool, N>
38 {
39 private:
41  using base_t = std::array<bool, N>;
42 
43 public:
45  using base_t::base_t;
46 
48  constexpr constexpr_pseudo_bitset operator|(constexpr_pseudo_bitset rhs) const noexcept
49  {
50  for (size_t i = 0; i < N; ++i)
51  rhs[i] = rhs[i] || base_t::operator[](i);
52 
53  return rhs;
54  }
56  constexpr constexpr_pseudo_bitset operator~() const noexcept
57  {
58  constexpr_pseudo_bitset ret{};
59  for (size_t i = 0; i < N; ++i)
60  ret[i] = !base_t::operator[](i);
61 
62  return ret;
63  }
64 };
65 
66 // ----------------------------------------------------------------------------
67 // condition_message_v
68 // ----------------------------------------------------------------------------
69 
78 template <char op, typename condition_head_t, typename... condition_ts>
79 inline const std::string condition_message_v{
80  std::string{"("}
81  + (condition_head_t::msg + ... + (std::string{" "} + std::string{{op, op}} + std::string{" "} + condition_ts::msg))
82  + std::string{")"}};
83 
84 // ----------------------------------------------------------------------------
85 // char_predicate
86 // ----------------------------------------------------------------------------
87 
89 template <typename condition_t>
90 struct char_predicate_base;
92 
103 template <typename condition_t>
104 concept char_predicate = requires {
105  requires std::predicate<std::remove_reference_t<condition_t>, char>;
106  requires std::is_base_of_v<char_predicate_base<std::remove_cvref_t<condition_t>>,
107  std::remove_cvref_t<condition_t>>;
108 
110 
111  //The msg type can be added with a std::string.
112  {
114  } -> std::convertible_to<decltype(std::remove_reference_t<condition_t>::msg)>;
115  };
117 
137 
138 // ----------------------------------------------------------------------------
139 // char_predicate
140 // ----------------------------------------------------------------------------
141 
143 template <char_predicate... condition_ts>
144  requires (sizeof...(condition_ts) >= 2)
145 struct char_predicate_disjunction;
146 
147 template <char_predicate condition_t>
148 struct char_predicate_negator;
150 
157 template <typename derived_t>
158 struct char_predicate_base
159 {
161  using data_t = constexpr_pseudo_bitset<257>; // sizeof(char) plus EOF
162 
168  template <char_predicate rhs_t>
169  constexpr auto operator||(rhs_t const &) const
170  {
171  return char_predicate_disjunction<derived_t, rhs_t>{};
172  }
173 
175  constexpr auto operator!() const
176  {
177  return char_predicate_negator<derived_t>{};
178  }
180 
185  template <std::integral value_t>
186  constexpr bool operator()(value_t const val) const noexcept
187  requires (sizeof(value_t) == 1)
188  {
189  return derived_t::data[static_cast<unsigned char>(val)];
190  }
191 
193  template <std::integral value_t>
194  constexpr bool operator()(value_t const val) const noexcept
195  requires (sizeof(value_t) != 1)
196  {
197  using char_trait = std::char_traits<value_t>;
198  return (static_cast<std::make_unsigned_t<value_t>>(val) < 256) ? operator()(static_cast<uint8_t>(val))
199  : (char_trait::eq_int_type(val, char_trait::eof())) ? derived_t::data[256]
200  : false;
201  }
203 
208  std::string message() const
209  {
210  return derived_t::msg;
211  }
213 };
214 
215 // ----------------------------------------------------------------------------
216 // char_predicate_disjunction
217 // ----------------------------------------------------------------------------
218 
225 template <char_predicate... condition_ts>
226  requires (sizeof...(condition_ts) >= 2)
227 struct char_predicate_disjunction : public char_predicate_base<char_predicate_disjunction<condition_ts...>>
228 {
230  static inline const std::string msg = detail::condition_message_v<'|', condition_ts...>;
231 
233  using base_t = char_predicate_base<char_predicate_disjunction<condition_ts...>>;
234 
236  using typename base_t::data_t;
238  static constexpr data_t data = (condition_ts::data | ...);
239 };
240 
247 template <char_predicate condition_t>
248 struct char_predicate_negator : public char_predicate_base<char_predicate_negator<condition_t>>
249 {
251  static inline const std::string msg = std::string{'!'} + condition_t::msg;
252 
254  using base_t = char_predicate_base<char_predicate_negator<condition_t>>;
255 
257  using typename base_t::data_t;
259  static constexpr data_t data = ~condition_t::data;
260 };
261 
262 // ----------------------------------------------------------------------------
263 // is_in_interval_type
264 // ----------------------------------------------------------------------------
265 
274 template <uint8_t interval_first, uint8_t interval_last>
275  requires (interval_first <= interval_last)
276 struct is_in_interval_type : public char_predicate_base<is_in_interval_type<interval_first, interval_last>>
277 {
279  static inline const std::string msg = std::string{"is_in_interval<'"} + std::string{interval_first}
280  + std::string{"', '"} + std::string{interval_last} + std::string{"'>"};
281 
283  using base_t = char_predicate_base<is_in_interval_type<interval_first, interval_last>>;
284 
286  using typename base_t::data_t;
288  static constexpr data_t data = []() constexpr
289  {
290  data_t ret{};
291 
292  for (size_t i = interval_first; i <= static_cast<size_t>(interval_last); ++i)
293  ret[i] = true;
294 
295  return ret;
296  }
297  ();
298 };
299 
300 // ----------------------------------------------------------------------------
301 // is_char_type
302 // ----------------------------------------------------------------------------
303 
309 template <int char_v>
310 struct is_char_type : public char_predicate_base<is_char_type<char_v>>
311 {
312  static_assert(char_v == EOF || static_cast<uint64_t>(char_v) < 256, "TODO");
313 
315  static inline const std::string msg =
316  std::string{"is_char<'"} + ((char_v == EOF) ? std::string{"EOF"} : std::string{char_v}) + std::string{"'>"};
317 
319  using base_t = char_predicate_base<is_char_type<char_v>>;
320 
322  using typename base_t::data_t;
324  static constexpr data_t data = []() constexpr
325  {
326  data_t ret{};
327 
328  if (char_v == EOF)
329  ret[256] = true;
330  else
331  ret[static_cast<uint8_t>(char_v)] = true;
332 
333  return ret;
334  }
335  ();
336 };
337 
338 } // namespace seqan3::detail
Provides various type traits on generic types.
The <concepts> header from C++20's standard library.
T data(T... args)
requires requires
The rank_type of the semi-alphabet; defined as the return type of seqan3::to_rank....
Definition: alphabet/concept.hpp:164
requires std::common_with< typename std::remove_reference_t< validator1_type >::option_value_type, typename std::remove_reference_t< validator2_type >::option_value_type > 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.