1
2 //
3 // This source file is part of appleseed.
4 // Visit https://appleseedhq.net/ for additional information and resources.
5 //
6 // This software is released under the MIT license.
7 //
8 // Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
9 // Copyright (c) 2014-2018 Francois Beaune, The appleseedhq Organization
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining a copy
12 // of this software and associated documentation files (the "Software"), to deal
13 // in the Software without restriction, including without limitation the rights
14 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 // copies of the Software, and to permit persons to whom the Software is
16 // furnished to do so, subject to the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be included in
19 // all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 // THE SOFTWARE.
28 //
29
30 #pragma once
31
32 // appleseed.foundation headers.
33 #include "foundation/utility/api/apistring.h"
34
35 // appleseed.main headers.
36 #include "main/dllsymbol.h"
37
38 // Standard headers.
39 #include <cstddef>
40 #include <string>
41
42 namespace foundation
43 {
44
45 //
46 // An ordered collection of search paths.
47 //
48 // Terminology:
49 //
50 // Root path
51 // A path used to resolve relative search paths.
52 //
53 // Environment search path
54 // A search path extracted from an environment variable.
55 //
56 // Explicit search path
57 // A search path explicitly and manually added to the collection.
58 //
59 // Priorities:
60 //
61 // Paths are ordered by ascending priority: paths inserted later have precedence
62 // over those inserted earlier.
63 //
64 // Environment search paths all have lower priority than explicit search paths.
65 //
66
67 class APPLESEED_DLLSYMBOL SearchPaths
68 {
69 public:
70 // Return the default environment path separator for the platform.
71 static const char environment_path_separator();
72
73 // Return the path separator used by OSL and OpenImageIO.
74 static const char osl_path_separator();
75
76 // Constructor.
77 // No root path is set and the search path collection is empty.
78 SearchPaths();
79
80 // Constructor.
81 // Initializes search paths with the contents of the specified environment variable.
82 SearchPaths(const char* envvar, const char separator);
83
84 // Copy constructor.
85 SearchPaths(const SearchPaths& other);
86
87 // Destructor.
88 ~SearchPaths();
89
90 // Assignment.
91 SearchPaths& operator=(const SearchPaths& other);
92
93 // Swap.
94 void swap(SearchPaths& other);
95
96 //
97 // Root path.
98 //
99
100 // Set the root path.
101 void set_root_path(const char* path);
102 void set_root_path(const std::string& path);
103
104 // Return the root path.
105 APIString get_root_path() const;
106
107 // Return true if the root path has been set.
108 bool has_root_path() const;
109
110 //
111 // Environment search paths.
112 //
113
114 // Return the number of environment search paths.
115 size_t get_environment_path_count() const;
116
117 // Return the i'th environment search path.
118 const char* get_environment_path(const size_t i) const;
119
120 //
121 // Explicit search paths.
122 //
123
124 // Remove all explicit search paths.
125 void clear_explicit_paths();
126
127 // Return the number of explicit search paths.
128 size_t get_explicit_path_count() const;
129
130 // Return the i'th explicit search path.
131 const char* get_explicit_path(const size_t i) const;
132
133 // Insert an explicit search path at the end of the collection.
134 void push_back_explicit_path(const char* path);
135 void push_back_explicit_path(const std::string& path);
136
137 // Remove the i'th explicit search path.
138 void remove_explicit_path(const size_t i);
139
140 //
141 // Combined search paths.
142 //
143
144 // Return the total number of search paths (environment paths and explicit paths).
145 size_t get_path_count() const;
146
147 // Return the i'th path from the collection of environment paths and explicit paths.
148 const char* get_path(const size_t i) const;
149
150 // Return true if a given file exists, that is, if the argument is the absolute
151 // path to a file that exists, or it is the name of a file that exists in one of
152 // the search paths.
153 bool exist(const char* filepath) const;
154 bool exist(const std::string& filepath) const;
155
156 // Find a file in the search paths. If the file was found, the qualified path to
157 // this file is returned. Otherwise the input path is returned.
158 APIString qualify(const char* filepath) const;
159 APIString qualify(const std::string& filepath) const;
160
161 // Same as above but also returns the search path inside which the file was found.
162 void qualify(const char* filepath, APIString* qualified_filepath, APIString* search_path) const;
163 void qualify(const std::string& filepath, APIString* qualified_filepath, APIString* search_path) const;
164
165 // Return a string with all search paths separated by the specified separator.
166 // The second variant returns search paths in reverse order.
167 APIString to_string(const char separator) const;
168 APIString to_string_reversed(const char separator) const;
169
170 protected:
171 struct Impl;
172 Impl* impl;
173
174 APIString do_to_string(const char separator, const bool reversed) const;
175 };
176
177
178 //
179 // SearchPaths class implementation.
180 //
181
set_root_path(const std::string & path)182 inline void SearchPaths::set_root_path(const std::string& path)
183 {
184 set_root_path(path.c_str());
185 }
186
push_back_explicit_path(const std::string & path)187 inline void SearchPaths::push_back_explicit_path(const std::string& path)
188 {
189 push_back_explicit_path(path.c_str());
190 }
191
exist(const std::string & filepath)192 inline bool SearchPaths::exist(const std::string& filepath) const
193 {
194 return exist(filepath.c_str());
195 }
196
qualify(const std::string & filepath)197 inline APIString SearchPaths::qualify(const std::string& filepath) const
198 {
199 return qualify(filepath.c_str());
200 }
201
qualify(const std::string & filepath,APIString * qualified_filepath,APIString * search_path)202 inline void SearchPaths::qualify(const std::string& filepath, APIString* qualified_filepath, APIString* search_path) const
203 {
204 qualify(filepath.c_str(), qualified_filepath, search_path);
205 }
206
to_string(const char separator)207 inline APIString SearchPaths::to_string(const char separator) const
208 {
209 return do_to_string(separator, false);
210 }
211
to_string_reversed(const char separator)212 inline APIString SearchPaths::to_string_reversed(const char separator) const
213 {
214 return do_to_string(separator, true);
215 }
216
217 } // namespace foundation
218