FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

fileName.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 \*---------------------------------------------------------------------------*/
00025 
00026 #include "fileName.H"
00027 #include <OpenFOAM/wordList.H>
00028 #include <OpenFOAM/DynamicList.H>
00029 #include <OpenFOAM/debug.H>
00030 #include <OpenFOAM/OSspecific.H>
00031 
00032 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00033 
00034 const char* const Foam::fileName::typeName = "fileName";
00035 int Foam::fileName::debug(debug::debugSwitch(fileName::typeName, 0));
00036 const Foam::fileName Foam::fileName::null;
00037 
00038 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00039 
00040 Foam::fileName::fileName(const wordList& lst)
00041 {
00042     forAll(lst, elemI)
00043     {
00044         operator=((*this)/lst[elemI]);
00045     }
00046 }
00047 
00048 
00049 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00050 
00051 Foam::fileName::Type Foam::fileName::type() const
00052 {
00053     return ::Foam::type(*this);
00054 }
00055 
00056 
00057 //
00058 // * remove repeated slashes
00059 //       /abc////def        -->   /abc/def
00060 //
00061 // * remove '/./'
00062 //       /abc/def/./ghi/.   -->   /abc/def/./ghi
00063 //       abc/def/./         -->   abc/def
00064 //
00065 // * remove '/../'
00066 //       /abc/def/../ghi/jkl/nmo/..   -->   /abc/ghi/jkl
00067 //       abc/../def/ghi/../jkl        -->   abc/../def/jkl
00068 //
00069 // * remove trailing '/'
00070 //
00071 bool Foam::fileName::clean()
00072 {
00073     // the top slash - we are never allowed to go above it
00074     register string::size_type top = this->find('/');
00075 
00076     // no slashes - nothing to do
00077     if (top == string::npos)
00078     {
00079         return false;
00080     }
00081 
00082     // start with the '/' found:
00083     register char prev = '/';
00084     register string::size_type nChar  = top+1;
00085     register string::size_type maxLen = this->size();
00086 
00087     for
00088     (
00089         register string::size_type src = nChar;
00090         src < maxLen;
00091         /*nil*/
00092     )
00093     {
00094         register char c = operator[](src++);
00095 
00096         if (prev == '/')
00097         {
00098             // repeated '/' - skip it
00099             if (c == '/')
00100             {
00101                 continue;
00102             }
00103 
00104             // could be '/./' or '/../'
00105             if (c == '.')
00106             {
00107                 // found trailing '/.' - skip it
00108                 if (src >= maxLen)
00109                 {
00110                     continue;
00111                 }
00112 
00113 
00114                 // peek at the next character
00115                 register char c1 = operator[](src);
00116 
00117                 // found '/./' - skip it
00118                 if (c1 == '/')
00119                 {
00120                     src++;
00121                     continue;
00122                 }
00123 
00124                 // it is '/..' or '/../'
00125                 if (c1 == '.' && (src+1 >= maxLen || operator[](src+1) == '/'))
00126                 {
00127                     string::size_type parent;
00128 
00129                     // backtrack to find the parent directory
00130                     // minimum of 3 characters:  '/x/../'
00131                     // strip it, provided it is above the top point
00132                     if
00133                     (
00134                         nChar > 2
00135                      && (parent = this->rfind('/', nChar-2)) != string::npos
00136                      && parent >= top
00137                     )
00138                     {
00139                         nChar = parent + 1;   // retain '/' from the parent
00140                         src += 2;
00141                         continue;
00142                     }
00143 
00144                     // bad resolution, eg 'abc/../../'
00145                     // retain the sequence, but move the top to avoid it being
00146                     // considered a valid parent later
00147                     top = nChar + 2;
00148                 }
00149             }
00150         }
00151         operator[](nChar++) = prev = c;
00152     }
00153 
00154     // remove trailing slash
00155     if (nChar > 1 && operator[](nChar-1) == '/')
00156     {
00157         nChar--;
00158     }
00159 
00160     this->resize(nChar);
00161 
00162     return (nChar != maxLen);
00163 }
00164 
00165 
00166 Foam::fileName Foam::fileName::clean() const
00167 {
00168     fileName fName(*this);
00169     fName.clean();
00170     return fName;
00171 }
00172 
00173 
00174 
00175 //  Return file name (part beyond last /)
00176 //
00177 //  behaviour compared to /usr/bin/basename:
00178 //    input           name()          basename
00179 //    -----           ------          --------
00180 //    "foo"           "foo"           "foo"
00181 //    "/foo"          "foo"           "foo"
00182 //    "foo/bar"       "bar"           "bar"
00183 //    "/foo/bar"      "bar"           "bar"
00184 //    "/foo/bar/"     ""              "bar"
00185 //
00186 Foam::word Foam::fileName::name() const
00187 {
00188     size_type i = rfind('/');
00189 
00190     if (i == npos)
00191     {
00192         return *this;
00193     }
00194     else
00195     {
00196         return substr(i+1, npos);
00197     }
00198 }
00199 
00200 
00201 //  Return directory path name (part before last /)
00202 //
00203 //  behaviour compared to /usr/bin/dirname:
00204 //    input           path()          dirname
00205 //    -----           ------          -------
00206 //    "foo"           "."             "."
00207 //    "/foo"          "/"             "foo"
00208 //    "foo/bar"       "foo"           "foo"
00209 //    "/foo/bar"      "/foo"          "/foo"
00210 //    "/foo/bar/"     "/foo/bar/"     "/foo"
00211 //
00212 Foam::fileName Foam::fileName::path() const
00213 {
00214     size_type i = rfind('/');
00215 
00216     if (i == npos)
00217     {
00218         return ".";
00219     }
00220     else if (i)
00221     {
00222         return substr(0, i);
00223     }
00224     else
00225     {
00226         return "/";
00227     }
00228 }
00229 
00230 
00231 //  Return file name without extension (part before last .)
00232 Foam::fileName Foam::fileName::lessExt() const
00233 {
00234     size_type i = find_last_of("./");
00235 
00236     if (i == npos || i == 0 || operator[](i) == '/')
00237     {
00238         return *this;
00239     }
00240     else
00241     {
00242         return substr(0, i);
00243     }
00244 }
00245 
00246 
00247 //  Return file name extension (part after last .)
00248 Foam::word Foam::fileName::ext() const
00249 {
00250     size_type i = find_last_of("./");
00251 
00252     if (i == npos || i == 0 || operator[](i) == '/')
00253     {
00254         return word::null;
00255     }
00256     else
00257     {
00258         return substr(i+1, npos);
00259     }
00260 }
00261 
00262 
00263 // Return the components of the file name as a wordList
00264 // note that concatenating the components will not necessarily retrieve
00265 // the original input fileName
00266 //
00267 //  behaviour
00268 //    input           components()
00269 //    -----           ------
00270 //    "foo"           1("foo")
00271 //    "/foo"          1("foo")
00272 //    "foo/bar"       2("foo", "bar")
00273 //    "/foo/bar"      2("foo", "bar")
00274 //    "/foo/bar/"     2("foo", "bar")
00275 //
00276 Foam::wordList Foam::fileName::components(const char delimiter) const
00277 {
00278     DynamicList<word> wrdList(20);
00279 
00280     size_type start=0, end=0;
00281 
00282     while ((end = find(delimiter, start)) != npos)
00283     {
00284         // avoid empty element (caused by doubled slashes)
00285         if (start < end)
00286         {
00287             wrdList.append(substr(start, end-start));
00288         }
00289         start = end + 1;
00290     }
00291 
00292     // avoid empty trailing element
00293     if (start < size())
00294     {
00295         wrdList.append(substr(start, npos));
00296     }
00297 
00298     // transfer to wordList
00299     return wordList(wrdList.xfer());
00300 }
00301 
00302 
00303 // Return a component of the file name
00304 Foam::word Foam::fileName::component
00305 (
00306     const size_type cmpt,
00307     const char delimiter
00308 ) const
00309 {
00310     return components(delimiter)[cmpt];
00311 }
00312 
00313 
00314 // * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
00315 
00316 const Foam::fileName& Foam::fileName::operator=(const fileName& str)
00317 {
00318     string::operator=(str);
00319     return *this;
00320 }
00321 
00322 
00323 const Foam::fileName& Foam::fileName::operator=(const word& str)
00324 {
00325     string::operator=(str);
00326     return *this;
00327 }
00328 
00329 
00330 const Foam::fileName& Foam::fileName::operator=(const string& str)
00331 {
00332     string::operator=(str);
00333     stripInvalid();
00334     return *this;
00335 }
00336 
00337 
00338 const Foam::fileName& Foam::fileName::operator=(const std::string& str)
00339 {
00340     string::operator=(str);
00341     stripInvalid();
00342     return *this;
00343 }
00344 
00345 
00346 const Foam::fileName& Foam::fileName::operator=(const char* str)
00347 {
00348     string::operator=(str);
00349     stripInvalid();
00350     return *this;
00351 }
00352 
00353 
00354 // * * * * * * * * * * * * * * * Friend Operators  * * * * * * * * * * * * * //
00355 
00356 Foam::fileName Foam::operator/(const string& a, const string& b)
00357 {
00358     if (a.size())           // First string non-null
00359     {
00360         if (b.size())       // Second string non-null
00361         {
00362             return fileName(a + '/' + b);
00363         }
00364         else                // Second string null
00365         {
00366             return a;
00367         }
00368     }
00369     else                    // First string null
00370     {
00371         if (b.size())       // Second string non-null
00372         {
00373             return b;
00374         }
00375         else                // Second string null
00376         {
00377             return fileName();
00378         }
00379     }
00380 }
00381 
00382 
00383 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines