Change naming convention for C++ interfaces
[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, 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 <string>
49 #include <vector>
50
51 #include "gromacs/utility/classhelpers.h"
52
53 namespace gmx
54 {
55
56 class DataFileFinder;
57
58 /*! \brief
59  * Search parameters for DataFileFinder.
60  *
61  * This class implements a named parameter idiom for DataFileFinder::findFile()
62  * and DataFileFinder::openFile() to support an easily readable and
63  * customizable way of searching data files.
64  *
65  * By default, the search first considers the current directory, followed by
66  * specified and default data directories, and an exception is thrown if the
67  * file could not be found.
68  * To skip searching in the current directory, use includeCurrentDir().
69  *
70  * Methods in this class do not throw.
71  *
72  * \inpublicapi
73  * \ingroup module_utility
74  */
75 class DataFileOptions
76 {
77     public:
78         /*! \brief
79          * Constructs default options for searching for a file with the
80          * specified name.
81          *
82          * \param[in] filename  File name to search for.
83          *
84          * This constructor is not explicit to allow passing a simple string to
85          * DataFileFinder methods to search for the string with the default
86          * parameters.
87          */
88         DataFileOptions(const char *filename)
89             : 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 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.
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         FILE *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         PrivateImplPointer<Impl> impl_;
254 };
255
256 } // namespace gmx
257
258 #endif