SeqAn3  3.0.2
The Modern C++ library for sequence analysis.
predicate_detail.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2020, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2020, 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 
26 
27 namespace seqan3::detail
28 {
29 
30 // ----------------------------------------------------------------------------
31 // constexpr_pseudo_bitset (could be replaced with constexpr std::bitset or github.com/ClaasBontus/bitset2)
32 // ----------------------------------------------------------------------------
33 
38 template <size_t N>
39 class constexpr_pseudo_bitset : public std::array<bool, N>
40 {
41 private:
43  using base_t = std::array<bool, N>;
44 public:
46  using base_t::base_t;
47 
49  constexpr constexpr_pseudo_bitset operator|(constexpr_pseudo_bitset rhs) const noexcept
50  {
51  for (size_t i = 0; i < N; ++i)
52  rhs[i] = rhs[i] || base_t::operator[](i);
53 
54  return rhs;
55  }
57  constexpr constexpr_pseudo_bitset operator~() const noexcept
58  {
59  constexpr_pseudo_bitset ret{};
60  for (size_t i = 0; i < N; ++i)
61  ret[i] = !base_t::operator[](i);
62 
63  return ret;
64  }
65 };
66 
67 // ----------------------------------------------------------------------------
68 // condition_message_v
69 // ----------------------------------------------------------------------------
70 
79 template <char op, typename condition_head_t, typename ...condition_ts>
80 inline const std::string condition_message_v
81 {
82  std::string{"("} +
83  (condition_head_t::msg + ... +
84  (std::string{" "} + std::string{{op, op}} + std::string{" "} + condition_ts::msg)) +
85  std::string{")"}
86 };
87 
88 // ----------------------------------------------------------------------------
89 // char_predicate
90 // ----------------------------------------------------------------------------
91 
93 template <typename condition_t>
94 struct char_predicate_base;
96 
106 template <typename condition_t>
108 SEQAN3_CONCEPT char_predicate = requires
109 {
110  requires std::predicate<std::remove_reference_t<condition_t>, char>;
111  requires std::is_base_of_v<char_predicate_base<std::remove_cvref_t<condition_t>>,
113 
115 
116  //The msg type can be added with a std::string.
118  std::convertible_to, decltype(std::remove_reference_t<condition_t>::msg));
119 };
121 
140 
142 // ----------------------------------------------------------------------------
143 // char_predicate
144 // ----------------------------------------------------------------------------
145 
147 template <char_predicate... condition_ts>
148  requires (sizeof...(condition_ts) >= 2)
149 struct char_predicate_combiner;
150 
151 template <char_predicate condition_t>
152 struct char_predicate_negator;
154 
161 template <typename derived_t>
162 struct char_predicate_base
163 {
165  using data_t = constexpr_pseudo_bitset<257>; // sizeof(char) plus EOF
166 
171  template <char_predicate rhs_t>
173  constexpr auto operator||(rhs_t const &) const
174  {
175  return char_predicate_combiner<derived_t, rhs_t>{};
176  }
177 
179  constexpr auto operator!() const
180  {
181  return char_predicate_negator<derived_t>{};
182  }
184 
188  template <std::integral value_t>
190  constexpr bool operator()(value_t const val) const noexcept
192  requires (sizeof(value_t) == 1)
194  {
195  return derived_t::data[static_cast<unsigned char>(val)];
196  }
197 
199  template <std::integral value_t>
200  constexpr bool operator()(value_t const val) const noexcept
202  requires (sizeof(value_t) != 1)
204  {
205  using char_trait = std::char_traits<value_t>;
206  return (static_cast<std::make_unsigned_t<value_t>>(val) < 256) ? operator()(static_cast<uint8_t>(val)) :
207  (char_trait::eq_int_type(val, char_trait::eof())) ? derived_t::data[256] : false;
208  }
210 
214  std::string message() const
216  {
217  return derived_t::msg;
218  }
220 };
221 
222 // ----------------------------------------------------------------------------
223 // char_predicate_combiner
224 // ----------------------------------------------------------------------------
225 
232 template <char_predicate... condition_ts>
234  requires (sizeof...(condition_ts) >= 2)
236 struct char_predicate_combiner : public char_predicate_base<char_predicate_combiner<condition_ts...>>
237 {
239  inline static const std::string msg = detail::condition_message_v<'|', condition_ts...>;
240 
242  using base_t = char_predicate_base<char_predicate_combiner<condition_ts...>>;
243 
245  using typename base_t::data_t;
247  static constexpr data_t data = (condition_ts::data | ...);
248 };
249 
256 template <char_predicate condition_t>
257 struct char_predicate_negator : public char_predicate_base<char_predicate_negator<condition_t>>
258 {
260  inline static const std::string msg = std::string{'!'} + condition_t::msg;
261 
263  using base_t = char_predicate_base<char_predicate_negator<condition_t>>;
264 
266  using typename base_t::data_t;
268  static constexpr data_t data = ~condition_t::data;
269 };
270 
271 // ----------------------------------------------------------------------------
272 // is_in_interval_type
273 // ----------------------------------------------------------------------------
274 
283 template <uint8_t interval_first, uint8_t interval_last>
285  requires (interval_first <= interval_last)
287 struct is_in_interval_type : public char_predicate_base<is_in_interval_type<interval_first, interval_last>>
288 {
290  inline static const std::string msg = std::string{"is_in_interval<'"} +
291  std::string{interval_first} +
292  std::string{"', '"} +
293  std::string{interval_last} +
294  std::string{"'>"};
295 
297  using base_t = char_predicate_base<is_in_interval_type<interval_first, interval_last>>;
298 
300  using typename base_t::data_t;
302  static constexpr data_t data = [] () constexpr
303  {
304  data_t ret{};
305 
306  for (size_t i = interval_first; i <= static_cast<size_t>(interval_last); ++i)
307  ret[i] = true;
308 
309  return ret;
310  }();
311 };
312 
313 // ----------------------------------------------------------------------------
314 // is_in_alphabet_type
315 // ----------------------------------------------------------------------------
316 
322 template <detail::constexpr_alphabet alphabet_t>
323 struct is_in_alphabet_type : public char_predicate_base<is_in_alphabet_type<alphabet_t>>
324 {
325 public:
327  inline static const std::string msg = std::string{"is_in_alphabet<"} +
328  detail::type_name_as_string<alphabet_t> +
329  std::string{">"};
330 
332  using base_t = char_predicate_base<is_in_alphabet_type<alphabet_t>>;
333 
335  using typename base_t::data_t;
337  static constexpr data_t data = [] () constexpr
338  {
339  data_t ret{};
340 
341  for (size_t i = 0; i < 256; ++i)
342  ret[i] = char_is_valid_for<alphabet_t>(static_cast<uint8_t>(i));
343 
344  return ret;
345  }();
346 };
347 
348 // ----------------------------------------------------------------------------
349 // is_char_type
350 // ----------------------------------------------------------------------------
351 
357 template <int char_v>
358 struct is_char_type : public char_predicate_base<is_char_type<char_v>>
359 {
360  static_assert(char_v == EOF || static_cast<uint64_t>(char_v) < 256, "TODO");
361 
363  inline static const std::string msg = std::string{"is_char<'"} +
364  ((char_v == EOF) ? std::string{"EOF"} : std::string{char_v}) +
365  std::string{"'>"};
366 
367 
368 
370  using base_t = char_predicate_base<is_char_type<char_v>>;
371 
373  using typename base_t::data_t;
375  static constexpr data_t data = [] () constexpr
376  {
377  data_t ret{};
378 
379  if (char_v == EOF)
380  ret[256] = true;
381  else
382  ret[static_cast<uint8_t>(char_v)] = true;
383 
384  return ret;
385  }();
386 };
387 
388 } // namespace seqan3::detail
std::string
basic.hpp
Provides various type traits on generic types.
seqan3::operator|
auto operator|(validator1_type &&vali1, validator2_type &&vali2)
Enables the chaining of validators.
Definition: validators.hpp:1037
concepts
The Concepts library.
stdexcept
std::char_traits
array
SEQAN3_RETURN_TYPE_CONSTRAINT
#define SEQAN3_RETURN_TYPE_CONSTRAINT(expression, concept_name,...)
Same as writing {expression} -> concept_name<type1[, ...]> in a concept definition.
Definition: platform.hpp:57
std::remove_reference_t
type_inspection.hpp
Provides traits to inspect some information of a type, for example its name.
cctype
std::remove_cvref_t
std::data
T data(T... args)
concept.hpp
Core alphabet concept and free function/type trait wrappers.
std::make_unsigned_t
string