Sort includes outside src/gromacs
[alexxy/gromacs.git] / src / testutils / cmdlinetest.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2012,2013,2014, 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 gmx::test::CommandLine.
38  *
39  * \author Teemu Murtola <teemu.murtola@gmail.com>
40  * \ingroup module_testutils
41  */
42 #include "gmxpre.h"
43
44 #include "cmdlinetest.h"
45
46 #include <cstdlib>
47 #include <cstring>
48
49 #include <new>
50 #include <sstream>
51 #include <vector>
52
53 #include "gromacs/commandline/cmdlineprogramcontext.h"
54 #include "gromacs/utility/arrayref.h"
55 #include "gromacs/utility/gmxassert.h"
56
57 namespace gmx
58 {
59 namespace test
60 {
61
62 /********************************************************************
63  * CommandLine::Impl
64  */
65
66 class CommandLine::Impl
67 {
68     public:
69         Impl(const char *const cmdline[], size_t count);
70         ~Impl();
71
72         std::vector<char *>     args_;
73         std::vector<char *>     argv_;
74         int                     argc_;
75 };
76
77 CommandLine::Impl::Impl(const char *const cmdline[], size_t count)
78 {
79     args_.reserve(count);
80     argv_.reserve(count + 1);
81     argc_ = static_cast<int>(count);
82     for (size_t i = 0; i < count; ++i)
83     {
84         char *arg = strdup(cmdline[i]);
85         if (arg == NULL)
86         {
87             throw std::bad_alloc();
88         }
89         args_.push_back(arg);
90         argv_.push_back(arg);
91     }
92     argv_.push_back(NULL);
93 }
94
95 CommandLine::Impl::~Impl()
96 {
97     for (size_t i = 0; i < args_.size(); ++i)
98     {
99         std::free(args_[i]);
100     }
101 }
102
103 /********************************************************************
104  * CommandLine
105  */
106
107 CommandLine::CommandLine()
108     : impl_(new Impl(NULL, 0))
109 {
110 }
111
112 CommandLine::CommandLine(const ConstArrayRef<const char *> &cmdline)
113     : impl_(new Impl(cmdline.data(), cmdline.size()))
114 {
115 }
116
117 CommandLine::CommandLine(const CommandLine &other)
118     : impl_(new Impl(other.argv(), other.argc()))
119 {
120 }
121
122 CommandLine::~CommandLine()
123 {
124 }
125
126 void CommandLine::initFromArray(const ConstArrayRef<const char *> &cmdline)
127 {
128     impl_.reset(new Impl(cmdline.data(), cmdline.size()));
129 }
130
131 void CommandLine::append(const char *arg)
132 {
133     GMX_RELEASE_ASSERT(impl_->argc_ == static_cast<int>(impl_->args_.size()),
134                        "Command-line has been modified externally");
135     size_t newSize = impl_->args_.size() + 1;
136     impl_->args_.reserve(newSize);
137     impl_->argv_.reserve(newSize + 1);
138     char *newArg = strdup(arg);
139     if (newArg == NULL)
140     {
141         throw std::bad_alloc();
142     }
143     impl_->args_.push_back(newArg);
144     impl_->argv_.pop_back(); // Remove the trailing NULL.
145     impl_->argv_.push_back(newArg);
146     impl_->argv_.push_back(NULL);
147     impl_->argc_ = static_cast<int>(newSize);
148 }
149
150 namespace
151 {
152
153 //! Helper function for converting values to strings
154 template <typename T>
155 std::string value2string(T value)
156 {
157     std::stringstream ss;
158     ss << value;
159     return ss.str();
160 }
161
162 }
163
164 void CommandLine::addOption(const char *name,
165                             const char *value)
166 {
167     append(name);
168     append(value);
169 }
170
171 void CommandLine::addOption(const char        *name,
172                             const std::string &value)
173 {
174     addOption(name, value.c_str());
175 }
176
177 void CommandLine::addOption(const char *name,
178                             int         value)
179 {
180     append(name);
181     append(value2string(value));
182 }
183
184 void CommandLine::addOption(const char *name,
185                             double      value)
186 {
187     append(name);
188     append(value2string(value));
189 }
190
191 int &CommandLine::argc()
192 {
193     return impl_->argc_;
194 }
195 char **CommandLine::argv()
196 {
197     return &impl_->argv_[0];
198 }
199 int CommandLine::argc() const
200 {
201     return impl_->argc_;
202 }
203 const char *const *CommandLine::argv() const
204 {
205     return &impl_->argv_[0];
206 }
207 const char *CommandLine::arg(int i) const
208 {
209     return impl_->argv_[i];
210 }
211
212 std::string CommandLine::toString() const
213 {
214     return CommandLineProgramContext(argc(), argv()).commandLine();
215 }
216
217 } // namespace test
218 } // namespace gmx