casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Path.h
Go to the documentation of this file.
00001 //# Path.h: Path name of a file
00002 //# Copyright (C) 1993,1994,1995,1996,1997,1998,1999,2000
00003 //# Associated Universities, Inc. Washington DC, USA.
00004 //#
00005 //# This library is free software; you can redistribute it and/or modify it
00006 //# under the terms of the GNU Library General Public License as published by
00007 //# the Free Software Foundation; either version 2 of the License, or (at your
00008 //# option) any later version.
00009 //#
00010 //# This library is distributed in the hope that it will be useful, but WITHOUT
00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00013 //# License for more details.
00014 //#
00015 //# You should have received a copy of the GNU Library General Public License
00016 //# along with this library; if not, write to the Free Software Foundation,
00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
00018 //#
00019 //# Correspondence concerning AIPS++ should be addressed as follows:
00020 //#        Internet email: aips2-request@nrao.edu.
00021 //#        Postal address: AIPS++ Project Office
00022 //#                        National Radio Astronomy Observatory
00023 //#                        520 Edgemont Road
00024 //#                        Charlottesville, VA 22903-2475 USA
00025 //#
00026 //# $Id: Path.h 21030 2011-03-16 13:44:34Z gervandiepen $
00027 
00028 
00029 #ifndef CASA_PATH_H
00030 #define CASA_PATH_H
00031 
00032 //# Includes
00033 #include <casa/aips.h>
00034 #include <casa/BasicSL/String.h>
00035 
00036 
00037 namespace casa { //# NAMESPACE CASA - BEGIN
00038 
00039 // <summary>
00040 // Path name of a file
00041 // </summary>
00042 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos="">
00043 // </reviewed>
00044 
00045 // <prerequisite> 
00046 //    <li> Basic knowledge of the UNIX file system 
00047 // </prerequisite>
00048 
00049 // <etymology>
00050 // The term 'path' is the standard term for describing the location of a file 
00051 // in a hierarchy of possibly nested directories. In order to find a 
00052 // particular file you must travel a specific path strating from a known 
00053 // point. We use the term in its standard sense in this class. 
00054 // </etymology>
00055 
00056 // <synopsis>
00057 // This class can be used to describe a pathname. One can also create,
00058 // validate, parse (get base or directory names or original, expanded or
00059 // absolute names), query and append strings. The client programmer can 
00060 // give a string, at construction, which describes a path. This string can 
00061 // be a relative or an absolute name. Environment variables and a tilde
00062 // (with or without user name) can also be used in the string and will
00063 // be expanded by the function expandedName.
00064 // <br> The function 
00065 // Once a Path has been constructed, you can query the object for its
00066 // original name, expanded name, absolute name, the name of the directory
00067 // where it is found or the name of only the file. Expanding the path name
00068 // means that possible environment variables and tilde get expanded.
00069 // There are also functions to get the length or maximum length of a path.
00070 // Pathnames can also be checked on correctness and they can be checked
00071 // if they conform the POSIX standard.
00072 // </synopsis>
00073 
00074 // <example>
00075 // In this example a few pathnames are created.
00076 // <srcblock>
00077 //    Path test1("~/test/$TEST1/..");     // absolute path
00078 //    Path test2("/$HOME/./analyse");     // absolute path
00079 //    Path test3("myFile");               // relative path
00080 // 
00081 //    cout << test1.originalName() << endl;
00082 //
00083 //    // Test1 is according the POSIX standard
00084 //    if (test1.isStrictlyPosix()){         
00085 //       cout << "test1 is strictly POSIX << endl;  
00086 //    }
00087 // 
00088 //    // Test1 is valid
00089 //    if (test1.isValid()){                 
00090 //       cout << test1.isValid() << endl;
00091 //    }
00092 //
00093 //    // if "TEST1=$TEST2 and TEST2=$TEST1"(recursive environment variables) 
00094 //    // an exception will be thrown. ~ is replaced by the homedirectory
00095 //    cout << test1.expandedName() << endl;
00096 //    // $HOME is expanded 
00097 //    cout << test2.expandedName() << endl; 
00098 //    cout << test1.absoluteName() << endl; 
00099 //    cout << test2.absoluteName() << endl; 
00100 //    cout << test2.baseName() << endl;
00101 //    cout << test1.dirName() << endl;
00102 //    cout << test3.originalName() << endl; // myFile is returned 
00103 //    cout << test3.expandedName() << endl; // Nothing is changed
00104 //    cout << test3.absoluteName() << endl; // The current working directory
00105 //                                             is placed before 'myFile'  
00106 //    cout << test3.baseName() << endl; // The current working directory 
00107 //                                      // is returned
00108 //    cout << test3.dirName() << endl;  // myFile is returned
00109 // </srcblock>
00110 // </example>
00111 
00112 // <motivation>
00113 // Programmer convenience and (eventually) OS independence.
00114 // </motivation>
00115 
00116 // <todo asof=$DATE$>
00117 // <li> To make the class OS independent some functions should be rebuild.
00118 //      These functions could be expandedName or absoluteName.
00119 // <li> The function expandedName or absoluteName could map the filename to 
00120 //      the native convention 
00121 // <li> A (maybe static) function contractName(const String& pathName)
00122 //      could be implemented to remove . and .. from the file name.
00123 // </todo>
00124 
00125 
00126 class Path
00127 {
00128 public:
00129     // Default constructor, the path is set to . (working directory).
00130     Path();
00131 
00132     // Construct a path with the given name.
00133     // When the name is empty, it is set to . (working directory).
00134     // It is not checked if the path name is valid.
00135     // Function isValid() can be used for that purpose.
00136     Path (const String& pathName);
00137 
00138     // Copy constructor, copy semantics.
00139     Path (const Path& that);
00140 
00141     // Destructor
00142     ~Path();
00143 
00144     // Assignment, copy semantics.
00145     Path& operator= (const Path& that);
00146 
00147     // Append a string to the path name.
00148     // When the current path does not end with a / and the string to append
00149     // does not start with a /, an intermediate / is also added.
00150     void append (const String& string);
00151 
00152     // Returns the string as given at construction. 
00153     const String& originalName () const;
00154 
00155     // Return a string giving the expanded pathname.
00156     // This means that the environment variables are expanded and the tilde 
00157     // is replaced by the home directory. An expanded name can still
00158     // be a relative path.
00159     // An exception is thrown when converting a recursive environment
00160     // variable results in an endless loop (that is, more than 25
00161     // substitutions).
00162     const String& expandedName () const;
00163 
00164     // Return the string which giving the absolute pathname.
00165     // It is generated from the expanded pathname by adding
00166     // the working directory when needed.
00167     const String& absoluteName () const;
00168 
00169     // Return the realpath which is the absolute pathname with possible
00170     // symlinks resolved. It also resolves //, /./, /../ and trailing /.
00171     // <br>The path must be an existing file or directory.
00172     // It uses the system's realpath function. In case it fails,
00173     // an exception is thrown.
00174     String resolvedName() const;
00175 
00176     // Check if pathname is valid. This function checks for: double slashes, 
00177     // non-printable characters, pathname length and filename lenghts, this 
00178     // function is more OS-specific.
00179     Bool isValid() const;
00180 
00181     // Check if pathname is valid according the POSIX standard.
00182     // This function checks for
00183     // double slashes, non-printable characters,pathname length and filename 
00184     // lenghts, all according to the POSIX-standard.
00185     Bool isStrictlyPosix() const;
00186 
00187     // Return length of path name
00188     uInt length() const;
00189 
00190     // Return the maximum length a path name can have.
00191     uInt maxLength() const;
00192 
00193     // Return the basename of the path; this is only the name of the file.
00194     // It takes it from the expanded path name.
00195     String baseName() const;
00196 
00197     // Return the dirname of the path; this is the directory where the 
00198     // filename is found. It takes it from the expanded path name.
00199     // <br>To get the absolute dirname one could do:
00200     // <srcblock>
00201     //     Path tmpPath (myPath.dirName());
00202     //     String absDir (tmpPath.absoluteName());
00203     // </srcblock>
00204     // or
00205     // <srcblock>
00206     //     Path tmpPath (myPath.absoluteName());
00207     //     String absDir (tmpPath.dirName());
00208     // </srcblock>
00209     String dirName() const;
00210 
00211     // Strip otherName from this name. If stripped, the result gets a
00212     // leading ././
00213     // If not stripped, it is tried if name can be stripped from otherName.
00214     // If stripped, the result gets a trailing /.
00215     // If still not stripped, it is tried to strip the directory of otherName.
00216     // If that succeeds, the result gets a leading ./
00217     // This is used by RefTable and TableKeyword to ensure that the
00218     // name of a subtable or referenced table is always relative to
00219     // the main table.
00220     static String stripDirectory (const String& name, const String& otherName);
00221 
00222     // If the name starts with ././ add otherName to it.
00223     // If the name ends with /. strip name from otherName and return the
00224     // remainder.
00225     // If the name starts with ./ add the directory of otherName to it.
00226     // It is the opposite of stripDirectory.
00227     static String addDirectory (const String& name, const String& otherName);
00228 
00229 
00230 private:
00231     // Strings to describe the pathname in three different ways.
00232     String itsOriginalPathName;
00233     // These variables are pointer to strings because the functions which use 
00234     // these variables are const functions. This means that they would not be 
00235     // able to modify the string, now they can.
00236     mutable String itsAbsolutePathName;
00237     mutable String itsExpandedPathName;
00238 
00239     // Define the maximum number of bytes in a pathname
00240     // This definition does not use Posix values.
00241     static uInt getMaxPathNameSize ();
00242     // Define the maximum number of bytes in a filename
00243     // This definition does not use Posix values.
00244     static uInt getMaxNameSize ();
00245 
00246 
00247     // This function is used by expandedName to replace the tilde and to
00248     // expand the environment variables
00249     String expandName (const String& inString) const;
00250 
00251     // This function is used by absoluteName to make a name absolute, 
00252     // this means that the name is described from the root
00253     String makeAbsoluteName (const String& inString) const;
00254 
00255     // Remove . and .. from the path name.
00256     // Also multiple slashes are replaced by a single.
00257     String removeDots (const String& inString) const;
00258 
00259     // This function is used by expandName and absoluteName. It sets the 
00260     // integer "count" on the next slash or on the end of a string
00261     void getNextName (const String& inString, uInt& count) const;
00262 };
00263 
00264 
00265 inline const String& Path::originalName() const
00266 {
00267     return itsOriginalPathName;
00268 }
00269 
00270 
00271 
00272 } //# NAMESPACE CASA - END
00273 
00274 #endif