From 16dd92b38ecf6dc2c01a6209e7d4beeef4e9f8a7 Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@esi-group.com>
Date: Fri, 12 Apr 2024 21:03:27 +0200
Subject: [PATCH] ENH: reduce reliance on stringListOps functions

- findStrings, findMatchingStrings now mostly covered by matching
  intrinsics in wordRe and wordRes.

  Add static wordRes match() and matching() variants

COMP: remove stringListOps include from objectRegistry.H

- was already noted for removal (NOV-2018)
---
 .../finiteArea/makeFaMesh/decomposeFaFields.H |   2 +-
 .../foamToEnsight/checkFieldAvailability.H    |   2 +-
 .../dataConversion/foamToVTK/foamToVTK.C      |   4 +-
 .../changeDictionary/changeDictionary.C       |  11 +-
 .../surfaceMeshExtract/surfaceMeshExtract.C   |   1 +
 .../searchableSurfaceModifier/cut.C           |   4 +-
 .../surface/surfacePatch/surfacePatch.C       |  12 +-
 .../surfaceSplitByPatch/surfaceSplitByPatch.C |   2 +-
 .../functionEntries/removeEntry/removeEntry.C |   6 +-
 .../functionObjectList/functionObjectList.C   |   2 +-
 .../db/objectRegistry/objectRegistry.H        |   5 -
 .../exprDriver/exprDriverFunctions.C          |   4 +-
 src/OpenFOAM/global/argList/argList.C         |   4 +-
 .../primitives/strings/stringOps/stringOps.H  |   8 +-
 .../primitives/strings/wordRes/wordRes.H      |  96 +++++++++-----
 .../primitives/strings/wordRes/wordResI.H     | 117 ++++++++++++++----
 src/fileFormats/ensight/mesh/ensightMesh.C    |   1 +
 .../fieldSelection/fieldSelection.C           |   2 +-
 src/functionObjects/field/ddt2/ddt2.C         |   9 +-
 .../field/externalCoupled/externalCoupled.C   |   5 +-
 .../field/wallHeatFlux/wallHeatFlux.C         |   2 +-
 .../field/wallShearStress/wallShearStress.C   |   2 +-
 .../field/zeroGradient/zeroGradient.C         |   9 +-
 .../utilities/ensightWrite/ensightWrite.C     |   2 +-
 .../utilities/vtkWrite/vtkWrite.C             |   4 +-
 .../ParticleErosion/ParticleErosion.C         |   9 +-
 .../ParticleHistogram/ParticleHistogram.C     |   1 -
 .../ParticlePostProcessing.C                  |   1 -
 .../PatchCollisionDensity.C                   |   1 -
 .../triSurfaceLoader/triSurfaceLoader.C       |  10 +-
 .../curvatureSeparation/curvatureSeparation.C |   1 -
 .../sampledSet/sampledSets/sampledSets.C      |   2 +-
 .../sampledMeshedSurface.C                    |   1 +
 .../sampledSurfaces/sampledSurfaces.C         |   2 +-
 .../surfaceFormats/surfaceFormatsCore.C       |   4 +-
 src/surfMesh/triSurface/triSurface.C          |   3 +-
 36 files changed, 233 insertions(+), 118 deletions(-)

diff --git a/applications/utilities/finiteArea/makeFaMesh/decomposeFaFields.H b/applications/utilities/finiteArea/makeFaMesh/decomposeFaFields.H
index fd5840f30ea..1e60c422d73 100644
--- a/applications/utilities/finiteArea/makeFaMesh/decomposeFaFields.H
+++ b/applications/utilities/finiteArea/makeFaMesh/decomposeFaFields.H
@@ -55,7 +55,7 @@ do
 
         bitSet haveMeshOnProc;
         std::unique_ptr<faMeshSubset> subsetter;
-        IOobjectList objects(0);
+        IOobjectList objects;
 
         refPtr<fileOperation> newHandler(fileOperation::NewUncollated());
 
diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/checkFieldAvailability.H b/applications/utilities/postProcessing/dataConversion/foamToEnsight/checkFieldAvailability.H
index 2cb2c78530d..a51456de2d8 100644
--- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/checkFieldAvailability.H
+++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/checkFieldAvailability.H
@@ -26,7 +26,7 @@ forAll(meshes, regioni)
 {
     const auto& mesh = meshes[regioni];
 
-    IOobjectList objects(0);
+    IOobjectList objects;
 
     if (doConvertFields && !timeDirs.empty())
     {
diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C
index 3d69fd3595b..b831277343c 100644
--- a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C
+++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C
@@ -141,7 +141,7 @@ Note
 #include "pointSet.H"
 #include "HashOps.H"
 #include "regionProperties.H"
-#include "stringListOps.H"
+#include "stringListOps.H"  // For stringListOps::findMatching()
 
 #include "Cloud.H"
 #include "readFields.H"
@@ -780,7 +780,7 @@ int main(int argc, char *argv[])
                 }
             }
 
