File indexing completed on 2026-09-19 08:29:11
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "ActsExamples/Utilities/Options.hpp"
0010
0011 #include <algorithm>
0012 #include <iostream>
0013 #include <stdexcept>
0014 #include <string>
0015 #include <utility>
0016
0017 namespace ActsExamples {
0018
0019 namespace {
0020 constexpr char s_separator = ':';
0021 }
0022
0023
0024
0025 std::istream& Options::operator>>(std::istream& is,
0026 Options::Interval& interval) {
0027 std::string buf;
0028 is >> buf;
0029
0030
0031 interval.lower.reset();
0032 interval.upper.reset();
0033
0034
0035 auto pos = buf.find_first_of(s_separator);
0036
0037 if (pos == std::string::npos) {
0038 return is;
0039 }
0040
0041
0042 if (0 < pos) {
0043 auto lowerStr = buf.substr(0, pos);
0044 interval.lower = std::stod(lowerStr);
0045 }
0046
0047 if ((pos + 1) < buf.size()) {
0048 auto upperStr = buf.substr(pos + 1);
0049 interval.upper = std::stod(upperStr);
0050 }
0051
0052 return is;
0053 }
0054
0055 std::ostream& Options::operator<<(std::ostream& os,
0056 const Options::Interval& interval) {
0057 if (!interval.lower.has_value() && !interval.upper.has_value()) {
0058 os << "unbounded";
0059 } else {
0060 if (interval.lower.has_value()) {
0061 os << interval.lower.value();
0062 }
0063 os << s_separator;
0064 if (interval.upper.has_value()) {
0065 os << interval.upper.value();
0066 }
0067 }
0068 return os;
0069 }
0070
0071
0072
0073 namespace {
0074
0075 template <typename value_t, typename converter_t>
0076 void parseVariable(std::istream& is, std::vector<value_t>& values,
0077 converter_t&& convert) {
0078 values.clear();
0079
0080 std::string buf;
0081 is >> buf;
0082 std::string bufValue;
0083 std::string::size_type pos = 0;
0084 std::string::size_type end = std::string::npos;
0085 do {
0086 end = buf.find_first_of(s_separator, pos);
0087 if (end == std::string::npos) {
0088
0089 bufValue = buf.substr(pos);
0090 } else {
0091 bufValue = buf.substr(pos, end - pos);
0092 pos = end + 1u;
0093 }
0094 values.push_back(convert(bufValue));
0095 } while (end != std::string::npos);
0096 }
0097
0098 template <typename value_t, typename converter_t>
0099 void parseFixed(std::istream& is, std::size_t size, value_t* values,
0100 converter_t&& convert) {
0101
0102 std::vector<value_t> tmp(size, 0);
0103 parseVariable(is, tmp, std::forward<converter_t>(convert));
0104 if (tmp.size() < size) {
0105 throw std::invalid_argument(
0106 "Not enough values for fixed-size user option, expected " +
0107 std::to_string(size) + " received " + std::to_string(tmp.size()));
0108 }
0109 if (size < tmp.size()) {
0110 throw std::invalid_argument(
0111 "Too many values for fixed-size user option, expected " +
0112 std::to_string(size) + " received " + std::to_string(tmp.size()));
0113 }
0114 std::copy(tmp.begin(), tmp.end(), values);
0115 }
0116
0117 template <typename value_t>
0118 void print(std::ostream& os, std::size_t size, const value_t* values) {
0119 for (std::size_t i = 0; i < size; ++i) {
0120 if (0u < i) {
0121 os << s_separator;
0122 }
0123 os << values[i];
0124 }
0125 }
0126
0127 }
0128
0129
0130
0131 void Options::detail::parseDoublesFixed(std::istream& is, std::size_t size,
0132 double* values) {
0133 parseFixed(is, size, values,
0134 [](const std::string& s) { return std::stod(s); });
0135 }
0136
0137 void Options::detail::parseDoublesVariable(std::istream& is,
0138 std::vector<double>& values) {
0139 parseVariable(is, values, [](const std::string& s) { return std::stod(s); });
0140 }
0141
0142 void Options::detail::printDoubles(std::ostream& os, std::size_t size,
0143 const double* values) {
0144 print(os, size, values);
0145 }
0146
0147
0148
0149 void Options::detail::parseIntegersFixed(std::istream& is, std::size_t size,
0150 int* values) {
0151 parseFixed(is, size, values,
0152 [](const std::string& s) { return std::stoi(s); });
0153 }
0154
0155 void Options::detail::parseIntegersVariable(std::istream& is,
0156 std::vector<int>& values) {
0157 parseVariable(is, values, [](const std::string& s) { return std::stoi(s); });
0158 }
0159
0160 void Options::detail::printIntegers(std::ostream& os, std::size_t size,
0161 const int* values) {
0162 print(os, size, values);
0163 }
0164
0165 }