Elements  5.12.0
A C++ base framework for the Euclid Software.
Path.icpp
Go to the documentation of this file.
1 /**
2  * @file ElementsKernel/_impl/Path.icpp
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 #ifdef ELEMENTSKERNEL_ELEMENTSKERNEL_PATH_IMPL_
22 
23 #include <string> // for string
24 #include <vector> // for vector
25 #include <unordered_set> // for unordered_set
26 #include <algorithm> // for find_if, transform, for_each
27 
28 #include <boost/filesystem/operations.hpp> // for exists
29 #include <boost/algorithm/string/join.hpp> // for join
30 
31 
32 namespace Elements {
33 namespace Path {
34 
35 template <typename T, typename U>
36 Item getPathFromLocations(const T& file_name, const std::vector<U>& locations) {
37 
38  Item found_path {};
39  Item file_path {file_name};
40 
41  auto found_pos = std::find_if(locations.cbegin(), locations.cend(),
42  [file_path](const U& l) {
43  return boost::filesystem::exists(Item {l} / file_path);
44  });
45 
46  if (found_pos != locations.cend()) {
47  found_path = Item {*found_pos} / file_path;
48  }
49 
50  return found_path;
51 
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(),
61  file_list.begin(),
62  [file_path](const U& l){
63  return Item {l} / file_path;
64  });
65 
66  auto found_pos = std::remove_if(file_list.begin(), file_list.end(),
67  [](const Item& p){
68  return not boost::filesystem::exists(p);
69  });
70 
71  file_list.erase(found_pos, file_list.end());
72 
73  return removeDuplicates(file_list);
74 
75 }
76 
77 template <typename T>
78 Item getPathFromEnvVariable(const T& file_name, const std::string& path_variable) {
79 
80  using std::vector;
81 
82  vector<Item> location_list = getLocationsFromEnv(path_variable);
83 
84  return getPathFromLocations(file_name, location_list);
85 
86 }
87 
88 template <typename T>
89 std::string joinPath(const std::vector<T>& path_list) {
90 
91  using std::vector;
92  using std::string;
93 
94  vector<string> elems(path_list.size());
95 
96  std::transform(path_list.cbegin(), path_list.cend(),
97  elems.begin(),
98  [](const T& s){
99  return Item{s}.string();
100  });
101 
102  std::string result = boost::algorithm::join(elems, PATH_SEP);
103 
104  return result;
105 }
106 
107 template <typename... Args>
108 auto join(Args&&... args) -> decltype(joinPath(std::forward<Args>(args)...)) {
109  return joinPath(std::forward<Args>(args)...);
110 }
111 
112 template <typename... Args>
113 auto split(Args&&... args) -> decltype(splitPath(std::forward<Args>(args)...)) {
114  return splitPath(std::forward<Args>(args)...);
115 }
116 
117 
118 template <typename T, typename U>
119 std::vector<Item> multiPathAppend(const std::vector<T>& initial_locations, const std::vector<U>& suffixes) {
120 
121  using std::vector;
122 
123  vector<Item> result(initial_locations.size()*suffixes.size());
124 
125  auto pos = result.begin();
126 
127  std::for_each(initial_locations.cbegin(), initial_locations.cend(),
128  [&pos, &suffixes](const T& l) {
129  std::transform(suffixes.cbegin(), suffixes.cend(),
130  pos,
131  [l](const U& s){
132  return Item {l} / s;
133  });
134  pos += static_cast<std::ptrdiff_t>(suffixes.size());
135 
136  });
137 
138 
139  return result;
140 }
141 
142 template <typename T>
143 std::vector<Item> removeDuplicates(const std::vector<T>& path_list) {
144 
145  std::unordered_set<std::string> s;
146 
147  std::vector<Item> output(path_list.size());
148 
149  auto end = copy_if(path_list.cbegin(), path_list.cend(), output.begin(),
150  [&s](const T& i) {
151  return s.insert(Item{i}.string()).second;
152  });
153 
154  output.erase(end, output.end());
155 
156  return output;
157 
158 }
159 
160 
161 } // namespace Path
162 } // namespace Elements
163 
164 #endif // ELEMENTSKERNEL_ELEMENTSKERNEL_PATH_IMPL_