-            IOobjectList objects(0);
+            IOobjectList objects;
 
             if (doConvertFields)
             {
diff --git a/applications/utilities/preProcessing/changeDictionary/changeDictionary.C b/applications/utilities/preProcessing/changeDictionary/changeDictionary.C
index 6d46b060971..b72a1c41c47 100644
--- a/applications/utilities/preProcessing/changeDictionary/changeDictionary.C
+++ b/applications/utilities/preProcessing/changeDictionary/changeDictionary.C
@@ -80,7 +80,6 @@ Usage
 #include "IOobjectList.H"
 #include "IOPtrList.H"
 #include "volFields.H"
-#include "stringListOps.H"
 #include "timeSelector.H"
 
 using namespace Foam;
@@ -189,7 +188,7 @@ labelList findMatches
     const HashTable<wordList>& shortcuts,
     const wordList& shortcutNames,
     const wordList& thisKeys,
-    const keyType& key
+    const wordRe& key
 )
 {
     labelList matches;
@@ -197,20 +196,20 @@ labelList findMatches
     if (key.isPattern())
     {
         // Wildcard match
-        matches = findStrings(key, thisKeys);
+        matches = wordRes::matching(key, thisKeys);
     }
     else if (shortcuts.size())
     {
         // See if patchGroups expand to valid thisKeys
-        labelList indices = findStrings(key, shortcutNames);
+        labelList indices = wordRes::matching(key, shortcutNames);
 
         for (const label idx : indices)
         {
             const word& name = shortcutNames[idx];
             const wordList& keys = shortcuts[name];
-            forAll(keys, j)
+            for (const word& k : keys)
             {
-                const label index = thisKeys.find(keys[j]);
+                const label index = thisKeys.find(k);
                 if (index != -1)
                 {
                     matches.append(index);
diff --git a/applications/utilities/surface/surfaceMeshExtract/surfaceMeshExtract.C b/applications/utilities/surface/surfaceMeshExtract/surfaceMeshExtract.C
index 21a9a20fc7d..3387ad26411 100644
--- a/applications/utilities/surface/surfaceMeshExtract/surfaceMeshExtract.C
+++ b/applications/utilities/surface/surfaceMeshExtract/surfaceMeshExtract.C
@@ -51,6 +51,7 @@ Description
 #include "emptyPolyPatch.H"
 #include "processorPolyPatch.H"
 #include "ListListOps.H"
+#include "stringListOps.H"  // For stringListOps::findMatching()
 #include "indirectPrimitivePatch.H"
 #include "globalMeshData.H"
 #include "globalIndex.H"
diff --git a/applications/utilities/surface/surfacePatch/searchableSurfaceModifier/cut.C b/applications/utilities/surface/surfacePatch/searchableSurfaceModifier/cut.C
index 247b33116a8..465da8e412a 100644
--- a/applications/utilities/surface/surfacePatch/searchableSurfaceModifier/cut.C
+++ b/applications/utilities/surface/surfacePatch/searchableSurfaceModifier/cut.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2014 OpenFOAM Foundation
-    Copyright (C) 2020 OpenCFD Ltd.
+    Copyright (C) 2020-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -294,7 +294,7 @@ bool Foam::searchableSurfaceModifiers::cut::modify
     // Find the surfaces to cut with
     for (const wordRe& cutterName : cutterNames_)
     {
-        labelList geomIDs = findStrings(cutterName, geometry_.names());
+        labelList geomIDs = wordRes::matching(cutterName, geometry_.names());
 
         for (const label geomI : geomIDs)
         {
diff --git a/applications/utilities/surface/surfacePatch/surfacePatch.C b/applications/utilities/surface/surfacePatch/surfacePatch.C
index 0a2ea07db3a..c07d22603a0 100644
--- a/applications/utilities/surface/surfacePatch/surfacePatch.C
+++ b/applications/utilities/surface/surfacePatch/surfacePatch.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2013 OpenFOAM Foundation
-    Copyright (C) 2015-2022 OpenCFD Ltd.
+    Copyright (C) 2015-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -130,9 +130,14 @@ int main(int argc, char *argv[])
 
                 for (const entry& e : regionsDict)
                 {
-                    const keyType& regionName = e.keyword();
+                    const wordRe regionName(e.keyword());
                     const dictionary& regionDict = e.dict();
 
+                    labelList regionIDs
+                    (
+                        wordRes::matching(regionName, surf.regions())
+                    );
+
                     autoPtr<searchableSurfaceModifier> modifier
                     (
                         searchableSurfaceModifier::New
@@ -143,9 +148,6 @@ int main(int argc, char *argv[])
                         )
                     );
 
-                    labelList regionIDs =
-                        findStrings(regionName, surf.regions());
-
                     if (modifier().modify(regionIDs, surf))
                     {
                         changed = true;
diff --git a/applications/utilities/surface/surfaceSplitByPatch/surfaceSplitByPatch.C b/applications/utilities/surface/surfaceSplitByPatch/surfaceSplitByPatch.C
index e4674a5b639..6bcd3b20ea4 100644
--- a/applications/utilities/surface/surfaceSplitByPatch/surfaceSplitByPatch.C
+++ b/applications/utilities/surface/surfaceSplitByPatch/surfaceSplitByPatch.C
@@ -56,7 +56,7 @@ Usage
 
 #include "argList.H"
 #include "MeshedSurfaces.H"
-#include "stringListOps.H"
+#include "stringListOps.H"  // For stringListOps::findMatching()
 #include "geometricSurfacePatch.H"
 
 using namespace Foam;
diff --git a/src/OpenFOAM/db/dictionary/functionEntries/removeEntry/removeEntry.C b/src/OpenFOAM/db/dictionary/functionEntries/removeEntry/removeEntry.C
index 2126d797e3f..3a3846080b9 100644
--- a/src/OpenFOAM/db/dictionary/functionEntries/removeEntry/removeEntry.C
+++ b/src/OpenFOAM/db/dictionary/functionEntries/removeEntry/removeEntry.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011 OpenFOAM Foundation
-    Copyright (C) 2017-2022 OpenCFD Ltd.
+    Copyright (C) 2017-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -28,7 +28,7 @@ License
 
 #include "removeEntry.H"
 #include "dictionary.H"
-#include "stringListOps.H"
+#include "wordRes.H"
 #include "addToMemberFunctionSelectionTable.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@@ -75,7 +75,7 @@ bool Foam::functionEntries::removeEntry::execute
         {
             // Remove by pattern
             const wordList dictKeys = parentDict.toc();
-            const labelList indices = findStrings(key, dictKeys);
+            const labelList indices = wordRes::matching(key, dictKeys);
 
             for (const auto idx : indices)
             {
diff --git a/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.C b/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.C
index c9b108be34f..806e9659b46 100644
--- a/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.C
+++ b/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.C
@@ -822,7 +822,7 @@ bool Foam::functionObjectList::execute
     {
         for (functionObject& funcObj : functions())
         {
-            if (stringOps::match(functionNames, funcObj.name()))
+            if (wordRes::match(functionNames, funcObj.name()))
             {
                 // Probably do not need try/catch...
 
diff --git a/src/OpenFOAM/db/objectRegistry/objectRegistry.H b/src/OpenFOAM/db/objectRegistry/objectRegistry.H
index 957eb5fb1ed..9fed2b2c2c9 100644
--- a/src/OpenFOAM/db/objectRegistry/objectRegistry.H
+++ b/src/OpenFOAM/db/objectRegistry/objectRegistry.H
@@ -46,11 +46,6 @@ SourceFiles
 #include "wordRes.H"
 #include "Pair.H"
 
-// Historically included by objectRegistryTemplates (until NOV-2018),
-// but not used by objectRegistry directly.
-// Leave here for now to avoid a missing include in other bits of code.
-#include "stringListOps.H"
-
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 namespace Foam
diff --git a/src/OpenFOAM/expressions/exprDriver/exprDriverFunctions.C b/src/OpenFOAM/expressions/exprDriver/exprDriverFunctions.C
index f1d0096a15e..9618e51bcdd 100644
--- a/src/OpenFOAM/expressions/exprDriver/exprDriverFunctions.C
+++ b/src/OpenFOAM/expressions/exprDriver/exprDriverFunctions.C
@@ -42,8 +42,8 @@ static wordHashSet getAcceptableFunctionKeys
     const bool report = false
 )
 {
-    wordHashSet acceptKeys(0);
-    wordHashSet rejectKeys(0);
+    wordHashSet acceptKeys;
+    wordHashSet rejectKeys;
 
     if (!dictPtr)
     {
diff --git a/src/OpenFOAM/global/argList/argList.C b/src/OpenFOAM/global/argList/argList.C
index 021abff1575..7f6966855a7 100644
--- a/src/OpenFOAM/global/argList/argList.C
+++ b/src/OpenFOAM/global/argList/argList.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2017 OpenFOAM Foundation
-    Copyright (C) 2015-2023 OpenCFD Ltd.
+    Copyright (C) 2015-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -1476,7 +1476,7 @@ void Foam::argList::parse
                 {
                     labelList matched
                     (
-                        findMatchingStrings(hostRoot.first(), hostMachine)
+                        wordRes::matching(hostRoot.first(), hostMachine)
                     );
                     for (const label matchi : matched)
                     {
diff --git a/src/OpenFOAM/primitives/strings/stringOps/stringOps.H b/src/OpenFOAM/primitives/strings/stringOps/stringOps.H
index 11807754ba3..8f8a7a110cf 100644
--- a/src/OpenFOAM/primitives/strings/stringOps/stringOps.H
+++ b/src/OpenFOAM/primitives/strings/stringOps/stringOps.H
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2012 OpenFOAM Foundation
-    Copyright (C) 2016-2021 OpenCFD Ltd.
+    Copyright (C) 2016-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -70,10 +70,10 @@ namespace stringOps
     //- Count the number of occurrences of the specified character
     std::string::size_type count(const std::string& s, const char c);
 
-    //- Return true if text matches one of the regular expressions.
-    inline bool match(const UList<wordRe>& patterns, const std::string& text)
+    //- True if text matches one of the selector expressions
+    inline bool match(const UList<wordRe>& selectors, const std::string& text)
     {
-        return wordRes::matcher(patterns)(text);
+        return wordRes::match(selectors, text);
     }
 
     //- Quote any meta-characters in given string
diff --git a/src/OpenFOAM/primitives/strings/wordRes/wordRes.H b/src/OpenFOAM/primitives/strings/wordRes/wordRes.H
index e665f4d52dc..f106b2c5981 100644
--- a/src/OpenFOAM/primitives/strings/wordRes/wordRes.H
+++ b/src/OpenFOAM/primitives/strings/wordRes/wordRes.H
@@ -5,7 +5,7 @@
     \\  /    A nd           | www.openfoam.com
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
-    Copyright (C) 2016-2023 OpenCFD Ltd.
+    Copyright (C) 2016-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -67,24 +67,13 @@ class wordRes
         (
             const UList<wordRe>& selectors,
             const std::string& text,
-            const bool literal=false
-        );
-
-        //- Smart match across entire list, returning the best match type.
-        //  Stops on the first literal match, or continues to examine
-        //  if a regex match occurs.
-        //  \return wordRe::LITERAL, wordRe::REGEX on match and
-        //      wordRe::UNKNOWN otherwise.
-        inline static wordRe::compOption found_matched
-        (
-            const UList<wordRe>& selectors,
-            const std::string& text
+            const bool literal = false
         );
 
 
 public:
 
-    // Static Data / Methods
+    // Static Methods
 
         //- Return a null wordRes (reference to a nullObject).
         //- Behaves like a empty wordRes.
@@ -93,10 +82,6 @@ public:
             return NullObjectRef<wordRes>();
         }
 
-        //- Return a wordRes with duplicate entries filtered out.
-        //  No distinction made between literals and regular expressions.
-        static wordRes uniq(const UList<wordRe>& input);
-
 
     // Constructors
 
@@ -108,6 +93,60 @@ public:
     ~wordRes() = default;
 
 
+    // Static Functions
+
+        //- Return a wordRes with duplicate entries filtered out.
+        //  No distinction made between literals and regular expressions.
+        static wordRes uniq(const UList<wordRe>& input);
+
+        //- Test for a match
+        inline static bool match
+        (
+            const UList<wordRe>& selectors,
+            const std::string& text,
+            bool literal = false
+        );
+
+        //- Smart match across entire list, returning the best match type.
+        //  Stops on the first literal match, or continues to examine
+        //  if a regex match occurs.
+        //  \return wordRe::LITERAL, wordRe::REGEX on match and
+        //      wordRe::UNKNOWN otherwise.
+        inline static wordRe::compOption matched
+        (
+            const UList<wordRe>& selectors,
+            const std::string& text
+        );
+
+        //- Determine the list indices for all matches.
+        //
+        //  \return indices of the matches in the input list
+        template<class StringType>
+        inline static labelList matching
+        (
+            //! A single literal or pattern matcher
+            const wordRe& select,
+            //! List of string inputs to match against
+            const UList<StringType>& input,
+            //! Invert the matching logic
+            const bool invert = false
+        );
+
+        //- Determine the list indices for all matches.
+        //
+        //  \return indices of the matches in the input list
+        template<class StringType>
+        inline static labelList matching
+        (
+            //! The list of matchers
+            const UList<wordRe>& selectors,
+            //! List of string inputs to match against
+            const UList<StringType>& input,
+            //! Invert the matching logic
+            const bool invert = false
+        );
+
+
     // Member Functions
 
         //- Filter out duplicate entries (inplace).
@@ -128,16 +167,16 @@ public:
         //      UNKNOWN otherwise.
         inline wordRe::compOption matched(const std::string& text) const;
 
-        //- Return list indices for all matches.
+        //- Determine the list indices for all matches.
         //
-        //  \param input  A list of string inputs to match against
-        //  \param invert invert the matching logic
         //  \return indices of the matches in the input list
         template<class StringType>
         inline labelList matching
         (
+            //! List of string inputs to match against
             const UList<StringType>& input,
-            const bool invert=false
+            //! Invert the matching logic
+            const bool invert = false
         ) const;
 
 
@@ -152,18 +191,19 @@ public:
         //- Functor wrapper of a list of wordRe for matching
         struct matcher
         {
-            //- Construct with 'allow' matcher
-            inline matcher(const UList<wordRe>& allow);
+            //- Construct with \em select matcher(s)
+            inline explicit matcher(const UList<wordRe>& selectors) noexcept;
 
-            //- Nothing defined
+            //- No selectors defined
             inline bool empty() const noexcept;
 
-            //- True if text matches ANY of the entries.
+            //- True if text matches ANY of the selectors.
+            //- Always false if entries are empty.
             //  Allows use as a predicate.
             inline bool operator()(const std::string& text) const;
 
         private:
-            const UList<wordRe>& allow_;
+            const UList<wordRe>& select_;
         };
 
 
@@ -188,7 +228,7 @@ public:
             (
                 const UList<wordRe>& allow,
                 const UList<wordRe>& deny
-            );
+            ) noexcept;
 
             //- Nothing defined
             inline bool empty() const noexcept;
diff --git a/src/OpenFOAM/primitives/strings/wordRes/wordResI.H b/src/OpenFOAM/primitives/strings/wordRes/wordResI.H
index 2b72076d961..d8a4a1d4343 100644
--- a/src/OpenFOAM/primitives/strings/wordRes/wordResI.H
+++ b/src/OpenFOAM/primitives/strings/wordRes/wordResI.H
@@ -48,7 +48,27 @@ inline Foam::label Foam::wordRes::first_match
 }
 
 
-inline Foam::wordRe::compOption Foam::wordRes::found_matched
+// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
+
+inline bool Foam::wordRes::match
+(
+    const UList<wordRe>& selectors,
+    const std::string& text,
+    bool literal
+)
+{
+    for (const wordRe& select : selectors)
+    {
+        if (select.match(text, literal))
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+
+inline Foam::wordRe::compOption Foam::wordRes::matched
 (
     const UList<wordRe>& selectors,
     const std::string& text
@@ -80,36 +100,59 @@ inline Foam::wordRe::compOption Foam::wordRes::found_matched
 }
 
 
-// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
-
-inline bool Foam::wordRes::match(const std::string& text, bool literal) const
+template<class StringType>
+inline Foam::labelList Foam::wordRes::matching
+(
+    const wordRe& select,
+    const UList<StringType>& input,
+    const bool invert
+)
 {
-    return (first_match(*this, text, literal) >= 0);
-}
+    if (select.empty() && !invert)
+    {
+        return labelList();
+    }
 
+    const label len = input.size();
 
-inline Foam::wordRe::compOption
-Foam::wordRes::matched(const std::string& text) const
-{
-    return found_matched(*this, text);
+    labelList indices(len);
+
+    label count = 0;
+    for (label i = 0; i < len; ++i)
+    {
+        if (select.match(input[i]) ? !invert : invert)
+        {
+            indices[count] = i;
+            ++count;
+        }
+    }
+    indices.resize(count);
+
+    return indices;
 }
 
 
 template<class StringType>
 inline Foam::labelList Foam::wordRes::matching
 (
+    const UList<wordRe>& selectors,
     const UList<StringType>& input,
     const bool invert
-) const
+)
 {
+    if (selectors.empty() && !invert)
+    {
+        return labelList();
+    }
+
     const label len = input.size();
 
     labelList indices(len);
 
     label count = 0;
-    for (label i=0; i < len; ++i)
+    for (label i = 0; i < len; ++i)
     {
-        if (match(input[i]) ? !invert : invert)
+        if (wordRes::match(selectors, input[i]) ? !invert : invert)
         {
             indices[count] = i;
             ++count;
@@ -121,11 +164,37 @@ inline Foam::labelList Foam::wordRes::matching
 }
 
 
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+inline bool Foam::wordRes::match(const std::string& text, bool literal) const
+{
+    return wordRes::match(*this, text, literal);
+}
+
+
+inline Foam::wordRe::compOption
+Foam::wordRes::matched(const std::string& text) const
+{
+    return wordRes::matched(*this, text);
+}
+
+
+template<class StringType>
+inline Foam::labelList Foam::wordRes::matching
+(
+    const UList<StringType>& input,
+    const bool invert
+) const
+{
+    return wordRes::matching(*this, input, invert);
+}
+
+
 // * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
 
 inline bool Foam::wordRes::operator()(const std::string& text) const
 {
-    return (wordRes::first_match(*this, text) >= 0);
+    return wordRes::match(*this, text);
 }
 
 
@@ -133,10 +202,10 @@ inline bool Foam::wordRes::operator()(const std::string& text) const
 
 inline Foam::wordRes::matcher::matcher
 (
-    const UList<wordRe>& allow
-)
+    const UList<wordRe>& selectors
+) noexcept
 :
-    allow_(allow)
+    select_(selectors)
 {}
 
 
@@ -144,7 +213,7 @@ inline Foam::wordRes::filter::filter
 (
     const UList<wordRe>& allow,
     const UList<wordRe>& deny
-)
+) noexcept
 :
     allow_(allow),
     deny_(deny)
@@ -153,7 +222,7 @@ inline Foam::wordRes::filter::filter
 
 inline bool Foam::wordRes::matcher::empty() const noexcept
 {
-    return allow_.empty();
+    return select_.empty();
 }
 
 inline bool Foam::wordRes::filter::empty() const noexcept
@@ -164,7 +233,7 @@ inline bool Foam::wordRes::filter::empty() const noexcept
 
 inline bool Foam::wordRes::matcher::operator()(const std::string& text) const
 {
-    return (wordRes::first_match(allow_, text) >= 0);
+    return wordRes::match(select_, text);
 }
 
 
@@ -173,17 +242,17 @@ inline bool Foam::wordRes::filter::operator()(const std::string& text) const
     if (allow_.empty())
     {
         // No allow specified, so accept everything that is NOT blocked
-        return (deny_.empty() || (wordRes::first_match(deny_, text) < 0));
+        return (deny_.empty() || !wordRes::match(deny_, text));
     }
     else if (deny_.empty())
     {
         // Nothing blocked, apply accept filter
-        return (wordRes::first_match(allow_, text) >= 0);
+        return wordRes::match(allow_, text);
     }
     else
     {
         // Both accept and deny filters, need to search more carefully
-        const auto result = wordRes::found_matched(allow_, text);
+        const auto result = wordRes::matched(allow_, text);
 
         return
         (
@@ -192,7 +261,7 @@ inline bool Foam::wordRes::filter::operator()(const std::string& text) const
           :
             (
                 result == wordRe::REGEX
-             && (wordRes::first_match(deny_, text) < 0)
+             && !wordRes::match(deny_, text)
             )
         );
     }
diff --git a/src/fileFormats/ensight/mesh/ensightMesh.C b/src/fileFormats/ensight/mesh/ensightMesh.C
index d57478fa2d8..233bb449d64 100644
--- a/src/fileFormats/ensight/mesh/ensightMesh.C
+++ b/src/fileFormats/ensight/mesh/ensightMesh.C
@@ -31,6 +31,7 @@ License
 #include "polyMesh.H"
 #include "emptyPolyPatch.H"
 #include "processorPolyPatch.H"
+#include "stringListOps.H"   // For stringListOps::findMatching()
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
diff --git a/src/finiteVolume/functionObjects/fieldSelections/fieldSelection/fieldSelection.C b/src/finiteVolume/functionObjects/fieldSelections/fieldSelection/fieldSelection.C
index a570ebdebd0..f07e1afc6d0 100644
--- a/src/finiteVolume/functionObjects/fieldSelections/fieldSelection/fieldSelection.C
+++ b/src/finiteVolume/functionObjects/fieldSelections/fieldSelection/fieldSelection.C
@@ -136,7 +136,7 @@ bool Foam::functionObjects::fieldSelection::resetFieldFilters
 
 bool Foam::functionObjects::fieldSelection::read(const dictionary& dict)
 {
-    HashSet<wordRe> fields(0);
+    HashSet<wordRe> fields;
     dict.readEntry("fields", fields);
 
     return resetFieldFilters(fields);
diff --git a/src/functionObjects/field/ddt2/ddt2.C b/src/functionObjects/field/ddt2/ddt2.C
index 0cdc3252977..c4f8f83dc26 100644
--- a/src/functionObjects/field/ddt2/ddt2.C
+++ b/src/functionObjects/field/ddt2/ddt2.C
@@ -5,7 +5,7 @@
     \\  /    A nd           | www.openfoam.com
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
-    Copyright (C) 2016-2022 OpenCFD Ltd.
+    Copyright (C) 2016-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -27,7 +27,6 @@ License
 
 #include "ddt2.H"
 #include "stringOps.H"
-#include "stringListOps.H"
 #include "volFields.H"
 #include "dictionary.H"
 #include "wordRes.H"
@@ -173,7 +172,11 @@ bool Foam::functionObjects::ddt2::execute()
 {
     results_.clear();
 
-    wordHashSet candidates(subsetStrings(selectFields_, mesh_.names()));
+    wordHashSet candidates
+    (
+        mesh_.names(selectFields_)
+    );
+
     DynamicList<word> missing(selectFields_.size());
     DynamicList<word> ignored(selectFields_.size());
 
diff --git a/src/functionObjects/field/externalCoupled/externalCoupled.C b/src/functionObjects/field/externalCoupled/externalCoupled.C
index fb91a1c315b..5b69105194e 100644
--- a/src/functionObjects/field/externalCoupled/externalCoupled.C
+++ b/src/functionObjects/field/externalCoupled/externalCoupled.C
@@ -581,7 +581,10 @@ bool Foam::functionObjects::externalCoupled::read(const dictionary& dict)
         const wordRe regionGroupName(dEntry.keyword());
         const dictionary& regionDict = dEntry.dict();
 
-        labelList regionIDs = findStrings(regionGroupName, allRegionNames);
+        labelList regionIDs
+        (
+            wordRes::matching(regionGroupName, allRegionNames)
+        );
 
         const wordList regionNames(allRegionNames, regionIDs);
 
diff --git a/src/functionObjects/field/wallHeatFlux/wallHeatFlux.C b/src/functionObjects/field/wallHeatFlux/wallHeatFlux.C
index 3235b4cbc55..70618231d07 100644
--- a/src/functionObjects/field/wallHeatFlux/wallHeatFlux.C
+++ b/src/functionObjects/field/wallHeatFlux/wallHeatFlux.C
@@ -146,7 +146,7 @@ bool Foam::functionObjects::wallHeatFlux::read(const dictionary& dict)
     dict.readIfPresent("qr", qrName_);
 
     wordRes patchNames;
-    labelHashSet patchSet(0);
+    labelHashSet patchSet;
     if (dict.readIfPresent("patches", patchNames) && !patchNames.empty())
     {
         patchSet = pbm.patchSet(patchNames);
diff --git a/src/functionObjects/field/wallShearStress/wallShearStress.C b/src/functionObjects/field/wallShearStress/wallShearStress.C
index 6fd8853dcc5..1a7325e03f9 100644
--- a/src/functionObjects/field/wallShearStress/wallShearStress.C
+++ b/src/functionObjects/field/wallShearStress/wallShearStress.C
@@ -131,7 +131,7 @@ bool Foam::functionObjects::wallShearStress::read(const dictionary& dict)
     const polyBoundaryMesh& pbm = mesh_.boundaryMesh();
 
     wordRes patchNames;
-    labelHashSet patchSet(0);
+    labelHashSet patchSet;
     if (dict.readIfPresent("patches", patchNames) && !patchNames.empty())
     {
         patchSet = pbm.patchSet(patchNames);
diff --git a/src/functionObjects/field/zeroGradient/zeroGradient.C b/src/functionObjects/field/zeroGradient/zeroGradient.C
index d0b953252e0..ba0977f6582 100644
--- a/src/functionObjects/field/zeroGradient/zeroGradient.C
+++ b/src/functionObjects/field/zeroGradient/zeroGradient.C
@@ -5,7 +5,7 @@
     \\  /    A nd           | www.openfoam.com
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
-    Copyright (C) 2016-2022 OpenCFD Ltd.
+    Copyright (C) 2016-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -26,7 +26,6 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "zeroGradient.H"
-#include "stringListOps.H"
 #include "volFields.H"
 #include "dictionary.H"
 #include "wordRes.H"
@@ -135,7 +134,11 @@ bool Foam::functionObjects::zeroGradient::execute()
 {
     results_.clear();
 
-    wordHashSet candidates(subsetStrings(selectFields_, mesh_.names()));
+    wordHashSet candidates
+    (
+        mesh_.names(selectFields_)
+    );
+
     DynamicList<word> missing(selectFields_.size());
     DynamicList<word> ignored(selectFields_.size());
 
diff --git a/src/functionObjects/utilities/ensightWrite/ensightWrite.C b/src/functionObjects/utilities/ensightWrite/ensightWrite.C
index 7b203564170..fcbca27eeb9 100644
--- a/src/functionObjects/utilities/ensightWrite/ensightWrite.C
+++ b/src/functionObjects/utilities/ensightWrite/ensightWrite.C
@@ -244,7 +244,7 @@ bool Foam::functionObjects::ensightWrite::write()
     // Output fields MUST be specified to avoid accidentally
     // writing everything. Can still use ".*" for everything
 
-    wordHashSet candidateNames(0);
+    wordHashSet candidateNames;
 
     if (!selectFields_.empty())
     {
diff --git a/src/functionObjects/utilities/vtkWrite/vtkWrite.C b/src/functionObjects/utilities/vtkWrite/vtkWrite.C
index ed322d5180c..6d808a1e903 100644
--- a/src/functionObjects/utilities/vtkWrite/vtkWrite.C
+++ b/src/functionObjects/utilities/vtkWrite/vtkWrite.C
@@ -29,7 +29,7 @@ License
 #include "dictionary.H"
 #include "Time.H"
 #include "areaFields.H"
-#include "stringListOps.H"
+#include "stringListOps.H"   // For stringListOps::foundOp()
 #include "foamVtkInternalWriter.H"
 #include "foamVtkPatchWriter.H"
 #include "foamVtkSeriesWriter.H"
@@ -304,7 +304,7 @@ bool Foam::functionObjects::vtkWrite::write()
         // Output fields MUST be specified to avoid accidentally
         // writing everything. Can still use ".*" for everything
 
-        wordHashSet candidateNames(0);
+        wordHashSet candidateNames;
 
         if (!selectFields_.empty())
         {
diff --git a/src/lagrangian/intermediate/submodels/CloudFunctionObjects/ParticleErosion/ParticleErosion.C b/src/lagrangian/intermediate/submodels/CloudFunctionObjects/ParticleErosion/ParticleErosion.C
index df282484581..9eba501588b 100644
--- a/src/lagrangian/intermediate/submodels/CloudFunctionObjects/ParticleErosion/ParticleErosion.C
+++ b/src/lagrangian/intermediate/submodels/CloudFunctionObjects/ParticleErosion/ParticleErosion.C
@@ -27,6 +27,7 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "ParticleErosion.H"
+#include "wordRes.H"
 
 // * * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * //
 
@@ -110,15 +111,15 @@ Foam::ParticleErosion<CloudType>::ParticleErosion
     );
 
     labelHashSet uniqIds;
-    for (const wordRe& re : patchNames)
+    for (const wordRe& select : patchNames)
     {
-        labelList ids = findMatchingStrings(re, allPatchNames);
+        labelList ids = wordRes::matching(select, allPatchNames);
 
         if (ids.empty())
         {
             WarningInFunction
-                << "Cannot find any patch names matching " << re
-                << endl;
+                << "Cannot find any patch names matching "
+                << select << nl;
         }
 
         uniqIds.insert(ids);
diff --git a/src/lagrangian/intermediate/submodels/CloudFunctionObjects/ParticleHistogram/ParticleHistogram.C b/src/lagrangian/intermediate/submodels/CloudFunctionObjects/ParticleHistogram/ParticleHistogram.C
index 437db3429c6..9fff625561a 100644
--- a/src/lagrangian/intermediate/submodels/CloudFunctionObjects/ParticleHistogram/ParticleHistogram.C
+++ b/src/lagrangian/intermediate/submodels/CloudFunctionObjects/ParticleHistogram/ParticleHistogram.C
@@ -27,7 +27,6 @@ License
 
 #include "ParticleHistogram.H"
 #include "Pstream.H"
-#include "stringListOps.H"
 #include "ListOps.H"
 #include "ListListOps.H"
 
diff --git a/src/lagrangian/intermediate/submodels/CloudFunctionObjects/ParticlePostProcessing/ParticlePostProcessing.C b/src/lagrangian/intermediate/submodels/CloudFunctionObjects/ParticlePostProcessing/ParticlePostProcessing.C
index 77e03bf659c..9703067440b 100644
--- a/src/lagrangian/intermediate/submodels/CloudFunctionObjects/ParticlePostProcessing/ParticlePostProcessing.C
+++ b/src/lagrangian/intermediate/submodels/CloudFunctionObjects/ParticlePostProcessing/ParticlePostProcessing.C
@@ -28,7 +28,6 @@ License
 
 #include "ParticlePostProcessing.H"
 #include "Pstream.H"
-#include "stringListOps.H"
 #include "ListOps.H"
 #include "ListListOps.H"
 
diff --git a/src/lagrangian/intermediate/submodels/CloudFunctionObjects/PatchCollisionDensity/PatchCollisionDensity.C b/src/lagrangian/intermediate/submodels/CloudFunctionObjects/PatchCollisionDensity/PatchCollisionDensity.C
index 170fd968c2d..68c3e804bba 100644
--- a/src/lagrangian/intermediate/submodels/CloudFunctionObjects/PatchCollisionDensity/PatchCollisionDensity.C
+++ b/src/lagrangian/intermediate/submodels/CloudFunctionObjects/PatchCollisionDensity/PatchCollisionDensity.C
@@ -28,7 +28,6 @@ License
 
 #include "PatchCollisionDensity.H"
 #include "Pstream.H"
-#include "stringListOps.H"
 #include "ListOps.H"
 #include "ListListOps.H"
 
diff --git a/src/meshTools/triSurface/triSurfaceLoader/triSurfaceLoader.C b/src/meshTools/triSurface/triSurfaceLoader/triSurfaceLoader.C
index 41fd1f783e6..e552d61cece 100644
--- a/src/meshTools/triSurface/triSurfaceLoader/triSurfaceLoader.C
+++ b/src/meshTools/triSurface/triSurfaceLoader/triSurfaceLoader.C
@@ -5,7 +5,7 @@
     \\  /    A nd           | www.openfoam.com
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
-    Copyright (C) 2017-2022 OpenCFD Ltd.
+    Copyright (C) 2017-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -106,7 +106,7 @@ Foam::label Foam::triSurfaceLoader::select(const word& name)
     if (available_.found(name))
     {
         selected_.resize(1);
-        selected_.first() = name;
+        selected_.front() = name;
     }
     else
     {
@@ -121,14 +121,14 @@ Foam::label Foam::triSurfaceLoader::select(const wordRe& mat)
 {
     if (mat.isPattern())
     {
-        labelList foundIds = findStrings(mat, available_);
+        labelList foundIds = wordRes::matching(mat, available_);
         Foam::sort(foundIds);
         selected_ = wordList(available_, foundIds);
     }
     else if (available_.found(static_cast<const word&>(mat)))
     {
         selected_.resize(1);
-        selected_.first() = mat;
+        selected_.front() = mat;
     }
     else
     {
@@ -162,7 +162,7 @@ Foam::label Foam::triSurfaceLoader::select(const UList<wordRe>& matcher)
     {
         if (mat.isPattern())
         {
-            labelList indices = findStrings(mat, available_);
+            labelList indices = wordRes::matching(mat, available_);
             Foam::sort(indices);
 
             for (const label idx : indices)
diff --git a/src/regionModels/surfaceFilmModels/submodels/kinematic/injectionModel/curvatureSeparation/curvatureSeparation.C b/src/regionModels/surfaceFilmModels/submodels/kinematic/injectionModel/curvatureSeparation/curvatureSeparation.C
index 6cf20ab7bc0..da3827b43a5 100644
--- a/src/regionModels/surfaceFilmModels/submodels/kinematic/injectionModel/curvatureSeparation/curvatureSeparation.C
+++ b/src/regionModels/surfaceFilmModels/submodels/kinematic/injectionModel/curvatureSeparation/curvatureSeparation.C
@@ -35,7 +35,6 @@ License
 #include "surfaceInterpolate.H"
 #include "fvcDiv.H"
 #include "fvcGrad.H"
-#include "stringListOps.H"
 #include "cyclicPolyPatch.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
diff --git a/src/sampling/sampledSet/sampledSets/sampledSets.C b/src/sampling/sampledSet/sampledSets/sampledSets.C
index f8b8ea35b04..16b9b69479b 100644
--- a/src/sampling/sampledSet/sampledSets/sampledSets.C
+++ b/src/sampling/sampledSet/sampledSets/sampledSets.C
@@ -174,7 +174,7 @@ Foam::IOobjectList Foam::sampledSets::preCheckFields(unsigned request)
     wordList allFields;    // Just needed for warnings
     HashTable<wordHashSet> selected;
 
-    IOobjectList objects(0);
+    IOobjectList objects;
 
     if (loadFromFiles_)
     {
diff --git a/src/sampling/sampledSurface/sampledMeshedSurface/sampledMeshedSurface.C b/src/sampling/sampledSurface/sampledMeshedSurface/sampledMeshedSurface.C
index 2cce5342e29..d095b5081d5 100644
--- a/src/sampling/sampledSurface/sampledMeshedSurface/sampledMeshedSurface.C
+++ b/src/sampling/sampledSurface/sampledMeshedSurface/sampledMeshedSurface.C
@@ -34,6 +34,7 @@ License
 #include "treeDataFace.H"
 #include "meshTools.H"
 #include "addToRunTimeSelectionTable.H"
+#include "stringListOps.H"   // For stringListOps::findMatching()
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
diff --git a/src/sampling/sampledSurface/sampledSurfaces/sampledSurfaces.C b/src/sampling/sampledSurface/sampledSurfaces/sampledSurfaces.C
index e6e912f6b07..b46ab90e475 100644
--- a/src/sampling/sampledSurface/sampledSurfaces/sampledSurfaces.C
+++ b/src/sampling/sampledSurface/sampledSurfaces/sampledSurfaces.C
@@ -75,7 +75,7 @@ Foam::IOobjectList Foam::sampledSurfaces::preCheckFields()
     wordList allFields;    // Just needed for warnings
     HashTable<wordHashSet> selected;
 
-    IOobjectList objects(0);
+    IOobjectList objects;
 
     if (loadFromFiles_)
     {
diff --git a/src/surfMesh/surfaceFormats/surfaceFormatsCore.C b/src/surfMesh/surfaceFormats/surfaceFormatsCore.C
index 7b852cb3c16..f95129a18ee 100644
--- a/src/surfMesh/surfaceFormats/surfaceFormatsCore.C
+++ b/src/surfMesh/surfaceFormats/surfaceFormatsCore.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2012 OpenFOAM Foundation
-    Copyright (C) 2017-2020 OpenCFD Ltd.
+    Copyright (C) 2017-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -30,7 +30,7 @@ License
 #include "Time.H"
 #include "ListOps.H"
 #include "surfMesh.H"
-#include "stringListOps.H"
+#include "stringListOps.H"   // For stringListOps::findMatching()
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
diff --git a/src/surfMesh/triSurface/triSurface.C b/src/surfMesh/triSurface/triSurface.C
index 984b995a7e9..efb0c92a8ec 100644
--- a/src/surfMesh/triSurface/triSurface.C
+++ b/src/surfMesh/triSurface/triSurface.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
-    Copyright (C) 2016-2020 OpenCFD Ltd.
+    Copyright (C) 2016-2024 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -31,6 +31,7 @@ License
 #include "surfZoneList.H"
 #include "MeshedSurface.H"
 #include "ListOps.H"
+#include "stringListOps.H"   // For stringListOps::findMatching()
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
-- 
GitLab