Merge remote-tracking branch 'origin/release-4-6'
[alexxy/gromacs.git] / src / testutils / cmdlinetest.cpp
1 /*
2  *
3  *                This source code is part of
4  *
5  *                 G   R   O   M   A   C   S
6  *
7  *          GROningen MAchine for Chemical Simulations
8  *
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.
13
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.
18  *
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.
25  *
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.
28  *
29  * For more info, check our website at http://www.gromacs.org
30  */
31 /*! \internal \file
32  * \brief
33  * Implements gmx::test::CommandLine.
34  *
35  * \author Teemu Murtola <teemu.murtola@cbr.su.se>
36  * \ingroup module_testutils
37  */
38 #include "cmdlinetest.h"
39
40 #include <cstdlib>
41 #include <cstring>
42
43 #include <new>
44 #include <vector>
45
46 namespace gmx
47 {
48 namespace test
49 {
50
51 /********************************************************************
52  * CommandLine::Impl
53  */
54
55 class CommandLine::Impl
56 {
57     public:
58         Impl(const char *const cmdline[], size_t count);
59         ~Impl();
60
61         std::vector<char *>     args_;
62         std::vector<char *>     argv_;
63         int                     argc_;
64 };
65
66 CommandLine::Impl::Impl(const char *const cmdline[], size_t count)
67 {
68     args_.reserve(count);
69     argv_.reserve(count);
70     argc_ = static_cast<int>(count);
71     for (size_t i = 0; i < count; ++i)
72     {
73         char *arg = strdup(cmdline[i]);
74         if (arg == NULL)
75         {
76             throw std::bad_alloc();
77         }
78         args_.push_back(arg);
79         argv_.push_back(arg);
80     }
81 }
82
83 CommandLine::Impl::~Impl()
84 {
85     for (size_t i = 0; i < args_.size(); ++i)
86     {
87         std::free(args_[i]);
88     }
89 }
90
91 /********************************************************************
92  * CommandLine
93  */
94
95 CommandLine::CommandLine()
96     : impl_(new Impl(NULL, 0))
97 {
98 }
99
100 CommandLine::CommandLine(const char *const cmdline[], size_t count)
101     : impl_(new Impl(cmdline, count))
102 {
103 }
104
105 CommandLine::CommandLine(const CommandLine &other)
106     : impl_(new Impl(other.argv(), other.argc()))
107 {
108 }
109
110 CommandLine::~CommandLine()
111 {
112 }
113
114 void CommandLine::append(const char *arg)
115 {
116     size_t newSize = impl_->args_.size() + 1;
117     impl_->args_.reserve(newSize);
118     impl_->argv_.reserve(newSize);
119     char *newArg = strdup(arg);
120     if (newArg == NULL)
121     {
122         throw std::bad_alloc();
123     }
124     impl_->args_.push_back(newArg);
125     impl_->argv_.push_back(newArg);
126     impl_->argc_ = static_cast<int>(newSize);
127 }
128
129 int &CommandLine::argc() { return impl_->argc_; }
130 char **CommandLine::argv() { return &impl_->argv_[0]; }
131 int CommandLine::argc() const { return impl_->argc_; }
132 const char *const *CommandLine::argv() const { return &impl_->argv_[0]; }
133 const char *CommandLine::arg(int i) const { return impl_->argv_[i]; }
134
135 std::string CommandLine::toString() const
136 {
137     std::string result;
138     for (size_t i = 0; i < impl_->args_.size(); ++i)
139     {
140         if (i > 0)
141         {
142             result.append(" ");
143         }
144         const char *arg = impl_->args_[i];
145         bool bSpaces = (std::strchr(arg, ' ') != NULL);
146         if (bSpaces)
147         {
148             result.append("'");
149         }
150         result.append(arg);
151         if (bSpaces)
152         {
153             result.append("'");
154         }
155     }
156     return result;
157 }
158
159 } // namespace test
160 } // namespace gmx