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

View File

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

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. \\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. 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 inline bool Foam::fileName::isAbsolute() const
{ {
return !empty() && operator[](0) == '/'; return !empty() && operator[](0) == '/';