From b072a481baec419e4760ea420c27ec0a6e2f75b3 Mon Sep 17 00:00:00 2001 From: Andreas Suter Date: Sat, 6 Jun 2026 11:15:02 +0200 Subject: [PATCH] PMsrHandler: replace ROOT tokenizer machinery with C++17 PStringUtils Reduce the ROOT footprint of the MSR parser by removing the pervasive TString::Tokenize / TObjArray / TObjString / dynamic_cast pattern (28 tokenize sites, 14 TObjArray, 106 TObjString) used to split lines into tokens, together with the manual `delete tokens` cleanup. Add a new dependency-free C++17 utility class PStringUtils (Split, IsInt, IsFloat, ToInt, ToDouble, IsEqualNoCase, ContainsNoCase, BeginsWithNoCase) that replicates the relevant TString semantics exactly, so it can be reused elsewhere in the suite. IsInt/IsFloat tolerate surrounding whitespace to match TString::IsDigit/IsFloat (needed for tokens split on ',' / ';' only). The public API and the PMusr.h data structures keep TString unchanged; only the internal tokenizing logic is rewritten. Net -451 lines in PMsrHandler.cpp. All 85 integration tests pass. Co-Authored-By: Claude Opus 4.8 --- src/classes/CMakeLists.txt | 2 + src/classes/PMsrHandler.cpp | 1201 +++++++++++----------------------- src/classes/PStringUtils.cpp | 225 +++++++ src/include/PStringUtils.h | 137 ++++ 4 files changed, 738 insertions(+), 827 deletions(-) create mode 100644 src/classes/PStringUtils.cpp create mode 100644 src/include/PStringUtils.h diff --git a/src/classes/CMakeLists.txt b/src/classes/CMakeLists.txt index 5ade0bb89..3ddbfd3b3 100644 --- a/src/classes/CMakeLists.txt +++ b/src/classes/CMakeLists.txt @@ -106,6 +106,7 @@ add_library(PMusr SHARED PMsgBoxDict.cxx PMsr2Data.cpp PMsrHandler.cpp + PStringUtils.cpp PMusrCanvas.cpp PMusrCanvasDict.cxx PMusr.cpp @@ -270,6 +271,7 @@ install( ${MUSRFIT_INC}/PRunSingleHisto.h ${MUSRFIT_INC}/PRunSingleHistoRRF.h ${MUSRFIT_INC}/PStartupHandler.h + ${MUSRFIT_INC}/PStringUtils.h ${MUSRFIT_INC}/PTheory.h ${MUSRFIT_INC}/PUserFcnBase.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} diff --git a/src/classes/PMsrHandler.cpp b/src/classes/PMsrHandler.cpp index 8194546b6..7db1597e3 100644 --- a/src/classes/PMsrHandler.cpp +++ b/src/classes/PMsrHandler.cpp @@ -30,16 +30,16 @@ #include #include +#include #include #include #include -#include -#include #include #include "PMusr.h" #include "PMsrHandler.h" +#include "PStringUtils.h" //-------------------------------------------------------------------------- // Constructor @@ -451,8 +451,6 @@ Int_t PMsrHandler::WriteMsrLogFile(const Bool_t messages) Int_t plotNo = -1; std::string line; TString logFileName, str, sstr, *pstr; - TObjArray *tokens = nullptr; - TObjString *ostr = nullptr; Bool_t found = false; Bool_t statisticBlockFound = false; Bool_t partialStatisticBlockFound = true; @@ -593,15 +591,13 @@ Int_t PMsrHandler::WriteMsrLogFile(const Bool_t messages) else fout << str.Data() << std::endl; break; - case MSR_TAG_FITPARAMETER: - tokens = str.Tokenize(" \t"); - if (tokens->GetEntries() == 0) { // not a parameter line + case MSR_TAG_FITPARAMETER: { + std::vector tokens = PStringUtils::Split(str.Data(), " \t"); + if (tokens.empty()) { // not a parameter line fout << str.Data() << std::endl; } else { - ostr = dynamic_cast(tokens->At(0)); - sstr = ostr->GetString(); - if (sstr.IsDigit()) { // parameter - number = sstr.Atoi(); + if (PStringUtils::IsInt(tokens[0])) { // parameter + number = PStringUtils::ToInt(tokens[0]); number--; // make sure number makes sense assert ((number >= 0) && (number < (Int_t)fParam.size())); @@ -670,10 +666,9 @@ Int_t PMsrHandler::WriteMsrLogFile(const Bool_t messages) } else { // not a parameter, hence just copy it fout << str.Data() << std::endl; } - // clean up tokens - delete tokens; } break; + } case MSR_TAG_THEORY: found = false; for (UInt_t i=0; i tokens; // fill param structure iter = lines.begin(); @@ -2865,66 +2858,48 @@ Bool_t PMsrHandler::HandleFitParameterEntry(PMsrLines &lines) param.fUpperBoundaryPresent = false; param.fUpperBoundary = 0.0; - tokens = iter->fLine.Tokenize(" \t"); - if (!tokens) { - fLastErrorMsg.str(""); - fLastErrorMsg.clear(); - fLastErrorMsg << ">> PMsrHandler::HandleFitParameterEntry: **SEVERE ERROR** Couldn't tokenize Parameters in line " << iter->fLineNo << "\n"; - std::cerr << fLastErrorMsg.str(); - return false; - } + tokens = PStringUtils::Split(iter->fLine.Data(), " \t"); // handle various input possiblities - if ((tokens->GetEntries() < 4) || (tokens->GetEntries() > 7) || (tokens->GetEntries() == 6)) { + if ((tokens.size() < 4) || (tokens.size() > 7) || (tokens.size() == 6)) { error = true; } else { // handle the first 4 parameter since they are always the same // parameter number - ostr = dynamic_cast(tokens->At(0)); - str = ostr->GetString(); - if (str.IsDigit()) - param.fNo = str.Atoi(); + if (PStringUtils::IsInt(tokens[0])) + param.fNo = PStringUtils::ToInt(tokens[0]); else error = true; // parameter name - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); - param.fName = str; + param.fName = tokens[1].c_str(); // parameter value - ostr = dynamic_cast(tokens->At(2)); - str = ostr->GetString(); - if (str.IsFloat()) - param.fValue = static_cast(str.Atof()); + if (PStringUtils::IsFloat(tokens[2])) + param.fValue = PStringUtils::ToDouble(tokens[2]); else error = true; // parameter value - ostr = dynamic_cast(tokens->At(3)); - str = ostr->GetString(); - if (str.IsFloat()) - param.fStep = static_cast(str.Atof()); + if (PStringUtils::IsFloat(tokens[3])) + param.fStep = PStringUtils::ToDouble(tokens[3]); else error = true; // 4 values, i.e. No Name Value Step - if (tokens->GetEntries() == 4) { + if (tokens.size() == 4) { param.fNoOfParams = 4; } // 5 values, i.e. No Name Value Neg_Error Pos_Error - if (tokens->GetEntries() == 5) { + if (tokens.size() == 5) { param.fNoOfParams = 5; // positive error - ostr = dynamic_cast(tokens->At(4)); - str = ostr->GetString(); - if (str.IsFloat()) { + if (PStringUtils::IsFloat(tokens[4])) { param.fPosErrorPresent = true; - param.fPosError = static_cast(str.Atof()); + param.fPosError = PStringUtils::ToDouble(tokens[4]); } else { - str.ToLower(); - if (!str.CompareTo("none", TString::kIgnoreCase)) + if (PStringUtils::IsEqualNoCase(tokens[4], "none")) param.fPosErrorPresent = false; else error = true; @@ -2932,32 +2907,27 @@ Bool_t PMsrHandler::HandleFitParameterEntry(PMsrLines &lines) } // 7 values, i.e. No Name Value Neg_Error Pos_Error Lower_Boundary Upper_Boundary - if (tokens->GetEntries() == 7) { + if (tokens.size() == 7) { param.fNoOfParams = 7; // positive error - ostr = dynamic_cast(tokens->At(4)); - str = ostr->GetString(); - if (str.IsFloat()) { + if (PStringUtils::IsFloat(tokens[4])) { param.fPosErrorPresent = true; - param.fPosError = static_cast(str.Atof()); + param.fPosError = PStringUtils::ToDouble(tokens[4]); } else { - str.ToLower(); - if (!str.CompareTo("none", TString::kIgnoreCase)) + if (PStringUtils::IsEqualNoCase(tokens[4], "none")) param.fPosErrorPresent = false; else error = true; } // lower boundary - ostr = dynamic_cast(tokens->At(5)); - str = ostr->GetString(); // check if lower boundary is "none", i.e. upper boundary limited only - if (!str.CompareTo("none", TString::kIgnoreCase)) { // none + if (PStringUtils::IsEqualNoCase(tokens[5], "none")) { // none param.fLowerBoundaryPresent = false; } else { // assuming that the lower boundary is a number - if (str.IsFloat()) { - param.fLowerBoundary = static_cast(str.Atof()); + if (PStringUtils::IsFloat(tokens[5])) { + param.fLowerBoundary = PStringUtils::ToDouble(tokens[5]); param.fLowerBoundaryPresent = true; } else { error = true; @@ -2965,14 +2935,12 @@ Bool_t PMsrHandler::HandleFitParameterEntry(PMsrLines &lines) } // upper boundary - ostr = dynamic_cast(tokens->At(6)); - str = ostr->GetString(); // check if upper boundary is "none", i.e. lower boundary limited only - if (!str.CompareTo("none", TString::kIgnoreCase)) { // none + if (PStringUtils::IsEqualNoCase(tokens[6], "none")) { // none param.fUpperBoundaryPresent = false; } else { // assuming a number - if (str.IsFloat()) { - param.fUpperBoundary = static_cast(str.Atof()); + if (PStringUtils::IsFloat(tokens[6])) { + param.fUpperBoundary = PStringUtils::ToDouble(tokens[6]); param.fUpperBoundaryPresent = true; } else { error = true; @@ -3012,12 +2980,6 @@ Bool_t PMsrHandler::HandleFitParameterEntry(PMsrLines &lines) fParam.push_back(param); } - // clean up - if (tokens) { - delete tokens; - tokens = nullptr; - } - iter++; } @@ -3122,8 +3084,7 @@ Bool_t PMsrHandler::HandleGlobalEntry(PMsrLines &lines) Bool_t error = false; TString str; - TObjArray *tokens = nullptr; - TObjString *ostr = nullptr; + std::vector tokens; Int_t ival = 0; Double_t dval = 0.0; UInt_t addT0Counter = 0; @@ -3140,23 +3101,14 @@ Bool_t PMsrHandler::HandleGlobalEntry(PMsrLines &lines) str.Remove(idx); // tokenize line - tokens = str.Tokenize(" \t"); - if (!tokens) { - fLastErrorMsg.str(""); - fLastErrorMsg.clear(); - fLastErrorMsg << ">> PMsrHandler::HandleGlobalEntry: **SEVERE ERROR** Couldn't tokenize line " << iter->fLineNo << "\n\n"; - std::cerr << fLastErrorMsg.str(); - return false; - } + tokens = PStringUtils::Split(str.Data(), " \t"); if (iter->fLine.BeginsWith("fittype", TString::kIgnoreCase)) { // fittype - if (tokens->GetEntries() < 2) { + if (tokens.size() < 2) { error = true; } else { - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); - if (str.IsDigit()) { - Int_t fittype = str.Atoi(); + if (PStringUtils::IsInt(tokens[1])) { + Int_t fittype = PStringUtils::ToInt(tokens[1]); if ((fittype == MSR_FITTYPE_SINGLE_HISTO) || (fittype == MSR_FITTYPE_SINGLE_HISTO_RRF) || (fittype == MSR_FITTYPE_ASYM) || @@ -3173,32 +3125,26 @@ Bool_t PMsrHandler::HandleGlobalEntry(PMsrLines &lines) } } } else if (iter->fLine.BeginsWith("rrf_freq", TString::kIgnoreCase)) { - if (tokens->GetEntries() < 3) { + if (tokens.size() < 3) { error = true; } else { - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); - if (str.IsFloat()) { - dval = str.Atof(); + if (PStringUtils::IsFloat(tokens[1])) { + dval = PStringUtils::ToDouble(tokens[1]); if (dval <= 0.0) error = true; } if (!error) { - ostr = dynamic_cast(tokens->At(2)); - str = ostr->GetString(); - global.SetRRFFreq(dval, str.Data()); - if (global.GetRRFFreq(str.Data()) == RRF_FREQ_UNDEF) + global.SetRRFFreq(dval, tokens[2].c_str()); + if (global.GetRRFFreq(tokens[2].c_str()) == RRF_FREQ_UNDEF) error = true; } } } else if (iter->fLine.BeginsWith("rrf_packing", TString::kIgnoreCase)) { - if (tokens->GetEntries() < 2) { + if (tokens.size() < 2) { error = true; } else { - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); - if (str.IsDigit()) { - ival = str.Atoi(); + if (PStringUtils::IsInt(tokens[1])) { + ival = PStringUtils::ToInt(tokens[1]); if (ival > 0) { global.SetRRFPacking(ival); } else { @@ -3209,27 +3155,23 @@ Bool_t PMsrHandler::HandleGlobalEntry(PMsrLines &lines) } } } else if (iter->fLine.BeginsWith("rrf_phase", TString::kIgnoreCase)) { - if (tokens->GetEntries() < 2) { + if (tokens.size() < 2) { error = true; } else { - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); - if (str.IsFloat()) { - dval = str.Atof(); + if (PStringUtils::IsFloat(tokens[1])) { + dval = PStringUtils::ToDouble(tokens[1]); global.SetRRFPhase(dval); } else { error = true; } } } else if (iter->fLine.BeginsWith("data", TString::kIgnoreCase)) { // data - if (tokens->GetEntries() < 3) { + if (tokens.size() < 3) { error = true; } else { - for (Int_t i=1; iGetEntries(); i++) { - ostr = dynamic_cast(tokens->At(i)); - str = ostr->GetString(); - if (str.IsDigit()) { - ival = str.Atoi(); + for (UInt_t i=1; i= 0) { global.SetDataRange(ival, i-1); } else { @@ -3241,14 +3183,12 @@ Bool_t PMsrHandler::HandleGlobalEntry(PMsrLines &lines) } } } else if (iter->fLine.BeginsWith("t0", TString::kIgnoreCase)) { // t0 - if (tokens->GetEntries() < 2) { + if (tokens.size() < 2) { error = true; } else { - for (Int_t i=1; iGetEntries(); i++) { - ostr = dynamic_cast(tokens->At(i)); - str = ostr->GetString(); - if (str.IsFloat()) { - dval = str.Atof(); + for (UInt_t i=1; i= 0.0) global.SetT0Bin(dval); else @@ -3259,14 +3199,12 @@ Bool_t PMsrHandler::HandleGlobalEntry(PMsrLines &lines) } } } else if (iter->fLine.BeginsWith("addt0", TString::kIgnoreCase)) { // addt0 - if (tokens->GetEntries() < 2) { + if (tokens.size() < 2) { error = true; } else { - for (Int_t i=1; iGetEntries(); i++) { - ostr = dynamic_cast(tokens->At(i)); - str = ostr->GetString(); - if (str.IsFloat()) { - dval = str.Atof(); + for (UInt_t i=1; i= 0.0) global.SetAddT0Bin(dval, addT0Counter, i-1); else @@ -3278,19 +3216,17 @@ Bool_t PMsrHandler::HandleGlobalEntry(PMsrLines &lines) } addT0Counter++; } else if (iter->fLine.BeginsWith("fit", TString::kIgnoreCase)) { // fit range - if (tokens->GetEntries() < 3) { + if (tokens.size() < 3) { error = true; } else { // fit given in time, i.e. fit , where , are given as doubles if (iter->fLine.Contains("fgb", TString::kIgnoreCase)) { // fit given in bins, i.e. fit fgb+n0 lgb-n1 // check 1st entry, i.e. fgb[+n0] - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); - Ssiz_t idx = str.First("+"); - TString numStr = str; - if (idx > -1) { // '+' present hence extract n0 - numStr.Remove(0,idx+1); - if (numStr.IsFloat()) { - global.SetFitRangeOffset(numStr.Atoi(), 0); + std::string numStr = tokens[1]; + std::string::size_type pos = numStr.find('+'); + if (pos != std::string::npos) { // '+' present hence extract n0 + numStr = numStr.substr(pos+1); + if (PStringUtils::IsFloat(numStr)) { + global.SetFitRangeOffset(PStringUtils::ToInt(numStr), 0); } else { error = true; } @@ -3298,14 +3234,12 @@ Bool_t PMsrHandler::HandleGlobalEntry(PMsrLines &lines) global.SetFitRangeOffset(0, 0); } // check 2nd entry, i.e. lgb[-n1] - ostr = dynamic_cast(tokens->At(2)); - str = ostr->GetString(); - idx = str.First("-"); - numStr = str; - if (idx > -1) { // '-' present hence extract n1 - numStr.Remove(0,idx+1); - if (numStr.IsFloat()) { - global.SetFitRangeOffset(numStr.Atoi(), 1); + numStr = tokens[2]; + pos = numStr.find('-'); + if (pos != std::string::npos) { // '-' present hence extract n1 + numStr = numStr.substr(pos+1); + if (PStringUtils::IsFloat(numStr)) { + global.SetFitRangeOffset(PStringUtils::ToInt(numStr), 1); } else { error = true; } @@ -3315,24 +3249,20 @@ Bool_t PMsrHandler::HandleGlobalEntry(PMsrLines &lines) if (!error) global.SetFitRangeInBins(true); } else { // fit given in time, i.e. fit , where , are given as doubles - for (Int_t i=1; i<3; i++) { - ostr = dynamic_cast(tokens->At(i)); - str = ostr->GetString(); - if (str.IsFloat()) - global.SetFitRange(str.Atof(), i-1); + for (UInt_t i=1; i<3; i++) { + if (PStringUtils::IsFloat(tokens[i])) + global.SetFitRange(PStringUtils::ToDouble(tokens[i]), i-1); else error = true; } } } } else if (iter->fLine.BeginsWith("packing", TString::kIgnoreCase)) { // packing - if (tokens->GetEntries() < 2) { + if (tokens.size() < 2) { error = true; } else { - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); - if (str.IsDigit()) { - ival = str.Atoi(); + if (PStringUtils::IsInt(tokens[1])) { + ival = PStringUtils::ToInt(tokens[1]); if (ival >= 0) { global.SetPacking(ival); } else { @@ -3343,27 +3273,19 @@ Bool_t PMsrHandler::HandleGlobalEntry(PMsrLines &lines) } } } else if (iter->fLine.BeginsWith("deadtime-cor", TString::kIgnoreCase)) { // deadtime correction - if (tokens->GetEntries() < 2) { + if (tokens.size() < 2) { error = true; } else { - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); - if (!str.CompareTo("no", TString::kIgnoreCase) || - !str.CompareTo("file", TString::kIgnoreCase) || - !str.CompareTo("estimate", TString::kIgnoreCase)) { - global.SetDeadTimeCorrection(str); + if (PStringUtils::IsEqualNoCase(tokens[1], "no") || + PStringUtils::IsEqualNoCase(tokens[1], "file") || + PStringUtils::IsEqualNoCase(tokens[1], "estimate")) { + global.SetDeadTimeCorrection(tokens[1].c_str()); } else { error = true; } } } - // clean up - if (tokens) { - delete tokens; - tokens = nullptr; - } - ++iter; } @@ -3403,8 +3325,7 @@ Bool_t PMsrHandler::HandleRunEntry(PMsrLines &lines) Bool_t runLinePresent = false; TString str, line; - TObjArray *tokens = nullptr; - TObjString *ostr = nullptr; + std::vector tokens; UInt_t addT0Counter = 0; @@ -3423,14 +3344,7 @@ Bool_t PMsrHandler::HandleRunEntry(PMsrLines &lines) str.Remove(idx); // tokenize line - tokens = str.Tokenize(" \t"); - if (!tokens) { - fLastErrorMsg.str(""); - fLastErrorMsg.clear(); - fLastErrorMsg << ">> PMsrHandler::HandleRunEntry: **SEVERE ERROR** Couldn't tokenize Parameters in line " << iter->fLineNo << "\n\n"; - std::cerr << fLastErrorMsg.str(); - return false; - } + tokens = PStringUtils::Split(str.Data(), " \t"); // copy of the current line line = iter->fLine; @@ -3451,29 +3365,26 @@ Bool_t PMsrHandler::HandleRunEntry(PMsrLines &lines) // get run name, beamline, institute, and file-format // the path/filename could potentially contain spaces! Hence the run name needs to be reconstructed from the parsing - if (tokens->GetEntries() < 5) { + if (tokens.size() < 5) { error = true; } else { // run name - str = TString(""); - for (Int_t i=1; iGetEntries()-3; i++) { - ostr = dynamic_cast(tokens->At(i)); - str += ostr->GetString(); - if (iGetEntries()-4) - str += TString(" "); + std::string runName(""); + for (UInt_t i=1; i(tokens->At(tokens->GetEntries()-3)); - str = ostr->GetString(); + str = tokens[tokens.size()-3].c_str(); param.SetBeamline(str); // institute - ostr = dynamic_cast(tokens->At(tokens->GetEntries()-2)); - str = ostr->GetString(); + str = tokens[tokens.size()-2].c_str(); param.SetInstitute(str); // data file format - ostr = dynamic_cast(tokens->At(tokens->GetEntries()-1)); - str = ostr->GetString(); + str = tokens[tokens.size()-1].c_str(); param.SetFileFormat(str); } @@ -3495,24 +3406,20 @@ Bool_t PMsrHandler::HandleRunEntry(PMsrLines &lines) } // get run name, beamline, institute, and file-format - if (tokens->GetEntries() < 5) { + if (tokens.size() < 5) { error = true; } else { // run name - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); + str = tokens[1].c_str(); param.SetRunName(str); // beamline - ostr = dynamic_cast(tokens->At(2)); - str = ostr->GetString(); + str = tokens[2].c_str(); param.SetBeamline(str); // institute - ostr = dynamic_cast(tokens->At(3)); - str = ostr->GetString(); + str = tokens[3].c_str(); param.SetInstitute(str); // data file format - ostr = dynamic_cast(tokens->At(4)); - str = ostr->GetString(); + str = tokens[4].c_str(); param.SetFileFormat(str); } } @@ -3522,13 +3429,11 @@ Bool_t PMsrHandler::HandleRunEntry(PMsrLines &lines) runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following - if (tokens->GetEntries() < 2) { + if (tokens.size() < 2) { error = true; } else { - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); - if (str.IsDigit()) { - Int_t fittype = str.Atoi(); + if (PStringUtils::IsInt(tokens[1])) { + Int_t fittype = PStringUtils::ToInt(tokens[1]); if ((fittype == MSR_FITTYPE_SINGLE_HISTO) || (fittype == MSR_FITTYPE_SINGLE_HISTO_RRF) || (fittype == MSR_FITTYPE_ASYM) || @@ -3551,20 +3456,18 @@ Bool_t PMsrHandler::HandleRunEntry(PMsrLines &lines) runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following - if (tokens->GetEntries() < 2) { + if (tokens.size() < 2) { error = true; } else { - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); - if (str.IsDigit()) { - ival = str.Atoi(); + if (PStringUtils::IsInt(tokens[1])) { + ival = PStringUtils::ToInt(tokens[1]); if (ival > 0) param.SetAlphaParamNo(ival); else error = true; - } else if (str.Contains("fun")) { + } else if (tokens[1].find("fun") != std::string::npos) { Int_t no; - if (FilterNumber(str, "fun", MSR_PARAM_FUN_OFFSET, no)) + if (FilterNumber(tokens[1].c_str(), "fun", MSR_PARAM_FUN_OFFSET, no)) param.SetAlphaParamNo(no); else error = true; @@ -3579,20 +3482,18 @@ Bool_t PMsrHandler::HandleRunEntry(PMsrLines &lines) runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following - if (tokens->GetEntries() < 2) { + if (tokens.size() < 2) { error = true; } else { - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); - if (str.IsDigit()) { - ival = str.Atoi(); + if (PStringUtils::IsInt(tokens[1])) { + ival = PStringUtils::ToInt(tokens[1]); if (ival > 0) param.SetBetaParamNo(ival); else - error = true; - } else if (str.Contains("fun")) { + error = true; + } else if (tokens[1].find("fun") != std::string::npos) { Int_t no; - if (FilterNumber(str, "fun", MSR_PARAM_FUN_OFFSET, no)) + if (FilterNumber(tokens[1].c_str(), "fun", MSR_PARAM_FUN_OFFSET, no)) param.SetBetaParamNo(no); else error = true; @@ -3607,16 +3508,14 @@ Bool_t PMsrHandler::HandleRunEntry(PMsrLines &lines) runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following - if (tokens->GetEntries() < 2) { + if (tokens.size() < 2) { error = true; } else { - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); - if (str.IsDigit()) { - param.SetNormParamNo(str.Atoi()); - } else if (str.Contains("fun")) { + if (PStringUtils::IsInt(tokens[1])) { + param.SetNormParamNo(PStringUtils::ToInt(tokens[1])); + } else if (tokens[1].find("fun") != std::string::npos) { Int_t no; - if (FilterNumber(str, "fun", MSR_PARAM_FUN_OFFSET, no)) + if (FilterNumber(tokens[1].c_str(), "fun", MSR_PARAM_FUN_OFFSET, no)) param.SetNormParamNo(no); else error = true; @@ -3631,13 +3530,11 @@ Bool_t PMsrHandler::HandleRunEntry(PMsrLines &lines) runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following - if (tokens->GetEntries() < 2) { + if (tokens.size() < 2) { error = true; } else { - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); - if (str.IsDigit()) { - ival = str.Atoi(); + if (PStringUtils::IsInt(tokens[1])) { + ival = PStringUtils::ToInt(tokens[1]); if (ival > 0) param.SetBkgFitParamNo(ival); else @@ -3653,13 +3550,11 @@ Bool_t PMsrHandler::HandleRunEntry(PMsrLines &lines) runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following - if (tokens->GetEntries() < 2) { + if (tokens.size() < 2) { error = true; } else { - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); - if (str.IsDigit()) { - ival = str.Atoi(); + if (PStringUtils::IsInt(tokens[1])) { + ival = PStringUtils::ToInt(tokens[1]); if (ival > 0) param.SetLifetimeParamNo(ival); else @@ -3683,11 +3578,9 @@ Bool_t PMsrHandler::HandleRunEntry(PMsrLines &lines) runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following - for (Int_t i=1; iGetEntries(); i++) { - ostr = dynamic_cast(tokens->At(i)); - str = ostr->GetString(); - if (str.IsDigit()) { - ival = str.Atoi(); + for (UInt_t i=1; i= 0) param.SetMap(ival); else @@ -3716,7 +3609,7 @@ Bool_t PMsrHandler::HandleRunEntry(PMsrLines &lines) runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following - if (tokens->GetEntries() < 2) { + if (tokens.size() < 2) { error = true; } else { PUIntVector group; @@ -3740,7 +3633,7 @@ Bool_t PMsrHandler::HandleRunEntry(PMsrLines &lines) runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following - if (tokens->GetEntries() < 2) { + if (tokens.size() < 2) { error = true; } else { PUIntVector group; @@ -3764,14 +3657,12 @@ Bool_t PMsrHandler::HandleRunEntry(PMsrLines &lines) runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following - if (tokens->GetEntries() < 2) { + if (tokens.size() < 2) { error = true; } else { - for (Int_t i=1; iGetEntries(); i++) { - ostr = dynamic_cast(tokens->At(i)); - str = ostr->GetString(); - if (str.IsFloat()) - param.SetBkgFix(str.Atof(), i-1); + for (UInt_t i=1; iGetEntries() < 3) || (tokens->GetEntries() % 2 != 1)) { // odd number (>=3) of entries needed + if ((tokens.size() < 3) || (tokens.size() % 2 != 1)) { // odd number (>=3) of entries needed error = true; } else { - for (Int_t i=1; iGetEntries(); i++) { - ostr = dynamic_cast(tokens->At(i)); - str = ostr->GetString(); - if (str.IsDigit()) { - ival = str.Atoi(); + for (UInt_t i=1; i 0) param.SetBkgRange(ival, i-1); else @@ -3807,14 +3696,12 @@ Bool_t PMsrHandler::HandleRunEntry(PMsrLines &lines) runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following - if ((tokens->GetEntries() < 3) || (tokens->GetEntries() % 2 != 1)) { // odd number (>=3) of entries needed + if ((tokens.size() < 3) || (tokens.size() % 2 != 1)) { // odd number (>=3) of entries needed error = true; } else { - for (Int_t i=1; iGetEntries(); i++) { - ostr = dynamic_cast(tokens->At(i)); - str = ostr->GetString(); - if (str.IsDigit()) { - ival = str.Atoi(); + for (UInt_t i=1; i 0) param.SetDataRange(ival, i-1); else @@ -3831,14 +3718,12 @@ Bool_t PMsrHandler::HandleRunEntry(PMsrLines &lines) runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following - if (tokens->GetEntries() < 2) { + if (tokens.size() < 2) { error = true; } else { - for (Int_t i=1; iGetEntries(); i++) { - ostr = dynamic_cast(tokens->At(i)); - str = ostr->GetString(); - if (str.IsFloat()) { - dval = str.Atof(); + for (UInt_t i=1; i= 0.0) param.SetT0Bin(dval); else @@ -3855,14 +3740,12 @@ Bool_t PMsrHandler::HandleRunEntry(PMsrLines &lines) runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following - if (tokens->GetEntries() < 2) { + if (tokens.size() < 2) { error = true; } else { - for (Int_t i=1; iGetEntries(); i++) { - ostr = dynamic_cast(tokens->At(i)); - str = ostr->GetString(); - if (str.IsFloat()) { - dval = str.Atof(); + for (UInt_t i=1; i= 0.0) param.SetAddT0Bin(dval, addT0Counter, i-1); else @@ -3881,19 +3764,17 @@ Bool_t PMsrHandler::HandleRunEntry(PMsrLines &lines) runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following - if (tokens->GetEntries() < 3) { + if (tokens.size() < 3) { error = true; } else { if (iter->fLine.Contains("fgb", TString::kIgnoreCase)) { // fit given in bins, i.e. fit fgb+n0 lgb-n1 // check 1st entry, i.e. fgb[+n0] - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); - Ssiz_t idx = str.First("+"); - TString numStr = str; - if (idx > -1) { // '+' present hence extract n0 - numStr.Remove(0,idx+1); - if (numStr.IsFloat()) { - param.SetFitRangeOffset(numStr.Atoi(), 0); + std::string numStr = tokens[1]; + std::string::size_type pos = numStr.find('+'); + if (pos != std::string::npos) { // '+' present hence extract n0 + numStr = numStr.substr(pos+1); + if (PStringUtils::IsFloat(numStr)) { + param.SetFitRangeOffset(PStringUtils::ToInt(numStr), 0); } else { error = true; } @@ -3901,14 +3782,12 @@ Bool_t PMsrHandler::HandleRunEntry(PMsrLines &lines) param.SetFitRangeOffset(0, 0); } // check 2nd entry, i.e. lgb[-n1] - ostr = dynamic_cast(tokens->At(2)); - str = ostr->GetString(); - idx = str.First("-"); - numStr = str; - if (idx > -1) { // '-' present hence extract n1 - numStr.Remove(0,idx+1); - if (numStr.IsFloat()) { - param.SetFitRangeOffset(numStr.Atoi(), 1); + numStr = tokens[2]; + pos = numStr.find('-'); + if (pos != std::string::npos) { // '-' present hence extract n1 + numStr = numStr.substr(pos+1); + if (PStringUtils::IsFloat(numStr)) { + param.SetFitRangeOffset(PStringUtils::ToInt(numStr), 1); } else { error = true; } @@ -3919,11 +3798,9 @@ Bool_t PMsrHandler::HandleRunEntry(PMsrLines &lines) if (!error) param.SetFitRangeInBins(true); } else { // fit given in time, i.e. fit , where , are given as doubles - for (Int_t i=1; i<3; i++) { - ostr = dynamic_cast(tokens->At(i)); - str = ostr->GetString(); - if (str.IsFloat()) - param.SetFitRange(str.Atof(), i-1); + for (UInt_t i=1; i<3; i++) { + if (PStringUtils::IsFloat(tokens[i])) + param.SetFitRange(PStringUtils::ToDouble(tokens[i]), i-1); else error = true; } @@ -3936,13 +3813,11 @@ Bool_t PMsrHandler::HandleRunEntry(PMsrLines &lines) runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following - if (tokens->GetEntries() != 2) { + if (tokens.size() != 2) { error = true; } else { - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); - if (str.IsDigit()) { - ival = str.Atoi(); + if (PStringUtils::IsInt(tokens[1])) { + ival = PStringUtils::ToInt(tokens[1]); if (ival > 0) param.SetPacking(ival); else @@ -3958,15 +3833,13 @@ Bool_t PMsrHandler::HandleRunEntry(PMsrLines &lines) runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following - if (tokens->GetEntries() < 2) { + if (tokens.size() < 2) { error = true; } else { - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); - if (!str.CompareTo("no", TString::kIgnoreCase) || - !str.CompareTo("file", TString::kIgnoreCase) || - !str.CompareTo("estimate", TString::kIgnoreCase)) { - param.SetDeadTimeCorrection(str); + if (PStringUtils::IsEqualNoCase(tokens[1], "no") || + PStringUtils::IsEqualNoCase(tokens[1], "file") || + PStringUtils::IsEqualNoCase(tokens[1], "estimate")) { + param.SetDeadTimeCorrection(tokens[1].c_str()); } else { error = true; } @@ -3979,17 +3852,13 @@ Bool_t PMsrHandler::HandleRunEntry(PMsrLines &lines) runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following - if (tokens->GetEntries() != 3) { // xy-data x-label y-label + if (tokens.size() != 3) { // xy-data x-label y-label error = true; } else { - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); - if (str.IsDigit()) { // xy-data indices given - param.SetXDataIndex(str.Atoi()); // x-index - ostr = dynamic_cast(tokens->At(2)); - str = ostr->GetString(); - if (str.IsDigit()) { - ival = str.Atoi(); + if (PStringUtils::IsInt(tokens[1])) { // xy-data indices given + param.SetXDataIndex(PStringUtils::ToInt(tokens[1])); // x-index + if (PStringUtils::IsInt(tokens[2])) { + ival = PStringUtils::ToInt(tokens[2]); if (ival > 0) param.SetYDataIndex(ival); // y-index else @@ -3998,20 +3867,14 @@ Bool_t PMsrHandler::HandleRunEntry(PMsrLines &lines) error = true; } } else { // xy-data labels given + str = tokens[1].c_str(); param.SetXDataLabel(str); // x-label - ostr = dynamic_cast(tokens->At(2)); - str = ostr->GetString(); + str = tokens[2].c_str(); param.SetYDataLabel(str); // y-label } } } - // clean up - if (tokens) { - delete tokens; - tokens = nullptr; - } - ++iter; } @@ -4173,34 +4036,23 @@ Bool_t PMsrHandler::ParseFourierPhaseValueVector(PMsrFourierStructure &fourier, { Bool_t result = true; - TObjArray *tok = str.Tokenize(" ,;\t"); - if (tok == nullptr) { - fLastErrorMsg.str(""); - fLastErrorMsg.clear(); - fLastErrorMsg << ">> PMsrHandler::ParseFourierPhaseValueVector: **ERROR** couldn't tokenize Fourier phase line.\n\n"; - std::cerr << fLastErrorMsg.str(); - return false; - } + std::vector tok = PStringUtils::Split(str.Data(), " ,;\t"); // make sure there are enough tokens - if (tok->GetEntries() < 2) { + if (tok.size() < 2) { error = true; return false; } // convert all acceptable tokens - TObjString *ostr = nullptr; - TString sstr(""); - for (Int_t i=1; iGetEntries(); i++) { - ostr = dynamic_cast(tok->At(i)); - sstr = ostr->GetString(); - if (sstr.IsFloat()) { - fourier.fPhase.push_back(sstr.Atof()); + for (UInt_t i=1; i1) { // make sure that no 'phase val, parX' mixture is present fLastErrorMsg.str(""); - fLastErrorMsg.clear(); + fLastErrorMsg.clear(); fLastErrorMsg << ">> PMsrHandler::ParseFourierPhaseValueVector: **ERROR** in Fourier phase line.\n"; fLastErrorMsg << ">> Attempt to mix val, parX? This is currently not supported.\n\n"; std::cerr << fLastErrorMsg.str(); @@ -4210,11 +4062,6 @@ Bool_t PMsrHandler::ParseFourierPhaseValueVector(PMsrFourierStructure &fourier, } } - // clean up - if (tok) { - delete tok; - } - return result; } @@ -4239,42 +4086,32 @@ Bool_t PMsrHandler::ParseFourierPhaseParVector(PMsrFourierStructure &fourier, co Bool_t result = true; Int_t refCount = 0; - TObjArray *tok = str.Tokenize(" ,;\t"); - if (tok == nullptr) { - fLastErrorMsg.str(""); - fLastErrorMsg.clear(); - fLastErrorMsg << ">> PMsrHandler::ParseFourierPhaseParVector: **ERROR** couldn't tokenize Fourier phase line.\n\n"; - std::cerr << fLastErrorMsg.str(); - return false; - } + std::vector tok = PStringUtils::Split(str.Data(), " ,;\t"); // make sure there are enough tokens - if (tok->GetEntries() < 2) { + if (tok.size() < 2) { error = true; return false; } // check that all tokens start with par - TString sstr; - for (Int_t i=1; iGetEntries(); i++) { - TObjString *ostr = dynamic_cast(tok->At(i)); - sstr = ostr->GetString(); - if (!sstr.BeginsWith("par")) { + for (UInt_t i=1; i> PMsrHandler::ParseFourierPhaseParVector: **ERROR** found unhandable token '" << sstr << "'\n"; + fLastErrorMsg.clear(); + fLastErrorMsg << ">> PMsrHandler::ParseFourierPhaseParVector: **ERROR** found unhandable token '" << tok[i] << "'\n"; std::cerr << fLastErrorMsg.str(); error = true; result = false; break; } - if (sstr.BeginsWith("parR")) { + if (tok[i].rfind("parR", 0) == 0) { refCount++; } // rule out par(X, offset, #Param) syntax - if (sstr.BeginsWith("par(")) { + if (tok[i].rfind("par(", 0) == 0) { result = false; break; } @@ -4282,7 +4119,7 @@ Bool_t PMsrHandler::ParseFourierPhaseParVector(PMsrFourierStructure &fourier, co if (refCount > 1) { fLastErrorMsg.str(""); - fLastErrorMsg.clear(); + fLastErrorMsg.clear(); fLastErrorMsg << ">> PMsrHandler::ParseFourierPhaseParVector: **ERROR** found multiple parR's! Only one reference phase is accepted.\n"; std::cerr << fLastErrorMsg.str(); result = false; @@ -4291,22 +4128,21 @@ Bool_t PMsrHandler::ParseFourierPhaseParVector(PMsrFourierStructure &fourier, co // check that token has the form parX, where X is an int Int_t rmNoOf = 3; if (result != false) { - for (Int_t i=1; iGetEntries(); i++) { - TObjString *ostr = dynamic_cast(tok->At(i)); - sstr = ostr->GetString(); + for (UInt_t i=1; i> PMsrHandler::ParseFourierPhaseParVector: **ERROR** found token '" << ostr->GetString() << "' which is not parX with X an integer.\n"; + fLastErrorMsg.clear(); + fLastErrorMsg << ">> PMsrHandler::ParseFourierPhaseParVector: **ERROR** found token '" << tok[i] << "' which is not parX with X an integer.\n"; std::cerr << fLastErrorMsg.str(); fourier.fPhaseParamNo.clear(); error = true; @@ -4315,17 +4151,12 @@ Bool_t PMsrHandler::ParseFourierPhaseParVector(PMsrFourierStructure &fourier, co } } - if (fourier.fPhaseParamNo.size() == tok->GetEntries()-1) { // everything as expected + if (fourier.fPhaseParamNo.size() == tok.size()-1) { // everything as expected result = true; } else { result = false; } - // clean up - if (tok) { - delete tok; - } - return result; } @@ -4376,71 +4207,53 @@ Bool_t PMsrHandler::ParseFourierPhaseParIterVector(PMsrFourierStructure &fourier wstr.Remove(idx, wstr.Length()-idx); // tokenize rest which should have the form 'X0, offset, #Param' - TObjArray *tok = wstr.Tokenize(",;"); - if (tok == nullptr) { - fLastErrorMsg.str(""); - fLastErrorMsg.clear(); - fLastErrorMsg << ">> PMsrHandler::ParseFourierPhaseParIterVector: **ERROR** tokenize failed.\n"; - std::cerr << fLastErrorMsg.str(); - error = true; - return false; - } + std::vector tok = PStringUtils::Split(wstr.Data(), ",;"); // check for proper number of expected elements - if (tok->GetEntries() != 3) { + if (tok.size() != 3) { fLastErrorMsg.str(""); - fLastErrorMsg.clear(); + fLastErrorMsg.clear(); fLastErrorMsg << ">> PMsrHandler::ParseFourierPhaseParIterVector: **ERROR** wrong syntax for the expected par(X0, offset, #param).\n"; std::cerr << fLastErrorMsg.str(); error = true; - delete tok; return false; } Int_t x0, offset, noParam; // get X0 - TObjString *ostr = dynamic_cast(tok->At(0)); - wstr = ostr->GetString(); - if (wstr.IsDigit()) { - x0 = wstr.Atoi(); + if (PStringUtils::IsInt(tok[0])) { + x0 = PStringUtils::ToInt(tok[0]); } else { fLastErrorMsg.str(""); - fLastErrorMsg.clear(); - fLastErrorMsg << ">> PMsrHandler::ParseFourierPhaseParIterVector: **ERROR** X0='" << wstr << "' is not an integer.\n"; + fLastErrorMsg.clear(); + fLastErrorMsg << ">> PMsrHandler::ParseFourierPhaseParIterVector: **ERROR** X0='" << tok[0] << "' is not an integer.\n"; std::cerr << fLastErrorMsg.str(); error = true; - delete tok; return false; } // get offset - ostr = dynamic_cast(tok->At(1)); - wstr = ostr->GetString(); - if (wstr.IsDigit()) { - offset = wstr.Atoi(); + if (PStringUtils::IsInt(tok[1])) { + offset = PStringUtils::ToInt(tok[1]); } else { fLastErrorMsg.str(""); - fLastErrorMsg.clear(); - fLastErrorMsg << ">> PMsrHandler::ParseFourierPhaseParIterVector: **ERROR** offset='" << wstr << "' is not an integer.\n"; + fLastErrorMsg.clear(); + fLastErrorMsg << ">> PMsrHandler::ParseFourierPhaseParIterVector: **ERROR** offset='" << tok[1] << "' is not an integer.\n"; std::cerr << fLastErrorMsg.str(); error = true; - delete tok; return false; } // get noParam - ostr = dynamic_cast(tok->At(2)); - wstr = ostr->GetString(); - if (wstr.IsDigit()) { - noParam = wstr.Atoi(); + if (PStringUtils::IsInt(tok[2])) { + noParam = PStringUtils::ToInt(tok[2]); } else { fLastErrorMsg.str(""); - fLastErrorMsg.clear(); - fLastErrorMsg << ">> PMsrHandler::ParseFourierPhaseParIterVector: **ERROR** #Param='" << wstr << "' is not an integer.\n"; + fLastErrorMsg.clear(); + fLastErrorMsg << ">> PMsrHandler::ParseFourierPhaseParIterVector: **ERROR** #Param='" << tok[2] << "' is not an integer.\n"; std::cerr << fLastErrorMsg.str(); error = true; - delete tok; return false; } @@ -4453,11 +4266,6 @@ Bool_t PMsrHandler::ParseFourierPhaseParIterVector(PMsrFourierStructure &fourier for (Int_t i=0; i tokens; + TString pcStr=TString(""); Int_t ival; iter = lines.begin(); while ((iter != lines.end()) && !error) { // tokenize line - tokens = iter->fLine.Tokenize(" \t"); - if (!tokens) { - fLastErrorMsg.str(""); - fLastErrorMsg.clear(); - fLastErrorMsg << ">> PMsrHandler::HandleFourierEntry: **SEVERE ERROR** Couldn't tokenize Parameters in line " << iter->fLineNo << "\n\n"; - std::cerr << fLastErrorMsg.str(); - return false; - } + tokens = PStringUtils::Split(iter->fLine.Data(), " \t"); if (iter->fLine.BeginsWith("units", TString::kIgnoreCase)) { // units - if (tokens->GetEntries() < 2) { // units are missing + if (tokens.size() < 2) { // units are missing error = true; continue; } else { - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); - if (!str.CompareTo("gauss", TString::kIgnoreCase)) { + if (PStringUtils::IsEqualNoCase(tokens[1], "gauss")) { fourier.fUnits = FOURIER_UNIT_GAUSS; - } else if (!str.CompareTo("tesla", TString::kIgnoreCase)) { + } else if (PStringUtils::IsEqualNoCase(tokens[1], "tesla")) { fourier.fUnits = FOURIER_UNIT_TESLA; - } else if (!str.CompareTo("mhz", TString::kIgnoreCase)) { + } else if (PStringUtils::IsEqualNoCase(tokens[1], "mhz")) { fourier.fUnits = FOURIER_UNIT_FREQ; - } else if (!str.CompareTo("mc/s", TString::kIgnoreCase)) { + } else if (PStringUtils::IsEqualNoCase(tokens[1], "mc/s")) { fourier.fUnits = FOURIER_UNIT_CYCLES; } else { error = true; @@ -4527,14 +4325,12 @@ Bool_t PMsrHandler::HandleFourierEntry(PMsrLines &lines) } } } else if (iter->fLine.BeginsWith("fourier_power", TString::kIgnoreCase)) { // fourier power (zero padding) - if (tokens->GetEntries() < 2) { // fourier power exponent is missing + if (tokens.size() < 2) { // fourier power exponent is missing error = true; continue; } else { - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); - if (str.IsDigit()) { - ival = str.Atoi(); + if (PStringUtils::IsInt(tokens[1])) { + ival = PStringUtils::ToInt(tokens[1]); if ((ival >= 0) && (ival <= 20)) { fourier.fFourierPower = ival; } else { // fourier power out of range @@ -4547,15 +4343,13 @@ Bool_t PMsrHandler::HandleFourierEntry(PMsrLines &lines) } } } else if (iter->fLine.BeginsWith("dc-corrected", TString::kIgnoreCase)) { // dc-corrected - if (tokens->GetEntries() < 2) { // dc-corrected tag is missing + if (tokens.size() < 2) { // dc-corrected tag is missing error = true; continue; } else { - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); - if (!str.CompareTo("true", TString::kIgnoreCase) || !str.CompareTo("1")) { + if (PStringUtils::IsEqualNoCase(tokens[1], "true") || (tokens[1] == "1")) { fourier.fDCCorrected = true; - } else if (!str.CompareTo("false", TString::kIgnoreCase) || !str.CompareTo("0")) { + } else if (PStringUtils::IsEqualNoCase(tokens[1], "false") || (tokens[1] == "0")) { fourier.fDCCorrected = false; } else { // unrecognized dc-corrected tag error = true; @@ -4563,19 +4357,17 @@ Bool_t PMsrHandler::HandleFourierEntry(PMsrLines &lines) } } } else if (iter->fLine.BeginsWith("apodization", TString::kIgnoreCase)) { // apodization - if (tokens->GetEntries() < 2) { // apodization tag is missing + if (tokens.size() < 2) { // apodization tag is missing error = true; continue; } else { - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); - if (!str.CompareTo("none", TString::kIgnoreCase)) { + if (PStringUtils::IsEqualNoCase(tokens[1], "none")) { fourier.fApodization = FOURIER_APOD_NONE; - } else if (!str.CompareTo("weak", TString::kIgnoreCase)) { + } else if (PStringUtils::IsEqualNoCase(tokens[1], "weak")) { fourier.fApodization = FOURIER_APOD_WEAK; - } else if (!str.CompareTo("medium", TString::kIgnoreCase)) { + } else if (PStringUtils::IsEqualNoCase(tokens[1], "medium")) { fourier.fApodization = FOURIER_APOD_MEDIUM; - } else if (!str.CompareTo("strong", TString::kIgnoreCase)) { + } else if (PStringUtils::IsEqualNoCase(tokens[1], "strong")) { fourier.fApodization = FOURIER_APOD_STRONG; } else { // unrecognized apodization tag error = true; @@ -4583,23 +4375,21 @@ Bool_t PMsrHandler::HandleFourierEntry(PMsrLines &lines) } } } else if (iter->fLine.BeginsWith("plot", TString::kIgnoreCase)) { // plot tag - if (tokens->GetEntries() < 2) { // plot tag is missing + if (tokens.size() < 2) { // plot tag is missing error = true; continue; } else { - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); - if (!str.CompareTo("real", TString::kIgnoreCase)) { + if (PStringUtils::IsEqualNoCase(tokens[1], "real")) { fourier.fPlotTag = FOURIER_PLOT_REAL; - } else if (!str.CompareTo("imag", TString::kIgnoreCase)) { + } else if (PStringUtils::IsEqualNoCase(tokens[1], "imag")) { fourier.fPlotTag = FOURIER_PLOT_IMAG; - } else if (!str.CompareTo("real_and_imag", TString::kIgnoreCase)) { + } else if (PStringUtils::IsEqualNoCase(tokens[1], "real_and_imag")) { fourier.fPlotTag = FOURIER_PLOT_REAL_AND_IMAG; - } else if (!str.CompareTo("power", TString::kIgnoreCase)) { + } else if (PStringUtils::IsEqualNoCase(tokens[1], "power")) { fourier.fPlotTag = FOURIER_PLOT_POWER; - } else if (!str.CompareTo("phase", TString::kIgnoreCase)) { + } else if (PStringUtils::IsEqualNoCase(tokens[1], "phase")) { fourier.fPlotTag = FOURIER_PLOT_PHASE; - } else if (!str.CompareTo("phase_opt_real", TString::kIgnoreCase)) { + } else if (PStringUtils::IsEqualNoCase(tokens[1], "phase_opt_real")) { fourier.fPlotTag = FOURIER_PLOT_PHASE_OPT_REAL; } else { // unrecognized plot tag error = true; @@ -4607,7 +4397,7 @@ Bool_t PMsrHandler::HandleFourierEntry(PMsrLines &lines) } } } else if (iter->fLine.BeginsWith("phase", TString::kIgnoreCase)) { // phase - if (tokens->GetEntries() < 2) { // phase value(s)/par(s) is(are) missing + if (tokens.size() < 2) { // phase value(s)/par(s) is(are) missing error = true; continue; } else { @@ -4678,15 +4468,13 @@ Bool_t PMsrHandler::HandleFourierEntry(PMsrLines &lines) // available at this point. pcStr = iter->fLine; } else if (iter->fLine.BeginsWith("range", TString::kIgnoreCase)) { // fourier plot range - if (tokens->GetEntries() < 3) { // plot range values are missing + if (tokens.size() < 3) { // plot range values are missing error = true; continue; } else { for (UInt_t i=0; i<2; i++) { - ostr = dynamic_cast(tokens->At(i+1)); - str = ostr->GetString(); - if (str.IsFloat()) { - fourier.fPlotRange[i] = str.Atof(); + if (PStringUtils::IsFloat(tokens[i+1])) { + fourier.fPlotRange[i] = PStringUtils::ToDouble(tokens[i+1]); } else { error = true; continue; @@ -4699,31 +4487,17 @@ Bool_t PMsrHandler::HandleFourierEntry(PMsrLines &lines) continue; } - // clean up - if (tokens) { - delete tokens; - tokens = nullptr; - } - ++iter; } - // clean up after error - if (tokens) { - delete tokens; - tokens = nullptr; - } - // handle range_for_phase_correction if present if ((pcStr.Length() != 0) && !error) { // tokenize line - tokens = pcStr.Tokenize(" \t"); + tokens = PStringUtils::Split(pcStr.Data(), " \t"); - switch (tokens->GetEntries()) { + switch (tokens.size()) { case 2: - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); - if (!str.CompareTo("all", TString::kIgnoreCase)) { + if (PStringUtils::IsEqualNoCase(tokens[1], "all")) { fourier.fRangeForPhaseCorrection[0] = fourier.fPlotRange[0]; fourier.fRangeForPhaseCorrection[1] = fourier.fPlotRange[1]; } else { @@ -4732,10 +4506,8 @@ Bool_t PMsrHandler::HandleFourierEntry(PMsrLines &lines) break; case 3: for (UInt_t i=0; i<2; i++) { - ostr = dynamic_cast(tokens->At(i+1)); - str = ostr->GetString(); - if (str.IsFloat()) { - fourier.fRangeForPhaseCorrection[i] = str.Atof(); + if (PStringUtils::IsFloat(tokens[i+1])) { + fourier.fRangeForPhaseCorrection[i] = PStringUtils::ToDouble(tokens[i+1]); } else { error = true; } @@ -4745,12 +4517,6 @@ Bool_t PMsrHandler::HandleFourierEntry(PMsrLines &lines) error = true; break; } - - // clean up - if (tokens) { - delete tokens; - tokens = nullptr; - } } if (error) { @@ -4803,9 +4569,7 @@ Bool_t PMsrHandler::HandlePlotEntry(PMsrLines &lines) PMsrLines::iterator iter1; PMsrLines::iterator iter2; - TObjArray *tokens = nullptr; - TObjString *ostr = nullptr; - TString str; + std::vector tokens; if (lines.empty()) { std::cerr << std::endl << ">> PMsrHandler::HandlePlotEntry(): **WARNING**: There is no PLOT block! Do you really want this?"; @@ -4848,29 +4612,15 @@ Bool_t PMsrHandler::HandlePlotEntry(PMsrLines &lines) line.Resize(line.First('#')); if (line.Contains("PLOT")) { // handle plot header - tokens = line.Tokenize(" \t"); - if (!tokens) { - fLastErrorMsg.str(""); - fLastErrorMsg.clear(); - fLastErrorMsg << ">> PMsrHandler::HandlePlotEntry: **SEVERE ERROR** Couldn't tokenize PLOT in line " << iter1->fLineNo << "\n\n"; - std::cerr << fLastErrorMsg.str(); - return false; - } - if (tokens->GetEntries() < 2) { // plot type missing + tokens = PStringUtils::Split(line.Data(), " \t"); + if (tokens.size() < 2) { // plot type missing error = true; } else { - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); - if (str.IsDigit()) - param.fPlotType = str.Atoi(); + if (PStringUtils::IsInt(tokens[1])) + param.fPlotType = PStringUtils::ToInt(tokens[1]); else error = true; } - // clean up - if (tokens) { - delete tokens; - tokens = nullptr; - } } else if (line.Contains("lifetimecorrection", TString::kIgnoreCase)) { param.fLifeTimeCorrection = true; } else if (line.Contains("runs", TString::kIgnoreCase)) { // handle plot runs @@ -4917,56 +4667,38 @@ Bool_t PMsrHandler::HandlePlotEntry(PMsrLines &lines) param.fYmin.clear(); param.fYmax.clear(); - tokens = line.Tokenize(" \t"); - if (!tokens) { - std::cerr << std::endl << ">> PMsrHandler::HandlePlotEntry: **SEVERE ERROR** Couldn't tokenize PLOT in line " << iter1->fLineNo; - std::cerr << std::endl << std::endl; - return false; - } - if ((tokens->GetEntries() != 3) && (tokens->GetEntries() != 5)) { + tokens = PStringUtils::Split(line.Data(), " \t"); + if ((tokens.size() != 3) && (tokens.size() != 5)) { error = true; } else { // handle t_min - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); - if (str.IsFloat()) - param.fTmin.push_back(static_cast(str.Atof())); + if (PStringUtils::IsFloat(tokens[1])) + param.fTmin.push_back(PStringUtils::ToDouble(tokens[1])); else error = true; // handle t_max - ostr = dynamic_cast(tokens->At(2)); - str = ostr->GetString(); - if (str.IsFloat()) - param.fTmax.push_back(static_cast(str.Atof())); + if (PStringUtils::IsFloat(tokens[2])) + param.fTmax.push_back(PStringUtils::ToDouble(tokens[2])); else error = true; - if (tokens->GetEntries() == 5) { // y-axis interval given as well + if (tokens.size() == 5) { // y-axis interval given as well // handle y_min - ostr = dynamic_cast(tokens->At(3)); - str = ostr->GetString(); - if (str.IsFloat()) - param.fYmin.push_back(static_cast(str.Atof())); + if (PStringUtils::IsFloat(tokens[3])) + param.fYmin.push_back(PStringUtils::ToDouble(tokens[3])); else error = true; // handle y_max - ostr = dynamic_cast(tokens->At(4)); - str = ostr->GetString(); - if (str.IsFloat()) - param.fYmax.push_back(static_cast(str.Atof())); + if (PStringUtils::IsFloat(tokens[4])) + param.fYmax.push_back(PStringUtils::ToDouble(tokens[4])); else error = true; } } - // clean up - if (tokens) { - delete tokens; - tokens = nullptr; - } } else if (line.Contains("sub_ranges", TString::kIgnoreCase)) { // remove previous entries param.fTmin.clear(); @@ -4974,102 +4706,68 @@ Bool_t PMsrHandler::HandlePlotEntry(PMsrLines &lines) param.fYmin.clear(); param.fYmax.clear(); - tokens = line.Tokenize(" \t"); - if (!tokens) { - std::cerr << std::endl << ">> PMsrHandler::HandlePlotEntry: **SEVERE ERROR** Couldn't tokenize PLOT in line " << iter1->fLineNo; - std::cerr << std::endl << std::endl; - return false; - } - if ((tokens->GetEntries() != static_cast(2*param.fRuns.size() + 1)) && (tokens->GetEntries() != static_cast(2*param.fRuns.size() + 3))) { + tokens = PStringUtils::Split(line.Data(), " \t"); + if ((tokens.size() != 2*param.fRuns.size() + 1) && (tokens.size() != 2*param.fRuns.size() + 3)) { error = true; } else { // get all the times for (UInt_t i=0; i(tokens->At(2*i+1)); - str = ostr->GetString(); - if (str.IsFloat()) - param.fTmin.push_back(static_cast(str.Atof())); + if (PStringUtils::IsFloat(tokens[2*i+1])) + param.fTmin.push_back(PStringUtils::ToDouble(tokens[2*i+1])); else error = true; // handle t_max - ostr = dynamic_cast(tokens->At(2*i+2)); - str = ostr->GetString(); - if (str.IsFloat()) - param.fTmax.push_back(static_cast(str.Atof())); + if (PStringUtils::IsFloat(tokens[2*i+2])) + param.fTmax.push_back(PStringUtils::ToDouble(tokens[2*i+2])); else error = true; } // get y-range if present - if (tokens->GetEntries() == static_cast(2*param.fRuns.size() + 3)) { + if (tokens.size() == 2*param.fRuns.size() + 3) { // handle y_min - ostr = dynamic_cast(tokens->At(2*param.fRuns.size()+1)); - str = ostr->GetString(); - if (str.IsFloat()) - param.fYmin.push_back(static_cast(str.Atof())); + if (PStringUtils::IsFloat(tokens[2*param.fRuns.size()+1])) + param.fYmin.push_back(PStringUtils::ToDouble(tokens[2*param.fRuns.size()+1])); else error = true; // handle y_max - ostr = dynamic_cast(tokens->At(2*param.fRuns.size()+2)); - str = ostr->GetString(); - if (str.IsFloat()) - param.fYmax.push_back(static_cast(str.Atof())); + if (PStringUtils::IsFloat(tokens[2*param.fRuns.size()+2])) + param.fYmax.push_back(PStringUtils::ToDouble(tokens[2*param.fRuns.size()+2])); else error = true; } } - - // clean up - if (tokens) { - delete tokens; - tokens = nullptr; - } } else if (line.Contains("use_fit_ranges", TString::kIgnoreCase)) { param.fUseFitRanges = true; // check if y-ranges are given - tokens = line.Tokenize(" \t"); - if (!tokens) { - std::cerr << std::endl << ">> PMsrHandler::HandlePlotEntry: **SEVERE ERROR** Couldn't tokenize PLOT in line " << iter1->fLineNo; - std::cerr << std::endl << std::endl; - return false; - } + tokens = PStringUtils::Split(line.Data(), " \t"); - if (tokens->GetEntries() == 3) { // i.e. use_fit_ranges ymin ymax + if (tokens.size() == 3) { // i.e. use_fit_ranges ymin ymax // handle y_min - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); - if (str.IsFloat()) - param.fYmin.push_back(static_cast(str.Atof())); + if (PStringUtils::IsFloat(tokens[1])) + param.fYmin.push_back(PStringUtils::ToDouble(tokens[1])); else error = true; // handle y_max - ostr = dynamic_cast(tokens->At(2)); - str = ostr->GetString(); - if (str.IsFloat()) - param.fYmax.push_back(static_cast(str.Atof())); + if (PStringUtils::IsFloat(tokens[2])) + param.fYmax.push_back(PStringUtils::ToDouble(tokens[2])); else error = true; } - if ((tokens->GetEntries() != 1) && (tokens->GetEntries() != 3)) { + if ((tokens.size() != 1) && (tokens.size() != 3)) { std::cerr << std::endl << ">> PMsrHandler::HandlePlotEntry: **WARNING** use_fit_ranges with undefined additional parameters in line " << iter1->fLineNo; std::cerr << std::endl << ">> Will ignore this PLOT block command line, sorry."; std::cerr << std::endl << ">> Proper syntax: use_fit_ranges [ymin ymax]"; std::cerr << std::endl << ">> Found: '" << iter1->fLine.Data() << "'" << std::endl; } - - // clean up - if (tokens) { - delete tokens; - tokens = nullptr; - } } else if (iter1->fLine.Contains("logx", TString::kIgnoreCase)) { param.fLogX = true; } else if (iter1->fLine.Contains("logy", TString::kIgnoreCase)) { @@ -5077,19 +4775,12 @@ Bool_t PMsrHandler::HandlePlotEntry(PMsrLines &lines) } else if (iter1->fLine.Contains("lifetimecorrection", TString::kIgnoreCase)) { param.fLifeTimeCorrection = true; } else if (iter1->fLine.Contains("view_packing", TString::kIgnoreCase)) { - tokens = iter1->fLine.Tokenize(" \t"); - if (!tokens) { - std::cerr << std::endl << ">> PMsrHandler::HandlePlotEntry: **SEVERE ERROR** Couldn't tokenize view_packing in line " << iter1->fLineNo; - std::cerr << std::endl << std::endl; - return false; - } - if (tokens->GetEntries() != 2) { + tokens = PStringUtils::Split(iter1->fLine.Data(), " \t"); + if (tokens.size() != 2) { error = true; } else { - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); - if (str.IsDigit()) { - Int_t val = str.Atoi(); + if (PStringUtils::IsInt(tokens[1])) { + Int_t val = PStringUtils::ToInt(tokens[1]); if (val > 0) param.fViewPacking = val; else @@ -5098,74 +4789,47 @@ Bool_t PMsrHandler::HandlePlotEntry(PMsrLines &lines) error = true; } } - - // clean up - if (tokens) { - delete tokens; - tokens = nullptr; - } } else if (iter1->fLine.Contains("rrf_freq", TString::kIgnoreCase)) { // expected entry: rrf_freq value unit // allowed units: kHz, MHz, Mc/s, G, T - tokens = iter1->fLine.Tokenize(" \t"); - if (!tokens) { - std::cerr << std::endl << ">> PMsrHandler::HandlePlotEntry: **SEVERE ERROR** Couldn't tokenize rrf_freq in line " << iter1->fLineNo; - std::cerr << std::endl << std::endl; - return false; - } - if (tokens->GetEntries() != 3) { + tokens = PStringUtils::Split(iter1->fLine.Data(), " \t"); + if (tokens.size() != 3) { error = true; } else { // get rrf frequency - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); - if (str.IsFloat()) { - param.fRRFFreq = str.Atof(); + if (PStringUtils::IsFloat(tokens[1])) { + param.fRRFFreq = PStringUtils::ToDouble(tokens[1]); } else { error = true; } // get unit - ostr = dynamic_cast(tokens->At(2)); - str = ostr->GetString(); - if (str.Contains("kHz", TString::kIgnoreCase)) + if (PStringUtils::ContainsNoCase(tokens[2], "kHz")) param.fRRFUnit = RRF_UNIT_kHz; - else if (str.Contains("MHz", TString::kIgnoreCase)) + else if (PStringUtils::ContainsNoCase(tokens[2], "MHz")) param.fRRFUnit = RRF_UNIT_MHz; - else if (str.Contains("Mc/s", TString::kIgnoreCase)) + else if (PStringUtils::ContainsNoCase(tokens[2], "Mc/s")) param.fRRFUnit = RRF_UNIT_Mcs; - else if (str.Contains("G", TString::kIgnoreCase)) + else if (PStringUtils::ContainsNoCase(tokens[2], "G")) param.fRRFUnit = RRF_UNIT_G; - else if (str.Contains("T", TString::kIgnoreCase)) + else if (PStringUtils::ContainsNoCase(tokens[2], "T")) param.fRRFUnit = RRF_UNIT_T; else error = true; } - // clean up - if (tokens) { - delete tokens; - tokens = nullptr; - } } else if (iter1->fLine.Contains("rrf_phase", TString::kIgnoreCase)) { // expected entry: rrf_phase value. value given in units of degree. or // rrf_phase parX. where X is the parameter number, e.g. par3 - tokens = iter1->fLine.Tokenize(" \t"); - if (!tokens) { - std::cerr << std::endl << ">> PMsrHandler::HandlePlotEntry: **SEVERE ERROR** Couldn't tokenize rrf_phase in line " << iter1->fLineNo; - std::cerr << std::endl << std::endl; - return false; - } - if (tokens->GetEntries() != 2) { + tokens = PStringUtils::Split(iter1->fLine.Data(), " \t"); + if (tokens.size() != 2) { error = true; } else { // get rrf phase - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); - if (str.IsFloat()) { - param.fRRFPhase = str.Atof(); + if (PStringUtils::IsFloat(tokens[1])) { + param.fRRFPhase = PStringUtils::ToDouble(tokens[1]); } else { - if (str.BeginsWith("par", TString::kIgnoreCase)) { // parameter value + if (PStringUtils::BeginsWithNoCase(tokens[1], "par")) { // parameter value Int_t no = 0; - if (FilterNumber(str, "par", 0, no)) { + if (FilterNumber(tokens[1].c_str(), "par", 0, no)) { // check that the parameter is in range if (static_cast(fParam.size()) < no) { error = true; @@ -5181,36 +4845,19 @@ Bool_t PMsrHandler::HandlePlotEntry(PMsrLines &lines) } } } - // clean up - if (tokens) { - delete tokens; - tokens = nullptr; - } } else if (iter1->fLine.Contains("rrf_packing", TString::kIgnoreCase)) { // expected entry: rrf_phase value. value given in units of degree - tokens = iter1->fLine.Tokenize(" \t"); - if (!tokens) { - std::cerr << std::endl << ">> PMsrHandler::HandlePlotEntry: **SEVERE ERROR** Couldn't tokenize rrf_packing in line " << iter1->fLineNo; - std::cerr << std::endl << std::endl; - return false; - } - if (tokens->GetEntries() != 2) { + tokens = PStringUtils::Split(iter1->fLine.Data(), " \t"); + if (tokens.size() != 2) { error = true; } else { // get rrf packing - ostr = dynamic_cast(tokens->At(1)); - str = ostr->GetString(); - if (str.IsDigit()) { - param.fRRFPacking = str.Atoi(); + if (PStringUtils::IsInt(tokens[1])) { + param.fRRFPacking = PStringUtils::ToInt(tokens[1]); } else { error = true; } } - // clean up - if (tokens) { - delete tokens; - tokens = nullptr; - } } else { error = true; } @@ -5448,8 +5095,7 @@ UInt_t PMsrHandler::GetNoOfFitParameters(UInt_t idx) PUIntVector paramVector; PUIntVector funVector; PUIntVector mapVector; - TObjArray *tokens = nullptr; - TObjString *ostr = nullptr; + std::vector tokens; TString str; UInt_t k, dval; Int_t status, pos; @@ -5498,42 +5144,31 @@ UInt_t PMsrHandler::GetNoOfFitParameters(UInt_t idx) if (pos >= 0) str.Resize(pos); // tokenize - tokens = str.Tokenize(" \t"); - if (!tokens) { - mapVector.clear(); - funVector.clear(); - paramVector.clear(); - return 0; - } + tokens = PStringUtils::Split(str.Data(), " \t"); - for (Int_t j=0; jGetEntries(); j++) { - ostr = dynamic_cast(tokens->At(j)); - str = ostr->GetString(); + for (UInt_t j=0; jGetEntries(); j++) { - ostr = dynamic_cast(tokens->At(j)); - str = ostr->GetString(); + for (UInt_t j=0; j tokens; TString str; Int_t ival, funNo; @@ -5664,33 +5290,23 @@ void PMsrHandler::FillParameterInUse(PMsrLines &theory, PMsrLines &funcs, PMsrLi str.ToLower(); // tokenize string - tokens = str.Tokenize(" \t"); - if (!tokens) - continue; + tokens = PStringUtils::Split(str.Data(), " \t"); // filter param no, map no, and fun no - for (Int_t i=0; iGetEntries(); i++) { - ostr = dynamic_cast(tokens->At(i)); - str = ostr->GetString(); - if (str.IsDigit()) { // parameter number - ival = str.Atoi(); + for (UInt_t i=0; i 0) && (ival < static_cast(fParam.size())+1)) { fParamInUse[ival-1]++; } - } else if (str.Contains("map")) { // map - if (FilterNumber(str, "map", MSR_PARAM_MAP_OFFSET, ival)) + } else if (tokens[i].find("map") != std::string::npos) { // map + if (FilterNumber(tokens[i].c_str(), "map", MSR_PARAM_MAP_OFFSET, ival)) map.push_back(ival-MSR_PARAM_MAP_OFFSET); - } else if (str.Contains("fun")) { // fun - if (FilterNumber(str, "fun", MSR_PARAM_FUN_OFFSET, ival)) + } else if (tokens[i].find("fun") != std::string::npos) { // fun + if (FilterNumber(tokens[i].c_str(), "fun", MSR_PARAM_FUN_OFFSET, ival)) fun.push_back(ival-MSR_PARAM_FUN_OFFSET); } } - - // delete tokens - if (tokens) { - delete tokens; - tokens = nullptr; - } } // go through all the function lines: 1st time ----------------------------- @@ -5703,14 +5319,12 @@ void PMsrHandler::FillParameterInUse(PMsrLines &theory, PMsrLines &funcs, PMsrLi // everything to lower case str.ToLower(); - tokens = str.Tokenize(" /t"); - if (!tokens) + tokens = PStringUtils::Split(str.Data(), " /t"); + if (tokens.empty()) continue; // filter fun number - ostr = dynamic_cast(tokens->At(0)); - str = ostr->GetString(); - if (!FilterNumber(str, "fun", MSR_PARAM_FUN_OFFSET, funNo)) + if (!FilterNumber(tokens[0].c_str(), "fun", MSR_PARAM_FUN_OFFSET, funNo)) continue; funNo -= MSR_PARAM_FUN_OFFSET; @@ -5759,12 +5373,6 @@ void PMsrHandler::FillParameterInUse(PMsrLines &theory, PMsrLines &funcs, PMsrLi break; // since function was found, break the loop } } - - // delete tokens - if (tokens) { - delete tokens; - tokens = nullptr; - } } // go through all the run block lines ------------------------------------- @@ -5783,61 +5391,42 @@ void PMsrHandler::FillParameterInUse(PMsrLines &theory, PMsrLines &funcs, PMsrLi str.Contains("norm") || str.Contains("backgr.fit") || str.Contains("lifetime ")) { // tokenize string - tokens = str.Tokenize(" \t"); - if (!tokens) - continue; - if (tokens->GetEntries()<2) + tokens = PStringUtils::Split(str.Data(), " \t"); + if (tokens.size()<2) continue; - ostr = dynamic_cast(tokens->At(1)); // parameter number or function - str = ostr->GetString(); + std::string tok1 = tokens[1]; // parameter number or function // check if parameter number - if (str.IsDigit()) { - ival = str.Atoi(); + if (PStringUtils::IsInt(tok1)) { + ival = PStringUtils::ToInt(tok1); fParamInUse[ival-1]++; } // check if fun - if (str.Contains("fun")) { - if (FilterNumber(str, "fun", MSR_PARAM_FUN_OFFSET, ival)) { + if (tok1.find("fun") != std::string::npos) { + if (FilterNumber(tok1.c_str(), "fun", MSR_PARAM_FUN_OFFSET, ival)) { fun.push_back(ival-MSR_PARAM_FUN_OFFSET); } } - - // delete tokens - if (tokens) { - delete tokens; - tokens = nullptr; - } } // handle the maps if (str.Contains("map")) { // tokenize string - tokens = str.Tokenize(" \t"); - if (!tokens) - continue; + tokens = PStringUtils::Split(str.Data(), " \t"); // get the parameter number via map for (UInt_t i=0; iGetEntries()) { - ostr = dynamic_cast(tokens->At(map[i])); - str = ostr->GetString(); - if (str.IsDigit()) { - ival = str.Atoi(); + if (map[i] < static_cast(tokens.size())) { + if (PStringUtils::IsInt(tokens[map[i]])) { + ival = PStringUtils::ToInt(tokens[map[i]]); if (ival > 0) { fParamInUse[ival-1]++; // this is OK since map is ranging from 1 .. } } } } - - // delete tokens - if (tokens) { - delete tokens; - tokens = nullptr; - } } } @@ -5851,14 +5440,12 @@ void PMsrHandler::FillParameterInUse(PMsrLines &theory, PMsrLines &funcs, PMsrLi // everything to lower case str.ToLower(); - tokens = str.Tokenize(" /t"); - if (!tokens) + tokens = PStringUtils::Split(str.Data(), " /t"); + if (tokens.empty()) continue; // filter fun number - ostr = dynamic_cast(tokens->At(0)); - str = ostr->GetString(); - if (!FilterNumber(str, "fun", MSR_PARAM_FUN_OFFSET, funNo)) + if (!FilterNumber(tokens[0].c_str(), "fun", MSR_PARAM_FUN_OFFSET, funNo)) continue; funNo -= MSR_PARAM_FUN_OFFSET; @@ -5906,12 +5493,6 @@ void PMsrHandler::FillParameterInUse(PMsrLines &theory, PMsrLines &funcs, PMsrLi } } } - - // delete tokens - if (tokens) { - delete tokens; - tokens = nullptr; - } } // go through all the run block lines 2nd time to filter remaining maps @@ -5927,31 +5508,21 @@ void PMsrHandler::FillParameterInUse(PMsrLines &theory, PMsrLines &funcs, PMsrLi // handle the maps if (str.Contains("map")) { // tokenize string - tokens = str.Tokenize(" \t"); - if (!tokens) - continue; + tokens = PStringUtils::Split(str.Data(), " \t"); // get the parameter number via map for (UInt_t i=0; iGetEntries()) { - ostr = dynamic_cast(tokens->At(map[i])); - str = ostr->GetString(); - if (str.IsDigit()) { - ival = str.Atoi(); + if (map[i] < static_cast(tokens.size())) { + if (PStringUtils::IsInt(tokens[map[i]])) { + ival = PStringUtils::ToInt(tokens[map[i]]); if (ival > 0) { fParamInUse[ival-1]++; // this is OK since map is ranging from 1 .. } } } } - - // delete tokens - if (tokens) { - delete tokens; - tokens = nullptr; - } } } @@ -6367,9 +5938,7 @@ Bool_t PMsrHandler::CheckMaps() PIntVector mapBlock; PIntVector mapLineNo; - TObjArray *tokens = nullptr; - TObjString *ostr = nullptr; - TString str; + std::vector tokens; Int_t no; @@ -6377,23 +5946,16 @@ Bool_t PMsrHandler::CheckMaps() for (UInt_t i=0; iGetEntries(); j++) { - ostr = dynamic_cast(tokens->At(j)); - str = ostr->GetString(); - if (str.Contains("map", TString::kIgnoreCase)) { - if (FilterNumber(str, "map", MSR_PARAM_MAP_OFFSET, no)) { + tokens = PStringUtils::Split(fTheory[i].fLine.Data(), " \t"); + for (UInt_t j=0; jGetEntries(); j++) { - ostr = dynamic_cast(tokens->At(j)); - str = ostr->GetString(); - if (str.Contains("map", TString::kIgnoreCase)) { - if (FilterNumber(str, "map", MSR_PARAM_MAP_OFFSET, no)) { + tokens = PStringUtils::Split(fFunctions[i].fLine.Data(), " \t"); + for (UInt_t j=0; j tokens; TString str; Int_t no; @@ -6490,23 +6044,16 @@ Bool_t PMsrHandler::CheckFuncs() for (UInt_t i=0; iGetEntries(); j++) { - ostr = dynamic_cast(tokens->At(j)); - str = ostr->GetString(); - if (str.Contains("fun", TString::kIgnoreCase)) { - if (FilterNumber(str, "fun", MSR_PARAM_FUN_OFFSET, no)) { + tokens = PStringUtils::Split(fTheory[i].fLine.Data(), " \t"); + for (UInt_t j=0; j +#include + +#include "PStringUtils.h" + +//-------------------------------------------------------------------------- +// Split (static) +//-------------------------------------------------------------------------- +/** + *

Splits a string into tokens on any character contained in delimiters, + * skipping empty tokens. Mirrors the semantics of TString::Tokenize(). + * + * \param str input string to be tokenized + * \param delimiters set of delimiter characters + * \return vector of tokens (without the delimiters) + */ +std::vector PStringUtils::Split(const std::string &str, const std::string &delimiters) +{ + std::vector tokens; + std::string::size_type start = str.find_first_not_of(delimiters); + while (start != std::string::npos) { + std::string::size_type end = str.find_first_of(delimiters, start); + if (end == std::string::npos) { + tokens.push_back(str.substr(start)); + break; + } + tokens.push_back(str.substr(start, end - start)); + start = str.find_first_not_of(delimiters, end); + } + return tokens; +} + +//-------------------------------------------------------------------------- +// IsInt (static) +//-------------------------------------------------------------------------- +/** + *

Returns true if the string is a non-empty sequence of decimal digits + * only. Mirrors the semantics of TString::IsDigit(). + * + * \param str string to be checked + * \return true if str consists of digits only + */ +bool PStringUtils::IsInt(const std::string &str) +{ + // mirror TString::IsDigit(): all characters must be digits or whitespace, + // and there must be at least one digit (surrounding/embedded whitespace is + // tolerated, e.g. for tokens split on ',' or ';' only). + bool hasDigit = false; + for (char c : str) { + if (std::isdigit(static_cast(c))) + hasDigit = true; + else if (!std::isspace(static_cast(c))) + return false; + } + return hasDigit; +} + +//-------------------------------------------------------------------------- +// IsFloat (static) +//-------------------------------------------------------------------------- +/** + *

Returns true if the string is a complete integer or floating point + * literal (optionally signed, with decimal point and/or exponent). Mirrors + * the semantics of TString::IsFloat() for the relevant cases. + * + * \param str string to be checked + * \return true if str is a valid number + */ +bool PStringUtils::IsFloat(const std::string &str) +{ + // mirror TString::IsFloat(): surrounding whitespace is ignored (e.g. for + // tokens split on ',' or ';' only), then a complete number is required. + const std::string ws(" \t\n\r\f\v"); + std::string::size_type b = str.find_first_not_of(ws); + if (b == std::string::npos) + return false; + std::string::size_type e = str.find_last_not_of(ws); + const std::string t = str.substr(b, e - b + 1); + + std::string::size_type i = 0; + if (t[i] == '+' || t[i] == '-') + ++i; + // reject things like "inf"/"nan" which strtod would otherwise accept + if (i >= t.size() || !(std::isdigit(static_cast(t[i])) || t[i] == '.')) + return false; + const char *begin = t.c_str(); + char *end = nullptr; + std::strtod(begin, &end); + return end == begin + t.size(); +} + +//-------------------------------------------------------------------------- +// ToInt (static) +//-------------------------------------------------------------------------- +/** + *

Converts the leading part of the string to an int (base 10), mirroring + * TString::Atoi(). Returns 0 if no conversion is possible. + * + * \param str string to be converted + * \return converted integer value + */ +int PStringUtils::ToInt(const std::string &str) +{ + return static_cast(std::strtol(str.c_str(), nullptr, 10)); +} + +//-------------------------------------------------------------------------- +// ToDouble (static) +//-------------------------------------------------------------------------- +/** + *

Converts the leading part of the string to a double, mirroring + * TString::Atof(). Returns 0.0 if no conversion is possible. + * + * \param str string to be converted + * \return converted double value + */ +double PStringUtils::ToDouble(const std::string &str) +{ + return std::strtod(str.c_str(), nullptr); +} + +//-------------------------------------------------------------------------- +// IsEqualNoCase (static) +//-------------------------------------------------------------------------- +/** + *

Case-insensitive full-string equality, mirroring + * TString::CompareTo(..., TString::kIgnoreCase) == 0. + * + * \param a first string + * \param b second string + * \return true if a and b are equal ignoring case + */ +bool PStringUtils::IsEqualNoCase(const std::string &a, const std::string &b) +{ + if (a.size() != b.size()) + return false; + for (std::string::size_type i = 0; i < a.size(); ++i) { + if (std::tolower(static_cast(a[i])) != + std::tolower(static_cast(b[i]))) + return false; + } + return true; +} + +//-------------------------------------------------------------------------- +// ContainsNoCase (static) +//-------------------------------------------------------------------------- +/** + *

Case-insensitive substring search, mirroring + * TString::Contains(..., TString::kIgnoreCase). + * + * \param haystack string to be searched in + * \param needle substring to be searched for + * \return true if needle is contained in haystack ignoring case + */ +bool PStringUtils::ContainsNoCase(const std::string &haystack, const std::string &needle) +{ + if (needle.empty()) + return true; + if (needle.size() > haystack.size()) + return false; + auto toLower = [](unsigned char c) { return std::tolower(c); }; + for (std::string::size_type i = 0; i + needle.size() <= haystack.size(); ++i) { + std::string::size_type j = 0; + for (; j < needle.size(); ++j) { + if (toLower(haystack[i+j]) != toLower(needle[j])) + break; + } + if (j == needle.size()) + return true; + } + return false; +} + +//-------------------------------------------------------------------------- +// BeginsWithNoCase (static) +//-------------------------------------------------------------------------- +/** + *

Case-insensitive prefix test, mirroring + * TString::BeginsWith(..., TString::kIgnoreCase). + * + * \param str string to be tested + * \param prefix prefix to be searched for + * \return true if str starts with prefix ignoring case + */ +bool PStringUtils::BeginsWithNoCase(const std::string &str, const std::string &prefix) +{ + if (prefix.size() > str.size()) + return false; + for (std::string::size_type i = 0; i < prefix.size(); ++i) { + if (std::tolower(static_cast(str[i])) != + std::tolower(static_cast(prefix[i]))) + return false; + } + return true; +} diff --git a/src/include/PStringUtils.h b/src/include/PStringUtils.h new file mode 100644 index 000000000..8bd71cc0a --- /dev/null +++ b/src/include/PStringUtils.h @@ -0,0 +1,137 @@ +/*************************************************************************** + + PStringUtils.h + + Author: Andreas Suter + e-mail: andreas.suter@psi.ch + +***************************************************************************/ + +/*************************************************************************** + * Copyright (C) 2007-2026 by Andreas Suter * + * andreas.suter@psi.ch * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef _PSTRINGUTILS_H_ +#define _PSTRINGUTILS_H_ + +#include +#include + +//------------------------------------------------------------- +/** + * \brief Lightweight, dependency-free string utilities (pure C++17). + * + * PStringUtils collects small string helpers used throughout the musrfit + * suite, in particular for tokenizing and parsing the plain-text MSR file + * format. The implementation deliberately relies only on the C++ standard + * library (no ROOT) so that it can be reused freely. + * + * The provided helpers replicate the semantics of the corresponding + * ROOT TString methods that were previously used: + * - Split replaces TString::Tokenize() (+ TObjArray/TObjString) + * - IsInt replaces TString::IsDigit() + * - IsFloat replaces TString::IsFloat() + * - ToInt replaces TString::Atoi() + * - ToDouble replaces TString::Atof() + * - IsEqualNoCase replaces TString::CompareTo(..., TString::kIgnoreCase) + * + * All methods are static; the class is a pure namespace-like utility. + */ +class PStringUtils +{ + public: + /** + *

Splits a string into tokens on any character contained in + * delimiters, skipping empty tokens. Mirrors TString::Tokenize(). + * + * @param str input string to be tokenized + * @param delimiters set of delimiter characters + * @return vector of tokens (without the delimiters) + */ + static std::vector Split(const std::string &str, const std::string &delimiters); + + /** + *

Returns true if the string is a non-empty sequence of decimal + * digits only. Mirrors TString::IsDigit(). + * + * @param str string to be checked + * @return true if str consists of digits only + */ + static bool IsInt(const std::string &str); + + /** + *

Returns true if the string is a complete integer or floating point + * literal (optionally signed, with decimal point and/or exponent). + * Mirrors TString::IsFloat() for the relevant cases. + * + * @param str string to be checked + * @return true if str is a valid number + */ + static bool IsFloat(const std::string &str); + + /** + *

Converts the leading part of the string to an int (base 10). + * Mirrors TString::Atoi(). Returns 0 if no conversion is possible. + * + * @param str string to be converted + * @return converted integer value + */ + static int ToInt(const std::string &str); + + /** + *

Converts the leading part of the string to a double. + * Mirrors TString::Atof(). Returns 0.0 if no conversion is possible. + * + * @param str string to be converted + * @return converted double value + */ + static double ToDouble(const std::string &str); + + /** + *

Case-insensitive full-string equality. + * Mirrors TString::CompareTo(..., TString::kIgnoreCase) == 0. + * + * @param a first string + * @param b second string + * @return true if a and b are equal ignoring case + */ + static bool IsEqualNoCase(const std::string &a, const std::string &b); + + /** + *

Case-insensitive substring search. + * Mirrors TString::Contains(..., TString::kIgnoreCase). + * + * @param haystack string to be searched in + * @param needle substring to be searched for + * @return true if needle is contained in haystack ignoring case + */ + static bool ContainsNoCase(const std::string &haystack, const std::string &needle); + + /** + *

Case-insensitive prefix test. + * Mirrors TString::BeginsWith(..., TString::kIgnoreCase). + * + * @param str string to be tested + * @param prefix prefix to be searched for + * @return true if str starts with prefix ignoring case + */ + static bool BeginsWithNoCase(const std::string &str, const std::string &prefix); +}; + +#endif // _PSTRINGUTILS_H_