ATLAS Offline Software
Loading...
Searching...
No Matches
LArBadChannelParser.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5#ifndef LArBadChannelParser_H
6#define LArBadChannelParser_H
7
8#include "GaudiKernel/MsgStream.h"
9#include <fstream>
10
12{
13public:
14
20 const std::string& filename, MsgStream* const log,
21 unsigned int numInts, int numStrings, unsigned int firstWildcard = 0);
22
23 virtual ~LArBadChannelParser();
24
29 bool fileStatusGood() const;
30
43
44 template<typename T>
45 std::vector< std::pair<std::vector<int>, std::vector<T> > > parseFile();
46
47private:
48
49 // Can not construct a parser without giving filename or MsgStream.
51
52 std::vector<int> getIdFields(const std::vector<std::string>& words);
53 std::vector<std::string> parseLine(std::string& line) const;
54
55 template<typename T>
56 bool stringToNumber(T& theNumber, const std::string& theStr) const;
57
58 template<typename T>
59 bool convertStrings(std::vector<T>& result, const std::vector<std::string>::const_iterator begin,
60 const std::vector<std::string>::const_iterator end) const;
61
62 std::ifstream m_fin; //to read the file
63 unsigned int m_linenumber; //line number currently being parsed
64 const std::string m_filename;
65 MsgStream* const m_log;
66
67 const unsigned int m_numInts; //the number of integers required to represent the Identifier(s)
68 const int m_numStrings; //the number of strings required to represent the status
69 const unsigned int m_firstWildcard; // The first admissible position for a wildcard ('*')
70 // The counting is from 1, i.e. first = 1
71 // If zero, then wildcards are not allowed
72};
73
75{
76 return m_fin.good();
77}
78
79template<typename T>
80inline std::vector< std::pair<std::vector<int>, std::vector<T> > > LArBadChannelParser::parseFile()
81{
82 typedef std::pair< std::vector<int>, std::vector<T> > LineData;
83 std::vector<LineData> result;
84
85 if(!fileStatusGood())
86 {
87 (*m_log) << MSG::ERROR << "LArBadChannelParser - Could not open file: " << m_filename << endmsg;
88 return result; //empty result
89 }
90
91 while(true)
92 {
93 std::string line;
94 std::getline(m_fin, line);
95 if(!fileStatusGood())
96 break; // loop termination at end of file
98 std::vector<std::string> input = parseLine(line);
99
100 if(input.size() < m_numInts + std::abs(m_numStrings)) // if line is too short, skip it
101 {
102 if(input.size() != 0) // complain only for non-empty lines
103 {(*m_log) << MSG::WARNING << "LArBadChannelParser REJECTED line " << m_linenumber \
104 << " -\t not enough parameters given: " << input.size() << endmsg;}
105 continue;
106 }
107
108 LineData parsedData;
109
110 parsedData.first = getIdFields(input);
111 if(parsedData.first.size() == 0)
112 continue; // getIdFields failed, with error message. Skip this line.
113
114 const std::vector<std::string>::const_iterator start = input.begin() + m_numInts;
115 const std::vector<std::string>::const_iterator stop = \
116 (m_numStrings < 0) ? static_cast<const std::vector<std::string>::const_iterator>(input.end()) : (start + m_numStrings);
117
118 if(stop > start)
119 {
120 if(!convertStrings<T>(parsedData.second, start, stop))
121 continue; //convertStrings failed with error message. Skip this line.
122 }
123
124 if(stop < input.end())
125 (*m_log) << MSG::WARNING << "LArBadChannelParser IGNORED unexpected input on line " << m_linenumber << "." << endmsg;
126
127 result.push_back(std::move(parsedData));
128 (*m_log) << MSG::VERBOSE << "LArBadChannelParser ACCEPTED line " << m_linenumber << " -\t " << line << endmsg;
129 }
130
131 (*m_log) << MSG::DEBUG << "LArBadChannelParser - Parsed " << m_linenumber << " lines in file '" << m_filename << "'." << endmsg;
132 return result;
133}
134
135// The convertStrings function reads the elements in the input line after the integer part,
136// and converts them to type T. The code can be easily extended by adding specialized template functions
137// to convert the elements to any desired type. The default template function below will work for any
138// standard C++ numeric type, and the specialized template function below that works for the trivial case
139// where T is string type.
140
141template<typename T> //works for any standard C++ numeric type
142inline bool LArBadChannelParser::convertStrings(std::vector<T>& result,
143 const std::vector<std::string>::const_iterator begin, const std::vector<std::string>::const_iterator end) const
144{
145 result.clear();
146 result.reserve(static_cast<unsigned int>(end - begin));
147 for(std::vector<std::string>::const_iterator iter = begin; iter != end; ++iter)
148 {
149 T element;
150 if(stringToNumber<T>(element, *iter))
151 result.push_back(element);
152 else
153 {
154 (*m_log) << MSG::WARNING << "LArBadChannelParser REJECTED line " << m_linenumber \
155 << " -\t failed to extract status." << endmsg;
156 return false;
157 }
158 }
159 return true;
160}
161
162//trivial case: convert string to string
163template<>
164inline bool LArBadChannelParser::convertStrings(std::vector<std::string>& result,
165 const std::vector<std::string>::const_iterator begin, const std::vector<std::string>::const_iterator end) const
166{
167 result.assign(begin, end);
168 return true;
169}
170
171//works for any built-in numeric C++ type
172template<typename T>
173inline bool LArBadChannelParser::stringToNumber(T& theNumber, const std::string& theString) const
174{
175 std::istringstream iss(theString);
176 //return !(iss >> std::dec >> theNumber).fail() && (static_cast<int>(theString.size()) == iss.tellg());
177 return !(iss >> std::dec >> theNumber).fail();
178 //the second condition checks for invalid input of the form "123abc"
179}
180
181#endif //end of #ifndef LArBadChannelParser_H
182
#define endmsg
std::vector< int > getIdFields(const std::vector< std::string > &words)
const unsigned int m_firstWildcard
bool fileStatusGood() const
You can use this function to check whether file-reading will succeed.
std::vector< std::string > parseLine(std::string &line) const
LArBadChannelParser(const std::string &filename, MsgStream *const log, unsigned int numInts, int numStrings, unsigned int firstWildcard=0)
A parser object must be initialized with the filename that it is to parse.
bool stringToNumber(T &theNumber, const std::string &theStr) const
const unsigned int m_numInts
const std::string m_filename
bool convertStrings(std::vector< T > &result, const std::vector< std::string >::const_iterator begin, const std::vector< std::string >::const_iterator end) const
std::vector< std::pair< std::vector< int >, std::vector< T > > > parseFile()
Parse the file using the following format for each line: First, exactly numInts integers are required...