diff --git a/otsdaq/Macros/StringMacros.cc b/otsdaq/Macros/StringMacros.cc index 093546561..2c320b723 100644 --- a/otsdaq/Macros/StringMacros.cc +++ b/otsdaq/Macros/StringMacros.cc @@ -18,22 +18,22 @@ const std::string StringMacros::TBD = "To-be-defined"; //============================================================================== /// wildCardMatch /// find needle in haystack -/// allow needle to have leading and/or trailing wildcard '*' +/// allow needle to have wildcard '*' anywhere /// consider priority in matching, no matter the order in the haystack: /// - 0: no match! /// - 1: highest priority is exact match /// - 2: next highest is partial TRAILING-wildcard match /// - 3: next highest is partial LEADING-wildcard match -/// - 4: lowest priority is partial full-wildcard match +/// - 4: lowest priority is wildcard match (including internal '*') +/// - 5: wildcard-only match /// return priority found by reference bool StringMacros::wildCardMatch(const std::string& needle, const std::string& haystack, unsigned int* priorityIndex) try { - // __COUT__ << "\t\t wildCardMatch: " << needle << - // " =in= " << haystack << " ??? " << - // std::endl; + __COUTT__ << "\t\t wildCardMatch: " << needle << " =in= " << haystack << " ??? " + << std::endl; // empty needle if(needle.size() == 0) @@ -59,6 +59,14 @@ try return true; } + const bool hasWildcard = (needle.find('*') != std::string::npos); + if(!hasWildcard) + { + if(priorityIndex) + *priorityIndex = 0; // no wildcard and not exact => no match + return false; + } + // trailing wildcard if(needle[needle.size() - 1] == '*' && needle.substr(0, needle.size() - 1) == haystack.substr(0, needle.size() - 1)) @@ -77,12 +85,44 @@ try return true; } - // leading wildcard and trailing wildcard - if(needle[0] == '*' && needle[needle.size() - 1] == '*' && - std::string::npos != haystack.find(needle.substr(1, needle.size() - 2))) + // generic wildcard matching with '*' anywhere in needle + // '*' matches any sequence (including empty) + std::size_t patternPos = 0; + std::size_t textPos = 0; + std::size_t lastStarPattern = std::string::npos; + std::size_t lastStarTextPos = std::string::npos; + while(textPos < haystack.size()) + { + if(patternPos < needle.size() && needle[patternPos] == haystack[textPos]) + { + ++patternPos; + ++textPos; + } + else if(patternPos < needle.size() && needle[patternPos] == '*') + { + lastStarPattern = patternPos++; + lastStarTextPos = textPos; + } + else if(lastStarPattern != std::string::npos) + { + patternPos = lastStarPattern + 1; + textPos = ++lastStarTextPos; + } + else + { + if(priorityIndex) + *priorityIndex = 0; // no match + return false; + } + } + + while(patternPos < needle.size() && needle[patternPos] == '*') + ++patternPos; + + if(patternPos == needle.size()) { if(priorityIndex) - *priorityIndex = 4; // leading and trailing wildcard match + *priorityIndex = 4; // wildcard match return true; } diff --git a/otsdaq/TableCore/TableView.cc b/otsdaq/TableCore/TableView.cc index bf9b0c71e..3ec722fb5 100644 --- a/otsdaq/TableCore/TableView.cc +++ b/otsdaq/TableCore/TableView.cc @@ -1541,10 +1541,15 @@ std::vector> TableView::getGroupRowsInVe colPriority_ != INVALID)) // if no priority column, all at same priorty [0] retVector.push_back(std::vector()); + __COUTS__(2) << "getGroupRowsInVectors: " << groupID << " at col " << groupIdCol + << __E__; for(unsigned int r = 0; r < getNumberOfRows(); ++r) if(groupID == "" || groupID == "*" || groupIdCol == INVALID || isEntryInGroupCol(r, groupIdCol, groupID)) { + if(groupIdCol != INVALID) + __COUTS__(2) << "Row " << r << " '" << getDataView()[r][groupIdCol] + << "' is in group " << groupID << __E__; // check status if needed if(onlyStatusTrue && colStatus_ != INVALID) { @@ -1563,6 +1568,9 @@ std::vector> TableView::getGroupRowsInVe else // assume equal priority retVector[0].push_back(r); } + else // already true that... if(groupIdCol != INVALID) + __COUTS__(2) << "Row " << r << " '" << getDataView()[r][groupIdCol] + << "' is NOT in group " << groupID << __E__; if(orderedByPriority && colPriority_ != INVALID) { @@ -1592,7 +1600,7 @@ bool TableView::removeRowFromGroup(const unsigned int& row, const std::string& groupNeedle, bool deleteRowIfNoGroupLeft) { - __COUT__ << "groupNeedle " << groupNeedle << __E__; + __COUT__ << "removeRowFromGroup groupNeedle " << groupNeedle << __E__; std::set groupIDList; if(!isEntryInGroupCol(row, col, groupNeedle, &groupIDList)) { @@ -1610,7 +1618,7 @@ bool TableView::removeRowFromGroup(const unsigned int& row, unsigned int cnt = 0; for(const auto& groupID : groupIDList) { - //__COUT__ << groupID << " " << groupNeedle << " " << newValue << __E__; + __COUTT__ << groupID << " " << groupNeedle << " " << newValue << __E__; if(groupID == groupNeedle) continue; // skip group to be removed @@ -1622,14 +1630,15 @@ bool TableView::removeRowFromGroup(const unsigned int& row, bool wasDeleted = false; if(deleteRowIfNoGroupLeft && newValue == "") { - __COUT__ << "Delete row since it no longer part of any group." << __E__; + __COUTT__ << "Delete row since it no longer part of any group." << __E__; deleteRow(row); wasDeleted = true; } else + { setValue(newValue, row, col); - - //__COUT__ << getDataView()[row][col] << __E__; + __COUTT__ << getDataView()[row][col] << __E__; + } return wasDeleted; } // end removeRowFromGroup() @@ -1674,7 +1683,7 @@ bool TableView::isEntryInGroupCol(const unsigned int& r, unsigned int j = 0; bool found = false; - //__COUT__ << "groupNeedle " << groupNeedle << __E__; + __COUTT__ << "groupNeedle " << groupNeedle << __E__; // go through the full groupString extracting groups and comparing to groupNeedle for(; j < theDataView_[r][c].size(); ++j) @@ -1690,10 +1699,14 @@ bool TableView::isEntryInGroupCol(const unsigned int& r, if(groupIDList) groupIDList->emplace(theDataView_[r][c].substr(i, j - i)); - //__COUT__ << "Group found to compare: " << - // theDataView_[r][c].substr(i,j-i) << __E__; - if(groupNeedle == theDataView_[r][c].substr(i, j - i)) + __COUTT__ << "Group found to compare: " << theDataView_[r][c].substr(i, j - i) + << __E__; + if(groupIDList ? groupNeedle == theDataView_[r][c].substr(i, j - i) + : StringMacros::wildCardMatch( + theDataView_[r][c].substr(i, j - i), groupNeedle)) { + __COUTT__ << "'" << theDataView_[r][c].substr(i, j - i) + << "' is in group '" << groupNeedle << "'!" << __E__; if(!groupIDList) // dont return if caller is trying to get group list return true; found = true; @@ -1707,10 +1720,16 @@ bool TableView::isEntryInGroupCol(const unsigned int& r, if(groupIDList) groupIDList->emplace(theDataView_[r][c].substr(i, j - i)); - //__COUT__ << "Group found to compare: " << - // theDataView_[r][c].substr(i,j-i) << __E__; - if(groupNeedle == theDataView_[r][c].substr(i, j - i)) + __COUTT__ << "Group found to compare: " << theDataView_[r][c].substr(i, j - i) + << __E__; + if(groupIDList ? groupNeedle == theDataView_[r][c].substr(i, j - i) + : StringMacros::wildCardMatch(theDataView_[r][c].substr(i, j - i), + groupNeedle)) + { + __COUTT__ << "'" << theDataView_[r][c].substr(i, j - i) << "' is in group '" + << groupNeedle << "'!" << __E__; return true; + } } return found;