midas-edge 0.1.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,88 +0,0 @@
1
- #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
2
- #define MAX(X, Y) (((X) > (Y)) ? (X) : (Y))
3
-
4
- #include <iostream>
5
- #include <math.h>
6
- #include <algorithm>
7
- #include <vector>
8
- #include "anom.hpp"
9
- #include "edgehash.hpp"
10
- #include "nodehash.hpp"
11
-
12
- vector<double>* midas(vector<int>& src, vector<int>& dst, vector<int>& times, int num_rows, int num_buckets)
13
- {
14
- int m = *max_element(src.begin(), src.end());
15
- Edgehash cur_count(num_rows, num_buckets, m);
16
- Edgehash total_count(num_rows, num_buckets, m);
17
- vector<double>* anom_score = new vector<double>(src.size());
18
- int cur_t = 1, size = src.size(), cur_src, cur_dst;
19
- double cur_mean, sqerr, cur_score;
20
- for (int i = 0; i < size; i++) {
21
-
22
- if (i == 0 || times[i] > cur_t) {
23
- cur_count.clear();
24
- cur_t = times[i];
25
- }
26
-
27
- cur_src = src[i];
28
- cur_dst = dst[i];
29
- cur_count.insert(cur_src, cur_dst, 1);
30
- total_count.insert(cur_src, cur_dst, 1);
31
- cur_mean = total_count.get_count(cur_src, cur_dst) / cur_t;
32
- sqerr = pow(cur_count.get_count(cur_src, cur_dst) - cur_mean, 2);
33
- if (cur_t == 1) cur_score = 0;
34
- else cur_score = sqerr / cur_mean + sqerr / (cur_mean * (cur_t - 1));
35
- (*anom_score)[i] = cur_score;
36
- }
37
-
38
- return anom_score;
39
- }
40
-
41
- double counts_to_anom(double tot, double cur, int cur_t)
42
- {
43
- double cur_mean = tot / cur_t;
44
- double sqerr = pow(MAX(0, cur - cur_mean), 2);
45
- return sqerr / cur_mean + sqerr / (cur_mean * MAX(1, cur_t - 1));
46
- }
47
-
48
- vector<double>* midasR(vector<int>& src, vector<int>& dst, vector<int>& times, int num_rows, int num_buckets, double factor)
49
- {
50
- int m = *max_element(src.begin(), src.end());
51
- Edgehash cur_count(num_rows, num_buckets, m);
52
- Edgehash total_count(num_rows, num_buckets, m);
53
- Nodehash src_score(num_rows, num_buckets);
54
- Nodehash dst_score(num_rows, num_buckets);
55
- Nodehash src_total(num_rows, num_buckets);
56
- Nodehash dst_total(num_rows, num_buckets);
57
- vector<double>* anom_score = new vector<double>(src.size());
58
- int cur_t = 1, size = src.size(), cur_src, cur_dst;
59
- double cur_score, cur_score_src, cur_score_dst, combined_score;
60
-
61
- for (int i = 0; i < size; i++) {
62
-
63
- if (i == 0 || times[i] > cur_t) {
64
- cur_count.lower(factor);
65
- src_score.lower(factor);
66
- dst_score.lower(factor);
67
- cur_t = times[i];
68
- }
69
-
70
- cur_src = src[i];
71
- cur_dst = dst[i];
72
- cur_count.insert(cur_src, cur_dst, 1);
73
- total_count.insert(cur_src, cur_dst, 1);
74
- src_score.insert(cur_src, 1);
75
- dst_score.insert(cur_dst, 1);
76
- src_total.insert(cur_src, 1);
77
- dst_total.insert(cur_dst, 1);
78
- cur_score = counts_to_anom(total_count.get_count(cur_src, cur_dst), cur_count.get_count(cur_src, cur_dst), cur_t);
79
- cur_score_src = counts_to_anom(src_total.get_count(cur_src), src_score.get_count(cur_src), cur_t);
80
- cur_score_dst = counts_to_anom(dst_total.get_count(cur_dst), dst_score.get_count(cur_dst), cur_t);
81
- //combined_score = MAX(cur_score_src, cur_score_dst) + cur_score;
82
- //combined_score = cur_score_src + cur_score_dst + cur_score;
83
- combined_score = MAX(MAX(cur_score_src, cur_score_dst), cur_score);
84
- (*anom_score)[i] = log(1 + combined_score);
85
- }
86
-
87
- return anom_score;
88
- }
@@ -1,10 +0,0 @@
1
- #ifndef anom_hpp
2
- #define anom_hpp
3
-
4
- #include <vector>
5
- using namespace std;
6
-
7
- vector<double>* midas(vector<int>& src, vector<int>& dst, vector<int>& times, int num_rows, int num_buckets);
8
- vector<double>* midasR(vector<int>& src, vector<int>& dst, vector<int>& times, int num_rows, int num_buckets, double factor);
9
-
10
- #endif /* anom_hpp */
@@ -1,539 +0,0 @@
1
- /*
2
- __ _ _ __ __ _ _ __ __ _ _ __ ___ ___
3
- / _` | '__/ _` | '_ \ / _` | '__/ __|/ _ \ Argument Parser for Modern C++
4
- | (_| | | | (_| | |_) | (_| | | \__ \ __/ http://github.com/p-ranav/argparse
5
- \__,_|_| \__, | .__/ \__,_|_| |___/\___|
6
- |___/|_|
7
-
8
- Licensed under the MIT License <http://opensource.org/licenses/MIT>.
9
- SPDX-License-Identifier: MIT
10
- Copyright (c) 2019 Pranav Srinivas Kumar <pranav.srinivas.kumar@gmail.com>.
11
-
12
- Permission is hereby granted, free of charge, to any person obtaining a copy
13
- of this software and associated documentation files (the "Software"), to deal
14
- in the Software without restriction, including without limitation the rights
15
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
- copies of the Software, and to permit persons to whom the Software is
17
- furnished to do so, subject to the following conditions:
18
-
19
- The above copyright notice and this permission notice shall be included in all
20
- copies or substantial portions of the Software.
21
-
22
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
- SOFTWARE.
29
- */
30
- #pragma once
31
- #include <algorithm>
32
- #include <any>
33
- #include <functional>
34
- #include <iomanip>
35
- #include <iostream>
36
- #include <iterator>
37
- #include <list>
38
- #include <map>
39
- #include <memory>
40
- #include <numeric>
41
- #include <sstream>
42
- #include <stdexcept>
43
- #include <string>
44
- #include <type_traits>
45
- #include <vector>
46
-
47
- namespace argparse {
48
-
49
- namespace details { // namespace for helper methods
50
-
51
- template <typename... Ts> struct is_container_helper {};
52
-
53
- template <typename T, typename _ = void>
54
- struct is_container : std::false_type {};
55
-
56
- template <> struct is_container<std::string> : std::false_type {};
57
-
58
- template <typename T>
59
- struct is_container<
60
- T,
61
- std::conditional_t<false,
62
- is_container_helper<typename T::value_type,
63
- decltype(std::declval<T>().begin()),
64
- decltype(std::declval<T>().end()),
65
- decltype(std::declval<T>().size())>,
66
- void>> : public std::true_type {};
67
-
68
- template <typename T>
69
- static constexpr bool is_container_v = is_container<T>::value;
70
-
71
- template <typename T>
72
- using enable_if_container = std::enable_if_t<is_container_v<T>, T>;
73
-
74
- template <typename T>
75
- using enable_if_not_container = std::enable_if_t<!is_container_v<T>, T>;
76
- } // namespace
77
-
78
- class Argument {
79
- friend class ArgumentParser;
80
-
81
- public:
82
- Argument() = default;
83
-
84
- template <typename... Args>
85
- explicit Argument(Args... args)
86
- : mNames({std::move(args)...}), mIsOptional((is_optional(args) || ...)) {
87
- std::sort(
88
- mNames.begin(), mNames.end(), [](const auto &lhs, const auto &rhs) {
89
- return lhs.size() == rhs.size() ? lhs < rhs : lhs.size() < rhs.size();
90
- });
91
- }
92
-
93
- Argument &help(std::string aHelp) {
94
- mHelp = std::move(aHelp);
95
- return *this;
96
- }
97
-
98
- Argument &default_value(std::any aDefaultValue) {
99
- mDefaultValue = std::move(aDefaultValue);
100
- return *this;
101
- }
102
-
103
- Argument &required() {
104
- mIsRequired = true;
105
- return *this;
106
- }
107
-
108
- Argument &implicit_value(std::any aImplicitValue) {
109
- mImplicitValue = std::move(aImplicitValue);
110
- mNumArgs = 0;
111
- return *this;
112
- }
113
-
114
- Argument &action(std::function<std::any(const std::string &)> aAction) {
115
- mAction = std::move(aAction);
116
- return *this;
117
- }
118
-
119
- Argument &nargs(size_t aNumArgs) {
120
- mNumArgs = aNumArgs;
121
- return *this;
122
- }
123
-
124
- template <typename Iterator>
125
- Iterator consume(Iterator start, Iterator end, std::string usedName = {}) {
126
- if (mIsUsed) {
127
- throw std::runtime_error("Duplicate argument");
128
- }
129
- mIsUsed = true;
130
- mUsedName = std::move(usedName);
131
- if (mNumArgs == 0) {
132
- mValues.emplace_back(mImplicitValue);
133
- return start;
134
- } else if (mNumArgs <= static_cast<size_t>(std::distance(start, end))) {
135
- end = std::next(start, mNumArgs);
136
- if (std::any_of(start, end, Argument::is_optional)) {
137
- throw std::runtime_error("optional argument in parameter sequence");
138
- }
139
- std::transform(start, end, std::back_inserter(mValues), mAction);
140
- return end;
141
- } else if (mDefaultValue.has_value()) {
142
- return start;
143
- } else {
144
- throw std::runtime_error("Too few arguments");
145
- }
146
- }
147
-
148
- /*
149
- * @throws std::runtime_error if argument values are not valid
150
- */
151
- void validate() const {
152
- if (mIsOptional) {
153
- if (mIsUsed && mValues.size() != mNumArgs && !mDefaultValue.has_value()) {
154
- std::stringstream stream;
155
- stream << mUsedName << ": expected " << mNumArgs
156
- << " argument(s). " << mValues.size() << " provided.";
157
- throw std::runtime_error(stream.str());
158
- } else {
159
- // TODO: check if an implicit value was programmed for this argument
160
- if (!mIsUsed && !mDefaultValue.has_value() && mIsRequired) {
161
- std::stringstream stream;
162
- stream << mNames[0] << ": required.";
163
- throw std::runtime_error(stream.str());
164
- }
165
- if (mIsUsed && mIsRequired && mValues.size() == 0) {
166
- std::stringstream stream;
167
- stream << mUsedName << ": no value provided.";
168
- throw std::runtime_error(stream.str());
169
- }
170
- }
171
- } else {
172
- if (mValues.size() != mNumArgs && !mDefaultValue.has_value()) {
173
- std::stringstream stream;
174
- stream << mUsedName << ": expected " << mNumArgs
175
- << " argument(s). " << mValues.size() << " provided.";
176
- throw std::runtime_error(stream.str());
177
- }
178
- }
179
- }
180
-
181
- size_t get_arguments_length() const {
182
- return std::accumulate(std::begin(mNames), std::end(mNames), size_t(0),
183
- [](const auto &sum, const auto &s) {
184
- return sum + s.size() +
185
- 1; // +1 for space between names
186
- });
187
- }
188
-
189
- friend std::ostream &operator<<(std::ostream &stream,
190
- const Argument &argument) {
191
- std::stringstream nameStream;
192
- std::copy(std::begin(argument.mNames), std::end(argument.mNames),
193
- std::ostream_iterator<std::string>(nameStream, " "));
194
- stream << nameStream.str() << "\t" << argument.mHelp;
195
- if (argument.mIsRequired)
196
- stream << "[Required]";
197
- stream << "\n";
198
- return stream;
199
- }
200
-
201
- template <typename T> bool operator!=(const T &aRhs) const {
202
- return !(*this == aRhs);
203
- }
204
-
205
- /*
206
- * Entry point for template non-container types
207
- * @throws std::logic_error in case of incompatible types
208
- */
209
- template <typename T>
210
- std::enable_if_t<!details::is_container_v<T>, bool> operator==(const T &aRhs) const {
211
- return get<T>() == aRhs;
212
- }
213
-
214
- /*
215
- * Template specialization for containers
216
- * @throws std::logic_error in case of incompatible types
217
- */
218
- template <typename T>
219
- std::enable_if_t<details::is_container_v<T>, bool> operator==(const T &aRhs) const {
220
- using ValueType = typename T::value_type;
221
- auto tLhs = get<T>();
222
- if (tLhs.size() != aRhs.size())
223
- return false;
224
- else {
225
- return std::equal(std::begin(tLhs), std::end(tLhs), std::begin(aRhs),
226
- [](const auto &lhs, const auto &rhs) {
227
- return std::any_cast<const ValueType &>(lhs) == rhs;
228
- });
229
- }
230
- }
231
-
232
- private:
233
- static bool is_integer(const std::string &aValue) {
234
- if (aValue.empty() ||
235
- ((!isdigit(aValue[0])) && (aValue[0] != '-') && (aValue[0] != '+')))
236
- return false;
237
- char *tPtr;
238
- strtol(aValue.c_str(), &tPtr, 10);
239
- return (*tPtr == 0);
240
- }
241
-
242
- static bool is_float(const std::string &aValue) {
243
- std::istringstream tStream(aValue);
244
- float tFloat;
245
- // noskipws considers leading whitespace invalid
246
- tStream >> std::noskipws >> tFloat;
247
- // Check the entire string was consumed
248
- // and if either failbit or badbit is set
249
- return tStream.eof() && !tStream.fail();
250
- }
251
-
252
- // If an argument starts with "-" or "--", then it's optional
253
- static bool is_optional(const std::string &aName) {
254
- return (!aName.empty() && aName[0] == '-' && !is_integer(aName) &&
255
- !is_float(aName));
256
- }
257
-
258
- static bool is_positional(const std::string &aName) {
259
- return !is_optional(aName);
260
- }
261
-
262
- /*
263
- * Getter for template non-container types
264
- * @throws std::logic_error in case of incompatible types
265
- */
266
- template <typename T> details::enable_if_not_container<T> get() const {
267
- if (!mValues.empty()) {
268
- return std::any_cast<T>(mValues.front());
269
- }
270
- if (mDefaultValue.has_value()) {
271
- return std::any_cast<T>(mDefaultValue);
272
- }
273
- throw std::logic_error("No value provided");
274
- }
275
-
276
- /*
277
- * Getter for container types
278
- * @throws std::logic_error in case of incompatible types
279
- */
280
- template <typename CONTAINER> details::enable_if_container<CONTAINER> get() const {
281
- using ValueType = typename CONTAINER::value_type;
282
- CONTAINER tResult;
283
- if (!mValues.empty()) {
284
- std::transform(
285
- std::begin(mValues), std::end(mValues), std::back_inserter(tResult),
286
- [](const auto &value) { return std::any_cast<ValueType>(value); });
287
- return tResult;
288
- }
289
- if (mDefaultValue.has_value()) {
290
- const auto &tDefaultValues =
291
- std::any_cast<const CONTAINER &>(mDefaultValue);
292
- std::transform(std::begin(tDefaultValues), std::end(tDefaultValues),
293
- std::back_inserter(tResult), [](const auto &value) {
294
- return std::any_cast<ValueType>(value);
295
- });
296
- return tResult;
297
- }
298
- throw std::logic_error("No value provided");
299
- }
300
-
301
- std::vector<std::string> mNames;
302
- std::string mUsedName;
303
- std::string mHelp;
304
- std::any mDefaultValue;
305
- std::any mImplicitValue;
306
- std::function<std::any(const std::string &)> mAction =
307
- [](const std::string &aValue) { return aValue; };
308
- std::vector<std::any> mValues;
309
- std::vector<std::string> mRawValues;
310
- size_t mNumArgs = 1;
311
- bool mIsOptional = false;
312
- bool mIsRequired = false;
313
- bool mIsUsed = false; // relevant for optional arguments. True if used by user
314
-
315
- public:
316
- static constexpr auto mHelpOption = "-h";
317
- static constexpr auto mHelpOptionLong = "--help";
318
- };
319
-
320
- class ArgumentParser {
321
- public:
322
- explicit ArgumentParser(std::string aProgramName = {})
323
- : mProgramName(std::move(aProgramName)) {
324
- add_argument(Argument::mHelpOption, Argument::mHelpOptionLong)
325
- .help("show this help message and exit")
326
- .nargs(0)
327
- .default_value(false)
328
- .implicit_value(true);
329
- }
330
-
331
- // Parameter packing
332
- // Call add_argument with variadic number of string arguments
333
- template <typename... Targs> Argument &add_argument(Targs... Fargs) {
334
- std::shared_ptr<Argument> tArgument =
335
- std::make_shared<Argument>(std::move(Fargs)...);
336
-
337
- if (tArgument->mIsOptional)
338
- mOptionalArguments.emplace_back(tArgument);
339
- else
340
- mPositionalArguments.emplace_back(tArgument);
341
-
342
- for (const auto &mName : tArgument->mNames) {
343
- mArgumentMap.insert_or_assign(mName, tArgument);
344
- }
345
- return *tArgument;
346
- }
347
-
348
- // Parameter packed add_parents method
349
- // Accepts a variadic number of ArgumentParser objects
350
- template <typename... Targs> void add_parents(Targs... Fargs) {
351
- const auto tNewParentParsers = {Fargs...};
352
- for (const auto &tParentParser : tNewParentParsers) {
353
- const auto &tPositionalArguments = tParentParser.mPositionalArguments;
354
- std::copy(std::begin(tPositionalArguments),
355
- std::end(tPositionalArguments),
356
- std::back_inserter(mPositionalArguments));
357
-
358
- const auto &tOptionalArguments = tParentParser.mOptionalArguments;
359
- std::copy(std::begin(tOptionalArguments), std::end(tOptionalArguments),
360
- std::back_inserter(mOptionalArguments));
361
-
362
- const auto &tArgumentMap = tParentParser.mArgumentMap;
363
- for (const auto &[tKey, tValue] : tArgumentMap) {
364
- mArgumentMap.insert_or_assign(tKey, tValue);
365
- }
366
- }
367
- std::move(std::begin(tNewParentParsers), std::end(tNewParentParsers),
368
- std::back_inserter(mParentParsers));
369
- }
370
-
371
- /* Call parse_args_internal - which does all the work
372
- * Then, validate the parsed arguments
373
- * This variant is used mainly for testing
374
- * @throws std::runtime_error in case of any invalid argument
375
- */
376
- void parse_args(const std::vector<std::string> &aArguments) {
377
- parse_args_internal(aArguments);
378
- parse_args_validate();
379
- }
380
-
381
- /* Main entry point for parsing command-line arguments using this
382
- * ArgumentParser
383
- * @throws std::runtime_error in case of any invalid argument
384
- */
385
- void parse_args(int argc, const char *const argv[]) {
386
- std::vector<std::string> arguments;
387
- std::copy(argv, argv + argc, std::back_inserter(arguments));
388
- parse_args(arguments);
389
- }
390
-
391
- /* Getter enabled for all template types other than std::vector and std::list
392
- * @throws std::logic_error in case of an invalid argument name
393
- * @throws std::logic_error in case of incompatible types
394
- */
395
- template <typename T = std::string> T get(const std::string &aArgumentName) {
396
- auto tIterator = mArgumentMap.find(aArgumentName);
397
- if (tIterator != mArgumentMap.end()) {
398
- return tIterator->second->get<T>();
399
- }
400
- throw std::logic_error("No such argument");
401
- }
402
-
403
- /* Indexing operator. Return a reference to an Argument object
404
- * Used in conjuction with Argument.operator== e.g., parser["foo"] == true
405
- * @throws std::logic_error in case of an invalid argument name
406
- */
407
- Argument &operator[](const std::string &aArgumentName) {
408
- auto tIterator = mArgumentMap.find(aArgumentName);
409
- if (tIterator != mArgumentMap.end()) {
410
- return *(tIterator->second);
411
- }
412
- throw std::logic_error("No such argument");
413
- }
414
-
415
- // Printing the one and only help message
416
- // I've stuck with a simple message format, nothing fancy.
417
- // TODO: support user-defined help and usage messages for the ArgumentParser
418
- std::string print_help() {
419
- std::stringstream stream;
420
- stream << std::left;
421
- stream << "Usage: ./" << mProgramName << " [options] ";
422
- size_t tLongestArgumentLength = get_length_of_longest_argument();
423
-
424
- for (const auto &argument : mPositionalArguments) {
425
- stream << argument->mNames.front() << " ";
426
- }
427
- stream << "\n\n";
428
-
429
- if (!mPositionalArguments.empty())
430
- stream << "Positional arguments:\n";
431
-
432
- for (const auto &mPositionalArgument : mPositionalArguments) {
433
- stream.width(tLongestArgumentLength);
434
- stream << *mPositionalArgument;
435
- }
436
-
437
- if (!mOptionalArguments.empty())
438
- stream << (mPositionalArguments.empty() ? "" : "\n")
439
- << "Options:\n";
440
-
441
- for (const auto &mOptionalArgument : mOptionalArguments) {
442
- stream.width(tLongestArgumentLength);
443
- stream << *mOptionalArgument;
444
- }
445
-
446
- std::cout << stream.str();
447
- return stream.str();
448
- }
449
-
450
- private:
451
- /*
452
- * @throws std::runtime_error in case of any invalid argument
453
- */
454
- void parse_args_internal(const std::vector<std::string> &aArguments) {
455
- if (mProgramName.empty() && !aArguments.empty()) {
456
- mProgramName = aArguments.front();
457
- }
458
- auto end = std::end(aArguments);
459
- auto positionalArgumentIt = std::begin(mPositionalArguments);
460
- for (auto it = std::next(std::begin(aArguments)); it != end;) {
461
- const auto &tCurrentArgument = *it;
462
- if (tCurrentArgument == Argument::mHelpOption ||
463
- tCurrentArgument == Argument::mHelpOptionLong) {
464
- throw std::runtime_error("help called");
465
- }
466
- if (Argument::is_positional(tCurrentArgument)) {
467
- if (positionalArgumentIt == std::end(mPositionalArguments)) {
468
- throw std::runtime_error(
469
- "Maximum number of positional arguments exceeded");
470
- }
471
- auto tArgument = *(positionalArgumentIt++);
472
- it = tArgument->consume(it, end);
473
- } else if (auto tIterator = mArgumentMap.find(tCurrentArgument);
474
- tIterator != mArgumentMap.end()) {
475
- auto tArgument = tIterator->second;
476
- it = tArgument->consume(std::next(it), end, tCurrentArgument);
477
- } else if (const auto &tCompoundArgument = tCurrentArgument;
478
- tCompoundArgument.size() > 1 && tCompoundArgument[0] == '-' &&
479
- tCompoundArgument[1] != '-') {
480
- ++it;
481
- for (size_t j = 1; j < tCompoundArgument.size(); j++) {
482
- auto tCurrentArgument = std::string{'-', tCompoundArgument[j]};
483
- if (auto tIterator = mArgumentMap.find(tCurrentArgument);
484
- tIterator != mArgumentMap.end()) {
485
- auto tArgument = tIterator->second;
486
- it = tArgument->consume(it, end, tCurrentArgument);
487
- } else {
488
- throw std::runtime_error("Unknown argument");
489
- }
490
- }
491
- } else {
492
- throw std::runtime_error("Unknown argument");
493
- }
494
- }
495
- }
496
-
497
- /*
498
- * @throws std::runtime_error in case of any invalid argument
499
- */
500
- void parse_args_validate() {
501
- // Check if all arguments are parsed
502
- std::for_each(std::begin(mArgumentMap), std::end(mArgumentMap),
503
- [](const auto &argPair) {
504
- const auto &tArgument = argPair.second;
505
- tArgument->validate();
506
- });
507
- }
508
-
509
- // Used by print_help.
510
- size_t get_length_of_longest_argument() {
511
- if (mArgumentMap.empty())
512
- return 0;
513
- std::vector<size_t> argumentLengths(mArgumentMap.size());
514
- std::transform(std::begin(mArgumentMap), std::end(mArgumentMap),
515
- std::begin(argumentLengths), [](const auto &argPair) {
516
- const auto &tArgument = argPair.second;
517
- return tArgument->get_arguments_length();
518
- });
519
- return *std::max_element(std::begin(argumentLengths),
520
- std::end(argumentLengths));
521
- }
522
-
523
- std::string mProgramName;
524
- std::vector<ArgumentParser> mParentParsers;
525
- std::vector<std::shared_ptr<Argument>> mPositionalArguments;
526
- std::vector<std::shared_ptr<Argument>> mOptionalArguments;
527
- std::map<std::string, std::shared_ptr<Argument>> mArgumentMap;
528
- };
529
-
530
- #define PARSE_ARGS(parser, argc, argv) \
531
- try { \
532
- parser.parse_args(argc, argv); \
533
- } catch (const std::runtime_error &err) { \
534
- std::cout << err.what() << std::endl; \
535
- parser.print_help(); \
536
- exit(0); \
537
- }
538
-
539
- } // namespace argparse