Tidy: modernize-use-nullptr
[alexxy/gromacs.git] / src / gromacs / commandline / cmdlineoptionsmodule.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2014,2015,2016,2017, 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 /*! \internal \file
36  * \brief
37  * Implements supporting routines for gmx::ICommandLineOptionsModule.
38  *
39  * \author Teemu Murtola <teemu.murtola@gmail.com>
40  * \ingroup module_commandline
41  */
42 #include "gmxpre.h"
43
44 #include "cmdlineoptionsmodule.h"
45
46 #include <memory>
47
48 #include "gromacs/commandline/cmdlinehelpwriter.h"
49 #include "gromacs/commandline/cmdlinemodulemanager.h"
50 #include "gromacs/commandline/cmdlineparser.h"
51 #include "gromacs/options/behaviorcollection.h"
52 #include "gromacs/options/filenameoptionmanager.h"
53 #include "gromacs/options/ioptionsbehavior.h"
54 #include "gromacs/options/options.h"
55 #include "gromacs/utility/arrayref.h"
56 #include "gromacs/utility/gmxassert.h"
57 #include "gromacs/utility/stringutil.h"
58
59 namespace gmx
60 {
61
62 namespace
63 {
64
65 /********************************************************************
66  * CommandLineOptionsModuleSettings
67  */
68
69 class CommandLineOptionsModuleSettings : public ICommandLineOptionsModuleSettings
70 {
71     public:
72         explicit CommandLineOptionsModuleSettings(
73             OptionsBehaviorCollection *behaviors)
74             : behaviors_(*behaviors)
75         {
76         }
77
78         const std::string &helpText() const { return helpText_; }
79
80         virtual void setHelpText(const ConstArrayRef<const char *> &help)
81         {
82             helpText_ = joinStrings(help, "\n");
83         }
84         virtual void addOptionsBehavior(const OptionsBehaviorPointer &behavior)
85         {
86             behaviors_.addBehavior(behavior);
87         }
88
89     private:
90         std::string                helpText_;
91         OptionsBehaviorCollection &behaviors_;
92 };
93
94 /********************************************************************
95  * CommandLineOptionsModule
96  */
97
98 class CommandLineOptionsModule : public ICommandLineModule
99 {
100     public:
101         //! Shorthand for the factory function pointer type.
102         typedef ICommandLineOptionsModule::FactoryMethod FactoryMethod;
103
104         CommandLineOptionsModule(const char *name, const char *description,
105                                  FactoryMethod factory)
106             : name_(name), description_(description), factory_(factory)
107         {
108         }
109         CommandLineOptionsModule(const char *name, const char *description,
110                                  ICommandLineOptionsModulePointer module)
111             : name_(name), description_(description), module_(std::move(module))
112         {
113         }
114         virtual const char *name() const { return name_; }
115         virtual const char *shortDescription() const { return description_; }
116
117         virtual void init(CommandLineModuleSettings *settings);
118         virtual int run(int argc, char *argv[]);
119         virtual void writeHelp(const CommandLineHelpContext &context) const;
120
121     private:
122         void parseOptions(int argc, char *argv[]);
123
124         const char                       *name_;
125         const char                       *description_;
126         FactoryMethod                     factory_;
127         ICommandLineOptionsModulePointer  module_;
128 };
129
130 void CommandLineOptionsModule::init(CommandLineModuleSettings *settings)
131 {
132     if (!module_)
133     {
134         GMX_RELEASE_ASSERT(factory_ != nullptr, "Neither factory nor module provided");
135         module_ = factory_();
136     }
137     module_->init(settings);
138 }
139
140 int CommandLineOptionsModule::run(int argc, char *argv[])
141 {
142     GMX_RELEASE_ASSERT(module_, "init() has not been called");
143     parseOptions(argc, argv);
144     return module_->run();
145 }
146
147 void CommandLineOptionsModule::writeHelp(const CommandLineHelpContext &context) const
148 {
149     ICommandLineOptionsModulePointer  moduleGuard;
150     ICommandLineOptionsModule        *module = module_.get();
151     if (!module)
152     {
153         GMX_RELEASE_ASSERT(factory_ != nullptr, "Neither factory nor module provided");
154         moduleGuard = factory_();
155         module      = moduleGuard.get();
156     }
157     Options                          options;
158     OptionsBehaviorCollection        behaviors(&options);
159     CommandLineOptionsModuleSettings settings(&behaviors);
160     module->initOptions(&options, &settings);
161     CommandLineHelpWriter(options)
162         .setHelpText(settings.helpText())
163         .writeHelp(context);
164 }
165
166 void CommandLineOptionsModule::parseOptions(int argc, char *argv[])
167 {
168     FileNameOptionManager fileoptManager;
169     Options               options;
170
171     options.addManager(&fileoptManager);
172
173     OptionsBehaviorCollection        behaviors(&options);
174     CommandLineOptionsModuleSettings settings(&behaviors);
175     module_->initOptions(&options, &settings);
176     {
177         CommandLineParser parser(&options);
178         parser.parse(&argc, argv);
179         behaviors.optionsFinishing();
180         options.finish();
181     }
182     module_->optionsFinished();
183     behaviors.optionsFinished();
184 }
185
186 }   // namespace
187
188 /********************************************************************
189  * ICommandLineOptionsModuleSettings
190  */
191
192 ICommandLineOptionsModuleSettings::~ICommandLineOptionsModuleSettings()
193 {
194 }
195
196 /********************************************************************
197  * ICommandLineOptionsModule
198  */
199
200 ICommandLineOptionsModule::~ICommandLineOptionsModule()
201 {
202 }
203
204 // static
205 std::unique_ptr<ICommandLineModule>
206 ICommandLineOptionsModule::createModule(
207         const char *name, const char *description,
208         ICommandLineOptionsModulePointer module)
209 {
210     return std::unique_ptr<ICommandLineModule>(
211             new CommandLineOptionsModule(name, description, std::move(module)));
212 }
213
214 // static
215 int ICommandLineOptionsModule::runAsMain(
216         int argc, char *argv[], const char *name, const char *description,
217         FactoryMethod factory)
218 {
219     CommandLineOptionsModule module(name, description, factory);
220     return CommandLineModuleManager::runAsMainSingleModule(argc, argv, &module);
221 }
222
223 // static
224 void ICommandLineOptionsModule::registerModuleFactory(
225         CommandLineModuleManager *manager, const char *name,
226         const char *description, FactoryMethod factory)
227 {
228     CommandLineModulePointer module(
229             new CommandLineOptionsModule(name, description, factory));
230     manager->addModule(std::move(module));
231 }
232
233 // static
234 void ICommandLineOptionsModule::registerModuleDirect(
235         CommandLineModuleManager *manager, const char *name,
236         const char *description, ICommandLineOptionsModulePointer module)
237 {
238     CommandLineModulePointer wrapperModule(
239             createModule(name, description, std::move(module)));
240     manager->addModule(std::move(wrapperModule));
241 }
242
243 } // namespace gmx