Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Options.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file Options.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2020 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
10 
11 #include <algorithm>
12 #include <iostream>
13 #include <sstream>
14 #include <stdexcept>
15 #include <string>
16 #include <utility>
17 
18 namespace {
19 constexpr char s_separator = ':';
20 }
21 
22 // interval
23 
25  std::istream& is, ActsExamples::Options::Interval& interval) {
26  std::string buf;
27  is >> buf;
28 
29  // default to an unbounded interval
30  interval.lower.reset();
31  interval.upper.reset();
32 
33  // find the limit separator
34  auto pos = buf.find_first_of(s_separator);
35  // no separator -> invalid input -> unbounded interval
36  if (pos == std::string::npos) {
37  return is;
38  }
39 
40  // if it exists, parse limit before separator
41  if (0 < pos) {
42  auto lowerStr = buf.substr(0, pos);
43  interval.lower = std::stod(lowerStr);
44  }
45  // if it exists, parse limit after separator
46  if ((pos + 1) < buf.size()) {
47  auto upperStr = buf.substr(pos + 1);
48  interval.upper = std::stod(upperStr);
49  }
50 
51  return is;
52 }
53 
55  std::ostream& os, const ActsExamples::Options::Interval& interval) {
56  if (not interval.lower.has_value() and not interval.upper.has_value()) {
57  os << "unbounded";
58  } else {
59  if (interval.lower.has_value()) {
60  os << interval.lower.value();
61  }
62  os << s_separator;
63  if (interval.upper.has_value()) {
64  os << interval.upper.value();
65  }
66  }
67  return os;
68 }
69 
70 // helper functions to parse and print multiple values
71 
72 namespace {
73 
74 template <typename value_t, typename converter_t>
75 void parseVariable(std::istream& is, std::vector<value_t>& values,
76  converter_t&& convert) {
77  values.clear();
78 
79  std::string buf;
80  is >> buf;
81  std::string bufValue;
82  std::string::size_type pos = 0;
83  std::string::size_type end = std::string::npos;
84  do {
85  end = buf.find_first_of(s_separator, pos);
86  if (end == std::string::npos) {
87  // last element; take the rest of the buffer
88  bufValue = buf.substr(pos);
89  } else {
90  bufValue = buf.substr(pos, end - pos);
91  pos = end + 1u;
92  }
93  values.push_back(convert(bufValue));
94  } while (end != std::string::npos);
95 }
96 
97 template <typename value_t, typename converter_t>
98 void parseFixed(std::istream& is, size_t size, value_t* values,
99  converter_t&& convert) {
100  // reserve space for the expected number of values
101  std::vector<value_t> tmp(size, 0);
102  parseVariable(is, tmp, std::forward<converter_t>(convert));
103  if (tmp.size() < size) {
104  throw std::invalid_argument(
105  "Not enough values for fixed-size user option, expected " +
106  std::to_string(size) + " received " + std::to_string(tmp.size()));
107  }
108  if (size < tmp.size()) {
109  throw std::invalid_argument(
110  "Too many values for fixed-size user option, expected " +
111  std::to_string(size) + " received " + std::to_string(tmp.size()));
112  }
113  std::copy(tmp.begin(), tmp.end(), values);
114 }
115 
116 template <typename value_t>
117 void print(std::ostream& os, size_t size, const value_t* values) {
118  for (size_t i = 0; i < size; ++i) {
119  if (0u < i) {
120  os << s_separator;
121  }
122  os << values[i];
123  }
124 }
125 
126 } // namespace
127 
128 // fixed and variable number of generic values
129 
131  size_t size,
132  double* values) {
133  parseFixed(is, size, values,
134  [](const std::string& s) { return std::stod(s); });
135 }
136 
138  std::istream& is, std::vector<double>& values) {
139  parseVariable(is, values, [](const std::string& s) { return std::stod(s); });
140 }
141 
142 void ActsExamples::Options::detail::printDoubles(std::ostream& os, size_t size,
143  const double* values) {
144  print(os, size, values);
145 }
146 
147 // fixed and variable number of integers
148 
150  size_t size,
151  int* values) {
152  parseFixed(is, size, values,
153  [](const std::string& s) { return std::stoi(s); });
154 }
155 
157  std::istream& is, std::vector<int>& values) {
158  parseVariable(is, values, [](const std::string& s) { return std::stoi(s); });
159 }
160 
161 void ActsExamples::Options::detail::printIntegers(std::ostream& os, size_t size,
162  const int* values) {
163  print(os, size, values);
164 }