Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:11:49

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 <sstream>
0014 #include <stdexcept>
0015 #include <string>
0016 #include <utility>
0017 
0018 namespace {
0019 constexpr char s_separator = ':';
0020 }
0021 
0022 // interval
0023 
0024 std::istream& ActsExamples::Options::operator>>(
0025     std::istream& is, ActsExamples::Options::Interval& interval) {
0026   std::string buf;
0027   is >> buf;
0028 
0029   // default to an unbounded interval
0030   interval.lower.reset();
0031   interval.upper.reset();
0032 
0033   // find the limit separator
0034   auto pos = buf.find_first_of(s_separator);
0035   // no separator -> invalid input -> unbounded interval
0036   if (pos == std::string::npos) {
0037     return is;
0038   }
0039 
0040   // if it exists, parse limit before separator
0041   if (0 < pos) {
0042     auto lowerStr = buf.substr(0, pos);
0043     interval.lower = std::stod(lowerStr);
0044   }
0045   // if it exists, parse limit after separator
0046   if ((pos + 1) < buf.size()) {
0047     auto upperStr = buf.substr(pos + 1);
0048     interval.upper = std::stod(upperStr);
0049   }
0050 
0051   return is;
0052 }
0053 
0054 std::ostream& ActsExamples::Options::operator<<(
0055     std::ostream& os, const ActsExamples::Options::Interval& interval) {
0056   if (!interval.lower.has_value() && !interval.upper.has_value()) {
0057     os << "unbounded";
0058   } else {
0059     if (interval.lower.has_value()) {
0060       os << interval.lower.value();
0061     }
0062     os << s_separator;
0063     if (interval.upper.has_value()) {
0064       os << interval.upper.value();
0065     }
0066   }
0067   return os;
0068 }
0069 
0070 // helper functions to parse and print multiple values
0071 
0072 namespace {
0073 
0074 template <typename value_t, typename converter_t>
0075 void parseVariable(std::istream& is, std::vector<value_t>& values,
0076                    converter_t&& convert) {
0077   values.clear();
0078 
0079   std::string buf;
0080   is >> buf;
0081   std::string bufValue;
0082   std::string::size_type pos = 0;
0083   std::string::size_type end = std::string::npos;
0084   do {
0085     end = buf.find_first_of(s_separator, pos);
0086     if (end == std::string::npos) {
0087       // last element; take the rest of the buffer
0088       bufValue = buf.substr(pos);
0089     } else {
0090       bufValue = buf.substr(pos, end - pos);
0091       pos = end + 1u;
0092     }
0093     values.push_back(convert(bufValue));
0094   } while (end != std::string::npos);
0095 }
0096 
0097 template <typename value_t, typename converter_t>
0098 void parseFixed(std::istream& is, std::size_t size, value_t* values,
0099                 converter_t&& convert) {
0100   // reserve space for the expected number of values
0101   std::vector<value_t> tmp(size, 0);
0102   parseVariable(is, tmp, std::forward<converter_t>(convert));
0103   if (tmp.size() < size) {
0104     throw std::invalid_argument(
0105         "Not enough values for fixed-size user option, expected " +
0106         std::to_string(size) + " received " + std::to_string(tmp.size()));
0107   }
0108   if (size < tmp.size()) {
0109     throw std::invalid_argument(
0110         "Too many values for fixed-size user option, expected " +
0111         std::to_string(size) + " received " + std::to_string(tmp.size()));
0112   }
0113   std::copy(tmp.begin(), tmp.end(), values);
0114 }
0115 
0116 template <typename value_t>
0117 void print(std::ostream& os, std::size_t size, const value_t* values) {
0118   for (std::size_t i = 0; i < size; ++i) {
0119     if (0u < i) {
0120       os << s_separator;
0121     }
0122     os << values[i];
0123   }
0124 }
0125 
0126 }  // namespace
0127 
0128 // fixed and variable number of generic values
0129 
0130 void ActsExamples::Options::detail::parseDoublesFixed(std::istream& is,
0131                                                       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 ActsExamples::Options::detail::parseDoublesVariable(
0138     std::istream& is, std::vector<double>& values) {
0139   parseVariable(is, values, [](const std::string& s) { return std::stod(s); });
0140 }
0141 
0142 void ActsExamples::Options::detail::printDoubles(std::ostream& os,
0143                                                  std::size_t size,
0144                                                  const double* values) {
0145   print(os, size, values);
0146 }
0147 
0148 // fixed and variable number of integers
0149 
0150 void ActsExamples::Options::detail::parseIntegersFixed(std::istream& is,
0151                                                        std::size_t size,
0152                                                        int* values) {
0153   parseFixed(is, size, values,
0154              [](const std::string& s) { return std::stoi(s); });
0155 }
0156 
0157 void ActsExamples::Options::detail::parseIntegersVariable(
0158     std::istream& is, std::vector<int>& values) {
0159   parseVariable(is, values, [](const std::string& s) { return std::stoi(s); });
0160 }
0161 
0162 void ActsExamples::Options::detail::printIntegers(std::ostream& os,
0163                                                   std::size_t size,
0164                                                   const int* values) {
0165   print(os, size, values);
0166 }