Elements  6.2
A C++ base framework for the Euclid Software.
Path.tpp
Go to the documentation of this file.
1 /**
2  * @file ElementsKernel/_impl/Path.tpp
3  * @brief implementation of the templates declared in ElementsKernel/Path.h
4  * @date May 17, 2016
5  * @author Hubert Degaudenzi
6  *
7  * @copyright 2012-2020 Euclid Science Ground Segment
8  *
9  * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General
10  * Public License as published by the Free Software Foundation; either version 3.0 of the License, or (at your option)
11  * any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
14  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
15  * details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #ifndef ELEMENTSKERNEL_ELEMENTSKERNEL_PATH_IMPL_
22 #error "This file should not be included directly! Use ElementsKernel/Path.h instead"
23 #else
24 
25 #include <algorithm> // for find_if, transform, for_each
26 #include <string> // for string
27 #include <unordered_set> // for unordered_set
28 #include <vector> // for vector
29 
30 #include <boost/algorithm/string/join.hpp> // for join
31 #include <boost/filesystem/operations.hpp> // for exists
32 
33 namespace Elements {
34 inline namespace Kernel {
35 namespace Path {
36 
37 template <typename T, typename U>
38 Item getPathFromLocations(const T& file_name, const std::vector<U>& locations) {
39 
40  Item found_path{};
41  Item file_path{file_name};
42 
43  auto found_pos = std::find_if(locations.cbegin(), locations.cend(), [file_path](const U& l) {
44  return boost::filesystem::exists(Item{l} / file_path);
45  });
46 
47  if (found_pos != locations.cend()) {
48  found_path = Item{*found_pos} / file_path;
49  }
50 
51  return found_path;
52 }
53 
54 template <typename T, typename U>
55 std::vector<Item> getAllPathFromLocations(const T& file_name, const std::vector<U>& locations) {
56 
57  std::vector<Item> file_list(locations.size());
58  Item file_path{file_name};
59 
60  std::transform(locations.cbegin(), locations.cend(), file_list.begin(), [file_path](const U& l) {
61  return Item{l} / file_path;
62  });
63 
64  auto found_pos = std::remove_if(file_list.begin(), file_list.end(), [](const Item& p) {
65  return not boost::filesystem::exists(p);
66  });
67 
68  file_list.erase(found_pos, file_list.end());
69 
70  return removeDuplicates(file_list);
71 }
72 
73 template <typename T>
74 Item getPathFromEnvVariable(const T& file_name, const std::string& path_variable) {
75 
76  using std::vector;
77 
78  vector<Item> location_list = getLocationsFromEnv(path_variable);
79 
80  return getPathFromLocations(file_name, location_list);
81 }
82 
83 template <typename T>
84 std::string joinPath(const std::vector<T>& path_list) {
85 
86  using std::string;
87  using std::vector;
88 
89  vector<string> elems(path_list.size());
90 
91  std::transform(path_list.cbegin(), path_list.cend(), elems.begin(), [](const T& s) {
92  return Item{s}.string();
93  });
94 
95  std::string result = boost::algorithm::join(elems, PATH_SEP);
96 
97  return result;
98 }
99 
100 template <typename... Args>
101 auto join(Args&&... args) -> decltype(joinPath(std::forward<Args>(args)...)) {
102  return joinPath(std::forward<Args>(args)...);
103 }
104 
105 template <typename... Args>
106 auto split(Args&&... args) -> decltype(splitPath(std::forward<Args>(args)...)) {
107  return splitPath(std::forward<Args>(args)...);
108 }
109 
110 template <typename T, typename U>
111 std::vector<Item> multiPathAppend(const std::vector<T>& initial_locations, const std::vector<U>& suffixes) {
112 
113  using std::vector;
114 
115  vector<Item> result(initial_locations.size() * suffixes.size());
116 
117  auto pos = result.begin();
118 
119  std::for_each(initial_locations.cbegin(), initial_locations.cend(), [&pos, &suffixes](const T& l) {
120  std::transform(suffixes.cbegin(), suffixes.cend(), pos, [l](const U& s) {
121  return Item{l} / s;
122  });
123  pos += static_cast<std::ptrdiff_t>(suffixes.size());
124  });
125 
126  return result;
127 }
128 
129 template <typename T>
130 std::vector<Item> removeDuplicates(const std::vector<T>& path_list) {
131 
132  std::unordered_set<std::string> s;
133 
134  std::vector<Item> output(path_list.size());
135 
136  auto end = copy_if(path_list.cbegin(), path_list.cend(), output.begin(), [&s](const T& i) {
137  return s.insert(Item{i}.string()).second;
138  });
139 
140  output.erase(end, output.end());
141 
142  return output;
143 }
144 
145 } // namespace Path
146 } // namespace Kernel
147 } // namespace Elements
148 
149 #endif // ELEMENTSKERNEL_ELEMENTSKERNEL_PATH_IMPL_