diff --git a/applications/test/IFstream/Make/files b/applications/test/IFstream/Make/files
new file mode 100644
index 0000000000000000000000000000000000000000..71a272eb18193ae35ed9bc6604450739b6e03d47
--- /dev/null
+++ b/applications/test/IFstream/Make/files
@@ -0,0 +1,3 @@
+Test-IFstream.C
+
+EXE = $(FOAM_USER_APPBIN)/Test-IFstream
diff --git a/applications/test/IFstream/Make/options b/applications/test/IFstream/Make/options
new file mode 100644
index 0000000000000000000000000000000000000000..18e6fe47afacb902cddccf82632772447704fd88
--- /dev/null
+++ b/applications/test/IFstream/Make/options
@@ -0,0 +1,2 @@
+/* EXE_INC = */
+/* EXE_LIBS = */
diff --git a/applications/test/IFstream/Test-IFstream.C b/applications/test/IFstream/Test-IFstream.C
new file mode 100644
index 0000000000000000000000000000000000000000..c55957109acc336f680b4ce968bc62a94277765b
--- /dev/null
+++ b/applications/test/IFstream/Test-IFstream.C
@@ -0,0 +1,105 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2020 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+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-IFstream
+
+Description
+    Tests on low-level reading
+
+\*---------------------------------------------------------------------------*/
+
+#include "argList.H"
+#include "Fstream.H"
+#include "etcFiles.H"
+
+using namespace Foam;
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+//  Main program:
+
+int main(int argc, char *argv[])
+{
+    argList::noBanner();
+    argList::noParallel();
+
+    #include "setRootCase.H"
+
+    // Test with etc/controlDict (mandatory, from distribution)
+
+    {
+        const fileName inputFile
+        (
+            findEtcFile("controlDict", true, 0007)
+        );
+
+        Info<< nl << "Test getLine" << nl << inputFile << nl;
+        IFstream is(inputFile);
+
+        string buf;
+
+        // Test that buffer resizing works as expected
+
+        Info<< "buf: " << buf.size() << '/' << buf.capacity() << nl;
+
+        bool skipDoc = true;
+
+        while (is.good())
+        {
+            if (skipDoc || is.lineNumber() % 2)
+            {
+                is.getLine(buf);
+
+                Info<< is.lineNumber() << ": "
+                    << buf.size() << '/' << buf.capacity() << ' '
+                    << buf << nl;
+
+                if (buf.starts_with("Documentation"))
+                {
+                    skipDoc = false;
+
+                    Info<< "Found Documentation: skip until closing '}'"
+                        << " line number will now be incorrect"
+                        << nl;
+
+                    auto n = is.getLine(nullptr, '}');
+                    Info<< is.lineNumber() << ": [" << label(n) << "]" << nl;
+                }
+            }
+            else
+            {
+                auto n = is.getLine(nullptr);
+
+                Info<< is.lineNumber() << ": [" << label(n) << "]" << nl;
+            }
+        }
+    }
+
+    Info<< "\nEnd\n" << endl;
+    return 0;
+}
+
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/db/IOstreams/Sstreams/ISstream.H b/src/OpenFOAM/db/IOstreams/Sstreams/ISstream.H
index 3fb471b1cd4535fff92d82fc779a587ea5bd0764..eaa2a92420d2cbeca29be9f02dc41ea00d1b717d 100644
--- a/src/OpenFOAM/db/IOstreams/Sstreams/ISstream.H
+++ b/src/OpenFOAM/db/IOstreams/Sstreams/ISstream.H
@@ -41,6 +41,7 @@ SourceFiles
 
 #include "Istream.H"
 #include "fileName.H"
+#include <limits>
 #include <iostream>
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@@ -148,9 +149,13 @@ public:
             //  end of file is read.
             inline int peek();
 
-            //- Raw, low-level getline into a string function.
+            //- Raw, low-level getline (until delimiter) into a string.
             inline ISstream& getLine(std::string& str, char delim = '\n');
 
+            //- Low-level discard until delimiter
+            //  \return the number of characters extracted
+            inline std::streamsize getLine(std::nullptr_t, char delim = '\n');
+
             //- Raw, low-level putback character function.
             inline ISstream& putback(const char c);
 
