ENH: static versions of fileName clean(), path(), name()

- useful operations for other string representations of fileName types.

  The return type is in general a std::string with any narrowing
  being done by the caller on the return value.
This commit is contained in:
Mark Olesen 2017-08-02 13:44:37 +02:00
parent e70fc61660
commit 46a2a73611
3 changed files with 123 additions and 60 deletions

View File

@ -104,25 +104,26 @@ Foam::fileName& Foam::fileName::toAbsolute()
}
bool Foam::fileName::clean()
bool Foam::fileName::clean(std::string& str)
{
// The top slash - we are never allowed to go above it
string::size_type top = this->find('/');
// Start with the top slash found - we are never allowed to go above it
char prev = '/';
auto top = str.find(prev);
// No slashes - nothing to do
if (top == string::npos)
if (top == std::string::npos)
{
return false;
}
// Start with the '/' found:
char prev = '/';
string::size_type nChar = top+1;
string::size_type maxLen = this->size();
// Number of output characters
std::string::size_type nChar = top+1;
const string::size_type maxLen = str.size();
for (string::size_type src = nChar; src < maxLen; /*nil*/)
{
const char c = operator[](src++);
const char c = str[src++];
if (prev == '/')
{
@ -132,28 +133,27 @@ bool Foam::fileName::clean()
continue;
}
// Could be '/./' or '/../'
// Could be "/./", "/../" or a trailing "/."
if (c == '.')
{
// Found trailing '/.' - skip it
// Trailing "/." - skip it
if (src >= maxLen)
{
continue;
break;
}
// Peek at the next character
const char c1 = operator[](src);
const char c1 = str[src];
// Found '/./' - skip it
// Found "/./" - skip it
if (c1 == '/')
{
++src;
continue;
}
// It is '/..' or '/../'
if (c1 == '.' && (src+1 >= maxLen || operator[](src+1) == '/'))
// Trailing "/.." or intermediate "/../"
if (c1 == '.' && (src+1 >= maxLen || str[src+1] == '/'))
{
string::size_type parent;
@ -163,7 +163,7 @@ bool Foam::fileName::clean()
if
(
nChar > 2
&& (parent = this->rfind('/', nChar-2)) != string::npos
&& (parent = str.rfind('/', nChar-2)) != string::npos
&& parent >= top
)
{
@ -179,47 +179,60 @@ bool Foam::fileName::clean()
}
}
}
operator[](nChar++) = prev = c;
str[nChar++] = prev = c;
}
// Remove trailing slash
if (nChar > 1 && operator[](nChar-1) == '/')
if (nChar > 1 && str[nChar-1] == '/')
{
nChar--;
}
this->resize(nChar);
str.resize(nChar);
return (nChar != maxLen);
}
bool Foam::fileName::clean()
{
return fileName::clean(*this);
}
Foam::fileName Foam::fileName::clean() const
{
fileName fName(*this);
fName.clean();
return fName;
fileName cleaned(*this);
fileName::clean(cleaned);
return cleaned;
}
std::string Foam::fileName::name(const std::string& str)
{
const auto beg = str.rfind('/');
if (beg == npos)
{
return str;
}
else
{
return str.substr(beg+1);
}
}
Foam::word Foam::fileName::name() const
{
const size_type i = rfind('/');
if (i == npos)
{
return *this;
}
else
{
return substr(i+1);
}
return fileName::name(*this);
}
Foam::word Foam::fileName::nameLessExt() const
std::string Foam::fileName::nameLessExt(const std::string& str)
{
size_type beg = rfind('/');
size_type beg = str.rfind('/');
size_type dot = str.rfind('.');
if (beg == npos)
{
@ -230,7 +243,6 @@ Foam::word Foam::fileName::nameLessExt() const
++beg;
}
size_type dot = rfind('.');
if (dot != npos && dot <= beg)
{
dot = npos;
@ -238,18 +250,24 @@ Foam::word Foam::fileName::nameLessExt() const
if (dot == npos)
{
return substr(beg, npos);
return str.substr(beg);
}
else
{
return substr(beg, dot - beg);
return str.substr(beg, dot - beg);
}
}
Foam::fileName Foam::fileName::path() const
Foam::word Foam::fileName::nameLessExt() const
{
const size_type i = rfind('/');
return nameLessExt(*this);
}
std::string Foam::fileName::path(const std::string& str)
{
const auto i = str.rfind('/');
if (i == npos)
{
@ -257,7 +275,7 @@ Foam::fileName Foam::fileName::path() const
}
else if (i)
{
return substr(0, i);
return str.substr(0, i);
}
else
{
@ -266,9 +284,15 @@ Foam::fileName Foam::fileName::path() const
}
Foam::fileName Foam::fileName::path() const
{
return path(*this);
}
Foam::fileName Foam::fileName::lessExt() const
{
const size_type i = find_ext();
const auto i = find_ext();
if (i == npos)
{
@ -325,7 +349,7 @@ Foam::wordList Foam::fileName::components(const char delimiter) const
// Avoid empty trailing element
if (beg < size())
{
wrdList.append(substr(beg, npos));
wrdList.append(substr(beg));
}
// Transfer to wordList

View File

@ -135,26 +135,42 @@ public:
//- Is this character valid for a fileName?
inline static bool valid(char c);
//- Cleanup file name
//- Cleanup filename
//
// * Removes repeated slashes
// Removes trailing \c /
// \verbatim
// / --> /
// /abc/ --> /abc
// \endverbatim
//
// Removes repeated slashes
// \verbatim
// /abc////def --> /abc/def
// \endverbatim
//
// * Removes '/./'
// /abc/def/./ghi/. --> /abc/def/./ghi
// Removes \c /./ (current directory)
// \verbatim
// /abc/def/./ghi/. --> /abc/def/ghi
// abc/def/./ --> abc/def
// ./abc/ --> ./abc
// \endverbatim
//
// * Removes '/../'
// Removes \c /../ (parent directory)
// \verbatim
// /abc/def/../ghi/jkl/nmo/.. --> /abc/ghi/jkl
// abc/../def/ghi/../jkl --> abc/../def/jkl
// \endverbatim
//
// * Removes trailing '/'
//
// \return True if any contents changed
// \return True if the content changed
static bool clean(std::string& str);
//- Cleanup filename inplace
// \return True if any contents changed
bool clean();
//- Cleanup file name
// eg, remove repeated slashes, etc.
//- Cleanup filename
// \return cleaned copy of fileName
fileName clean() const;
@ -164,6 +180,9 @@ public:
// LINK (only if followLink=false)
Type type(const bool followLink = true) const;
//- Return true if string starts with a '/'
inline static bool isAbsolute(const std::string& str);
//- Return true if file name is absolute (starts with a '/')
inline bool isAbsolute() const;
@ -174,19 +193,28 @@ public:
// Decomposition
//- Return basename (part beyond last /), including its extension
// The result normally coresponds to a Foam::word
//
// Behaviour compared to /usr/bin/basename:
// \verbatim
// input name() basename
// ----- ------ --------
// "foo" "foo" "foo"
// "/" "" "/"
// "/foo" "foo" "foo"
// "foo/bar" "bar" "bar"
// "/foo/bar" "bar" "bar"
// "/foo/bar/" "" "bar"
// \endverbatim
static std::string name(const std::string& str);
//- Return basename (part beyond last /), including its extension
word name() const;
//- Return basename, without extension
// The result normally coresponds to a Foam::word
static std::string nameLessExt(const std::string& str);
//- Return basename, without extension
word nameLessExt() const;
@ -199,17 +227,22 @@ public:
}
//- Return directory path name (part before last /)
// The result normally coresponds to a Foam::fileName
//
// Behaviour compared to /usr/bin/dirname:
// \verbatim
// input path() dirname
// ----- ------ -------
// "foo" "." "."
// "/" "/" "/"
// "/foo" "/" "foo"
// "foo/bar" "foo" "foo"
// "/foo/bar" "/foo" "/foo"
// "/foo/bar/" "/foo/bar/" "/foo"
// \endverbatim
static std::string path(const std::string& str);
//- Return directory path name (part before last /)
fileName path() const;
//- Return file name without extension (part before last .)
@ -242,11 +275,11 @@ public:
// \verbatim
// Input components()
// ----- ------
// "foo" 1("foo")
// "/foo" 1("foo")
// "foo/bar" 2("foo", "bar")
// "/foo/bar" 2("foo", "bar")
// "/foo/bar/" 2("foo", "bar")
// "foo" ("foo")
// "/foo" ("foo")
// "foo/bar" ("foo", "bar")
// "/foo/bar" ("foo", "bar")
// "/foo/bar/" ("foo", "bar")
// \endverbatim
wordList components(const char delimiter = '/') const;

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
\\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -116,6 +116,12 @@ inline bool Foam::fileName::valid(char c)
}
inline bool Foam::fileName::isAbsolute(const std::string& str)
{
return !str.empty() && str[0] == '/';
}
inline bool Foam::fileName::isAbsolute() const
{
return !empty() && operator[](0) == '/';