Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-19 08:29:11

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
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 // interval
0024 
0025 std::istream& Options::operator>>(std::istream& is,
0026                                   Options::Interval& interval) {
0027   std::string buf;
0028   is >> buf;
0029 
0030   // default to an unbounded interval
0031   interval.lower.reset();
0032   interval.upper.reset();
0033 
0034   // find the limit separator
0035   auto pos = buf.find_first_of(s_separator);
0036   // no separator -> invalid input -> unbounded interval
0037   if (pos == std::string::npos) {
0038     return is;
0039   }
0040 
0041   // if it exists, parse limit before separator
0042   if (0 < pos) {
0043     auto lowerStr = buf.substr(0, pos);
0044     interval.lower = std::stod(lowerStr);
0045   }
0046   // if it exists, parse limit after separator
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 // helper functions to parse and print multiple values
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       // last element; take the rest of the buffer
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   // reserve space for the expected number of values
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 }  // namespace
0128 
0129 // fixed and variable number of generic values
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 // fixed and variable number of integers
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 }  // namespace ActsExamples