SeqAn3
validators.hpp
Go to the documentation of this file.
1 // ============================================================================
2 // SeqAn - The Library for Sequence Analysis
3 // ============================================================================
4 //
5 // Copyright (c) 2006-2018, Knut Reinert & Freie Universitaet Berlin
6 // Copyright (c) 2016-2018, Knut Reinert & MPI Molekulare Genetik
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are met:
11 //
12 // * Redistributions of source code must retain the above copyright
13 // notice, this list of conditions and the following disclaimer.
14 // * Redistributions in binary form must reproduce the above copyright
15 // notice, this list of conditions and the following disclaimer in the
16 // documentation and/or other materials provided with the distribution.
17 // * Neither the name of Knut Reinert or the FU Berlin nor the names of
18 // its contributors may be used to endorse or promote products derived
19 // from this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 // ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
25 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31 // DAMAGE.
32 //
33 // ============================================================================
34 
40 #pragma once
41 
42 #include <sstream>
43 #include <regex>
44 
48 #include <seqan3/io/filesystem.hpp>
50 #include <seqan3/std/concepts>
52 
53 namespace seqan3
54 {
55 
97 template <typename validator_type>
100 concept validator_concept = std::Copyable<remove_cvref_t<validator_type>> &&
101  requires(validator_type validator,
102  typename std::remove_reference_t<validator_type>::value_type value)
103 {
104  typename std::remove_reference_t<validator_type>::value_type;
105 
106  { validator(value) } -> void;
107  { validator.get_help_page_message() } -> std::string;
108 };
110 
112 template <typename option_value_type>
113 class integral_range_validator;
115 
130 template <std::Integral option_value_type>
131 class integral_range_validator<option_value_type>
132 {
133 public:
135  using value_type = option_value_type;
136 
142  min{min_}, max{max_}
143  {}
144 
149  void operator()(value_type const & cmp) const
150  {
151  if (!((cmp <= max) && (cmp >= min)))
152  throw parser_invalid_argument(detail::to_string("Validation Failed - Value ", cmp,
153  " is not in range [", min, ",", max, "]."));
154  }
155 
157  std::string get_help_page_message() const
158  {
159  return detail::to_string("Value must be in range [", min, ",", max, "].");
160  }
161 
162 private:
164  value_type min{};
165 
167  value_type max{};
168 };
169 
171 template <container_concept option_value_type>
173 class integral_range_validator<option_value_type>
174 {
175 public:
177  using value_type = option_value_type;
179  using inner_value_type = typename value_type::value_type;
180 
185  integral_range_validator(inner_value_type const min_,
186  inner_value_type const max_) :
187  min{min_}, max{max_}
188  {}
189 
194  void operator()(value_type const & cmp) const
195  {
196  std::for_each(cmp.begin(), cmp.end(), [&] (auto cmp_v)
197  {
198  if (!((cmp_v <= max) && (cmp_v >= min)))
199  throw parser_invalid_argument(detail::to_string("Validation Failed - Value ", cmp_v,
200  " is not in range [", min, ",", max, "]."));
201  });
202  }
203 
205  std::string get_help_page_message() const
206  {
207  return detail::to_string("Value must be in range [", min, ",", max, "].");
208  }
209 
210 private:
212  inner_value_type min{};
213 
215  inner_value_type max{};
216 };
218 
231 template <typename option_value_type>
233 {
234 public:
236  using value_type = option_value_type;
237 
241  value_list_validator(std::vector<option_value_type> const & v) :
242  values{v}
243  {}
244 
248  value_list_validator(std::initializer_list<option_value_type> const & v) :
249  values{v}
250  {}
251 
256  void operator()(option_value_type const & cmp) const
257  {
258  if (!(std::find(values.begin(), values.end(), cmp) != values.end()))
259  throw parser_invalid_argument(detail::to_string("Value ", cmp, " is not one of ", view::all(values), "."));
260  }
261 
263  std::string get_help_page_message() const
264  {
265  return detail::to_string("Value must be one of ", view::all(values), ".");
266  }
267 
268 private:
269 
271  std::vector<option_value_type> values;
272 };
273 
281 template <container_concept option_value_type>
283  requires !std::is_same_v<option_value_type, std::string>
285 class value_list_validator<option_value_type>
286 {
287 public:
289  using value_type = option_value_type;
291  using inner_value_type = typename value_type::value_type;
292 
296  value_list_validator(std::vector<inner_value_type> const & v) :
297  values{v}
298  {}
299 
303  value_list_validator(std::initializer_list<inner_value_type> const & v) :
304  values{v}
305  {}
306 
311  void operator()(value_type const & cmp) const
312  {
313  std::for_each(cmp.begin(), cmp.end(), [&] (auto cmp_v)
314  {
315  if (!(std::find(values.begin(), values.end(), cmp_v) != values.end()))
316  throw parser_invalid_argument(detail::to_string("Value ", cmp_v, " is not one of ",
317  view::all(values), "."));
318  });
319  }
320 
322  std::string get_help_page_message() const
323  {
324  return detail::to_string("Value must be one of ", view::all(values), ".");
325  }
326 
327 private:
328 
330  std::vector<inner_value_type> values;
331 };
332 
346 {
347 public:
349  using value_type = std::string;
350 
354  file_ext_validator(std::vector<std::string> const & v) :
355  extensions{v}
356  {}
357 
361  file_ext_validator(std::initializer_list<std::string> const & v) :
362  extensions{v}
363  {}
364 
369  void operator()(filesystem::path const & path) const
370  {
371  std::string ext{path.extension().string()};
372  ext = ext.substr(std::min(1, static_cast<int>(ext.size()))); // drop '.' if extension is non-empty
373  if (!(std::find(extensions.begin(), extensions.end(), ext) != extensions.end()))
374  throw parser_invalid_argument(detail::to_string("Extension ", ext, " is not one of ",
375  view::all(extensions), "."));
376  }
377 
379  void operator()(std::vector<std::string> const & v) const
380  {
381  std::for_each(v.begin(), v.end(), [&] (auto cmp) { (*this)(cmp); });
382  }
383 
385  std::string get_help_page_message() const
386  {
387  return detail::to_string("File name extension must be one of ", view::all(extensions), ".");
388  }
389 
390 private:
392  std::vector<std::string> extensions;
393 };
394 
406 {
407 public:
409  using value_type = filesystem::path;
410 
415  void operator()(filesystem::path const & path) const
416  {
417  if (!(filesystem::exists(path)))
418  throw parser_invalid_argument(detail::to_string("File ", path, " does not exist."));
419  }
420 
422  void operator()(std::vector<filesystem::path> const & v) const
423  {
424  std::for_each(v.begin(), v.end(), [&] (auto cmp) { (*this)(cmp); });
425  }
426 
428  std::string get_help_page_message() const
429  {
430  return detail::to_string("The file is checked for existence.");
431  }
432 };
433 
435 template <typename option_value_type>
436 class regex_validator;
438 
455 template <>
456 class regex_validator<std::string>
457 {
458 public:
460  using value_type = std::string;
461 
465  regex_validator(std::string const & pattern_) :
466  pattern{pattern_}
467  {}
468 
473  void operator()(value_type const & cmp) const
474  {
475  std::regex rgx(pattern);
476  if (!std::regex_match(cmp, rgx))
477  throw parser_invalid_argument(detail::to_string("Value ", cmp, " did not match the pattern ", pattern, "."));
478  }
479 
481  std::string get_help_page_message() const
482  {
483  return detail::to_string("Value must match the pattern '", pattern, "'.");
484  }
485 
486 private:
488  std::string pattern;
489 };
490 
496 template <>
497 class regex_validator<std::vector<std::string>>
498 {
499 public:
501  using value_type = std::vector<std::string>;
505  regex_validator(std::string const & pattern_) :
506  pattern{pattern_}
507  {}
508 
513  void operator()(value_type const & cmp) const
514  {
515  std::regex rgx(pattern);
516  for (auto const & cmp_v : cmp)
517  if (!std::regex_match(cmp_v, rgx))
518  throw parser_invalid_argument(detail::to_string("Value ", cmp_v, " did not match the pattern ", pattern, "."));
519  }
520 
522  std::string get_help_page_message() const
523  {
524  return detail::to_string("Value must match the pattern '", pattern, "'.");
525  }
526 
527 private:
529  std::string pattern;
530 };
531 
536  regex_validator(char const *) -> regex_validator<std::string>;
538 
539 namespace detail
540 {
541 
551 template <typename option_value_type>
552 struct default_validator
553 {
555  using value_type = option_value_type;
556 
558  void operator()(option_value_type const & /*cmp*/) const noexcept
559  {}
560 
562  std::string get_help_page_message() const
563  {
564  return "";
565  }
566 };
567 
579 template <validator_concept validator1_type, validator_concept validator2_type>
583 class validator_chain_adaptor
584 {
585 public:
587  using value_type = typename validator1_type::value_type;
588 
592  validator_chain_adaptor() = delete;
594  validator_chain_adaptor(validator_chain_adaptor const & pf) = default;
595  validator_chain_adaptor & operator=(validator_chain_adaptor const & pf) = default;
596  validator_chain_adaptor(validator_chain_adaptor &&) = default;
597  validator_chain_adaptor & operator=(validator_chain_adaptor &&) = default;
598 
603  validator_chain_adaptor(validator1_type vali1_, validator2_type vali2_) :
604  vali1{std::move(vali1_)}, vali2{std::move(vali2_)}
605  {}
606 
608  ~validator_chain_adaptor() = default;
610 
618  void operator()(value_type const & cmp) const
619  {
620  vali1(cmp);
621  vali2(cmp);
622  }
623 
625  std::string get_help_page_message() const
626  {
627  return detail::to_string(vali1.get_help_page_message(), " ", vali2.get_help_page_message());
628  }
629 
630 private:
632  validator1_type vali1;
634  validator2_type vali2;
635 };
636 
637 } // namespace detail
638 
666 template <validator_concept validator1_type, validator_concept validator2_type>
669  typename std::remove_reference_t<validator2_type>::value_type>
671 auto operator|(validator1_type && vali1, validator2_type && vali2)
672 {
673  return detail::validator_chain_adaptor{std::forward<validator1_type>(vali1),
674  std::forward<validator2_type>(vali2)};
675 }
676 
677 } // namespace seqan3
A validator that checks if a matches a regular expression pattern.
Definition: validators.hpp:456
option_value_type value_type
The type of value that this validator invoked upon.
Definition: validators.hpp:135
regex_validator(std::string const &pattern_)
Constructing from a vector.
Definition: validators.hpp:465
void operator()(value_type const &cmp) const
Tests whether cmp lies inside values.
Definition: validators.hpp:513
std::string get_help_page_message() const
Returns a message that can be appended to the (positional) options help page info.
Definition: validators.hpp:322
Contains parser related exceptions.
SeqAn specific customisations in the standard namespace.
Definition: align_result.hpp:221
std::string value_type
Type of values that are tested by validator.
Definition: validators.hpp:460
std::string get_help_page_message() const
Returns a message that can be appended to the (positional) options help page info.
Definition: validators.hpp:522
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:58
regex_validator(std::string const &pattern_)
Constructing from a vector.
Definition: validators.hpp:505
void operator()(std::vector< std::string > const &v) const
Tests whether every value of v lies inside extensions.
Definition: validators.hpp:379
The concept Integral is satisfied if and only if T is an integral type.
value_list_validator(std::initializer_list< option_value_type > const &v)
Constructing from an initializer_list.
Definition: validators.hpp:248
std::vector< std::string > value_type
Type of values that are tested by validator.
Definition: validators.hpp:501
std::string value_type
Type of values that are tested by validator.
Definition: validators.hpp:349
void operator()(option_value_type const &cmp) const
Tests whether cmp lies inside values.
Definition: validators.hpp:256
The Concepts library.
value_list_validator(std::initializer_list< inner_value_type > const &v)
Constructing from an initializer_list.
Definition: validators.hpp:303
file_ext_validator(std::vector< std::string > const &v)
Constructing from a vector.
Definition: validators.hpp:354
A validator that checks if a filenames has one of the valid extensions.
Definition: validators.hpp:345
void operator()(value_type const &cmp) const
Tests whether cmp lies inside values.
Definition: validators.hpp:473
std::string get_help_page_message() const
Returns a message that can be appended to the (positional) options help page info.
Definition: validators.hpp:385
integral_range_validator(value_type const min_, value_type const max_)
The constructor.
Definition: validators.hpp:141
std::string get_help_page_message() const
Returns a message that can be appended to the (positional) options help page info.
Definition: validators.hpp:263
Provides seqan3::view::all.
option_value_type value_type
Type of values that are tested by validator.
Definition: validators.hpp:236
The concept std::Same<T, U> is satisfied if and only if T and U denote the same type.
Argument parser exception that is thrown whenever there is an error while parsing the command line ar...
Definition: exceptions.hpp:64
void operator()(value_type const &cmp) const
Tests whether cmp lies inside values.
Definition: validators.hpp:311
value_list_validator(std::vector< inner_value_type > const &v)
Constructing from a vector.
Definition: validators.hpp:296
This header includes C++17 filesystem support and imports it into namespace seqan3::filesystem (indep...
Provides various metafunctions on generic types.
auto operator|(validator1_type &&vali1, validator2_type &&vali2)
Enables the chaining of validators. !
Definition: validators.hpp:671
A validator that checks if a file exists.
Definition: validators.hpp:405
file_ext_validator(std::initializer_list< std::string > const &v)
Constructing from an initializer_list.
Definition: validators.hpp:361
void operator()(filesystem::path const &path) const
Tests whether path exists.
Definition: validators.hpp:415
std::string get_help_page_message() const
Returns a message that can be appended to the (positional) options help page info.
Definition: validators.hpp:481
A validator that checks whether a value is inside a list of valid values.
Definition: validators.hpp:232
constexpr auto all
A view that safely wraps a container (you will likely not need to use this unless defining a new view...
Definition: view_all.hpp:95
filesystem::path value_type
Type of values that are tested by validator.
Definition: validators.hpp:409
value_list_validator(std::vector< option_value_type > const &v)
Constructing from a vector.
Definition: validators.hpp:241
Subsumes std::Movable, std::CopyConstructible, and requires that the type be std::Assignable bool fro...
void operator()(value_type const &cmp) const
Tests whether cmp lies inside [min,max].
Definition: validators.hpp:149
std::string get_help_page_message() const
Returns a message that can be appended to the (positional) options help page info.
Definition: validators.hpp:157
Adaptations of concepts from the standard library.
std::string get_help_page_message() const
Returns a message that can be appended to the (positional) options help page info.
Definition: validators.hpp:428
typename value_type::value_type inner_value_type
Underlying type of the container.
Definition: validators.hpp:291
void operator()(filesystem::path const &path) const
Tests whether the filepath path ends with a valid extension.
Definition: validators.hpp:369
Contains auxiliary information.
void operator()(std::vector< filesystem::path > const &v) const
Tests whether every filename in list v exists.
Definition: validators.hpp:422