SYCL: Avoid using no_init read accessor in rocFFT
[alexxy/gromacs.git] / src / gromacs / utility / datafilefinder.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2014,2015,2018,2019,2021, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35 /*! \file
36  * \brief
37  * Declares gmx::DataFileFinder and related classes.
38  *
39  * \author Teemu Murtola <teemu.murtola@gmail.com>
40  * \inpublicapi
41  * \ingroup module_utility
42  */
43 #ifndef GMX_UTILITY_LIBFILEFINDER_H
44 #define GMX_UTILITY_LIBFILEFINDER_H
45
46 #include <cstdio>
47
48 #include <memory>
49 #include <string>
50 #include <vector>
51
52 #include "gromacs/utility/fileptr.h"
53
54 namespace gmx
55 {
56
57 class DataFileFinder;
58
59 /*! \brief
60  * Search parameters for DataFileFinder.
61  *
62  * This class implements a named parameter idiom for DataFileFinder::findFile()
63  * and DataFileFinder::openFile() to support an easily readable and
64  * customizable way of searching data files.
65  *
66  * By default, the search first considers the current directory, followed by
67  * specified and default data directories, and an exception is thrown if the
68  * file could not be found.
69  * To skip searching in the current directory, use includeCurrentDir().
70  *
71  * Methods in this class do not throw.
72  *
73  * \inpublicapi
74  * \ingroup module_utility
75  */
76 class DataFileOptions
77 {
78 public:
79     /*! \brief
80      * Constructs default options for searching for a file with the
81      * specified name.
82      *
83      * \param[in] filename  File name to search for.
84      *
85      * This constructor is not explicit to allow passing a simple string to
86      * DataFileFinder methods to search for the string with the default
87      * parameters.
88      */
89     DataFileOptions(const char* filename) : filename_(filename), bCurrentDir_(true), bThrow_(true)
90     {
91     }
92     //! \copydoc DataFileOptions(const char *)
93     DataFileOptions(const std::string& filename) :
94         filename_(filename.c_str()), bCurrentDir_(true), bThrow_(true)
95     {
96     }
97
98     //! Sets whether to search first in the current (working) directory.
99     DataFileOptions& includeCurrentDir(bool bInclude)
100     {
101         bCurrentDir_ = bInclude;
102         return *this;
103     }
104     //! Sets whether an exception is thrown if the file could not be found.
105     DataFileOptions& throwIfNotFound(bool bThrow)
106     {
107         bThrow_ = bThrow;
108         return *this;
109     }
110
111 private:
112     const char* filename_;
113     bool        bCurrentDir_;
114     bool        bThrow_;
115
116     /*! \brief
117      * Needed to access the members without otherwise unnecessary accessors.
118      */
119     friend class DataFileFinder;
120 };
121
122 /*! \brief
123  * Information about a data file found by DataFileFinder::enumerateFiles().
124  *
125  * \inpublicapi
126  * \ingroup module_utility
127  */
128 struct DataFileInfo
129 {
130     //! Initializes the structure with given values.
131     DataFileInfo(const std::string& dir, const std::string& name, bool bDefault) :
132         dir(dir), name(name), bFromDefaultDir(bDefault)
133     {
134     }
135
136     /*! \brief
137      * Directory from which the file was found.
138      *
139      * If the file was found from the current directory, this will be `"."`.
140      * In other cases, this will be a full path (except if the user-provided
141      * search path contains relative paths).
142      */
143     std::string dir;
144     /*! \brief
145      * Name of the file without any directory name.
146      */
147     std::string name;
148     /*! \brief
149      * Whether the file was found from the default directory.
150      *
151      * If `true`, the file was found from the default installation data
152      * directory, not from the current directory or any user-provided (through
153      * DataFileFinder::setSearchPathFromEnv()) location.
154      * \todo
155      * Consider replacing with an enum that identifies the source (current dir,
156      * GMXLIB, default).
157      */
158     bool bFromDefaultDir;
159 };
160
161 /*! \brief
162  * Searches data files from a set of paths.
163  *
164  * \inpublicapi
165  * \ingroup module_utility
166  */
167 class DataFileFinder
168 {
169 public:
170     /*! \brief
171      * Constructs a default data file finder.
172      *
173      * The constructed finder searches only in the directory specified by
174      * the global program context (see IProgramContext), and
175      * optionally in the current directory.
176      *
177      * Does not throw.
178      */
179     DataFileFinder();
180     ~DataFileFinder();
181
182     /*! \brief
183      * Adds search path from an environment variable.
184      *
185      * \param[in] envVarName  Name of the environment variable to use.
186      * \throws std::bad_alloc if out of memory.
187      *
188      * If the specified environment variable is set, it is interpreted like
189      * a `PATH` environment variable on the platform (split at appropriate
190      * separators), and each path found is added to the search path this
191      * finder searches.  The added paths take precedence over the default
192      * directory specified by the global program context, but the current
193      * directory is searched first.
194      */
195     void setSearchPathFromEnv(const char* envVarName);
196
197     /*! \brief
198      * Opens a data file (if found) in an RAII-style `FILE` handle.
199      *
200      * \param[in] options  Identifies the file to be searched for.
201      * \returns The opened file handle, or `NULL` if the file could not be
202      *     found and exceptions were turned off.
203      * \throws  std::bad_alloc if out of memory.
204      * \throws  FileIOError if
205      *   - no such file can be found, and \p options specifies that an
206      *     exception should be thrown, or
207      *   - there is an error opening the file (note that a file is skipped
208      *     during the search if the user does not have rights to open the
209      *     file at all).
210      *
211      * See findFile() for more details.
212      */
213     FilePtr openFile(const DataFileOptions& options) const;
214     /*! \brief
215      * Finds a full path to a data file if found.
216      *
217      * \param[in] options  Identifies the file to be searched for.
218      * \returns Full path to the data file, or an empty string if the file
219      *     could not be found and exceptions were turned off.
220      * \throws  std::bad_alloc if out of memory.
221      * \throws  FileIOError if no such file can be found, and \p options
222      *     specifies that an exception should be thrown.
223      *
224      * Searches for a data file in the search paths configured for the
225      * finder, as well as in the current directory if so required.
226      * Returns the full path to the first file found.
227      */
228     std::string findFile(const DataFileOptions& options) const;
229     /*! \brief
230      * Enumerates files in the data directories.
231      *
232      * \param[in] options  Idenfies files to be searched for.
233      * \returns Information about each found file.
234      * \throws  std::bad_alloc if out of memory.
235      * \throws  FileIOError if no such file can be found, and \p options
236      *     specifies that an exception should be thrown.
237      *
238      * Enumerates all files in the data directories that have the
239      * extension/suffix specified by the file name in \p options.
240      * Unlike findFile() and openFile(), this only works on files that are
241      * in the actual data directories, not for any entry within
242      * subdirectories of those.
243      * See DataFileInfo for details on what is returned for each found
244      * file.
245      * Files from the same directory will be returned as a continuous block
246      * in the returned vector.
247      */
248     std::vector<DataFileInfo> enumerateFiles(const DataFileOptions& options) const;
249
250 private:
251     class Impl;
252
253     std::unique_ptr<Impl> impl_;
254 };
255
256 } // namespace gmx
257
258 #endif