2 * @file ElementsKernel/_impl/Path.tpp
3 * @brief implementation of the templates declared in ElementsKernel/Path.h
5 * @author Hubert Degaudenzi
7 * @copyright 2012-2020 Euclid Science Ground Segment
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)
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
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
21 #ifndef ELEMENTSKERNEL_ELEMENTSKERNEL_PATH_IMPL_
22 #error "This file should not be included directly! Use ElementsKernel/Path.h instead"
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
30 #include <boost/algorithm/string/join.hpp> // for join
31 #include <boost/filesystem/operations.hpp> // for exists
34 inline namespace Kernel {
37 template <typename T, typename U>
38 Item getPathFromLocations(const T& file_name, const std::vector<U>& locations) {
41 Item file_path{file_name};
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);
47 if (found_pos != locations.cend()) {
48 found_path = Item{*found_pos} / file_path;
54 template <typename T, typename U>
55 std::vector<Item> getAllPathFromLocations(const T& file_name, const std::vector<U>& locations) {
57 std::vector<Item> file_list(locations.size());
58 Item file_path{file_name};
60 std::transform(locations.cbegin(), locations.cend(), file_list.begin(), [file_path](const U& l) {
61 return Item{l} / file_path;
64 auto found_pos = std::remove_if(file_list.begin(), file_list.end(), [](const Item& p) {
65 return not boost::filesystem::exists(p);
68 file_list.erase(found_pos, file_list.end());
70 return removeDuplicates(file_list);
74 Item getPathFromEnvVariable(const T& file_name, const std::string& path_variable) {
78 vector<Item> location_list = getLocationsFromEnv(path_variable);
80 return getPathFromLocations(file_name, location_list);
84 std::string joinPath(const std::vector<T>& path_list) {
89 vector<string> elems(path_list.size());
91 std::transform(path_list.cbegin(), path_list.cend(), elems.begin(), [](const T& s) {
92 return Item{s}.string();
95 std::string result = boost::algorithm::join(elems, PATH_SEP);
100 template <typename... Args>
101 auto join(Args&&... args) -> decltype(joinPath(std::forward<Args>(args)...)) {
102 return joinPath(std::forward<Args>(args)...);
105 template <typename... Args>
106 auto split(Args&&... args) -> decltype(splitPath(std::forward<Args>(args)...)) {
107 return splitPath(std::forward<Args>(args)...);
110 template <typename T, typename U>
111 std::vector<Item> multiPathAppend(const std::vector<T>& initial_locations, const std::vector<U>& suffixes) {
115 vector<Item> result(initial_locations.size() * suffixes.size());
117 auto pos = result.begin();
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) {
123 pos += static_cast<std::ptrdiff_t>(suffixes.size());
129 template <typename T>
130 std::vector<Item> removeDuplicates(const std::vector<T>& path_list) {
132 std::unordered_set<std::string> s;
134 std::vector<Item> output(path_list.size());
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;
140 output.erase(end, output.end());
146 } // namespace Kernel
147 } // namespace Elements
149 #endif // ELEMENTSKERNEL_ELEMENTSKERNEL_PATH_IMPL_