From b3ac6c3fed34e3af4bb3e1498147f62bc801754a Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@esi-group.com>
Date: Thu, 20 Jul 2017 19:53:57 +0200
Subject: [PATCH] ENH: add Foam::SubStrings container and stringOps::split

- generic means of holding ranges of substring iterators
---
 applications/test/stringSplit/Make/files      |   3 +
 applications/test/stringSplit/Make/options    |   0
 .../test/stringSplit/Test-stringSplit.C       |  81 +++++++++++
 .../primitives/strings/lists/SubStrings.H     | 127 ++++++++++++++++++
 .../primitives/strings/stringOps/stringOps.H  |  13 +-
 .../strings/stringOps/stringOpsTemplates.C    |  34 ++++-
 6 files changed, 255 insertions(+), 3 deletions(-)
 create mode 100644 applications/test/stringSplit/Make/files
 create mode 100644 applications/test/stringSplit/Make/options
 create mode 100644 applications/test/stringSplit/Test-stringSplit.C
 create mode 100644 src/OpenFOAM/primitives/strings/lists/SubStrings.H

diff --git a/applications/test/stringSplit/Make/files b/applications/test/stringSplit/Make/files
new file mode 100644
index 0000000000..06bdafe1b2
--- /dev/null
+++ b/applications/test/stringSplit/Make/files
@@ -0,0 +1,3 @@
+Test-stringSplit.C
+
+EXE = $(FOAM_USER_APPBIN)/Test-stringSplit
diff --git a/applications/test/stringSplit/Make/options b/applications/test/stringSplit/Make/options
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/applications/test/stringSplit/Test-stringSplit.C b/applications/test/stringSplit/Test-stringSplit.C
new file mode 100644
index 0000000000..9b1208c252
--- /dev/null
+++ b/applications/test/stringSplit/Test-stringSplit.C
@@ -0,0 +1,81 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2017 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM 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 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM 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 OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Application
+    Test-stringSplit
+
+Description
+    Test string splitting
+
+\*---------------------------------------------------------------------------*/
+
+#include "argList.H"
+#include "fileName.H"
+#include "stringOps.H"
+
+using namespace Foam;
+
+template<class String>
+void printSplitting(const String& str, const char delimiter)
+{
+    auto split = stringOps::split(str, delimiter);
+
+    Info<< "string {" << str.size() << " chars} = " << str << nl
+        << split.size() << " elements {" << split.length() << " chars}"
+        << nl;
+
+    unsigned i = 0;
+    for (const auto s : split)
+    {
+        Info<< "[" << i++ << "] {" << s.length() << " chars} = "
+            << s.str() << nl;
+    }
+}
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// Main program:
+
+int main(int argc, char *argv[])
+{
+    argList::noBanner();
+    argList::noParallel();
+
+    argList args(argc, argv, false, true);
+
+    if (args.size() <= 1 && args.options().empty())
+    {
+        args.printUsage();
+    }
+
+    for (label argi=1; argi < args.size(); ++argi)
+    {
+        printSplitting(args[argi], '/');
+    }
+
+    Info<< "\nEnd\n" << endl;
+    return 0;
+}
+
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/primitives/strings/lists/SubStrings.H b/src/OpenFOAM/primitives/strings/lists/SubStrings.H
new file mode 100644
index 0000000000..3e37fd7edd
--- /dev/null
+++ b/src/OpenFOAM/primitives/strings/lists/SubStrings.H
@@ -0,0 +1,127 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2017 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM 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 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM 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 OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::SubStrings
+
+Description
+    Sub-ranges of a string with a structure similar to std::match_results,
+    but without the underlying regular expression matching.
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef SubStrings_H
+#define SubStrings_H
+
+#include <string>
+#include <regex>
+#include <vector>
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                         Class SubStrings Declaration
+\*---------------------------------------------------------------------------*/
+
+template<class String>
+class SubStrings
+:
+    public std::vector<std::sub_match<typename String::const_iterator>>
+{
+public:
+
+    // Typedefs
+
+        //- The element type
+        using value_type =
+            typename std::sub_match<typename String::const_iterator>;
+
+        //- The const_iterator for the underlying string type
+        using string_iterator = typename String::const_iterator;
+
+
+    // Constructors
+
+        //- Construct null
+        SubStrings()
+        {}
+
+
+    // Member Functions
+
+        //- The total length of all sub-elements.
+        //  Use size() for the number elements.
+        std::string::size_type length() const
+        {
+            std::string::size_type len = 0;
+
+            for (const auto& elem : *this)
+            {
+                len += elem.length();
+            }
+
+            return len;
+        }
+
+
+        //- Append sub-string defined by begin/end iterators
+        void append(string_iterator b, string_iterator e)
+        {
+            value_type range;
+            range.first = b;
+            range.second = e;
+            range.matched = true;
+
+            this->push_back(range);
+        }
+
+
+        //- Const reference to the first element,
+        //  for consistency with other OpenFOAM containers
+        auto first() const -> decltype(this->front())
+        {
+            return this->front();
+        }
+
+
+        //- Const reference to the last element,
+        //  for consistency with other OpenFOAM containers
+        auto last() const -> decltype(this->back())
+        {
+            return this->back();
+        }
+
+};
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/primitives/strings/stringOps/stringOps.H b/src/OpenFOAM/primitives/strings/stringOps/stringOps.H
index 66e87623e5..0d7d459f59 100644
--- a/src/OpenFOAM/primitives/strings/stringOps/stringOps.H
+++ b/src/OpenFOAM/primitives/strings/stringOps/stringOps.H
@@ -30,12 +30,14 @@ Description
 
 SourceFiles
     stringOps.C