diff --git a/src/OpenFOAM/db/IOstreams/Sstreams/ISstreamI.H b/src/OpenFOAM/db/IOstreams/Sstreams/ISstreamI.H
index 69c847d2c2ff013c4ff6422c17dd32f7bc0816fb..23817ceb187378c7e43b12eb2e9c8835cefd9f03 100644
--- a/src/OpenFOAM/db/IOstreams/Sstreams/ISstreamI.H
+++ b/src/OpenFOAM/db/IOstreams/Sstreams/ISstreamI.H
@@ -87,6 +87,22 @@ inline Foam::ISstream& Foam::ISstream::getLine(std::string& str, char delim)
 }
 
 
+inline std::streamsize Foam::ISstream::getLine(std::nullptr_t, char delim)
+{
+    is_.ignore(std::numeric_limits<std::streamsize>::max(), delim);
+    setState(is_.rdstate());
+
+    std::streamsize count = is_.gcount();
+
+    if (count && delim == '\n')
+    {
+        ++lineNumber_;
+    }
+
+    return count;
+}
+
+
 inline Foam::ISstream& Foam::ISstream::putback(const char c)
 {
     if (c == '\n')
diff --git a/src/OpenFOAM/interpolations/interpolationTable/tableReaders/csv/csvTableReader.C b/src/OpenFOAM/interpolations/interpolationTable/tableReaders/csv/csvTableReader.C
index 0ee5c6d7663328870aa6bc8d0d8b763432800c81..ea6e419791fa0e893134c192ef19503e4fd930df 100644
--- a/src/OpenFOAM/interpolations/interpolationTable/tableReaders/csv/csvTableReader.C
+++ b/src/OpenFOAM/interpolations/interpolationTable/tableReaders/csv/csvTableReader.C
@@ -134,12 +134,12 @@ void Foam::csvTableReader<Type>::operator()
     const label maxEntry =
         max(refColumn_, componentColumns_[findMax(componentColumns_)]);
 
+    string line;
     label lineNo = 0;
 
     // Skip header
     if (headerLine_)
     {
-        string line;
         is.getLine(line);
         ++lineNo;
     }
@@ -149,7 +149,6 @@ void Foam::csvTableReader<Type>::operator()
 
     while (is.good())
     {
-        string line;
         is.getLine(line);
         ++lineNo;
 
diff --git a/src/OpenFOAM/primitives/functions/Function1/CSV/CSV.C b/src/OpenFOAM/primitives/functions/Function1/CSV/CSV.C
index 53b7bb796e5ba308757012692368c52bb5a14b7d..495cd5a481e1910ebca660c8eff03389350a946c 100644
--- a/src/OpenFOAM/primitives/functions/Function1/CSV/CSV.C
+++ b/src/OpenFOAM/primitives/functions/Function1/CSV/CSV.C
@@ -118,12 +118,12 @@ void Foam::Function1Types::CSV<Type>::read()
     const label maxEntry =
         max(refColumn_, componentColumns_[findMax(componentColumns_)]);
 
+    string line;
     label lineNo = 0;
 
     // Skip header
     for (label i = 0; i < nHeaderLine_; ++i)
     {
-        string line;
         is.getLine(line);
         ++lineNo;
     }
@@ -133,7 +133,6 @@ void Foam::Function1Types::CSV<Type>::read()
 
     while (is.good())
     {
-        string line;
         is.getLine(line);
         ++lineNo;
 
diff --git a/src/OpenFOAM/primitives/strings/lists/SubStrings.H b/src/OpenFOAM/primitives/strings/lists/SubStrings.H
index 41835c5e9e199310ae2fd1cc9385cd585e15000f..189865864710563f6c7baa5c26858571031e0e49 100644
--- a/src/OpenFOAM/primitives/strings/lists/SubStrings.H
+++ b/src/OpenFOAM/primitives/strings/lists/SubStrings.H
@@ -5,7 +5,7 @@
     \\  /    A nd           | www.openfoam.com
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
-    Copyright (C) 2017 OpenCFD Ltd.
+    Copyright (C) 2017-2020 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -35,8 +35,8 @@ Description
 #ifndef SubStrings_H
 #define SubStrings_H
 
-#include <string>
 #include <regex>
+#include <string>
 #include <vector>
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@@ -67,13 +67,13 @@ public:
 
     // Constructors
 
-        //- Construct null
+        //- Default construct
         SubStrings() = default;
 
 
     // Member Functions
 
-        //- The total length of all sub-elements.
+        //- The total string length of all sub-elements.
         //  Use size() for the number elements.
         std::string::size_type length() const
         {
@@ -89,7 +89,11 @@ public:
 
 
         //- Append sub-string defined by begin/end iterators
-        void append(string_iterator b, string_iterator e)
+        void append
+        (
+            const typename String::const_iterator& b,
+            const typename String::const_iterator& e
+        )
         {
             value_type range;
             range.first = b;
@@ -101,7 +105,7 @@ public:
 
 
         //- Const reference to the first element,
-        //  for consistency with other OpenFOAM containers
+        //- for consistency with other OpenFOAM containers
         auto first() const -> decltype(this->front())
         {
             return this->front();
@@ -109,7 +113,7 @@ public:
 
 
         //- Const reference to the last element,
-        //  for consistency with other OpenFOAM containers
+        //- for consistency with other OpenFOAM containers
         auto last() const -> decltype(this->back())
         {
             return this->back();
@@ -121,9 +125,9 @@ public:
         {
             return (*this)[pos].str();
         }
-
 };
 
+
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 } // End namespace Foam
diff --git a/src/OpenFOAM/primitives/strings/string/string.C b/src/OpenFOAM/primitives/strings/string/string.C
index 34bc400d91ac06572e8ddc2774e051d3f1228bc7..b7076865c53ca8aeb19c2a2ad3184d64e4319faa 100644
--- a/src/OpenFOAM/primitives/strings/string/string.C
+++ b/src/OpenFOAM/primitives/strings/string/string.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
-    Copyright (C) 2016-2019 OpenCFD Ltd.
+    Copyright (C) 2016-2020 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -190,7 +190,7 @@ bool Foam::string::removeRepeated(const char character)
             }
         }
 
-        resize(nChar);
+        erase(nChar);
     }
 
     return changed;
@@ -219,7 +219,7 @@ bool Foam::string::removeEnd(const std::string& text)
 
     if (txtLen && strLen >= txtLen && !compare(strLen - txtLen, npos, text))
     {
-        resize(strLen - txtLen);
+        erase(strLen - txtLen);
         return true;
     }
 
@@ -244,7 +244,7 @@ bool Foam::string::removeEnd(const char c)
     const auto n = length();
     if (n > 1 && back() == c)
     {
-        resize(n-1);
+        erase(n-1);
         return true;
     }
 
diff --git a/src/OpenFOAM/primitives/strings/stringOps/stringOps.C b/src/OpenFOAM/primitives/strings/stringOps/stringOps.C
index dc3a12d84b3f5d86bdeb85265e43845dcd2c0925..a6860584b65cab59701132f378236c472eef2db8 100644
--- a/src/OpenFOAM/primitives/strings/stringOps/stringOps.C
+++ b/src/OpenFOAM/primitives/strings/stringOps/stringOps.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
-    Copyright (C) 2017-2019 OpenCFD Ltd.
+    Copyright (C) 2017-2020 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -29,10 +29,11 @@ License
 #include "stringOps.H"
 #include "typeInfo.H"
 #include "etcFiles.H"
-#include "Pstream.H"
+#include "UPstream.H"
 #include "StringStream.H"
 #include "OSstream.H"
 #include "OSspecific.H"
+#include <algorithm>
 #include <cctype>
 
 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
@@ -162,7 +163,7 @@ static void expandLeadingTilde(std::string& s)
 
         // Single warning (on master) with guard to avoid Pstream::master()
         // when Pstream has not yet been initialized
-        if (Pstream::parRun() ? Pstream::master() : true)
+        if (UPstream::parRun() ? UPstream::master() : true)
         {
             std::cerr
                 << nl
@@ -696,55 +697,35 @@ static void expandString
 
 std::string::size_type Foam::stringOps::count
 (
-    const std::string& str,
+    const std::string& s,
     const char c
 )
 {
-    std::string::size_type n = 0;
-
-    for (auto iter = str.cbegin(); iter != str.cend(); ++iter)
-    {
-        if (*iter == c)
-        {
-            ++n;
-        }
-    }
-
-    return n;
+    return std::count(s.cbegin(), s.cend(), c);
 }
 
 
-std::string::size_type Foam::stringOps::count(const char* str, const char c)
+std::string::size_type Foam::stringOps::count(const char* s, const char c)
 {
-    if (!str)
-    {
-        return 0;
-    }
-
-    std::string::size_type n = 0;
-
-    for (const char *iter = str; *iter; ++iter)
-    {
-        if (*iter == c)
-        {
-            ++n;
-        }
-    }
-
-    return n;
+    return
+    (
+        s == nullptr
+      ? 0
+      : std::count(s, (s + std::char_traits<char>::length(s)), c)
+    );
 }
 
 
 Foam::string Foam::stringOps::expand
 (
-    const std::string& str,
+    const std::string& s,
     const HashTable<string, word, string::hash>& mapping,
     const char sigil
 )
 {
-    string s(str);
-    inplaceExpand(s, mapping);
-    return s;
+    string out(s);
+    inplaceExpand(out, mapping);
+    return out;
 }
 
 
@@ -862,14 +843,14 @@ void Foam::stringOps::inplaceExpand
 
 Foam::string Foam::stringOps::expand
 (
-    const std::string& str,
+    const std::string& s,
     const dictionary& dict,
     const char sigil
 )
 {
-    string s(str);
-    inplaceExpand(s, dict, sigil);
-    return s;
+    string out(s);
+    inplaceExpand(out, dict, sigil);
+    return out;
 }
 
 
@@ -902,13 +883,13 @@ void Foam::stringOps::inplaceExpand
 
 Foam::string Foam::stringOps::expand
 (
-    const std::string& str,
+    const std::string& s,
     const bool allowEmpty
 )
 {
-    string s(str);
-    inplaceExpand(s, allowEmpty);
-    return s;
+    string out(s);
+    inplaceExpand(out, allowEmpty);
+    return out;
 }
 
 
@@ -1064,24 +1045,24 @@ Foam::stringOps::findTrim
 }
 
 
-Foam::string Foam::stringOps::trim(const std::string& str)
+Foam::string Foam::stringOps::trim(const std::string& s)
 {
     std::string::size_type pos = 0;
-    std::string::size_type end = str.length();
+    std::string::size_type end = s.length();
 
     // Right
-    while (pos < end && std::isspace(str[end-1]))
+    while (pos < end && std::isspace(s[end-1]))
     {
         --end;
     }
 
     // Left
-    while (pos < end && std::isspace(str[pos]))
+    while (pos < end && std::isspace(s[pos]))
     {
         ++pos;
     }
 
-    return str.substr(pos, end-pos);
+    return s.substr(pos, end-pos);
 }
 
 
@@ -1092,11 +1073,17 @@ void Foam::stringOps::inplaceTrim(std::string& s)
 }
 
 
-Foam::string Foam::stringOps::removeComments(const std::string& str)
+void Foam::stringOps::inplaceRemoveSpace(std::string& s)
 {
-    string s(str);
-    inplaceRemoveComments(s);
-    return s;
+    s.erase(std::remove_if(s.begin(), s.end(), ::isspace), s.end());
+}
+
+
+Foam::string Foam::stringOps::removeComments(const std::string& s)
+{
+    string out(s);
+    inplaceRemoveComments(out);
+    return out;
 }
 
 
@@ -1196,43 +1183,35 @@ void Foam::stringOps::inplaceRemoveComments(std::string& s)
 }
 
 
