3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
9 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
10 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
11 * Copyright (c) 2001-2009, The GROMACS development team,
12 * check out http://www.gromacs.org for more information.
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * If you want to redistribute modifications, please consider that
20 * scientific software is very special. Version control is crucial -
21 * bugs must be traceable. We will be happy to consider code for
22 * inclusion in the official distribution, but derived work must not
23 * be called official GROMACS. Details are found in the README & COPYING
24 * files - if they are missing, get the official version at www.gromacs.org.
26 * To help us fund GROMACS development, we humbly ask that you cite
27 * the papers on the package - you can find them in the top README file.
29 * For more info, check our website at http://www.gromacs.org
33 * Implements classes in filenameoption.h, filenameoptioninfo.h and
34 * filenameoptionstorage.h.
36 * \author Teemu Murtola <teemu.murtola@cbr.su.se>
37 * \ingroup module_options
39 #include "filenameoption.h"
44 #include "gromacs/options/filenameoptioninfo.h"
45 #include "gromacs/utility/file.h"
46 #include "gromacs/utility/stringutil.h"
48 #include "filenameoptionstorage.h"
56 class FileTypeRegistry;
58 /********************************************************************
63 * Handles a single file type known to FileNameOptionStorage.
65 * \ingroup module_options
70 //! Returns whether \p filename has a valid extension for this type.
71 bool hasKnownExtension(const std::string &filename) const;
72 //! Adds a default extension for this type to \p filename.
73 std::string addExtension(const std::string &filename) const;
75 * Adds an extension to \p filename if it results in an existing file.
77 * Tries to add each extension for this file type to \p filename and
78 * checks whether this results in an existing file.
79 * The first match is returned.
80 * Returns an empty string if no existing file is found.
82 std::string findFileWithExtension(const std::string &filename) const;
85 //! Possible extensions for this file type.
86 std::vector<const char *> extensions_;
89 * Needed for initialization; all initialization is handled by
92 friend class FileTypeRegistry;
96 FileTypeHandler::hasKnownExtension(const std::string &filename) const
98 for (size_t i = 0; i < extensions_.size(); ++i)
100 if (endsWith(filename, extensions_[i]))
109 FileTypeHandler::addExtension(const std::string &filename) const
111 if (extensions_.empty())
115 return filename + extensions_[0];
119 FileTypeHandler::findFileWithExtension(const std::string &filename) const
121 for (size_t i = 0; i < extensions_.size(); ++i)
123 std::string testFilename(filename + extensions_[i]);
124 if (File::exists(testFilename))
129 return std::string();
132 /********************************************************************
137 * Singleton for managing static file type info for FileNameOptionStorage.
139 * \ingroup module_options
141 class FileTypeRegistry
144 //! Returns a singleton instance of this class.
145 static const FileTypeRegistry &instance();
146 //! Returns a handler for a single file type.
147 const FileTypeHandler &handlerForType(OptionFileType type) const;
150 //! Initializes the file type registry.
153 //! Registers a file type with a single extension.
154 void registerType(OptionFileType type, const char *extension);
155 //! Registers a file type with multiple extensions.
156 template <size_t count>
157 void registerType(OptionFileType type,
158 const char *const (&extensions)[count]);
160 std::vector<FileTypeHandler> filetypes_;
164 const FileTypeRegistry &
165 FileTypeRegistry::instance()
167 static FileTypeRegistry singleton;
171 const FileTypeHandler &
172 FileTypeRegistry::handlerForType(OptionFileType type) const
174 GMX_RELEASE_ASSERT(type >= 0 && static_cast<size_t>(type) < filetypes_.size(),
175 "Invalid file type");
176 return filetypes_[type];
179 FileTypeRegistry::FileTypeRegistry()
181 filetypes_.resize(eftOptionFileType_NR);
182 const char *const topExtensions[] = {
183 ".tpr", ".tpb", ".tpa", ".gro", ".g96", ".pdb", ".brk", ".ent"
185 const char *const trajExtensions[] = {
186 ".xtc", ".trr", ".trj", ".cpt", ".gro", ".g96", ".g87", ".pdb"
188 registerType(eftTopology, topExtensions);
189 registerType(eftTrajectory, trajExtensions);
190 registerType(eftIndex, ".ndx");
191 registerType(eftPlot, ".xvg");
192 registerType(eftGenericData, ".dat");
195 void FileTypeRegistry::registerType(OptionFileType type,
196 const char *extension)
198 GMX_RELEASE_ASSERT(type >= 0 && static_cast<size_t>(type) < filetypes_.size(),
199 "Invalid file type");
200 filetypes_[type].extensions_.assign(1, extension);
203 template <size_t count>
204 void FileTypeRegistry::registerType(OptionFileType type,
205 const char *const (&extensions)[count])
207 GMX_RELEASE_ASSERT(type >= 0 && static_cast<size_t>(type) < filetypes_.size(),
208 "Invalid file type");
209 filetypes_[type].extensions_.assign(extensions, extensions + count);
213 * Helper method to complete a file name provided to a file name option.
215 * \param[in] value Value provided to the file name option.
216 * \param[in] filetype File type for the option.
217 * \param[in] bCompleteToExisting
218 * Whether to check existing files when completing the extension.
219 * \returns \p value with possible extension added.
221 std::string completeFileName(const std::string &value, OptionFileType filetype,
222 bool bCompleteToExisting)
224 if (bCompleteToExisting && File::exists(value))
226 // TODO: This may not work as expected if the value is passed to a
227 // function that uses fn2ftp() to determine the file type and the input
228 // file has an unrecognized extension.
231 const FileTypeRegistry ®istry = FileTypeRegistry::instance();
232 const FileTypeHandler &typeHandler = registry.handlerForType(filetype);
233 if (typeHandler.hasKnownExtension(value))
237 if (bCompleteToExisting)
239 std::string newValue = typeHandler.findFileWithExtension(value);
240 if (!newValue.empty())
245 return typeHandler.addExtension(value);
250 /********************************************************************
251 * FileNameOptionStorage
254 FileNameOptionStorage::FileNameOptionStorage(const FileNameOption &settings)
255 : MyBase(settings), info_(this), filetype_(settings.filetype_),
256 bRead_(settings.bRead_), bWrite_(settings.bWrite_),
257 bLibrary_(settings.bLibrary_)
259 if (settings.defaultValue())
261 setDefaultValue(completeFileName(*settings.defaultValue(),
264 if (settings.defaultValueIfSet())
266 setDefaultValueIfSet(completeFileName(*settings.defaultValueIfSet(),
271 std::string FileNameOptionStorage::formatSingleValue(const std::string &value) const
276 void FileNameOptionStorage::convertValue(const std::string &value)
278 bool bInput = isInputFile() || isInputOutputFile();
279 addValue(completeFileName(value, filetype_, bInput));
282 /********************************************************************
286 FileNameOptionInfo::FileNameOptionInfo(FileNameOptionStorage *option)
291 const FileNameOptionStorage &FileNameOptionInfo::option() const
293 return static_cast<const FileNameOptionStorage &>(OptionInfo::option());
296 bool FileNameOptionInfo::isInputFile() const
298 return option().isInputFile();
301 bool FileNameOptionInfo::isOutputFile() const
303 return option().isOutputFile();
306 bool FileNameOptionInfo::isInputOutputFile() const
308 return option().isInputOutputFile();
311 bool FileNameOptionInfo::isLibraryFile() const
313 return option().isLibraryFile();
316 /********************************************************************
320 AbstractOptionStoragePointer FileNameOption::createStorage() const
322 return AbstractOptionStoragePointer(new FileNameOptionStorage(*this));