Chaste Commit::baa90ac2819b962188b7562f2326be23c47859a7
CommandLineArguments.cpp
1/*
2
3Copyright (c) 2005-2024, University of Oxford.
4All rights reserved.
5
6University of Oxford means the Chancellor, Masters and Scholars of the
7University of Oxford, having an administrative office at Wellington
8Square, Oxford OX1 2JD, UK.
9
10This file is part of Chaste.
11
12Redistribution and use in source and binary forms, with or without
13modification, are permitted provided that the following conditions are met:
14 * Redistributions of source code must retain the above copyright notice,
15 this list of conditions and the following disclaimer.
16 * Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19 * Neither the name of the University of Oxford nor the names of its
20 contributors may be used to endorse or promote products derived from this
21 software without specific prior written permission.
22
23THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
34*/
35
36#include "CommandLineArguments.hpp"
37
38#include <cassert>
39#include <cstddef>
40#include <algorithm>
41
43 : p_argc(nullptr),
44 p_argv(nullptr)
45{
46 // Make doubly sure there's only one instance
47 assert(mpInstance == nullptr);
48}
49
58
60
61bool CommandLineArguments::OptionExists(const std::string& rOption)
62{
63 TestOptionFormat(rOption);
64 try
65 {
66 return(GetIndexForArgument(rOption));
67 }
68 catch (const Exception&)
69 {
70 return false;
71 }
72}
73
74char* CommandLineArguments::GetValueCorrespondingToOption(const std::string& rOption, int valueNumber)
75{
76 EXCEPT_IF_NOT(valueNumber>0);
77 TestOptionFormat(rOption);
78
79 int index = GetIndexForArgument(rOption);
80 int num_args = GetNumberOfArgumentsForOption(rOption, true);
81 if (num_args < valueNumber)
82 {
83 std::stringstream ss;
84 ss<<"Index="<<valueNumber<<" requested for '"<<rOption<<"', but only "<<num_args<<" given.";
85 EXCEPTION(ss.str());
86 }
87
88 return (*p_argv)[index+valueNumber];
89}
90
91double CommandLineArguments::GetDoubleCorrespondingToOption(const std::string& rOption, int valueNumber)
92{
93 char* val = GetValueCorrespondingToOption(rOption, valueNumber);
94 return atof(val);
95}
96
97int CommandLineArguments::GetIntCorrespondingToOption(const std::string& rOption, int valueNumber)
98{
99 char* val = GetValueCorrespondingToOption(rOption, valueNumber);
100 return atoi(val);
101}
102
103unsigned CommandLineArguments::GetUnsignedCorrespondingToOption(const std::string& rOption, int valueNumber)
104{
105 char* val = GetValueCorrespondingToOption(rOption, valueNumber);
106 int i = atoi(val);
107 if (i < 0)
108 {
109 EXCEPTION("Option is a negative number and cannot be converted to unsigned.");
110 }
111 return (unsigned)(i);
112}
113
115{
116 TestOptionFormat(rOption);
117
118 for (int i=1; i<*p_argc; i++)
119 {
120 if (rOption==std::string((*p_argv)[i]))
121 {
122 return i;
123 }
124 }
125 EXCEPTION("Command line option '"+rOption+"' does not exist");
126}
127
128int CommandLineArguments::GetNumberOfArgumentsForOption(const std::string& rOption, bool throwIfNone)
129{
130 int start_idx = GetIndexForArgument(rOption);
131
132 int end_idx = start_idx;
133 for (int i=start_idx+1; i<*p_argc; i++)
134 {
135 std::string argument = std::string((*p_argv)[i]);
136 if (argument.substr(0,1)=="-" && argument.substr(1,1).find_first_of("0123456789")==std::string::npos)
137 {
138 break;
139 }
140 end_idx = i;
141 }
142
143 if (end_idx == start_idx)
144 {
145 if (throwIfNone)
146 {
147 EXCEPTION("No value(s) given after command line option '" + rOption + "'");
148 }
149 else
150 {
151 return 0;
152 }
153 }
154
155 return end_idx - start_idx;
156}
157
158std::string CommandLineArguments::GetStringCorrespondingToOption(const std::string& rOption, int valueNumber)
159{
160 char* val = GetValueCorrespondingToOption(rOption, valueNumber);
161 std::string string_arg(val);
162 return string_arg;
163}
164
165std::vector<std::string> CommandLineArguments::GetStringsCorrespondingToOption(const std::string& rOption)
166{
167 std::vector<std::string> strings;
168 int num_args = GetNumberOfArgumentsForOption(rOption, true);
169 for (int i=1; i<=num_args; ++i)
170 {
171 strings.push_back(GetStringCorrespondingToOption(rOption, i));
172 }
173 return strings;
174}
175
176std::vector<double> CommandLineArguments::GetDoublesCorrespondingToOption(const std::string& rOption)
177{
178 std::vector<double> doubles;
179 int num_args = GetNumberOfArgumentsForOption(rOption, true);
180 for (int i=1; i<=num_args; ++i)
181 {
182 doubles.push_back(GetDoubleCorrespondingToOption(rOption, i));
183 }
184 return doubles;
185}
186
187std::vector<unsigned> CommandLineArguments::GetUnsignedsCorrespondingToOption(const std::string& rOption)
188{
189 std::vector<unsigned> unsigneds;
190 int num_args = GetNumberOfArgumentsForOption(rOption, true);
191 for (int i=1; i<=num_args; ++i)
192 {
193 unsigneds.push_back(GetUnsignedCorrespondingToOption(rOption, i));
194 }
195 return unsigneds;
196}
197
198std::vector<int> CommandLineArguments::GetIntsCorrespondingToOption(const std::string& rOption)
199{
200 std::vector<int> ints;
201 int num_args = GetNumberOfArgumentsForOption(rOption, true);
202 for (int i=1; i<=num_args; ++i)
203 {
204 ints.push_back(GetIntCorrespondingToOption(rOption, i));
205 }
206 return ints;
207}
208
210{
211 bool result;
212 std::string string_result = GetStringCorrespondingToOption(rOption);
213
214 // Convert to lowercase
215 std::transform(string_result.begin(), string_result.end(), string_result.begin(), ::tolower);
216
217 if (string_result=="0" || string_result=="false")
218 {
219 result = false;
220 }
221 else if (string_result=="1" || string_result=="true")
222 {
223 result = true;
224 }
225 else
226 {
227 EXCEPTION("The option '" << rOption << "' argument '" <<
228 GetStringCorrespondingToOption(rOption) << "' cannot be converted to a bool.");
229 }
230
231 return result;
232}
233
234void CommandLineArguments::TestOptionFormat(const std::string& rOption)
235{
236 if (!( rOption.substr(0,1) == "-" && rOption.substr(1,1).find_first_of("0123456789")==std::string::npos))
237 {
238 EXCEPTION("A command line option must begin with '-' followed by a non-numeric character.");
239 }
240}
#define EXCEPTION(message)
#define EXCEPT_IF_NOT(test)
bool OptionExists(const std::string &rOption)
static CommandLineArguments * Instance()
static CommandLineArguments * mpInstance
std::vector< double > GetDoublesCorrespondingToOption(const std::string &rOption)
std::string GetStringCorrespondingToOption(const std::string &rOption, int valueNumber=1)
int GetIndexForArgument(std::string rOption)
std::vector< std::string > GetStringsCorrespondingToOption(const std::string &rOption)
int GetIntCorrespondingToOption(const std::string &rOption, int valueNumber=1)
std::vector< unsigned > GetUnsignedsCorrespondingToOption(const std::string &rOption)
double GetDoubleCorrespondingToOption(const std::string &rOption, int valueNumber=1)
unsigned GetUnsignedCorrespondingToOption(const std::string &rOption, int valueNumber=1)
bool GetBoolCorrespondingToOption(const std::string &rOption)
char * GetValueCorrespondingToOption(const std::string &rOption, int valueNumber=1)
int GetNumberOfArgumentsForOption(const std::string &rOption, bool throwIfNone=false)
std::vector< int > GetIntsCorrespondingToOption(const std::string &rOption)
void TestOptionFormat(const std::string &rOption)