SeqAn3
The Modern C++ library for sequence analysis.
predicate_detail.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2019, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2019, 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 <stdexcept>
19 #include <string>
20 
21 #include <seqan3/std/concepts>
22 
27 
28 namespace seqan3::detail
29 {
30 
31 // ----------------------------------------------------------------------------
32 // constexpr_pseudo_bitset (could be replaced with constexpr std::bitset or github.com/ClaasBontus/bitset2)
33 // ----------------------------------------------------------------------------
34 
39 template <size_t N>
40 class constexpr_pseudo_bitset : public std::array<bool, N>
41 {
42 private:
44  using base_t = std::array<bool, N>;
45 public:
47  using base_t::base_t;
48 
50  constexpr constexpr_pseudo_bitset operator|(constexpr_pseudo_bitset rhs) const noexcept
51  {
52  for (size_t i = 0; i < N; ++i)
53  rhs[i] = rhs[i] || base_t::operator[](i);
54 
55  return rhs;
56  }
58  constexpr constexpr_pseudo_bitset operator~() const noexcept
59  {
60  constexpr_pseudo_bitset ret{};
61  for (size_t i = 0; i < N; ++i)
62  ret[i] = !base_t::operator[](i);
63 
64  return ret;
65  }
66 };
67 
68 // ----------------------------------------------------------------------------
69 // condition_message_v
70 // ----------------------------------------------------------------------------
71 
80 template <char op, typename condition_head_t, typename ...condition_ts>
81 inline small_string constexpr condition_message_v
82 {
83  small_string{"("} +
84  (condition_head_t::msg + ... +
85  (small_string{" "} + small_string{{op, op, '\0'}} + small_string{" "} + condition_ts::msg)) +
86  small_string{")"}
87 };
88 
89 // ----------------------------------------------------------------------------
90 // CharPredicate
91 // ----------------------------------------------------------------------------
92 
94 template <typename condition_t>
95 class char_predicate_base;
97 
107 template <typename condition_t>
109 SEQAN3_CONCEPT CharPredicate = requires
110 {
112  requires std::is_base_of_v<char_predicate_base<remove_cvref_t<condition_t>>,
113  remove_cvref_t<condition_t>>;
114 
116 
117  //The msg type can be added with a small_string.
118  { small_string<0>{} + std::remove_reference_t<condition_t>::msg } ->
120 };
122 
141 
143 
144 // ----------------------------------------------------------------------------
145 // char_predicate
146 // ----------------------------------------------------------------------------
147 
149 template <CharPredicate... condition_ts>
150  requires sizeof...(condition_ts) >= 2
151 struct char_predicate_combiner;
152 
153 template <CharPredicate 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 
173  template <CharPredicate rhs_t>
175  constexpr auto operator||(rhs_t const &) const
176  {
177  return char_predicate_combiner<derived_t, rhs_t>{};
178  }
179 
181  constexpr auto operator!() const
182  {
183  return char_predicate_negator<derived_t>{};
184  }
186 
190  template <std::Integral value_t>
192  constexpr bool operator()(value_t const val) const noexcept
193  requires sizeof(value_t) == 1
194  {
195  return derived_t::data[static_cast<unsigned char>(val)];
196  }
197  template <std::Integral value_t>
198  constexpr bool operator()(value_t const val) const noexcept
199  requires sizeof(value_t) != 1
200  {
201  return (static_cast<std::make_unsigned_t<value_t>>(val) < 256) ? operator()(static_cast<uint8_t>(val)) :
202  (static_cast<decltype(EOF)>(val) == EOF) ? derived_t::data[256] : false;
203  }
205 
209  std::string message() const
211  {
212  return derived_t::msg;
213  }
215 };
216 
217 // ----------------------------------------------------------------------------
218 // char_predicate_combiner
219 // ----------------------------------------------------------------------------
220 
227 template <CharPredicate... condition_ts>
229  requires sizeof...(condition_ts) >= 2
231 struct char_predicate_combiner : public char_predicate_base<char_predicate_combiner<condition_ts...>>
232 {
234  static constexpr auto msg = detail::condition_message_v<'|', condition_ts...>;
235 
237  using base_t = char_predicate_base<char_predicate_combiner<condition_ts...>>;
238 
240  using typename base_t::data_t;
242  static constexpr data_t data = (condition_ts::data | ...);
243 };
244 
251 template <CharPredicate condition_t>
252 struct char_predicate_negator : public char_predicate_base<char_predicate_negator<condition_t>>
253 {
255  static constexpr auto msg = small_string{'!'} + condition_t::msg;
256 
258  using base_t = char_predicate_base<char_predicate_negator<condition_t>>;
259 
261  using typename base_t::data_t;
263  static constexpr data_t data = ~condition_t::data;
264 };
265 
266 // ----------------------------------------------------------------------------
267 // is_in_interval_type
268 // ----------------------------------------------------------------------------
269 
278 template <uint8_t interval_first, uint8_t interval_last>
280  requires interval_first <= interval_last
282 struct is_in_interval_type : public char_predicate_base<is_in_interval_type<interval_first, interval_last>>
283 {
285  static constexpr small_string msg = small_string{"is_in_interval<'"} +
286  small_string{interval_first} +
287  small_string{"', '"} +
288  small_string{interval_last} +
289  small_string{"'>"};
290 
292  using base_t = char_predicate_base<is_in_interval_type<interval_first, interval_last>>;
293 
295  using typename base_t::data_t;
297  static constexpr data_t data = [] () constexpr
298  {
299  data_t ret{};
300 
301  for (size_t i = interval_first; i <= static_cast<size_t>(interval_last); ++i)
302  ret[i] = true;
303 
304  return ret;
305  }();
306 };
307 
308 // ----------------------------------------------------------------------------
309 // is_in_alphabet_type
310 // ----------------------------------------------------------------------------
311 
317 template <detail::ConstexprAlphabet alphabet_t>
318 struct is_in_alphabet_type : public char_predicate_base<is_in_alphabet_type<alphabet_t>>
319 {
320 public:
322  static constexpr auto msg = small_string{"is_in_alphabet<"} +
323  small_string{detail::get_display_name_v<alphabet_t>} +
324  small_string{">"};
325 
327  using base_t = char_predicate_base<is_in_alphabet_type<alphabet_t>>;
328 
330  using typename base_t::data_t;
332  static constexpr data_t data = [] () constexpr
333  {
334  data_t ret{};
335 
336  for (size_t i = 0; i < 256; ++i)
337  ret[i] = char_is_valid_for<alphabet_t>(static_cast<uint8_t>(i));
338 
339  return ret;
340  }();
341 };
342 
343 // ----------------------------------------------------------------------------
344 // is_char_type
345 // ----------------------------------------------------------------------------
346 
352 template <int char_v>
353 struct is_char_type : public char_predicate_base<is_char_type<char_v>>
354 {
355  static_assert(char_v == EOF || static_cast<uint64_t>(char_v) < 256, "TODO");
356 
358  static constexpr auto msg = small_string{"is_char<'"} +
359  small_string{char_v} +
360  small_string("'>");
361 
362 
363 
365  using base_t = char_predicate_base<is_char_type<char_v>>;
366 
368  using typename base_t::data_t;
370  static constexpr data_t data = [] () constexpr
371  {
372  data_t ret{};
373 
374  if (char_v == EOF)
375  ret[256] = true;
376  else
377  ret[static_cast<uint8_t>(char_v)] = true;
378 
379  return ret;
380  }();
381 };
382 
383 } // namespace seqan3::detail
small_string constexpr condition_message_v
Defines a compound seqan3::small_string consisting of all given conditions separated by the operator-...
Definition: predicate_detail.hpp:82
::ranges::data data
Alias for ranges::data. Returns a pointer the block of data of a ContiguousRange. ...
Definition: ranges:184
Specifies whether the given callable is std::RegularInvocable and returns bool.
The Concepts library.
Definition: aligned_sequence_concept.hpp:35
A constexpr string implementation to manipulate string literals at compile time.
Provides various type traits on generic types.
auto operator|(validator1_type &&vali1, validator2_type &&vali2)
Enables the chaining of validators.
Definition: validators.hpp:889
Core alphabet concept and free function/type trait wrappers.
Static reflection for arbitrary types.