msr2msr: replace TObjArray/TObjString with PStringUtils

Replace ROOT's TString::Tokenize() + TObjArray/TObjString token
handling with the dependency-free PStringUtils::Split() across
msr2msr_run, msr2msr_param and msr2msr_theory. Split() mirrors
Tokenize() semantics (skips empty tokens), so token counts and
indices are unchanged.

Using a std::vector<std::string> removes the manual TObjArray
cleanup and incidentally fixes a pre-existing leak in
msr2msr_theory, which tokenized in every branch but never deleted
the TObjArray.

Since msr2msr links only against ROOT (not PMusr, where
PStringUtils lives) and PStringUtils is pure C++17, compile
classes/PStringUtils.cpp directly into the msr2msr executable
rather than pulling in the whole PMusr library.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-06 15:16:50 +02:00
parent e7af0a781e
commit 76070f2098
2 changed files with 53 additions and 87 deletions
+1 -1
View File
@@ -75,7 +75,7 @@ target_include_directories(msr2data
)
target_link_libraries(msr2data ${ROOT_LIBRARIES} ${MUSRFIT_LIBS})
add_executable(msr2msr msr2msr.cpp)
add_executable(msr2msr msr2msr.cpp classes/PStringUtils.cpp)
target_link_libraries(msr2msr ${ROOT_LIBRARIES})
add_executable(musrfit musrfit.cpp)
+52 -86
View File
@@ -35,8 +35,8 @@
#include <cstdlib>
#include <TString.h>
#include <TObjArray.h>
#include <TObjString.h>
#include "PStringUtils.h"
//-------------------------------------------------------------
// msr block header tags
@@ -88,8 +88,6 @@ bool msr2msr_run(char *str, const std::size_t size)
TString run(str);
TString line(str);
TObjArray *tokens;
TObjString *ostr[2];
// for filtering
run.ToUpper();
@@ -100,8 +98,8 @@ bool msr2msr_run(char *str, const std::size_t size)
line.Remove(idx);
// tokenize run
tokens = line.Tokenize(" \t");
if (tokens->GetEntries() < 4) {
std::vector<std::string> tokens = PStringUtils::Split(line.Data(), " \t");
if (tokens.size() < 4) {
std::cout << std::endl << "**ERROR**: Something is wrong with the RUN block header:";
std::cout << std::endl << " >> " << str;
std::cout << std::endl << " >> no <msr-file-out> is created";
@@ -109,35 +107,22 @@ bool msr2msr_run(char *str, const std::size_t size)
return false;
}
if (tokens->GetEntries() == 5) { // already a new msr file, do only add the proper run comment
if (tokens.size() == 5) { // already a new msr file, do only add the proper run comment
snprintf(str, size, "%s (name beamline institute data-file-format)", line.Data());
return true;
}
if (run.Contains("NEMU")) {
ostr[0] = dynamic_cast<TObjString*>(tokens->At(1)); // file name
snprintf(str, size, "RUN %s MUE4 PSI WKM (name beamline institute data-file-format)", ostr[0]->GetString().Data());
snprintf(str, size, "RUN %s MUE4 PSI WKM (name beamline institute data-file-format)", tokens[1].c_str());
} else if (run.Contains("PSI")) {
ostr[0] = dynamic_cast<TObjString*>(tokens->At(1)); // file name
ostr[1] = dynamic_cast<TObjString*>(tokens->At(2)); // beamline
snprintf(str, size, "RUN %s %s PSI PSI-BIN (name beamline institute data-file-format)",
ostr[0]->GetString().Data(), ostr[1]->GetString().Data());
tokens[1].c_str(), tokens[2].c_str());
} else if (run.Contains("TRIUMF")) {
ostr[0] = dynamic_cast<TObjString*>(tokens->At(1)); // file name
ostr[1] = dynamic_cast<TObjString*>(tokens->At(2)); // beamline
snprintf(str, size, "RUN %s %s TRIUMF MUD (name beamline institute data-file-format)",
ostr[0]->GetString().Data(), ostr[1]->GetString().Data());
tokens[1].c_str(), tokens[2].c_str());
} else if (run.Contains("RAL")) {
ostr[0] = dynamic_cast<TObjString*>(tokens->At(1)); // file name
ostr[1] = dynamic_cast<TObjString*>(tokens->At(2)); // beamline
snprintf(str, size, "RUN %s %s RAL NEXUS (name beamline institute data-file-format)",
ostr[0]->GetString().Data(), ostr[1]->GetString().Data());
}
// clean up
if (tokens) {
delete tokens;
tokens = nullptr;
tokens[1].c_str(), tokens[2].c_str());
}
return true;
@@ -165,38 +150,34 @@ bool msr2msr_param(char *str)
// handle parameter line
TString line(str);
TObjArray *tokens;
TObjString *ostr[6];
char sstr[256];
char spaces[256];
tokens = line.Tokenize(" \t");
Int_t noTokens = tokens->GetEntries();
std::vector<std::string> tokens = PStringUtils::Split(line.Data(), " \t");
std::size_t noTokens = tokens.size();
if (noTokens == 4) {
for (unsigned int i=0; i<4; i++)
ostr[i] = dynamic_cast<TObjString*>(tokens->At(i));
// number
snprintf(sstr, sizeof(sstr), "%10s", ostr[0]->GetString().Data());
snprintf(sstr, sizeof(sstr), "%10s", tokens[0].c_str());
// name
strcat(sstr, " ");
strcat(sstr, ostr[1]->GetString().Data());
strcat(sstr, tokens[1].c_str());
memset(spaces, 0, sizeof(spaces));
memset(spaces, ' ', 12-strlen(ostr[1]->GetString().Data()));
memset(spaces, ' ', 12-strlen(tokens[1].c_str()));
strcat(sstr, spaces);
// value
strcat(sstr, ostr[2]->GetString().Data());
if (strlen(ostr[2]->GetString().Data()) < 10) {
strcat(sstr, tokens[2].c_str());
if (strlen(tokens[2].c_str()) < 10) {
memset(spaces, 0, sizeof(spaces));
memset(spaces, ' ', 10-strlen(ostr[2]->GetString().Data()));
memset(spaces, ' ', 10-strlen(tokens[2].c_str()));
strcat(sstr, spaces);
} else {
strcat(sstr, " ");
}
// step
strcat(sstr, ostr[3]->GetString().Data());
if (strlen(ostr[3]->GetString().Data()) < 12) {
strcat(sstr, tokens[3].c_str());
if (strlen(tokens[3].c_str()) < 12) {
memset(spaces, 0, sizeof(spaces));
memset(spaces, ' ', 12-strlen(ostr[3]->GetString().Data()));
memset(spaces, ' ', 12-strlen(tokens[3].c_str()));
strcat(sstr, spaces);
} else {
strcat(sstr, " ");
@@ -204,30 +185,28 @@ bool msr2msr_param(char *str)
strcat(sstr, "none");
strcpy(str, sstr);
} else if (noTokens == 6) {
for (unsigned int i=0; i<6; i++)
ostr[i] = dynamic_cast<TObjString*>(tokens->At(i));
// number
snprintf(sstr, sizeof(sstr), "%10s", ostr[0]->GetString().Data());
snprintf(sstr, sizeof(sstr), "%10s", tokens[0].c_str());
// name
strcat(sstr, " ");
strcat(sstr, ostr[1]->GetString().Data());
strcat(sstr, tokens[1].c_str());
memset(spaces, 0, sizeof(spaces));
memset(spaces, ' ', 12-strlen(ostr[1]->GetString().Data()));
memset(spaces, ' ', 12-strlen(tokens[1].c_str()));
strcat(sstr, spaces);
// value
strcat(sstr, ostr[2]->GetString().Data());
if (strlen(ostr[2]->GetString().Data()) < 10) {
strcat(sstr, tokens[2].c_str());
if (strlen(tokens[2].c_str()) < 10) {
memset(spaces, 0, sizeof(spaces));
memset(spaces, ' ', 10-strlen(ostr[2]->GetString().Data()));
memset(spaces, ' ', 10-strlen(tokens[2].c_str()));
strcat(sstr, spaces);
} else {
strcat(sstr, " ");
}
// step
strcat(sstr, ostr[3]->GetString().Data());
if (strlen(ostr[3]->GetString().Data()) < 12) {
strcat(sstr, tokens[3].c_str());
if (strlen(tokens[3].c_str()) < 12) {
memset(spaces, 0, sizeof(spaces));
memset(spaces, ' ', 12-strlen(ostr[3]->GetString().Data()));
memset(spaces, ' ', 12-strlen(tokens[3].c_str()));
strcat(sstr, spaces);
} else {
strcat(sstr, " ");
@@ -235,25 +214,19 @@ bool msr2msr_param(char *str)
// pos. error
strcat(sstr, "none ");
// lower boundary
strcat(sstr, ostr[4]->GetString().Data());
if (strlen(ostr[4]->GetString().Data()) < 8) {
strcat(sstr, tokens[4].c_str());
if (strlen(tokens[4].c_str()) < 8) {
memset(spaces, 0, sizeof(spaces));
memset(spaces, ' ', 8-strlen(ostr[4]->GetString().Data()));
memset(spaces, ' ', 8-strlen(tokens[4].c_str()));
strcat(sstr, spaces);
} else {
strcat(sstr, " ");
}
// upper boundary
strcat(sstr, ostr[5]->GetString().Data());
strcat(sstr, tokens[5].c_str());
strcpy(str, sstr);
}
// clean up
if (tokens) {
delete tokens;
tokens = nullptr;
}
return true;
}
@@ -274,8 +247,7 @@ bool msr2msr_theory(char *str, int &tag, int &noOfAddionalParams)
{
// handle theory line
TString line(str);
TObjArray *tokens;
TObjString *ostr;
std::vector<std::string> tokens;
char sstr[256];
if ((line.Contains("sktt") || line.Contains("statKTTab")) && line.Contains("glf")) { // static Gauss KT LF table
@@ -283,8 +255,8 @@ bool msr2msr_theory(char *str, int &tag, int &noOfAddionalParams)
strcpy(sstr, "statGssKTLF ");
// tokenize the rest and extract the first two parameters
tokens = line.Tokenize(" \t");
Int_t noTokens = tokens->GetEntries();
tokens = PStringUtils::Split(line.Data(), " \t");
std::size_t noTokens = tokens.size();
if (noTokens < 3) {
std::cout << std::endl << "**ERROR** in THEORY block";
std::cout << std::endl << " Line: '" << str << "' is not a valid statKTTab statement.";
@@ -293,8 +265,7 @@ bool msr2msr_theory(char *str, int &tag, int &noOfAddionalParams)
}
for (Int_t i=1; i<3; i++) {
strcat(sstr, " ");
ostr = dynamic_cast<TObjString*>(tokens->At(i));
strcat(sstr, ostr->GetString().Data());
strcat(sstr, tokens[i].c_str());
}
strcat(sstr, " (frequency damping)");
strcpy(str, sstr);
@@ -303,8 +274,8 @@ bool msr2msr_theory(char *str, int &tag, int &noOfAddionalParams)
strcpy(sstr, "statExpKTLF ");
// tokenize the rest and extract the first two parameters
tokens = line.Tokenize(" \t");
Int_t noTokens = tokens->GetEntries();
tokens = PStringUtils::Split(line.Data(), " \t");
std::size_t noTokens = tokens.size();
if (noTokens < 3) {
std::cout << std::endl << "**ERROR** in THEORY block";
std::cout << std::endl << " Line: '" << str << "' is not a valid statKTTab statement.";
@@ -313,8 +284,7 @@ bool msr2msr_theory(char *str, int &tag, int &noOfAddionalParams)
}
for (Int_t i=1; i<3; i++) {
strcat(sstr, " ");
ostr = dynamic_cast<TObjString*>(tokens->At(i));
strcat(sstr, ostr->GetString().Data());
strcat(sstr, tokens[i].c_str());
}
strcat(sstr, " (frequency damping)");
strcpy(str, sstr);
@@ -323,8 +293,8 @@ bool msr2msr_theory(char *str, int &tag, int &noOfAddionalParams)
strcpy(sstr, "dynGssKTLF ");
// tokenize the rest and extract the first three parameters
tokens = line.Tokenize(" \t");
Int_t noTokens = tokens->GetEntries();
tokens = PStringUtils::Split(line.Data(), " \t");
std::size_t noTokens = tokens.size();
if (noTokens < 4) {
std::cout << std::endl << "**ERROR** in THEORY block";
std::cout << std::endl << " Line: '" << str << "' is not a valid dynmKTTab statement.";
@@ -333,8 +303,7 @@ bool msr2msr_theory(char *str, int &tag, int &noOfAddionalParams)
}
for (Int_t i=1; i<4; i++) {
strcat(sstr, " ");
ostr = dynamic_cast<TObjString*>(tokens->At(i));
strcat(sstr, ostr->GetString().Data());
strcat(sstr, tokens[i].c_str());
}
strcat(sstr, " (frequency damping hopping-rate)");
strcpy(str, sstr);
@@ -343,8 +312,8 @@ bool msr2msr_theory(char *str, int &tag, int &noOfAddionalParams)
strcpy(sstr, "dynExpKTLF ");
// tokenize the rest and extract the first three parameters
tokens = line.Tokenize(" \t");
Int_t noTokens = tokens->GetEntries();
tokens = PStringUtils::Split(line.Data(), " \t");
std::size_t noTokens = tokens.size();
if (noTokens < 4) {
std::cout << std::endl << "**ERROR** in THEORY block";
std::cout << std::endl << " Line: '" << str << "' is not a valid dynmKTTab statement.";
@@ -353,8 +322,7 @@ bool msr2msr_theory(char *str, int &tag, int &noOfAddionalParams)
}
for (Int_t i=1; i<4; i++) {
strcat(sstr, " ");
ostr = dynamic_cast<TObjString*>(tokens->At(i));
strcat(sstr, ostr->GetString().Data());
strcat(sstr, tokens[i].c_str());
}
strcat(sstr, " (frequency damping hopping-rate)");
strcpy(str, sstr);
@@ -366,8 +334,8 @@ bool msr2msr_theory(char *str, int &tag, int &noOfAddionalParams)
strcpy(sstr, "internFld ");
// tokenize the rest and extract the first three parameters
tokens = line.Tokenize(" \t");
Int_t noTokens = tokens->GetEntries();
tokens = PStringUtils::Split(line.Data(), " \t");
std::size_t noTokens = tokens.size();
if (noTokens < 4) {
std::cout << std::endl << "**ERROR** in THEORY block";
std::cout << std::endl << " Line: '" << str << "' is not a valid internFld statement.";
@@ -377,8 +345,7 @@ bool msr2msr_theory(char *str, int &tag, int &noOfAddionalParams)
strcat(sstr, " _x_");
for (Int_t i=1; i<4; i++) {
strcat(sstr, " ");
ostr = dynamic_cast<TObjString*>(tokens->At(i));
strcat(sstr, ostr->GetString().Data());
strcat(sstr, tokens[i].c_str());
}
strcat(sstr, " (fraction phase frequency Trate Lrate)");
strcpy(str, sstr);
@@ -390,8 +357,8 @@ bool msr2msr_theory(char *str, int &tag, int &noOfAddionalParams)
strcpy(sstr, "internBsl ");
// tokenize the rest and extract the first three parameters
tokens = line.Tokenize(" \t");
Int_t noTokens = tokens->GetEntries();
tokens = PStringUtils::Split(line.Data(), " \t");
std::size_t noTokens = tokens.size();
if (noTokens < 4) {
std::cout << std::endl << "**ERROR** in THEORY block";
std::cout << std::endl << " Line: '" << str << "' is not a valid internBsl statement.";
@@ -401,8 +368,7 @@ bool msr2msr_theory(char *str, int &tag, int &noOfAddionalParams)
strcat(sstr, " _x_");
for (Int_t i=1; i<4; i++) {
strcat(sstr, " ");
ostr = dynamic_cast<TObjString*>(tokens->At(i));
strcat(sstr, ostr->GetString().Data());
strcat(sstr, tokens[i].c_str());
}
strcat(sstr, " (fraction phase frequency Trate Lrate)");
strcpy(str, sstr);