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