JAPAn
Just Another Parity Analyzer
Loading...
Searching...
No Matches
QwParameterFile.cc
Go to the documentation of this file.
1/*!
2 * \file QwParameterFile.cc
3 * \brief Implementation for parameter file parsing and management
4 */
5
6#include "QwParameterFile.h"
7
8// System headers
9#include <sstream>
10#include <climits>
11#include <algorithm>
12#include <cctype>
13
14// Qweak headers
15#include "QwLog.h"
16
17// Initialize the list of search paths
18std::vector<fs::path> QwParameterFile::fSearchPaths;
19
20// Set current run number to zero
22
23// Set default comment, whitespace, section, module characters
24const std::string QwParameterFile::kDefaultCommentChars = "#!;";
25const std::string QwParameterFile::kDefaultWhitespaceChars = " \t\r";
26const std::string QwParameterFile::kDefaultTokenSepChars = ", \t";
27const std::string QwParameterFile::kDefaultSectionChars = "[]";
28const std::string QwParameterFile::kDefaultModuleChars = "<>";
29
30/**
31 * Append a directory to the list of search paths
32 * @param searchdir Directory to be added
33 */
34void QwParameterFile::AppendToSearchPath(const TString& searchdir)
35{
36 fs::path tmppath(searchdir.Data());
37 if( fs::exists(tmppath) && fs::is_directory(tmppath)) {
38 std::cout << tmppath.string()
39 << " is a directory; adding it to the search path\n";
40 fSearchPaths.push_back(tmppath);
41 } else if( fs::exists(tmppath)) {
42 std::cout<<tmppath.string()<<" exists but is not a directory.\n";
43 } else {
44 std::cout<<tmppath.string()<<" doesn't exist.\n";
45 }
46}
47
48/**
49 * Convert a string number value to an unsigned integer
50 * @param varvalue String with decimal or hexadecimal number
51 * @return Unsigned integer
52 */
53UInt_t QwParameterFile::GetUInt(const TString& varvalue)
54{
55 UInt_t value = 0;
56 if (varvalue.IsDigit()){
57 value = varvalue.Atoi();
58 } else if (varvalue.BeginsWith("0x") || varvalue.BeginsWith("0X")
59 || varvalue.BeginsWith("x") || varvalue.BeginsWith("X")
60 || varvalue.IsHex()){
61 //any whitespace ?
62 Int_t end = varvalue.Index(" ");
63 std::istringstream stream1;
64 if (end == -1){
65 stream1.str(varvalue.Data());
66 } else {
67 //make temporary string, removing whitespace
68 Int_t start = 0;
69 TString tmp;
70 //loop over all whitespace
71 while (end > -1) {
72 tmp += varvalue(start, end-start);
73 start = end+1;
74 end = varvalue.Index(" ", start);
75 }
76 //finally add part from last whitespace to end of string
77 end = varvalue.Length();
78 tmp += varvalue(start, end-start);
79 stream1.str(tmp.Data());
80 }
81 stream1 >> std::hex >> value;
82 }
83 return value;
84}
85
86
87/**
88 * Constructor
89 * @param stream String stream for reading
90 */
102
103
104/**
105 * Constructor
106 * @param name Name of the file to be opened
107 *
108 * If file starts with an explicit slash ('/'), it is assumed to be a full path.
109 */
110QwParameterFile::QwParameterFile(const std::string& name)
116 fFilename(name),
117 fBeGreedy(kFALSE)
118{
119 // Create a file from the name
120 fs::path file(name);
121
122 // Immediately try to open absolute paths and return
123 if (name.find("/") == 0) {
124 if (OpenFile(file) == false) {
125 QwWarning << "Could not open absolute path " << name << ". "
126 << "Parameter file will remain empty." << QwLog::endl;
127 SetEOF();
128 return;
129 }
130
131 // Print file name of file that was used
132 QwMessage << "Parameter file: "
133 << QwColor(Qw::kGreen) << file.string()
135
136 // Else, loop through search path and files
137 } else {
138
139 // Separate file in stem and extension
140 std::string file_stem = file.stem().string();
141 std::string file_ext = file.extension().string();
142
143 // Find the best match
144 Int_t best_score = 0;
145 fs::path best_path;
146 for (size_t i = 0; i < fSearchPaths.size(); i++) {
147
148 fs::path path;
149 Int_t score = FindFile(fSearchPaths[i], file_stem, file_ext, path);
150 if (score > best_score) {
151 // Found file with better score
152 best_score = score;
153 best_path = path;
154 } else if (score == best_score) {
155 // Found file with identical score
156 QwWarning << "Equally likely parameter files encountered: " << best_path.string()
157 << " and " << path.string() << QwLog::endl;
158 QwMessage << "Analysis will use parameter file: " << best_path.string()
159 << QwLog::endl;
160 }
161 } // end of loop over search paths
162
163 // File not found
164 if (best_score == 0) {
165 QwError << "Could not find any parameter file with name " << name << ". "
166 << "Parameter file will remain empty." << QwLog::endl;
167 SetEOF();
168 exit(-1);
169 return;
170 }
171
172 // Found but unable to open
173 if (best_score > 0 && OpenFile(best_path) == false) {
174 QwError << "Could not open parameter file " << best_path.string() << ". "
175 << "Parameter file will remain empty." << QwLog::endl;
176 SetEOF();
177 exit(-1);
178 return;
179 }
180
181 // Print file name of file that was used
182 QwMessage << "Parameter file: "
183 << QwColor(Qw::kGreen) << best_path.string()
185 }
186}
187
188
189/**
190 * Open a file at the specified location
191 * @param file Path to file to be opened
192 * @return False if the file could not be opened
193 */
194bool QwParameterFile::OpenFile(const fs::path& file)
195{
196 Bool_t local_debug = false;
197
198 Bool_t status = false;
199
200 Bool_t check_whether_path_exists_and_is_a_regular_file = false;
201
202 // Check whether path exists and is a regular file
203 check_whether_path_exists_and_is_a_regular_file = fs::exists(file) && fs::is_regular_file(file);
204
205 if (check_whether_path_exists_and_is_a_regular_file) {
206
207 fBestParamFileNameAndPath = file.string();
208 this->SetParamFilename();
209
210 // Connect stream (fFile) to file
211 fFile.open(file.string().c_str());
212 if (! fFile.good())
213 QwError << "QwParameterFile::OpenFile Unable to read parameter file "
214 << file.string() << QwLog::endl;
215 // Load into stream
216 fStream << fFile.rdbuf();
217 status = true;
218 if(local_debug) {
219 std::cout << "------before close------------" << std::endl;
220 std::cout << fStream.str() << std::endl;
221 }
222
223 // fFile.clear();
224 // fFile.close(); // disconnect file
225 // this->Test();
226 } else {
227
228 // File does not exist or is not a regular file
229 QwError << "QwParameterFile::OpenFile Unable to open parameter file "
230 << file.string() << QwLog::endl;
231 status = false;
232 }
233 if(local_debug) {
234 std::cout << "-------after close ----------" << std::endl;
235 std::cout << fStream.str() << std::endl;
236 }
237
238 return status;
239}
240
241
242/**
243 * Find the file in a directory with highest-scoring run label
244 * @param directory Directory to search in
245 * @param file_stem File name stem to search for
246 * @param file_ext File name extensions to search for
247 * @param best_path (returns) Path to the highest-scoring file
248 * @return Score of file
249 */
251 const fs::path& directory,
252 const std::string& file_stem,
253 const std::string& file_ext,
254 fs::path& best_path)
255{
256 // Return false if the directory does not exist
257 if (! fs::exists(directory)) return false;
258
259 // Default score indicates no match found
260 int best_score = -1;
261 int score = -1;
262 // Multiple overlapping open-ended ranges
263 int open_ended_latest_start = 0;
264 int open_ended_range_score = 0;
265
266 // Loop over all files in the directory
267 // note: default iterator constructor yields past-the-end
268 fs::directory_iterator end_iterator;
269 for (fs::directory_iterator file_iterator(directory);
270 file_iterator != end_iterator;
271 file_iterator++) {
272
273 // Match the stem and extension
274 // note: filename() returns only the file name, not the path
275 std::string file_name = file_iterator->path().filename().string();
276 // stem
277 size_t pos_stem = file_name.find(file_stem);
278 if (pos_stem != 0) continue;
279 // extension (reverse find)
280 size_t pos_ext = file_name.rfind(file_ext);
281 if (pos_ext != file_name.length() - file_ext.length()) continue;
282
283 // Scores (from low to high)
284 const int score_no_run_label = 1;
285 // Open run range:
286 // score increments each time a higher-starting range is found
287 // difference between min and max gives maximum number of open ranges
288 const int score_open_ended_run_range_min = 1000;
289 const int score_open_ended_run_range_max = 9000;
290 // Close run range:
291 // score decremented from max by size of run range, small range -> high score
292 // difference between min and max gives maximum number of runs in closed range
293 const int score_closed_run_range_min = 10000;
294 const int score_closed_run_range_max = 90000;
295 // Single run label will always have maximum score
296 const int score_single_run_label = INT_MAX;
297
298 // Determine run label length
299 size_t label_length = pos_ext - file_stem.length();
300 // no run label
301 if (label_length == 0) {
302 score = score_no_run_label;
303 } else {
304 // run label starts after dot ('.') and that dot is included in the label length
305 if (file_name.at(pos_stem + file_stem.length()) == '.') {
306 std::string label = file_name.substr(pos_stem + file_stem.length() + 1, label_length - 1);
307 std::pair<int,int> range = ParseIntRange("-",label);
308 int run = fCurrentRunNumber;
309 if ((range.first <= run) && (run <= range.second)) {
310
311 // run is in single-value range
312 if (range.first == range.second) {
313 score = score_single_run_label;
314
315 // run is in double-value range
316 } else if (range.second < INT_MAX) {
317 int number_of_runs = abs(range.second - range.first);
318 score = score_closed_run_range_max - number_of_runs;
319 if (score < score_closed_run_range_min) {
320 score = score_closed_run_range_min;
321 QwError << "Too many runs in closed run range for " << file_stem << QwLog::endl;
322 QwWarning << "Range is from " << range.first << " to " << range.second << QwLog::endl;
323 }
324
325 // run is in open-ended range
326 } else if (range.second == INT_MAX) {
327 // each matching open-ended range
328 if (range.first > open_ended_latest_start) {
329 open_ended_latest_start = range.first;
330 open_ended_range_score++;
331 score = score_open_ended_run_range_min + open_ended_range_score;
332 if (score > score_open_ended_run_range_max) {
333 score = score_open_ended_run_range_max;
334 QwError << "Too many open ended run ranges for " << file_stem << QwLog::endl;
335 }
336
337 } else score = score_open_ended_run_range_min;
338 }
339 } else
340 // run not in range
341 score = -1;
342 } else
343 // run label does not start with a dot (i.e. partial match of stem)
344 score = -1;
345 }
346
347 // Look for the match with highest score
348 if (score > best_score) {
349 best_path = *file_iterator;
350 best_score = score;
351 }
352 }
353 return best_score;
354}
355
356
357void QwParameterFile::TrimWhitespace(TString::EStripType head_tail)
358{
359 // If the first bit is set, this routine removes leading spaces from the
360 // line. If the second bit is set, this routine removes trailing spaces
361 // from the line. The default behavior is to remove both.
362 TrimWhitespace(fLine, head_tail);
363}
364
366 const std::string& chars,
367 std::string& token,
368 TString::EStripType head_tail)
369{
370 // If the first bit is set, this routine removes leading chars from the
371 // line. If the second bit is set, this routine removes trailing chars
372 // from the line. The default behavior is to remove both.
373 size_t mypos;
374 // Remove leading chars. If this first test returns "npos", it means
375 // this line is all chars, so get rid of it all.
376 // If we're not removing leading chars, lines which are all chars
377 // will not be removed.
378 mypos = token.find_first_not_of(chars);
379 if (head_tail & TString::kLeading) token.erase(0,mypos);
380 // Remove trailing spaces
381 mypos = token.find_last_not_of(chars);
382 mypos = token.find_first_of(chars,mypos);
383 if (mypos != std::string::npos && (head_tail & TString::kTrailing)){
384 token.erase(mypos);
385 }
386}
387
389 std::string &token,
390 TString::EStripType head_tail)
391{
392 Trim(fWhitespaceChars,token,head_tail);
393}
394
395void QwParameterFile::TrimComment(const char commentchar)
396{
397 std::string commentchars = ""; // no std::string c'tor from single char
398 commentchars += commentchar; // so we have to use the operator+= overload
399 TrimComment(commentchars);
400}
401
402void QwParameterFile::TrimComment(const std::string& commentchars)
403{
404 // Remove everything after the comment character
405 size_t mypos = fLine.find_first_of(commentchars);
406 if (mypos != std::string::npos){
407 fLine.erase(mypos);
408 }
409}
410
412{
413 // Trim section delimiter character on both sides
414 Trim(fSectionChars,fLine,TString::kBoth);
415}
416
418{
419 // Trim module delimiter character on both sides
420 Trim(fModuleChars,fLine,TString::kBoth);
421}
422
423
424Bool_t QwParameterFile::HasValue(TString& vname)
425{
426 Bool_t status=kFALSE;
427 TString vline;
428
430 while (ReadNextLine()){
432 vline=(GetLine()).c_str();
433
434 vline.ToLower();
435 TRegexp regexp(vline);
436 vname.ToLower();
437 if (vname.Contains(regexp)){
438 QwMessage <<" QwParameterFile::HasValue "<<vline<<" "<<vname<<QwLog::endl;
439 status=kTRUE;
440 break;
441 }
442 }
443
444 return status;
445}
446
447
449 const std::string& separatorchars,
450 TString &varname,
451 TString &varvalue)
452{
453 std::string tmpvar, tmpval;
454 Bool_t status = HasVariablePair(separatorchars, tmpvar, tmpval);
455 if (status){
456 varname = tmpvar.c_str();
457 varvalue = tmpval.c_str();
458 }
459 return status;
460}
461
463 const std::string& separatorchars,
464 std::string &varname,
465 std::string &varvalue)
466{
467 Bool_t status = kFALSE;
468 size_t equiv_pos1 = fLine.find_first_of(separatorchars);
469 if (equiv_pos1 != std::string::npos){
470 size_t equiv_pos2 = fLine.find_first_not_of(separatorchars,equiv_pos1);
471 if (equiv_pos2 != std::string::npos){
472 varname = fLine.substr(0,equiv_pos1);
473 varvalue = fLine.substr(equiv_pos2);
474 TrimWhitespace(varname, TString::kBoth);
475 TrimWhitespace(varvalue, TString::kBoth);
476 status = kTRUE;
477 }
478 }
479 return status;
480}
481
483 const std::string& separatorchars,
484 const TString& varname,
485 TString& varvalue)
486{
487 std::string tmpval;
488 Bool_t status = FileHasVariablePair(separatorchars, varname.Data(), tmpval);
489 if (status) varvalue = tmpval.c_str();
490 return status;
491}
492
494 const std::string& separatorchars,
495 const std::string& varname,
496 std::string& varvalue)
497{
499 while (ReadNextLine()) {
500 std::string this_varname;
501 if (HasVariablePair(separatorchars, this_varname, varvalue)) {
502 if (this_varname == varname) return kTRUE;
503 }
504 }
505 return false;
506}
507
508
510{
511 std::string secname;
512 return LineHasSectionHeader(secname);
513}
514
516{
517 std::string secname_tmp = secname.Data();
518 Bool_t status = LineHasSectionHeader(secname_tmp);
519 secname = secname_tmp;
520 return status;
521}
522
523Bool_t QwParameterFile::LineHasSectionHeader(std::string& secname)
524{
525 TrimComment();
526 Bool_t status = kFALSE;
527 size_t equiv_pos1 = fLine.find_first_of(fSectionChars[0]);
528 if (equiv_pos1 != std::string::npos) {
529 size_t equiv_pos2 = fLine.find_last_of(fSectionChars[1]);
530 if (equiv_pos2 != std::string::npos && equiv_pos2 - equiv_pos1 > 1) {
531 secname = fLine.substr(equiv_pos1 + 1, equiv_pos2 - equiv_pos1 - 1);
532 TrimWhitespace(secname, TString::kBoth);
533 status = kTRUE;
534 }
535 }
536 return status;
537}
538
540{
541 std::string secname;
542 return LineHasModuleHeader(secname);
543}
544
546{
547 std::string secname_tmp = secname.Data();
548 Bool_t status = LineHasModuleHeader(secname_tmp);
549 secname = secname_tmp;
550 return status;
551}
552
553Bool_t QwParameterFile::LineHasModuleHeader(std::string& secname)
554{
555 TrimComment();
556 Bool_t status = kFALSE;
557 size_t equiv_pos1 = fLine.find_first_of(fModuleChars[0]);
558 if (equiv_pos1 != std::string::npos) {
559 size_t equiv_pos2 = fLine.find_last_of(fModuleChars[1]);
560 if (equiv_pos2 != std::string::npos && equiv_pos2 - equiv_pos1 > 1) {
561 secname = fLine.substr(equiv_pos1 + 1, equiv_pos2 - equiv_pos1 - 1);
562 TrimWhitespace(secname, TString::kBoth);
563 status = kTRUE;
564 }
565 }
566 return status;
567}
568
569
570Bool_t QwParameterFile::FileHasSectionHeader(const TString& secname)
571{
573 while (ReadNextLine()) {
574 std::string this_secname;
575 if (LineHasSectionHeader(this_secname)) {
576 if (this_secname == secname) return kTRUE;
577 }
578 }
579 return false;
580}
581
582Bool_t QwParameterFile::FileHasSectionHeader(const std::string& secname)
583{
585 while (ReadNextLine()) {
586 std::string this_secname;
587 if (LineHasSectionHeader(this_secname)) {
588 if (this_secname == secname) return kTRUE;
589 }
590 }
591 return false;
592}
593
594Bool_t QwParameterFile::FileHasModuleHeader(const TString& secname)
595{
597 while (ReadNextLine()) {
598 std::string this_secname;
599 if (LineHasModuleHeader(this_secname)) {
600 if (this_secname == secname) return kTRUE;
601 }
602 }
603 return false;
604}
605
606Bool_t QwParameterFile::FileHasModuleHeader(const std::string& secname)
607{
609 while (ReadNextLine()) {
610 std::string this_secname;
611 if (LineHasModuleHeader(this_secname)) {
612 if (this_secname == secname) return kTRUE;
613 }
614 }
615 return false;
616}
617
618/**
619 * Read from current position until next section header
620 * @return Pointer to the parameter stream until next section
621 */
622std::unique_ptr<QwParameterFile> QwParameterFile::ReadUntilNextSection(const bool add_current_line)
623{
624 std::string nextheader; // dummy
625 std::unique_ptr<QwParameterFile> section(new QwParameterFile());
626 if (add_current_line) section->AddLine(GetLine()); // add current line
627 while (ReadNextLine() && ! LineHasSectionHeader(nextheader)) {
628 section->AddLine(GetLine());
629 }
630 return section;
631}
632
633/**
634 * Read from current position until next module header
635 * @return Pointer to the parameter stream until next module
636 */
637std::unique_ptr<QwParameterFile> QwParameterFile::ReadUntilNextModule(const bool add_current_line)
638{
639 std::string nextheader; // dummy
640 std::unique_ptr<QwParameterFile> section(new QwParameterFile()); // std::make_unique requires public c'tor
641 if (add_current_line) section->AddLine(GetLine()); // add current line
642 while (ReadNextLine() && ! LineHasModuleHeader(nextheader)) {
643 section->AddLine(GetLine());
644 }
645 return section;
646}
647
648Bool_t QwParameterFile::SkipSection(std::string secname)
649{
650 // If the current line begins the section to be skipped,
651 // just keep reading until we get to the next section.
652 // Recurse, just in case the next section is the same
653 // section name.
654 Bool_t status = kTRUE;
655 std::string tmpname;
656 if (LineHasSectionHeader(tmpname)){
657 if (tmpname == secname){
658 QwDebug << "QwParameterFile::SkipSection: "
659 << "Begin skipping section " << tmpname << QwLog::endl;
660 while ((status=ReadNextLine()) && ! LineHasSectionHeader(tmpname)) {
661 // Do nothing for each line.
662 }
663 QwDebug << "QwParameterFile::SkipSection: "
664 << "Reached the end of the section."
665 << QwLog::endl;
666 if (status){
667 // Recurse, in case the next section has the same
668 // section name, but only if we found a new section
669 // header.
670 status = SkipSection(secname);
671 }
672 }
673 }
674 return status;
675}
676
677
678/**
679 * Read the lines until the first header
680 * @return Pointer to the parameter stream until first section
681 */
682std::unique_ptr<QwParameterFile> QwParameterFile::ReadSectionPreamble()
683{
685 return ReadUntilNextSection();
686}
687
688/**
689 * Read the lines of the next section
690 * @param secname Name of the next section (returns)
691 * @param keep_header Keep the header inside the section
692 * @return Pointer to the parameter stream of the next section
693 */
694std::unique_ptr<QwParameterFile> QwParameterFile::ReadNextSection(std::string &secname, const bool keep_header)
695{
696 if (IsEOF()) return nullptr;
697 while (! LineHasSectionHeader(secname) && ReadNextLine()); // skip until header
698 return ReadUntilNextSection(keep_header);
699}
700
701std::unique_ptr<QwParameterFile> QwParameterFile::ReadNextSection(TString &secname, const bool keep_header)
702{
703 if (IsEOF()) return nullptr;
704 while (! LineHasSectionHeader(secname) && ReadNextLine()); // skip until header
705 return ReadUntilNextSection(keep_header);
706}
707
708
709/**
710 * Read the lines until the first header
711 * @return Pointer to the parameter stream until first module
712 */
713std::unique_ptr<QwParameterFile> QwParameterFile::ReadModulePreamble()
714{
716 return ReadUntilNextModule();
717}
718
719/**
720 * Read the lines of the next module
721 * @param secname Name of the next module (returns)
722 * @param keep_header Flag to keep header of module
723 * @return Pointer to the parameter stream of the next module
724 */
725std::unique_ptr<QwParameterFile> QwParameterFile::ReadNextModule(std::string &secname, const bool keep_header)
726{
727 if (IsEOF()) return nullptr;
728 while (! LineHasModuleHeader(secname) && ReadNextLine()); // skip until header
729 return ReadUntilNextModule(keep_header);
730}
731
732std::unique_ptr<QwParameterFile> QwParameterFile::ReadNextModule(TString &secname, const bool keep_header)
733{
734 if (IsEOF()) return nullptr;
735 while (! LineHasModuleHeader(secname) && ReadNextLine()); // skip until header
736 return ReadUntilNextModule(keep_header);
737}
738
739std::string QwParameterFile::GetNextToken(const std::string& separatorchars)
740{
741 std::string tmpstring = "";
742 if (fCurrentPos != std::string::npos){
743 size_t pos1 = fCurrentPos;
744 size_t pos2 = fLine.find_first_of(separatorchars.c_str(), pos1);
745 if (pos2 == std::string::npos){
746 fCurrentPos = pos2;
747 tmpstring = fLine.substr(pos1);
748 } else {
749 fCurrentPos = fLine.find_first_not_of(separatorchars.c_str(), pos2);
750 tmpstring = fLine.substr(pos1,pos2-pos1);
751 }
752 }
753 TrimWhitespace(tmpstring,TString::kBoth);
754 return tmpstring;
755}
756
757std::ostream& operator<< (std::ostream& stream, const QwParameterFile& file)
758{
759 /// \todo TODO (wdc) operator<< on QwParameterFile requires RewindToFileStart
760 std::string line;
761 stream << file.fStream.rdbuf();
762 return stream;
763}
764
765
766/** @brief Interpret an integer with optional scale factor
767 *
768 * @param value String containing an integer with optional scale factor
769 *
770 * @return Pure integer value with any scale factor applied
771 */
772int QwParameterFile::ParseInt(const std::string& value)
773{
774 int retval;
775
776 const std::string scalechars("kM");
777 size_t pos = value.find_first_of(scalechars);
778 if (pos == std::string::npos) {
779 // Separator not found.
780 retval = atoi(value.c_str());
781 } else if (pos == value.length()-1) {
782 retval = atoi(value.substr(0,pos).c_str());
783 switch (value[pos]) {
784 case 'k': retval *= 1e3; break;
785 case 'M': retval *= 1e6; break;
786 default:
787 QwError << "Integer contains unknown scale factor! " << value << QwLog::endl;
788 break;
789 }
790 } else {
791 QwError << "Integer must end with scale factor! " << value << QwLog::endl;
792 return INT_MAX;
793 }
794
795 // Print the integer for debugging.
796 QwVerbose << "The integer is " << retval << QwLog::endl;
797
798 return retval;
799}
800
801
802/** @brief Separate a separated range of integers into a pair of values
803 *
804 * @param separatorchars String with possible separator characters to consider.
805 * @param range String containing two integers separated by a separator character,
806 * or a single value.
807 * If the string begins with the separator character, the first value
808 * is taken as zero. If the string ends with the separator character,
809 * the second value is taken as kMaxInt.
810 *
811 * @return Pair of integers of the first and last values of the range.
812 * If the range contains a single value, the two integers will
813 * be identical.
814 */
815std::pair<int,int> QwParameterFile::ParseIntRange(const std::string& separatorchars, const std::string& range)
816{
817 std::pair<int,int> mypair;
818 size_t pos = range.find_first_of(separatorchars);
819 if (pos == std::string::npos) {
820 // Separator not found.
821 mypair.first = ParseInt(range.substr(0,range.length()).c_str());
822 mypair.second = mypair.first;
823 } else {
824 size_t end = range.length() - pos - 1;
825 if (pos == 0) {
826 // Separator is the first character
827 mypair.first = 0;
828 mypair.second = ParseInt(range.substr(pos+1, end).c_str());
829 } else if (pos == range.length() - 1) {
830 // Separator is the last character
831 mypair.first = ParseInt(range.substr(0,pos).c_str());
832 mypair.second = INT_MAX;
833 } else {
834 mypair.first = ParseInt(range.substr(0,pos).c_str());
835 mypair.second = ParseInt(range.substr(pos+1, end).c_str());
836 }
837 }
838
839 // Check the values for common errors.
840 if (mypair.first < 0){
841 QwError << "The first value must not be negative!" << QwLog::endl;
842 return std::pair<int,int>(INT_MAX,INT_MAX);
843 } else if (mypair.first > mypair.second){
844 QwError << "The first value ("<< mypair.first<< ") must not be larger than the second value (" << mypair.second <<")"
845 << QwLog::endl;
846 return std::pair<int,int>(INT_MAX,INT_MAX);
847 }
848
849 // Print the contents of the pair for debugging.
850 QwVerbose << "The range goes from " << mypair.first
851 << " to " << mypair.second << QwLog::endl;
852
853 return mypair;
854}
855
856
857
859{
860 Char_t delimiters[] = "/";
862 return;
863};
864
865
866TString QwParameterFile::LastString(TString in, char* delim)
867{
868 TObjArray* all_strings = in.Tokenize(delim);
869 TObjString* last_string = (TObjString*) all_strings->Last();
870 TString return_string = last_string->GetString();
871 delete all_strings;
872 return return_string;
873};
874
875
877{
878 TMacro *fParameterFile = new TMacro(fBestParamFileNameAndPath);
879 TString ms;
880 TList *list = fParameterFile->GetListOfLines();
881 for(Int_t i=0; i < list->GetSize(); i++) {
882 ms += list->At(i)->GetName();
883 ms += "\n";
884 }
885 delete fParameterFile;
886 fParameterFile = NULL;
887 return ms;
888}
889
890
892 std::transform(keyname.begin(), keyname.end(),
893 keyname.begin(), ::tolower);
894 fBreakpointWords.insert(keyname);
895}
896
897Bool_t QwParameterFile::ReadNextLine_Greedy(std::string &varvalue)
898{
899 // Keep reading until a non-comment, non-empty,
900 // non-keyword-value-pair line has been found.
901 Bool_t status;
902 std::string tmpname, tmpvalue;
903 while ((status = ReadNextLine_Single(varvalue))){
904 TrimComment();
906 if (LineIsEmpty()) continue;
907 if (HasVariablePair("=",tmpname,tmpvalue)){
908 std::transform(tmpname.begin(), tmpname.end(),
909 tmpname.begin(), ::tolower);
910 QwDebug << "QwParameterFile::ReadNextLine_Greedy: varname="
911 << tmpname << "; varvalue=" << tmpvalue <<QwLog::endl;
912 if (fBreakpointWords.count(tmpname)==1){
914 break;
915 } else {
916 fKeyValuePair[tmpname] = tmpvalue;
917 fHasNewPairs = kTRUE;
918 continue;
919 }
920 }
921 break;
922 }
923 return status;
924}
A logfile class, based on an identical class in the Hermes analyzer.
#define QwVerbose
Predefined log drain for verbose messages.
Definition QwLog.h:54
#define QwError
Predefined log drain for errors.
Definition QwLog.h:39
#define QwWarning
Predefined log drain for warnings.
Definition QwLog.h:44
#define QwMessage
Predefined log drain for regular messages.
Definition QwLog.h:49
#define QwDebug
Predefined log drain for debugging output.
Definition QwLog.h:59
Parameter file parsing and management.
std::ostream & operator<<(std::ostream &stream, const QwParameterFile &file)
@ kGreen
Definition QwColor.h:77
@ kNormal
Definition QwColor.h:81
A color changing class for the output stream.
Definition QwColor.h:103
static std::ostream & endl(std::ostream &)
End of the line.
Definition QwLog.cc:297
size_t fCurrentPos
Internal line storage.
Bool_t LineHasSectionHeader()
static const std::string kDefaultWhitespaceChars
Bool_t ReadNextLine_Single(std::string &varvalue)
std::string GetNextToken()
std::map< std::string, std::string > fKeyValuePair
static int ParseInt(const std::string &value)
Parse an integer as #[kM] with optional metric scale factor.
std::stringstream fStream
static const std::string kDefaultTokenSepChars
Bool_t LineHasModuleHeader()
static void AppendToSearchPath(const TString &searchdir)
Add a directory to the search path.
TString GetParameterFileContents()
bool OpenFile(const fs::path &path_found)
Open a file.
Bool_t HasValue(TString &vname)
std::unique_ptr< QwParameterFile > ReadUntilNextModule(const bool add_current_line=false)
static const std::string kDefaultSectionChars
Bool_t ReadNextLine_Greedy(std::string &varvalue)
std::unique_ptr< QwParameterFile > ReadNextModule(std::string &secname, const bool keep_header=false)
Bool_t FileHasSectionHeader(const std::string &secname)
void TrimWhitespace(TString::EStripType head_tail=TString::kBoth)
Bool_t HasVariablePair(const std::string &separatorchars, std::string &varname, std::string &varvalue)
std::string fModuleChars
std::set< std::string > fBreakpointWords
int FindFile(const fs::path &dir_path, const std::string &file_stem, const std::string &file_ext, fs::path &path_found)
Find the first file in a directory that conforms to the run label.
TString LastString(TString in, char *delim)
Bool_t SkipSection(std::string secname)
Skips from the beginning of the section 'secname' until the first section that does not have that nam...
std::string GetLine()
static std::pair< int, int > ParseIntRange(const std::string &separatorchars, const std::string &range)
Parse a range of integers as #:# where either can be missing.
std::string fSectionChars
std::string fWhitespaceChars
void AddBreakpointKeyword(std::string keyname)
std::ifstream fFile
QwParameterFile(const std::string &filename)
static UInt_t fCurrentRunNumber
static const std::string kDefaultCommentChars
TString fBestParamFileNameAndPath
static UInt_t GetUInt(const TString &varvalue)
Bool_t FileHasModuleHeader(const std::string &secname)
std::string fTokenSepChars
const std::string fFilename
std::unique_ptr< QwParameterFile > ReadModulePreamble()
Rewinds to the start and read until it finds next module header.
void Trim(const std::string &chars, std::string &token, TString::EStripType head_tail=TString::kBoth)
std::string fCommentChars
std::unique_ptr< QwParameterFile > ReadUntilNextSection(const bool add_current_line=false)
static const std::string kDefaultModuleChars
std::unique_ptr< QwParameterFile > ReadSectionPreamble()
Rewinds to the start and read until it finds next section header.
Bool_t FileHasVariablePair(const std::string &separatorchars, const std::string &varname, std::string &varvalue)
static std::vector< fs::path > fSearchPaths
std::unique_ptr< QwParameterFile > ReadNextSection(std::string &secname, const bool keep_header=false)