Commit ec38e7a4 authored by Mark Olesen's avatar Mark Olesen
Browse files

ENH: prevent conversion of string to regExp in stringListOps (closes #739)

* For most cases, this conversion would be largely unintentional
  and also less efficient. If the regex is desirable, the caller
  should invoke it explicitly.
  For example,

      findStrings(regExp(str), listOfStrings);

  Or use one of the keyType, wordRe, wordRes variants instead.
  If string is to be used as a plain (non-regex) matcher,
  this can be directly invoked

      findMatchingStrings(str, listOfStrings);

  or using the ListOps instead:

      findIndices(listOfStrings, str);

* provide function interfaces for keyType.
parent f9599279
......@@ -53,7 +53,7 @@ int main(int argc, char *argv[])
Info<< "stringList " << strLst << nl;
labelList matches = findStrings(".*ee.*", strLst);
labelList matches = findStrings(regExp(".*ee.*"), strLst);
Info<< "matches found for regexp .*ee.* :" << nl << matches << nl;
forAll(matches, i)
......@@ -71,7 +71,7 @@ int main(int argc, char *argv[])
}
Info<< endl;
stringList subLst = subsetStrings(".*ee.*", strLst);
stringList subLst = subsetStrings(regExp(".*ee.*"), strLst);
Info<< "subset stringList: " << subLst << nl;
subLst = subsetStrings(reLst, strLst);
......@@ -80,7 +80,7 @@ int main(int argc, char *argv[])
inplaceSubsetStrings(reLst, strLst);
Info<< "subsetted stringList: " << strLst << nl;
inplaceSubsetStrings(".*l.*", strLst);
inplaceSubsetStrings(regExp(".*l.*"), strLst);
Info<< "subsetted stringList: " << strLst << nl;
Info<< "\nEnd\n" << endl;
......
......@@ -178,7 +178,6 @@ bool addEntry
}
// List of indices into thisKeys
labelList findMatches
(
......@@ -194,19 +193,19 @@ labelList findMatches
{
// Wildcard match
matches = findStrings(key, thisKeys);
}
else if (shortcuts.size())
{
// See if patchGroups expand to valid thisKeys
labelList indices = findStrings(key, shortcutNames);
forAll(indices, i)
for (const label idx : indices)
{
const word& name = shortcutNames[indices[i]];
const word& name = shortcutNames[idx];
const wordList& keys = shortcuts[name];
forAll(keys, j)
{
label index = thisKeys.find(keys[j]);
const label index = thisKeys.find(keys[j]);
if (index != -1)
{
matches.append(index);
......
......@@ -137,6 +137,7 @@ int main(int argc, char *argv[])
labelList regionIDs =
findStrings(regionName, surf.regions());
if (modifier().modify(regionIDs, surf))
{
changed = true;
......
......@@ -576,63 +576,65 @@ Foam::labelList Foam::polyBoundaryMesh::findIndices
{
DynamicList<label> indices;
if (!key.empty())
if (key.empty())
{
if (key.isPattern())
// no-op
}
else if (key.isPattern())
{
const regExp keyRe(key);
indices = findStrings(keyRe, this->names());
if (usePatchGroups && groupPatchIDs().size())
{
indices = findStrings(key, this->names());
labelHashSet indexSet(indices);
if (usePatchGroups && groupPatchIDs().size())
const wordList allGroupNames = groupPatchIDs().toc();
labelList groupIDs = findStrings(keyRe, allGroupNames);
forAll(groupIDs, i)
{
labelHashSet indexSet(indices);
const wordList allGroupNames = groupPatchIDs().toc();
labelList groupIDs = findStrings(key, allGroupNames);
forAll(groupIDs, i)
const word& grpName = allGroupNames[groupIDs[i]];
const labelList& patchIDs = groupPatchIDs()[grpName];
forAll(patchIDs, j)
{
const word& grpName = allGroupNames[groupIDs[i]];
const labelList& patchIDs = groupPatchIDs()[grpName];
forAll(patchIDs, j)
if (indexSet.insert(patchIDs[j]))
{
if (indexSet.insert(patchIDs[j]))
{
indices.append(patchIDs[j]);
}
indices.append(patchIDs[j]);
}
}
}
}
else
{
// Literal string. Special version of above to avoid
// unnecessary memory allocations
}
else
{
// Literal string. Special version of above to avoid
// unnecessary memory allocations
indices.setCapacity(1);
forAll(*this, i)
indices.setCapacity(1);
forAll(*this, i)
{
if (key == operator[](i).name())
{
if (key == operator[](i).name())
{
indices.append(i);
break;
}
indices.append(i);
break;
}
}
if (usePatchGroups && groupPatchIDs().size())
if (usePatchGroups && groupPatchIDs().size())
{
const auto iter = groupPatchIDs().cfind(key);
if (iter.found())
{
const HashTable<labelList>::const_iterator iter =
groupPatchIDs().find(key);
labelHashSet indexSet(indices);
if (iter.found())
const labelList& patchIDs = iter();
forAll(patchIDs, j)
{
labelHashSet indexSet(indices);
const labelList& patchIDs = iter();
forAll(patchIDs, j)
if (indexSet.insert(patchIDs[j]))
{
if (indexSet.insert(patchIDs[j]))
{
indices.append(patchIDs[j]);
}
indices.append(patchIDs[j]);
}
}
}
......@@ -645,26 +647,27 @@ Foam::labelList Foam::polyBoundaryMesh::findIndices
Foam::label Foam::polyBoundaryMesh::findIndex(const keyType& key) const
{
if (!key.empty())
if (key.empty())
{
if (key.isPattern())
{
labelList indices = this->findIndices(key);
// no-op
}
else if (key.isPattern())
{
labelList indices = this->findIndices(key);
// return first element
if (!indices.empty())
{
return indices[0];
}
// return first element
if (!indices.empty())
{
return indices[0];
}
else
}
else
{
forAll(*this, i)
{
forAll(*this, i)
if (key == operator[](i).name())
{
if (key == operator[](i).name())
{
return i;
}
return i;
}
}
}
......
......@@ -342,25 +342,26 @@ Foam::labelList Foam::ZoneMesh<ZoneType, MeshType>::findIndices
{
labelList indices;
if (!key.empty())
if (key.empty())
{
if (key.isPattern())
{
indices = findStrings(key, this->names());
}
else
// no-op
}
else if (key.isPattern())
{
indices = findStrings(key, this->names());
}
else
{
indices.setSize(this->size());
label count = 0;
forAll(*this, i)
{
indices.setSize(this->size());
label count = 0;
forAll(*this, i)
if (key == operator[](i).name())
{
if (key == operator[](i).name())
{
indices[count++] = i;
}
indices[count++] = i;
}
indices.setSize(count);
}
indices.setSize(count);
}
return indices;
......@@ -373,26 +374,26 @@ Foam::label Foam::ZoneMesh<ZoneType, MeshType>::findIndex
const keyType& key
) const
{
if (!key.empty())
if (key.empty())
{
if (key.isPattern())
{
labelList indices = this->findIndices(key);
// no-op
}
else if (key.isPattern())
{
labelList indices = this->findIndices(key);
// return first element
if (!indices.empty())
{
return indices[0];
}
if (!indices.empty())
{
return indices.first(); // first match
}
else
}
else
{
forAll(*this, i)
{
forAll(*this, i)
if (key == operator[](i).name())
{
if (key == operator[](i).name())
{
return i;
}
return i;
}
}
}
......@@ -412,7 +413,7 @@ Foam::label Foam::ZoneMesh<ZoneType, MeshType>::findZoneID
forAll(zones, zonei)
{
if (zones[zonei].name() == zoneName)
if (zoneName == zones[zonei].name())
{
return zonei;
}
......
......@@ -43,7 +43,7 @@ SourceFiles
namespace Foam
{
//- Extract list indices
//- Extract list indices for all matches.
// The unary match predicate has the following signature:
// \code
// bool operator()(const std::string& text);
......@@ -78,26 +78,17 @@ namespace Foam
template<class StringType>
labelList findStrings
(
const char* re,
const keyType& matcher,
const UList<StringType>& input,
const bool invert=false
)
{
return findMatchingStrings(regExp(re), input, invert);
}
//- Return list indices for strings matching the regular expression
// Template partial specialization of findMatchingStrings
template<class StringType>
labelList findStrings
(
const std::string& re,
const UList<StringType>& input,
const bool invert=false
)
{
return findMatchingStrings(regExp(re), input, invert);
return
(
matcher.isPattern()
? findMatchingStrings(regExp(matcher), input, invert)
: findMatchingStrings(matcher, input, invert)
);
}
......@@ -178,25 +169,17 @@ namespace Foam
template<class StringListType>
StringListType subsetStrings
(
const char* re,
const keyType& matcher,
const StringListType& input,
const bool invert=false
)
{
return subsetMatchingStrings(regExp(re), input, invert);
}
//- Extract elements of StringList when regular expression matches
// Template partial specialization of subsetMatchingStrings
template<class StringListType>
StringListType subsetStrings
(
const std::string& re,
const StringListType& input,
const bool invert=false
)
{
return subsetMatchingStrings(regExp(re), input, invert);
return
(
matcher.isPattern()
? subsetMatchingStrings(regExp(matcher), input, invert)
: subsetMatchingStrings(matcher, input, invert)
);
}
//- Extract elements of StringList when regular expression matches
......@@ -265,17 +248,22 @@ namespace Foam
inplaceSubsetMatchingStrings(matcher, input, invert);
}
//- Inplace extract elements of StringList when regular expression matches
// Template partial specialization of inplaceSubsetMatchingStrings
//- Extract elements of StringList when regular expression matches
// Template partial specialization of subsetMatchingStrings
template<class StringListType>
void inplaceSubsetStrings
(
const char* re,
const keyType& matcher,
StringListType& input,
const bool invert=false
)
{
inplaceSubsetMatchingStrings(regExp(re), input, invert);
return
(
matcher.isPattern()
? inplaceSubsetMatchingStrings(regExp(matcher), input, invert)
: inplaceSubsetMatchingStrings(matcher, input, invert)
);
}
//- Inplace extract elements of StringList when regular expression matches
......@@ -283,12 +271,12 @@ namespace Foam
template<class StringListType>
void inplaceSubsetStrings
(
const std::string& re,
const wordRe& matcher,
StringListType& input,
const bool invert=false
)
{
inplaceSubsetMatchingStrings(regExp(re), input, invert);
inplaceSubsetMatchingStrings(matcher, input, invert);
}
//- Inplace extract elements of StringList when regular expression matches
......@@ -296,7 +284,7 @@ namespace Foam
template<class StringListType>
void inplaceSubsetStrings
(
const wordRe& matcher,
const wordRes& matcher,
StringListType& input,
const bool invert=false
)
......@@ -309,26 +297,86 @@ namespace Foam
template<class StringListType>
void inplaceSubsetStrings
(
const wordRes& matcher,
const UList<wordRe>& regexs,
StringListType& input,
const bool invert=false
)
{
inplaceSubsetMatchingStrings(matcher, input, invert);
inplaceSubsetMatchingStrings(wordRes::matcher(regexs), input, invert);
}
//- Inplace extract elements of StringList when regular expression matches
// Template partial specialization of inplaceSubsetMatchingStrings
//- Find using C-string as a regex
// \deprecated (FEB-2018) Treating string as regex may be inefficient
// and lead to unintended results.
// Use regExp, keyType, wordRe instead, or findMatchingStrings()
template<class StringType>
labelList findStrings
(
const char* disallowed,
const UList<StringType>& input,
const bool invert=false
) = delete;
//- Find using string as a regex
// \deprecated (FEB-2018) Treating string as regex may be inefficient
// and lead to unintended results.
// Use regExp, keyType, wordRe instead, or findMatchingStrings()
template<class StringType>
labelList findStrings
(
const std::string& disallowed,
const UList<StringType>& input,
const bool invert=false
) = delete;
//- Subset using C-string as a regex
// \deprecated (FEB-2018) Treating string as regex may be inefficient
// and lead to unintended results.
// Use regExp, keyType, wordRe instead, or subsetMatchingStrings()
template<class StringListType>
StringListType subsetStrings
(
const char* disallowed,
const StringListType& input,
const bool invert=false
) = delete;
//- Subset using string as a regex
// \deprecated (FEB-2018) Treating string as regex may be inefficient
// and lead to unintended results.
// Use regExp, keyType, wordRe instead, or subsetMatchingStrings()
template<class StringListType>
StringListType subsetStrings
(
const std::string& disallowed,
const StringListType& input,
const bool invert=false
) = delete;
//- Subset using C-string as a regex
// \deprecated (FEB-2018) Treating string as regex may be inefficient
// and lead to unintended results.
// Use regExp, keyType, wordRe instead, or inplaceSubsetMatchingStrings()
template<class StringListType>
void inplaceSubsetStrings
(
const UList<wordRe>& regexs,
const char* disallowed,
StringListType& input,
const bool invert=false
)
{
inplaceSubsetMatchingStrings(wordRes::matcher(regexs), input, invert);
}
) = delete;
//- Subset using string as a regex
// \deprecated (FEB-2018) Treating string as regex may be inefficient
// and lead to unintended results.
// Use keyType, wordRe instead, or inplaceSubsetMatchingStrings()
template<class StringListType>
void inplaceSubsetStrings
(
const std::string& disallowed,
StringListType& input,
const bool invert=false
) = delete;
}
......
......@@ -149,11 +149,7 @@ void Foam::ensightMesh::correct()
if (!matcher.empty())
{
useAll = false;
matched = findMatchingStrings
(
matcher,
patchNames
);
matched = findStrings(matcher, patchNames);
}
}
......@@ -248,11 +244,7 @@ void Foam::ensightMesh::correct()
const wordRes& matcher = option().faceZoneSelection();
wordList selectZones = mesh_.faceZones().names();
inplaceSubsetMatchingStrings
(
matcher,
selectZones
);
subsetMatchingStrings(matcher, selectZones);
// have same order as later with sortedToc()
Foam::sort(selectZones);
......
......@@ -194,25 +194,26 @@ Foam::labelList Foam::faBoundaryMesh::findIndices
{
DynamicList<label> indices;
if (!key.empty())
if (key.empty())
{
if (key.isPattern())
{
indices = findStrings(key, this->names());
}
else
{
// Literal string. Special version of above to avoid
// unnecessary memory allocations
// no-op
}
else if (key.isPattern())
{
indices = findStrings(key, this->names());
}
else
{
// Literal string. Special version of above to avoid
// unnecessary memory allocations
indices.setCapacity(1);
forAll(*this, i)
indices.setCapacity(1);
forAll(*this, i)
{
if (key == operator[](i).name())
{
if (key == operator[](i).name())
{
indices.append(i);
break;
}
indices.append(i);
break;
}
}
}
......