383ccfb7ea5269fe2ff3d6362a49a40b43dad3f2
[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
50 #include "gromacs/utility/classhelpers.h"
51
52 namespace gmx
53 {
54
55 class DataFileFinder;
56
57 /*! \brief
58  * Search parameters for DataFileFinder.
59  *
60  * This class implements a named parameter idiom for DataFileFinder::findFile()
61  * and DataFileFinder::openFile() to support an easily readable and
62  * customizable way of searching data files.
63  *
64  * By default, the search first considers the current directory, followed by
65  * specified and default data directories, and an exception is thrown if the
66  * file could not be found.
67  * To skip searching in the current directory, use includeCurrentDir().
68  *
69  * Methods in this class do not throw.
70  *
71  * \inpublicapi
72  * \ingroup module_utility
73  */
74 class DataFileOptions
75 {
76     public:
77         /*! \brief
78          * Constructs default options for searching for a file with the
79          * specified name.
80          *
81          * \param[in] filename  File name to search for.
82          *
83          * This constructor is not explicit to allow passing a simple string to
84          * DataFileFinder methods to search for the string with the default
85          * parameters.
86          */
87         DataFileOptions(const char *filename)
88             : filename_(filename), bCurrentDir_(true), bThrow_(true)
89         {
90         }
91         //! \copydoc DataFileOptions(const char *)
92         DataFileOptions(const std::string &filename)
93             : filename_(filename.c_str()), bCurrentDir_(true), bThrow_(true)
94         {
95         }
96
97         //! Sets whether to search in the current (working) directory.
98         DataFileOptions &includeCurrentDir(bool bInclude)
99         {
100             bCurrentDir_ = bInclude;
101             return *this;
102         }
103         //! Sets whether an exception is thrown if the file could not be found.
104         DataFileOptions &throwIfNotFound(bool bThrow)
105         {
106             bThrow_ = bThrow;
107             return *this;
108         }
109
110     private:
111         const char *filename_;
112         bool        bCurrentDir_;
113         bool        bThrow_;
114
115         /*! \brief
116          * Needed to access the members without otherwise unnecessary accessors.
117          */
118         friend class DataFileFinder;
119 };
120
121 /*! \brief
122  * Searches data files from a set of paths.
123  *
124  * \inpublicapi
125  * \ingroup module_utility
126  */
127 class DataFileFinder
128 {
129     public:
130         /*! \brief
131          * Constructs a default data file finder.
132          *
133          * The constructed finder searches only in the directory specified by
134          * the global program context (see ProgramContextInterface), and
135          * optionally in the current directory.
136          *
137          * Does not throw.
138          */
139         DataFileFinder();
140         ~DataFileFinder();
141
142         /*! \brief
143          * Adds search path from an environment variable.
144          *
145          * \param[in] envVarName  Name of the environment variable to use.
146          * \throws std::bad_alloc if out of memory.
147          *
148          * If the specified environment variable is set, it is interpreted like
149          * a `PATH` environment variable on the platform (split at appropriate
150          * separators), and each path found is added to the search path this
151          * finder searches.  The added paths take precedence over the default
152          * directory specified by the global program context, but the current
153          * directory is searched first.
154          */
155         void setSearchPathFromEnv(const char *envVarName);
156
157         /*! \brief
158          * Opens a data file if found.
159          *
160          * \param[in] options  Identifies the file to be searched for.
161          * \returns The opened file handle, or `NULL` if the file could not be
162          *     found and exceptions were turned off.
163          * \throws  FileIOError if
164          *   - no such file can be found, and \p options specifies that an
165          *     exception should be thrown, or
166          *   - there is an error opening the file (note that a file is skipped
167          *     during the search if the user does not have rights to open the
168          *     file at all).
169          *
170          * See findFile() for more details.
171          */
172         FILE *openFile(const DataFileOptions &options) const;
173         /*! \brief
174          * Finds a full path to a data file if found.
175          *
176          * \param[in] options  Identifies the file to be searched for.
177          * \returns Full path to the data file, or an empty string if the file
178          *     could not be found and exceptions were turned off.
179          * \throws  FileIOError if no such file can be found, and \p options
180          *     specifies that an exception should be thrown.
181          *
182          * Searches for a data file in the search paths configured for the
183          * finder, as well as in the current directory if so required.
184          * Returns the full path to the first file found.
185          */
186         std::string findFile(const DataFileOptions &options) const;
187
188     private:
189         class Impl;
190
191         PrivateImplPointer<Impl> impl_;
192 };
193
194 } // namespace gmx
195
196 #endif