forked from degauden/Elements
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathExtProgram.cpp
More file actions
219 lines (191 loc) · 8.61 KB
/
Copy pathExtProgram.cpp
File metadata and controls
219 lines (191 loc) · 8.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
/**
* @file ExtProgram.cpp
* @date 2015-01-06
* @author Pierre Dubath
*
* @copyright 2012-2020 Euclid Science Ground Segment
*
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General
* Public License as published by the Free Software Foundation; either version 3.0 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <cstdint> // for int64_t
#include <map> // for map
#include <memory> // for allocator, unique_ptr
#include <string> // for basic_string, string, operator<
#include <utility> // for move
#include <vector> // for vector
#include <boost/program_options.hpp> // for value, typed_value, options_description_easy_init,
// variable_value, bool_switch
#include "ElementsExamples/ClassExample.h" // for ClassExample
#include "ElementsExamples/FunctionExample.h" // for functionExample
#include "ElementsExamples/PrintProject.h" // for printProject
#include "ElementsKernel/Exception.h" // for Exception
#include "ElementsKernel/Main.h" // for MAIN_FOR
#include "ElementsKernel/Module.h" // for Module
#include "ElementsKernel/ModuleInfo.h" // for ModuleInfo
#include "ElementsKernel/Program.h" // for Program
#include "ElementsKernel/Project.h" // for Project, operator<<
#include "ElementsKernel/ThisModule.h" // for getThisExecutableInfo
using std::map;
using std::string;
using std::vector;
using boost::program_options::bool_switch;
using boost::program_options::value;
using std::int64_t;
/**
* @class ExtProgram
* @brief
* Simple example of an Elements program outside of the Elements namespace
* @details
* All C++ executable must extend the Elements::Program base class
*
*/
class ExtProgram final : public Elements::Program {
public:
/**
* @brief
* Allows to define the (command line and configuration file) options specific to
* this program
* @details
* See the ElementsProgram documentation for more details.
* @return
* A BOOST program options_description
*/
OptionsDescription defineSpecificProgramOptions() override {
OptionsDescription config_options{"Example program options"};
auto add = config_options.add_options();
bool flag = false;
// Add the specific program options
add("int-option", value<int>()->default_value(int{111}), "An example int option");
add("int-option-with-default-and-default-in-conf", value<int>()->default_value(int{222}), "An example int option");
add("int-option-with-default-no-default-in-conf", value<int>()->default_value(int{444}), "An example int option");
add("int-option-no-default-not-defined-in-conf", value<int>(), "An example int option");
add("int-option-with-no-defaults-anywhere", value<int>(), "An example int option");
add("string-option", value<string>()->default_value(string{}), "An example string option");
add("boolean-option", value<bool>()->default_value(false), "An example boolean option");
add("flag,f", bool_switch(&flag), "An option to set to true");
add("string-option-no-default", value<string>(), "A string option without default value");
add("long-long-option", value<int64_t>()->default_value(int64_t{}), "An example long long option");
add("double-option", value<double>()->default_value(double{}), "An example double option");
add("int-vector-option", value<vector<int>>()->multitoken()->default_value(vector<int>{}, "Empty"),
"An example vector option");
add("threshold,t", value<double>()->default_value(double{0.5}), "An example double option");
return config_options;
}
/**
* @brief
* The "main" method.
* @details
* This method is the entry point to the program. In this sense, it is similar to a main
* (and it is why it is called mainMethod()). The code below contains the calls to the
* different classes created for the first developer's workshop
*
* See the ElementsProgram documentation for more details.
*
*/
ExitCode mainMethod(map<string, VariableValue>& args) override {
using Elements::Examples::ClassExample;
const auto log = Logging::getLogger("ExtProgram");
log.info("Entering mainMethod()");
log.info("#");
/*
* Check availability of mandatory program arguments (or options)
*
* Arguments values may come from
* 1) the default value provided in above defineSpecificProgramOptions()
* 2) the configuration file
* 3) the command line
*
* If none of the three options provide any values for a mandatory
* argument, you should check if your option has any values following the
* below example. Note that this may happen for all options without default
* values.
*/
if (args["string-option-no-default"].empty()) {
log.info() << "No value are available for string-option-no-default";
/*
* An exception may be thrown her if the above option is mandatory and there
* is no way to continue without value
*/
}
/*
* Get and log one of the program arguments (or options)
*
* The string-option has a default empty string value, so that it can always be
* printed event as an empty string
*/
const string string_example{args["string-option"].as<string>()};
log.info() << "String option value: " << string_example;
log.info() << "The int-option value is " << args["int-option"].as<int>();
log.info() << "The threshold value is " << args["threshold"].as<double>();
// Some initialization
constexpr double input_variable = 3.4756;
constexpr int64_t source_id = 12345;
constexpr double ra = 45.637;
// Factory method example
ClassExample example_class_object = ClassExample::factoryMethod(source_id, ra);
/*
* All fundamental type variables can be copied forth and back without significant
* cost in (almost) all cases
*/
const double method_result = ClassExample::fundamentalTypeMethod(input_variable);
log.info() << "Some result: " << method_result;
constexpr double first = 1.0;
double division_result;
try {
log.info("#");
log.info("# Calling a method throwing an exception ");
log.info("#");
constexpr double second = 0.0;
division_result = ClassExample::divideNumbers(first, second);
//
} catch (const Elements::Exception& e) {
log.info("#");
log.info() << e.what();
log.info("#");
log.info("# In this silly example we continue with a fake fix ");
log.info("#");
division_result = ClassExample::divideNumbers(first, 0.000001);
}
log.info() << "Second result is: " << division_result;
/*
* Illustration on how best to use smart pointer (regular pointer should not
* be used anymore). The move() indicate that the ownership of the pointer is given to the
* method called. The vector_unique_ptr cannot be used in this method anymore after the
* call.
*/
const std::unique_ptr<vector<double>> vector_unique_ptr{new vector{1.0, 2.3, 4.5}};
ClassExample::passingUniquePointer(vector_unique_ptr);
/*
* Illustration on how best to pass any object. The passingObjectInGeneral() is taking
* a reference to this object.
*/
const auto object_example{vector{1.0, 2.3, 4.5}};
ClassExample::passingObjectInGeneral(object_example);
log.info() << "Function Example: " << Elements::Examples::functionExample(3);
log.info() << "This executable name: " << Elements::System::getThisExecutableInfo().name();
Elements::Examples::printProject();
log.info() << Elements::Project();
log.info() << "Project Name: " << Elements::Project::name();
log.info() << "Project Version: " << Elements::Project::versionString();
log.info() << "Module Name: " << Elements::Module::name();
log.info() << "Module Version: " << Elements::Module::versionString();
log.info("#");
log.info("Exiting mainMethod()");
return ExitCode::OK;
}
};
/**
* Implementation of a main using a base class macro
* This must be present in all Elements programs
*/
MAIN_FOR(ExtProgram)