1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
28 #include "DynamicList.H"
30 #include "OSspecific.H"
32 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
34 const char* const Foam::fileName::typeName = "fileName";
35 int Foam::fileName::debug(debug::debugSwitch(fileName::typeName, 0));
36 const Foam::fileName Foam::fileName::null;
38 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
40 Foam::fileName::fileName(const wordList& lst)
44 operator=((*this)/lst[elemI]);
49 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
51 Foam::fileName::Type Foam::fileName::type() const
53 return ::Foam::type(*this);
57 bool Foam::fileName::isAbsolute() const
59 return !empty() && operator[](0) == '/';
64 // * remove repeated slashes
65 // /abc////def --> /abc/def
68 // /abc/def/./ghi/. --> /abc/def/./ghi
69 // abc/def/./ --> abc/def
72 // /abc/def/../ghi/jkl/nmo/.. --> /abc/ghi/jkl
73 // abc/../def/ghi/../jkl --> abc/../def/jkl
75 // * remove trailing '/'
77 bool Foam::fileName::clean()
79 // the top slash - we are never allowed to go above it
80 register string::size_type top = this->find('/');
82 // no slashes - nothing to do
83 if (top == string::npos)
88 // start with the '/' found:
89 register char prev = '/';
90 register string::size_type nChar = top+1;
91 register string::size_type maxLen = this->size();
95 register string::size_type src = nChar;
100 register char c = operator[](src++);
104 // repeated '/' - skip it
110 // could be '/./' or '/../'
113 // found trailing '/.' - skip it
120 // peek at the next character
121 register char c1 = operator[](src);
123 // found '/./' - skip it
130 // it is '/..' or '/../'
131 if (c1 == '.' && (src+1 >= maxLen || operator[](src+1) == '/'))
133 string::size_type parent;
135 // backtrack to find the parent directory
136 // minimum of 3 characters: '/x/../'
137 // strip it, provided it is above the top point
141 && (parent = this->rfind('/', nChar-2)) != string::npos
145 nChar = parent + 1; // retain '/' from the parent
150 // bad resolution, eg 'abc/../../'
151 // retain the sequence, but move the top to avoid it being
152 // considered a valid parent later
157 operator[](nChar++) = prev = c;
160 // remove trailing slash
161 if (nChar > 1 && operator[](nChar-1) == '/')
168 return (nChar != maxLen);
172 Foam::fileName Foam::fileName::clean() const
174 fileName fName(*this);
181 // Return file name (part beyond last /)
183 // behaviour compared to /usr/bin/basename:
184 // input name() basename
185 // ----- ------ --------
187 // "/foo" "foo" "foo"
188 // "foo/bar" "bar" "bar"
189 // "/foo/bar" "bar" "bar"
190 // "/foo/bar/" "" "bar"
192 Foam::word Foam::fileName::name() const
194 size_type i = rfind('/');
202 return substr(i+1, npos);
207 Foam::word Foam::fileName::name(const bool noExt) const
211 size_type beg = rfind('/');
221 size_type dot = rfind('.');
222 if (dot != npos && dot <= beg)
229 return substr(beg, npos);
233 return substr(beg, dot - beg);
243 // Return directory path name (part before last /)
245 // behaviour compared to /usr/bin/dirname:
246 // input path() dirname
247 // ----- ------ -------
250 // "foo/bar" "foo" "foo"
251 // "/foo/bar" "/foo" "/foo"
252 // "/foo/bar/" "/foo/bar/" "/foo"
254 Foam::fileName Foam::fileName::path() const
256 size_type i = rfind('/');
273 // Return file name without extension (part before last .)
274 Foam::fileName Foam::fileName::lessExt() const
276 size_type i = find_last_of("./");
278 if (i == npos || i == 0 || operator[](i) == '/')
289 // Return file name extension (part after last .)
290 Foam::word Foam::fileName::ext() const
292 size_type i = find_last_of("./");
294 if (i == npos || i == 0 || operator[](i) == '/')
300 return substr(i+1, npos);
305 // Return the components of the file name as a wordList
306 // note that concatenating the components will not necessarily retrieve
307 // the original input fileName
310 // input components()
314 // "foo/bar" 2("foo", "bar")
315 // "/foo/bar" 2("foo", "bar")
316 // "/foo/bar/" 2("foo", "bar")
318 Foam::wordList Foam::fileName::components(const char delimiter) const
320 DynamicList<word> wrdList(20);
322 size_type beg=0, end=0;
324 while ((end = find(delimiter, beg)) != npos)
326 // avoid empty element (caused by doubled slashes)
329 wrdList.append(substr(beg, end-beg));
334 // avoid empty trailing element
337 wrdList.append(substr(beg, npos));
340 // transfer to wordList
341 return wordList(wrdList.xfer());
345 // Return a component of the file name
346 Foam::word Foam::fileName::component
348 const size_type cmpt,
352 return components(delimiter)[cmpt];
356 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
358 const Foam::fileName& Foam::fileName::operator=(const fileName& str)
360 string::operator=(str);
365 const Foam::fileName& Foam::fileName::operator=(const word& str)
367 string::operator=(str);
372 const Foam::fileName& Foam::fileName::operator=(const string& str)
374 string::operator=(str);
380 const Foam::fileName& Foam::fileName::operator=(const std::string& str)
382 string::operator=(str);
388 const Foam::fileName& Foam::fileName::operator=(const char* str)
390 string::operator=(str);
396 // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
398 Foam::fileName Foam::operator/(const string& a, const string& b)
400 if (a.size()) // First string non-null
402 if (b.size()) // Second string non-null
404 return fileName(a + '/' + b);
406 else // Second string null
411 else // First string null
413 if (b.size()) // Second string non-null
417 else // Second string null
425 // ************************************************************************* //