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 
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 public:
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 
77 template <char op, typename condition_head_t, typename ...condition_ts>
78 inline 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 
91 template <typename condition_t>
92 struct char_predicate_base;
94 
105 template <typename condition_t>
106 SEQAN3_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 
145 template <char_predicate... condition_ts>
146  requires (sizeof...(condition_ts) >= 2)
147 struct char_predicate_disjunction;
148 
149 template <char_predicate condition_t>
150 struct char_predicate_negator;
152 
159 template <typename derived_t>
160 struct 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 
230 template <char_predicate... condition_ts>
232  requires (sizeof...(condition_ts) >= 2)
234 struct 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 
254 template <char_predicate condition_t>
255 struct 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 
281 template <uint8_t interval_first, uint8_t interval_last>
283  requires (interval_first <= interval_last)
285 struct 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 
320 template <int char_v>
321 struct 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
typename remove_cvref< t >::type remove_cvref_t
Return the input type with const, volatile and references removed (transformation_trait shortcut).
Definition: type_traits:73
#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.