-Foam::string Foam::stringOps::lower(const std::string& str)
+Foam::string Foam::stringOps::lower(const std::string& s)
 {
-    string s(str);
-    inplaceLower(s);
-    return s;
+    string out;
+    out.resize(s.length());
+
+    std::transform(s.begin(), s.end(), out.begin(), ::tolower);
+    return out;
 }
 
 
 void Foam::stringOps::inplaceLower(std::string& s)
 {
-    for (auto iter = s.begin(); iter != s.end(); ++iter)
-    {
-        *iter = static_cast<std::string::value_type>
-        (
-            std::tolower(static_cast<unsigned char>(*iter))
-        );
-    }
+    std::transform(s.begin(), s.end(), s.begin(), ::tolower);
 }
 
 
-Foam::string Foam::stringOps::upper(const std::string& str)
+Foam::string Foam::stringOps::upper(const std::string& s)
 {
-    string s(str);
-    inplaceUpper(s);
-    return s;
+    string out;
+    out.resize(s.length());
+
+    std::transform(s.begin(), s.end(), out.begin(), ::toupper);
+    return out;
 }
 
 
 void Foam::stringOps::inplaceUpper(std::string& s)
 {
-    for (auto iter = s.begin(); iter != s.end(); ++iter)
-    {
-        *iter = static_cast<std::string::value_type>
-        (
-            std::toupper(static_cast<unsigned char>(*iter))
-        );
-    }
+    std::transform(s.begin(), s.end(), s.begin(), ::toupper);
 }
 
 
