SeqAn3  3.2.0
The Modern C++ library for sequence analysis.
io/detail/misc.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2022, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2022, 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 
13 #pragma once
14 
15 #include <algorithm>
16 #include <filesystem>
17 #include <iterator>
18 #include <variant>
19 #include <vector>
20 
22 #include <seqan3/io/exception.hpp>
24 
25 namespace seqan3::detail
26 {
27 
30 template <typename list_t, template <typename...> typename output_t>
31 struct variant_from_tags;
32 
35 template <template <typename...> typename output_t, typename... ts>
36 struct variant_from_tags<type_list<ts...>, output_t>
37 {
39  using type = std::variant<output_t<ts>...>;
40 };
41 
48 template <std::output_iterator<char> it_t>
49 constexpr void write_eol(it_t & it, bool const add_cr)
50 {
51  if (add_cr)
52  it = '\r';
53 
54  it = '\n';
55 }
56 
67 template <typename format_variant_type>
68 void set_format(format_variant_type & format, std::filesystem::path const & file_name)
69 {
70  using valid_formats = detail::transfer_template_args_onto_t<format_variant_type, type_list>;
71 
72  bool format_found = false;
73  std::string extension = file_name.extension().string();
74  if (extension.size() > 1)
75  {
76  extension = extension.substr(1); // drop leading "."
77  detail::for_each<valid_formats>(
78  [&](auto fmt)
79  {
80  using fm_type = typename decltype(fmt)::type; // remove type_identity wrapper
81 
82  for (auto const & ext : fm_type::file_extensions)
83  {
84  if (std::ranges::equal(ext, extension))
85  {
86  format.template emplace<fm_type>();
87  format_found = true;
88  return;
89  }
90  }
91  });
92  }
93 
94  if (!format_found)
95  throw unhandled_extension_error("No valid format found for this extension.");
96 }
97 
103 template <typename list_t>
104 inline constexpr bool has_member_file_extensions = false;
105 
107 template <template <typename...> typename list_t, typename... ts>
108  requires (
109  requires { ts::file_extensions; },
110  ...,
111  true)
112 inline constexpr bool has_member_file_extensions<list_t<ts...>> = true;
114 
120 template <typename query_t>
121 inline constexpr bool has_type_valid_formats = false;
122 
124 template <typename query_t>
125  requires requires { typename query_t::valid_formats; }
126 inline constexpr bool has_type_valid_formats<query_t> = true;
128 
149 template <typename formats_t>
150 inline std::vector<std::string> valid_file_extensions()
151 {
152  static_assert(has_member_file_extensions<formats_t>,
153  "Expects that all formats have a static member file_extensions storing the extensions in a range");
154 
155  std::vector<std::string> extensions;
156  detail::for_each<formats_t>(
157  [&extensions](auto t_identity)
158  {
159  using format_t = typename decltype(t_identity)::type;
160  std::ranges::copy(format_t::file_extensions, std::back_inserter(extensions));
161  });
162 
163  return extensions;
164 }
165 } // namespace seqan3::detail
T back_inserter(T... args)
T extension(T... args)
requires requires
The rank_type of the semi-alphabet; defined as the return type of seqan3::to_rank....
Definition: alphabet/concept.hpp:164
list_t
Apply a transformation trait to every type in the list and return a seqan3::type_list of the results.
Definition: type_list/traits.hpp:412
Provides exceptions used in the I/O module.
T size(T... args)
T substr(T... args)
Provides type traits for working with templates.
Provides algorithms for meta programming, parameter packs and seqan3::type_list.