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 
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) try {
64  return safe_conversion<L>(field);
65  }
66  catch (...) {
67  throw_configuration_exception(event_spec);
68  }
69 }
70 
71 std::tuple<art::RunNumber_t, art::SubRunNumber_t, art::EventNumber_t>
73 {
74  std::smatch parts;
75  auto const success = std::regex_match(event_spec, parts, re_event_id);
76  if (!success) {
77  throw_configuration_exception(event_spec);
78  }
79 
80  assert(parts.size() == 4ull);
81  // A successful match will populate 'parts' with 5 elements.
82  // Consider the following valid specifications:
83  //
84  // +-------------+---------+
85  // | User spec. | '1:0:3' |
86  // +-------------+---------+
87  // | parts[0] == | '1:0:3' |
88  // | parts[1] == | '1' |
89  // | parts[2] == | '0' |
90  // | parts[3] == | '3' |
91  // +-------------+---------+
92 
93  auto const run = convert_or_throw<Level::Run>(parts[1], event_spec);
94  auto const subrun = convert_or_throw<Level::SubRun>(parts[2], event_spec);
95  auto const event = convert_or_throw<Level::Event>(parts[3], event_spec);
96 
97  return std::make_tuple(run, subrun, event);
98 }
static std::string trim(const std::string &str, const std::string &whitespace=" \t")
Definition: doxyindexer.cpp:47
std::string string
Definition: nybbler.cc:12
std::tuple< RunNumber_t, SubRunNumber_t, EventNumber_t > event_start(std::string const &str_num)
Definition: event_start.cc:72
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.