diff --git a/src/OpenFOAM/primitives/strings/stringOps/stringOps.H b/src/OpenFOAM/primitives/strings/stringOps/stringOps.H
index 51d3a4e37d64a5aabb0c4d6ff1af88eae70bae85..b771277c7fed5dc9f3d7e5619c14b0778fcbe1d1 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-2019 OpenCFD Ltd.
+    Copyright (C) 2016-2020 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -55,7 +55,7 @@ SourceFiles
 namespace Foam
 {
 
-// Forward declarations
+// Forward Declarations
 class OSstream;
 
 /*---------------------------------------------------------------------------*\
@@ -65,11 +65,11 @@ class OSstream;
 namespace stringOps
 {
     //- Count the number of occurrences of the specified character
-    std::string::size_type count(const std::string& str, const char c);
+    std::string::size_type count(const std::string& s, const char c);
 
     //- Count the number of occurrences of the specified character
     //  Correctly handles nullptr.
-    std::string::size_type count(const char* str, const char c);
+    std::string::size_type count(const char* 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)
@@ -83,7 +83,7 @@ namespace stringOps
     //  \sa stringOps::inplaceExpand() for details
     string expand
     (
-        const std::string& str,
+        const std::string& s,
         const HashTable<string, word, string::hash>& mapping,
         const char sigil = '$'
     );
@@ -213,7 +213,7 @@ namespace stringOps
     //  \sa stringOps::inplaceExpand(std::string&, const dictionary&, char)
     string expand
     (
-        const std::string& str,
+        const std::string& s,
         const dictionary& dict,
         const char sigil = '$'
     );
@@ -246,11 +246,7 @@ namespace stringOps
     //
     //  \sa
     //  stringOps::inplaceExpand(std::string&, bool);
-    string expand
-    (
-        const std::string& str,
-        const bool allowEmpty = false
-    );
+    string expand(const std::string& s, const bool allowEmpty = false);
 
 
     //- Expand initial tags, tildes, and all occurrences of environment
@@ -268,11 +264,7 @@ namespace stringOps
     // - allow empty = Given by parameter (default: False)
     // - subDict = Not applicable
     // .
-    void inplaceExpand
-    (
-        std::string& s,
-        const bool allowEmpty = false
-    );
+    void inplaceExpand(std::string& s, const bool allowEmpty = false);
 
 
     //- Replace environment variable contents with its name.
@@ -305,27 +297,30 @@ namespace stringOps
     void inplaceTrimRight(std::string& s);
 
     //- Return string trimmed of leading and trailing whitespace
-    string trim(const std::string& str);
+    string trim(const std::string& s);
 
     //- Trim leading and trailing whitespace inplace
     void inplaceTrim(std::string& s);
 
+    //- Eliminate whitespace inplace
+    void inplaceRemoveSpace(std::string& s);
+
 
     //- Return string with C/C++ comments removed
-    string removeComments(const std::string& str);
+    string removeComments(const std::string& s);
 
     //- Remove C/C++ comments inplace
     void inplaceRemoveComments(std::string& s);
 
 
-    //- Return string transformed with std::tolower on each character
-    string lower(const std::string& str);
+    //- Return string copy transformed with std::tolower on each character
+    string lower(const std::string& s);
 
     //- Inplace transform string with std::tolower on each character
     void inplaceLower(std::string& s);
 
-    //- Return string transformed with std::toupper on each character
-    string upper(const std::string& str);
+    //- Return string copy transformed with std::toupper on each character
+    string upper(const std::string& s);
 
     //- Inplace transform string with std::toupper on each character
     void inplaceUpper(std::string& s);
diff --git a/src/OpenFOAM/primitives/strings/word/word.C b/src/OpenFOAM/primitives/strings/word/word.C
index 52c1334f0af51f9f648dd0b1ecc3a479b8a3b269..9cc7dc15c5cf79b5da1e8f38fbc07cf5a64c5860 100644
--- a/src/OpenFOAM/primitives/strings/word/word.C
+++ b/src/OpenFOAM/primitives/strings/word/word.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011 OpenFOAM Foundation
-    Copyright (C) 2017-2019 OpenCFD Ltd.
+    Copyright (C) 2017-2020 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -68,7 +68,7 @@ Foam::word Foam::word::validate(const std::string& s, const bool prefix)
         }
     }
 
-    out.resize(len);
+    out.erase(len);
 
     return out;
 }
@@ -102,7 +102,7 @@ Foam::word Foam::word::validate
         }
     }
 
-    out.resize(len);
+    out.erase(len);
 
     return out;
 }