From 17d9969ae575297396c2c998a5862fa48707beac Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Fri, 13 Dec 2019 12:10:53 +0100 Subject: [PATCH] ENH: stringOps::findTrim helper - finds beg/end indices of string trimmed of leading/trailing whitespace --- applications/test/string2/Test-string2.C | 50 +++++++++- .../primitives/strings/stringOps/stringOps.C | 93 ++++++++++++++----- .../primitives/strings/stringOps/stringOps.H | 12 +++ .../strings/stringOps/stringOpsEvaluate.C | 34 +------ 4 files changed, 133 insertions(+), 56 deletions(-) diff --git a/applications/test/string2/Test-string2.C b/applications/test/string2/Test-string2.C index f3f944893e..65368a0670 100644 --- a/applications/test/string2/Test-string2.C +++ b/applications/test/string2/Test-string2.C @@ -2,8 +2,10 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2019 OpenCFD Ltd. + \\ / A nd | www.openfoam.com \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -93,6 +95,30 @@ void testNumericEvaluation(const std::string& s) } +// Test findTrim - uses '<' and '>' as pseudo-placeholders +void testFindTrim(const std::string& s) +{ + auto pos = s.find('<'); + auto len = s.find('>'); + + // Conform with expected value for substr + + if (pos == std::string::npos) pos = 0; else ++pos; + if (len != std::string::npos) len = (len - pos); + + const auto pts = stringOps::findTrim(s, pos, len); + + Info<< "input" << nl + << "========" << nl + << s << nl + << "pos=" << pos << " len=" << int(len) << nl + << s.substr(pos, len) << nl + << "trim=" << pts.first << " to " << pts.second << nl + << s.substr(pts.first, pts.second-pts.first) << nl + << "========" << nl; +} + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // Main program: @@ -150,6 +176,28 @@ int main(int argc, char *argv[]) } + // Test findTrim - uses '<' and '>' as pseudo-placeholders + { + Info<< nl << "Test findTrim" << nl; + + for + ( + const auto& cstr + : + { + "", // Empty + " \n\t ", // whitespace only + " Leading and trailing ", + " Alt end and trai>ling ", + " Alt start< space ", + } + ) + { + testFindTrim(cstr); + } + } + + Info<< "\nEnd\n" << endl; return 0; } diff --git a/src/OpenFOAM/primitives/strings/stringOps/stringOps.C b/src/OpenFOAM/primitives/strings/stringOps/stringOps.C index 0f9d181c2e..848dee60b6 100644 --- a/src/OpenFOAM/primitives/strings/stringOps/stringOps.C +++ b/src/OpenFOAM/primitives/strings/stringOps/stringOps.C @@ -947,15 +947,17 @@ Foam::string Foam::stringOps::trimLeft(const std::string& s) { if (!s.empty()) { - std::string::size_type beg = 0; - while (beg < s.size() && std::isspace(s[beg])) + std::string::size_type pos = 0; + const auto end = s.length(); + + while (pos < end && std::isspace(s[pos])) { - ++beg; + ++pos; } - if (beg) + if (pos) { - return s.substr(beg); + return s.substr(pos); } } @@ -967,15 +969,17 @@ void Foam::stringOps::inplaceTrimLeft(std::string& s) { if (!s.empty()) { - std::string::size_type beg = 0; - while (beg < s.size() && std::isspace(s[beg])) + std::string::size_type pos = 0; + const auto end = s.length(); + + while (pos < end && std::isspace(s[pos])) { - ++beg; + ++pos; } - if (beg) + if (pos) { - s.erase(0, beg); + s.erase(0, pos); } } } @@ -985,15 +989,15 @@ Foam::string Foam::stringOps::trimRight(const std::string& s) { if (!s.empty()) { - auto n = s.size(); - while (n && std::isspace(s[n-1])) + auto end = s.length(); + while (end && std::isspace(s[end-1])) { - --n; + --end; } - if (n < s.size()) + if (end < s.length()) { - return s.substr(0, n); + return s.substr(0, end); } } @@ -1005,35 +1009,74 @@ void Foam::stringOps::inplaceTrimRight(std::string& s) { if (!s.empty()) { - auto n = s.size(); - while (n && std::isspace(s[n-1])) + auto end = s.length(); + while (end && std::isspace(s[end-1])) { - --n; + --end; } - s.resize(n); + s.erase(end); } } +std::pair +Foam::stringOps::findTrim +( + const std::string& s, + std::size_t pos, + std::size_t len +) +{ + size_t end = s.length(); + if (pos >= end) + { + pos = end; + } + else if (len != std::string::npos) + { + len += pos; + + if (len < end) + { + end = len; + } + } + + // Right = last + while (pos < end && std::isspace(s[end-1])) + { + --end; + } + + // Left = first + while (pos < end && std::isspace(s[pos])) + { + ++pos; + } + + return std::pair(pos, end); +} + + Foam::string Foam::stringOps::trim(const std::string& str) { - std::string::size_type beg = 0; - std::string::size_type end = str.size(); + std::string::size_type pos = 0; + std::string::size_type end = str.length(); // Right - while (beg < end && std::isspace(str[end-1])) + while (pos < end && std::isspace(str[end-1])) { --end; } // Left - while (beg < end && std::isspace(str[beg])) + while (pos < end && std::isspace(str[pos])) { - ++beg; + ++pos; } - return str.substr(beg, end-beg); + return str.substr(pos, end-pos); } diff --git a/src/OpenFOAM/primitives/strings/stringOps/stringOps.H b/src/OpenFOAM/primitives/strings/stringOps/stringOps.H index 11b0e15da3..9b12511191 100644 --- a/src/OpenFOAM/primitives/strings/stringOps/stringOps.H +++ b/src/OpenFOAM/primitives/strings/stringOps/stringOps.H @@ -36,6 +36,7 @@ SourceFiles stringOpsTemplates.C \*---------------------------------------------------------------------------*/ + #ifndef stringOps_H #define stringOps_H @@ -48,6 +49,7 @@ SourceFiles #include "stringOpsSort.H" #include "stringOpsEvaluate.H" #include "wordRes.H" +#include // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -257,6 +259,16 @@ namespace stringOps bool inplaceReplaceVar(std::string& s, const word& varName); + //- Find (first, last) non-space locations in string or sub-string. + // This may change to std::string_view in the future. + std::pair + findTrim + ( + const std::string& s, + size_t pos = 0, + size_t len = std::string::npos + ); + //- Return string trimmed of leading whitespace string trimLeft(const std::string& s); diff --git a/src/OpenFOAM/primitives/strings/stringOps/stringOpsEvaluate.C b/src/OpenFOAM/primitives/strings/stringOps/stringOpsEvaluate.C index 6eb7d30962..3520c62e3c 100644 --- a/src/OpenFOAM/primitives/strings/stringOps/stringOpsEvaluate.C +++ b/src/OpenFOAM/primitives/strings/stringOps/stringOpsEvaluate.C @@ -42,42 +42,16 @@ Foam::string Foam::stringOps::evaluate { /// InfoErr<< "Evaluate " << str.substr(pos, len) << nl; - size_t end = str.length(); - if (pos > end) - { - pos = end; - } - else if (len != std::string::npos) - { - len += pos; + const auto trimPoints = stringOps::findTrim(str, pos, len); - if (len < end) - { - end = len; - } - } + pos = trimPoints.first; + len = (trimPoints.second - trimPoints.first); - // Adjust like inplaceTrim - - // Right - while (pos < end && std::isspace(str[end-1])) - { - --end; - } - - // Left - while (pos < end && std::isspace(str[pos])) - { - ++pos; - } - - if ((pos >= end) || std::isspace(str[pos])) + if (!len) { return ""; } - len = (end - pos); - /// InfoErr<< "Evaluate " << str.substr(pos, len) << nl; expressions::exprResult result;