+    stringOpsTemplates.C
 
 \*---------------------------------------------------------------------------*/
 #ifndef stringOps_H
 #define stringOps_H
 
 #include "string.H"
+#include "SubStrings.H"
 #include "word.H"
 #include "dictionary.H"
 #include "HashTable.H"
@@ -302,14 +304,21 @@ namespace stringOps
     Foam::word name(const std::string& fmt, const PrimitiveType& val);
 
 
-} // End namespace stringOps
+    //- Split a string into sub-strings at the delimiter character.
+    //  An empty sub-strings are suppressed.
+    template<class StringType>
+    Foam::SubStrings<StringType> split
+    (
+        const StringType& str,
+        const char delimiter
+    );
 
+} // End namespace stringOps
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 } // End namespace Foam
 
-
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 #ifdef NoRepository
diff --git a/src/OpenFOAM/primitives/strings/stringOps/stringOpsTemplates.C b/src/OpenFOAM/primitives/strings/stringOps/stringOpsTemplates.C
index a8f7030300..1b0aa62e9f 100644
--- a/src/OpenFOAM/primitives/strings/stringOps/stringOpsTemplates.C
+++ b/src/OpenFOAM/primitives/strings/stringOps/stringOpsTemplates.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2016 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2016-2017 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -65,4 +65,36 @@ Foam::word Foam::stringOps::name
 }
 
 
+template<class StringType>
+Foam::SubStrings<StringType> Foam::stringOps::split
+(
+    const StringType& str,
+    const char delimiter
+)
+{
+    Foam::SubStrings<StringType> lst;
+    lst.reserve(20);
+
+    std::string::size_type beg = 0, end = 0;
+
+    while ((end = str.find(delimiter, beg)) != std::string::npos)
+    {
+        if (beg < end)
+        {
+            // (Non-empty) intermediate element
+            lst.append(str.cbegin() + beg, str.cbegin() + end);
+        }
+        beg = end + 1;
+    }
+
+    // (Non-empty) trailing element
+    if (beg < str.size())
+    {
+        lst.append(str.cbegin() + beg, str.cbegin() + str.size());
+    }
+
+    return lst;
+}
+
+
 // ************************************************************************* //
-- 
GitLab