LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
event_start.cc
Go to the documentation of this file.
2 
3 #include "boost/algorithm/string.hpp"
5 
6 #include <cassert>
7 #include <iostream>
8 #include <regex>
9 
10 namespace {
11  auto
12  group(std::string const& spec)
13  {
14  return "(" + spec + ")";
15  }
16 
17  std::string const number{R"(\s*\d+\s*)"};
18  std::regex const re_event_id{group(number) + ":" + group(number) + ":" +
19  group(number)};
20  std::string const context{"An error was encountered while processing the "
21  "-e|--estart program option.\n"};
22 
23  template <art::Level L>
24  auto
25  safe_conversion(std::string str_num)
26  {
27  boost::trim(str_num);
28  auto const num = std::stoull(str_num);
29 
30  if (num > art::IDNumber<L>::max_valid() ||
31  num < art::IDNumber<L>::first()) {
32  // No need to provide exception message since it will be
33  // included in the rethrown exception.
35  }
36  return static_cast<art::IDNumber_t<L>>(num);
37  }
38 
39  template <art::Level L>
40  auto
41  range()
42  {
43  std::stringstream oss;
44  oss << '[' << art::IDNumber<L>::first() << ", "
45  << art::IDNumber<L>::invalid() << ')';
46  return oss.str();
47  }
48 
49  [[noreturn]] void
50  throw_configuration_exception(std::string const& spec) noexcept(false)
51  {
53  << "The specification '" << spec << "' is not a valid EventID.\n"
54  << "Please specify a value of the form '<run>:<subrun>:<event>' where:\n"
55  << " <run> is in the range " << range<art::Level::Run>() << '\n'
56  << " <subrun> is in the range " << range<art::Level::SubRun>() << '\n'
57  << " <event> is in the range " << range<art::Level::Event>() << '\n';
58  }
59 
60  template <art::Level L>
61  auto
62  convert_or_throw(std::string const& field,
63  std::string const& event_spec) noexcept(false)
64  try {
65  return safe_conversion<L>(field);
66  }
67  catch (...) {
68  throw_configuration_exception(event_spec);
69  }
70 }
71 
72 std::tuple<art::RunNumber_t, art::SubRunNumber_t, art::EventNumber_t>
73 art::detail::event_start(std::string const& event_spec)
74 {
75  std::smatch parts;
76  auto const success = std::regex_match(event_spec, parts, re_event_id);
77  if (!success) {
78  throw_configuration_exception(event_spec);
79  }
80 
81  assert(parts.size() == 4ull);
82  // A successful match will populate 'parts' with 5 elements.
83  // Consider the following valid specifications:
84  //
85  // +-------------+---------+
86  // | User spec. | '1:0:3' |
87  // +-------------+---------+
88  // | parts[0] == | '1:0:3' |
89  // | parts[1] == | '1' |
90  // | parts[2] == | '0' |
91  // | parts[3] == | '3' |
92  // +-------------+---------+
93 
94  auto const run = convert_or_throw<Level::Run>(parts[1], event_spec);
95  auto const subrun = convert_or_throw<Level::SubRun>(parts[2], event_spec);
96  auto const event = convert_or_throw<Level::Event>(parts[3], event_spec);
97 
98  return std::make_tuple(run, subrun, event);
99 }
std::tuple< RunNumber_t, SubRunNumber_t, EventNumber_t > event_start(std::string const &str_num)
Definition: event_start.cc:73
typename IDNumber< L >::type IDNumber_t
Definition: IDNumber.h:109
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
Event finding and building.