SeqAn3  3.0.3
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 
25 #ifdef SEQAN3_DEPRECATED_310
27 #endif // SEQAN3_DEPRECATED_310
28 
29 namespace seqan3::detail
30 {
31 
32 // ----------------------------------------------------------------------------
33 // constexpr_pseudo_bitset (could be replaced with constexpr std::bitset or github.com/ClaasBontus/bitset2)
34 // ----------------------------------------------------------------------------
35 
40 template <size_t N>
41 class constexpr_pseudo_bitset : public std::array<bool, N>
42 {
43 private:
45  using base_t = std::array<bool, N>;
46 public:
48  using base_t::base_t;
49 
51  constexpr constexpr_pseudo_bitset operator|(constexpr_pseudo_bitset rhs) const noexcept
52  {
53  for (size_t i = 0; i < N; ++i)
54  rhs[i] = rhs[i] || base_t::operator[](i);
55 
56  return rhs;
57  }
59  constexpr constexpr_pseudo_bitset operator~() const noexcept
60  {
61  constexpr_pseudo_bitset ret{};
62  for (size_t i = 0; i < N; ++i)
63  ret[i] = !base_t::operator[](i);
64 
65  return ret;
66  }
67 };
68 
69 // ----------------------------------------------------------------------------
70 // condition_message_v
71 // ----------------------------------------------------------------------------
72 
81 template <char op, typename condition_head_t, typename ...condition_ts>
82 inline const std::string condition_message_v
83 {
84  std::string{"("} +
85  (condition_head_t::msg + ... +
86  (std::string{" "} + std::string{{op, op}} + std::string{" "} + condition_ts::msg)) +
87  std::string{")"}
88 };
89 
90 // ----------------------------------------------------------------------------
91 // char_predicate
92 // ----------------------------------------------------------------------------
93 
95 template <typename condition_t>
96 struct char_predicate_base;
98 
109 template <typename condition_t>
110 SEQAN3_CONCEPT char_predicate = requires
111 {
112  requires std::predicate<std::remove_reference_t<condition_t>, char>;
113  requires std::is_base_of_v<char_predicate_base<std::remove_cvref_t<condition_t>>,
115 
117 
118  //The msg type can be added with a std::string.
120  std::convertible_to, decltype(std::remove_reference_t<condition_t>::msg));
121 };
123 
143 
144 // ----------------------------------------------------------------------------
145 // char_predicate
146 // ----------------------------------------------------------------------------
147 
149 template <char_predicate... condition_ts>
150  requires (sizeof...(condition_ts) >= 2)
151 struct char_predicate_disjunction;
152 
153 template <char_predicate condition_t>
154 struct char_predicate_negator;
156 
163 template <typename derived_t>
164 struct char_predicate_base
165 {
167  using data_t = constexpr_pseudo_bitset<257>; // sizeof(char) plus EOF
168 
174  template <char_predicate rhs_t>
175  constexpr auto operator||(rhs_t const &) const
176  {
177  return char_predicate_disjunction<derived_t, rhs_t>{};
178  }
179 
181  constexpr auto operator!() const
182  {
183  return char_predicate_negator<derived_t>{};
184  }
186 
191  template <std::integral value_t>
192  constexpr bool operator()(value_t const val) const noexcept
194  requires (sizeof(value_t) == 1)
196  {
197  return derived_t::data[static_cast<unsigned char>(val)];
198  }
199 
201  template <std::integral value_t>
202  constexpr bool operator()(value_t const val) const noexcept
204  requires (sizeof(value_t) != 1)
206  {
207  using char_trait = std::char_traits<value_t>;
208  return (static_cast<std::make_unsigned_t<value_t>>(val) < 256) ? operator()(static_cast<uint8_t>(val)) :
209  (char_trait::eq_int_type(val, char_trait::eof())) ? derived_t::data[256] : false;
210  }
212 
217  std::string message() const
218  {
219  return derived_t::msg;
220  }
222 };
223 
224 // ----------------------------------------------------------------------------
225 // char_predicate_disjunction
226 // ----------------------------------------------------------------------------
227 
234 template <char_predicate... condition_ts>
236  requires (sizeof...(condition_ts) >= 2)
238 struct char_predicate_disjunction : public char_predicate_base<char_predicate_disjunction<condition_ts...>>
239 {
241  inline static const std::string msg = detail::condition_message_v<'|', condition_ts...>;
242 
244  using base_t = char_predicate_base<char_predicate_disjunction<condition_ts...>>;
245 
247  using typename base_t::data_t;
249  static constexpr data_t data = (condition_ts::data | ...);
250 };
251 
258 template <char_predicate condition_t>
259 struct char_predicate_negator : public char_predicate_base<char_predicate_negator<condition_t>>
260 {
262  inline static const std::string msg = std::string{'!'} + condition_t::msg;
263 
265  using base_t = char_predicate_base<char_predicate_negator<condition_t>>;
266 
268  using typename base_t::data_t;
270  static constexpr data_t data = ~condition_t::data;
271 };
272 
273 // ----------------------------------------------------------------------------
274 // is_in_interval_type
275 // ----------------------------------------------------------------------------
276 
285 template <uint8_t interval_first, uint8_t interval_last>
287  requires (interval_first <= interval_last)
289 struct is_in_interval_type : public char_predicate_base<is_in_interval_type<interval_first, interval_last>>
290 {
292  inline static const std::string msg = std::string{"is_in_interval<'"} +
293  std::string{interval_first} +
294  std::string{"', '"} +
295  std::string{interval_last} +
296  std::string{"'>"};
297 
299  using base_t = char_predicate_base<is_in_interval_type<interval_first, interval_last>>;
300 
302  using typename base_t::data_t;
304  static constexpr data_t data = [] () constexpr
305  {
306  data_t ret{};
307 
308  for (size_t i = interval_first; i <= static_cast<size_t>(interval_last); ++i)
309  ret[i] = true;
310 
311  return ret;
312  }();
313 };
314 
315 #ifdef SEQAN3_DEPRECATED_310
316 // ----------------------------------------------------------------------------
317 // is_in_alphabet_type
318 // ----------------------------------------------------------------------------
319 
325 template <detail::constexpr_alphabet alphabet_t>
326 struct is_in_alphabet_type : public char_predicate_base<is_in_alphabet_type<alphabet_t>>
327 {
328 public:
330  inline static const std::string msg = std::string{"is_in_alphabet<"} +
331  detail::type_name_as_string<alphabet_t> +
332  std::string{">"};
333 
335  using base_t = char_predicate_base<is_in_alphabet_type<alphabet_t>>;
336 
338  using typename base_t::data_t;
340  static constexpr data_t data = [] () constexpr
341  {
342  data_t ret{};
343 
344  for (size_t i = 0; i < 256; ++i)
345  ret[i] = char_is_valid_for<alphabet_t>(static_cast<uint8_t>(i));
346 
347  return ret;
348  }();
349 };
350 #endif // SEQAN3_DEPRECATED_310
351 
352 // ----------------------------------------------------------------------------
353 // is_char_type
354 // ----------------------------------------------------------------------------
355 
361 template <int char_v>
362 struct is_char_type : public char_predicate_base<is_char_type<char_v>>
363 {
364  static_assert(char_v == EOF || static_cast<uint64_t>(char_v) < 256, "TODO");
365 
367  inline static const std::string msg = std::string{"is_char<'"} +
368  ((char_v == EOF) ? std::string{"EOF"} : std::string{char_v}) +
369  std::string{"'>"};
370 
371 
372 
374  using base_t = char_predicate_base<is_char_type<char_v>>;
375 
377  using typename base_t::data_t;
379  static constexpr data_t data = [] () constexpr
380  {
381  data_t ret{};
382 
383  if (char_v == EOF)
384  ret[256] = true;
385  else
386  ret[static_cast<uint8_t>(char_v)] = true;
387 
388  return ret;
389  }();
390 };
391 
392 } // namespace seqan3::detail
Core alphabet concept and free function/type trait wrappers.
The Concepts library.
T data(T... args)
auto operator|(validator1_type &&vali1, validator2_type &&vali2)
Enables the chaining of validators.
Definition: validators.hpp:1103
#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.
Provides various type traits on generic types.