]>
git.saurik.com Git - wxWidgets.git/blob - src/common/filename.cpp
086598ef3bbae2cad467dd51878d1393e2763006
   1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/common/filename.cpp 
   3 // Purpose:     wxFileName - encapsulates a file path 
   4 // Author:      Robert Roebling, Vadim Zeitlin 
   8 // Copyright:   (c) 2000 Robert Roebling 
   9 // Licence:     wxWindows license 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  21     #pragma implementation "filename.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  36 #include "wx/filename.h" 
  37 #include "wx/tokenzr.h" 
  38 #include "wx/config.h"          // for wxExpandEnvVars 
  41 // ============================================================================ 
  43 // ============================================================================ 
  45 // ---------------------------------------------------------------------------- 
  46 // wxFileName construction 
  47 // ---------------------------------------------------------------------------- 
  49 void wxFileName::Assign( const wxFileName 
&filepath 
) 
  51     m_ext 
= filepath
.GetExt(); 
  52     m_name 
= filepath
.GetName(); 
  53     m_dirs 
= filepath
.GetDirs(); 
  56 void wxFileName::Assign( const wxString
& path
, 
  61     wxStringTokenizer 
tn(path
, GetPathSeparators(format
), 
  62                          wxTOKEN_RET_EMPTY_ALL
); 
  65     while ( tn
.HasMoreTokens() ) 
  67         wxString token 
= tn
.GetNextToken(); 
  69         // If the path starts with a slash, we need the first 
  70         // dir entry to be an empty for later reassembly. 
  71         if (first 
|| !token
.IsEmpty()) 
  81 void wxFileName::Assign(const wxString
& fullpath
, 
  84     wxString path
, name
, ext
; 
  85     SplitPath(fullpath
, &path
, &name
, &ext
, format
); 
  87     Assign(path
, name
, ext
, format
); 
  90 void wxFileName::Assign(const wxString
& path
, 
  91                         const wxString
& fullname
, 
  95     SplitPath(fullname
, NULL 
/* no path */, &name
, &ext
, format
); 
  97     Assign(path
, name
, ext
, format
); 
 100 void wxFileName::Clear() 
 104     m_ext 
= wxEmptyString
; 
 108 wxFileName 
wxFileName::FileName(const wxString
& file
) 
 110     return wxFileName(file
); 
 114 wxFileName 
wxFileName::DirName(const wxString
& dir
) 
 121 // ---------------------------------------------------------------------------- 
 123 // ---------------------------------------------------------------------------- 
 125 bool wxFileName::FileExists() 
 127     return wxFileName::FileExists( GetFullPath() ); 
 130 bool wxFileName::FileExists( const wxString 
&file 
) 
 132     return ::wxFileExists( file 
); 
 135 bool wxFileName::DirExists() 
 137     return wxFileName::DirExists( GetFullPath() ); 
 140 bool wxFileName::DirExists( const wxString 
&dir 
) 
 142     return ::wxDirExists( dir 
); 
 145 // ---------------------------------------------------------------------------- 
 146 // CWD and HOME stuff 
 147 // ---------------------------------------------------------------------------- 
 149 void wxFileName::AssignCwd() 
 151     AssignDir(wxFileName::GetCwd()); 
 155 wxString 
wxFileName::GetCwd() 
 160 bool wxFileName::SetCwd() 
 162     return wxFileName::SetCwd( GetFullPath() ); 
 165 bool wxFileName::SetCwd( const wxString 
&cwd 
) 
 167     return ::wxSetWorkingDirectory( cwd 
); 
 170 void wxFileName::AssignHomeDir() 
 172     AssignDir(wxFileName::GetHomeDir()); 
 175 wxString 
wxFileName::GetHomeDir() 
 177     return ::wxGetHomeDir(); 
 180 void wxFileName::AssignTempFileName( const wxString 
&prefix 
) 
 183     if ( wxGetTempFileName(prefix
, fullname
) ) 
 193 // ---------------------------------------------------------------------------- 
 194 // directory operations 
 195 // ---------------------------------------------------------------------------- 
 197 bool wxFileName::Mkdir( int perm 
) 
 199     return wxFileName::Mkdir( GetFullPath(), perm 
); 
 202 bool wxFileName::Mkdir( const wxString 
&dir
, int perm 
) 
 204     return ::wxMkdir( dir
, perm 
); 
 207 bool wxFileName::Rmdir() 
 209     return wxFileName::Rmdir( GetFullPath() ); 
 212 bool wxFileName::Rmdir( const wxString 
&dir 
) 
 214     return ::wxRmdir( dir 
); 
 217 // ---------------------------------------------------------------------------- 
 218 // path normalization 
 219 // ---------------------------------------------------------------------------- 
 221 bool wxFileName::Normalize(wxPathNormalize flags
, 
 225     // the existing path components 
 226     wxArrayString dirs 
= GetDirs(); 
 228     // the path to prepend in front to make the path absolute 
 231     format 
= GetFormat(format
); 
 233     // make the path absolute 
 234     if ( (flags 
& wxPATH_NORM_ABSOLUTE
) && !IsAbsolute() ) 
 239             curDir
.AssignDir(cwd
); 
 242     // handle ~ stuff under Unix only 
 243     if ( (format 
== wxPATH_UNIX
) && (flags 
& wxPATH_NORM_TILDE
) ) 
 245         if ( !dirs
.IsEmpty() ) 
 247             wxString dir 
= dirs
[0u]; 
 248             if ( !dir
.empty() && dir
[0u] == _T('~') ) 
 250                 curDir
.AssignDir(wxGetUserHome(dir
.c_str() + 1)); 
 259         wxArrayString dirsNew 
= curDir
.GetDirs(); 
 260         size_t count 
= dirs
.GetCount(); 
 261         for ( size_t n 
= 0; n 
< count
; n
++ ) 
 263             dirsNew
.Add(dirs
[n
]); 
 269     // now deal with ".", ".." and the rest 
 271     size_t count 
= dirs
.GetCount(); 
 272     for ( size_t n 
= 0; n 
< count
; n
++ ) 
 274         wxString dir 
= dirs
[n
]; 
 276         if ( flags 
&& wxPATH_NORM_DOTS 
) 
 278             if ( dir 
== wxT(".") ) 
 284             if ( dir 
== wxT("..") ) 
 286                 if ( m_dirs
.IsEmpty() ) 
 288                     wxLogError(_("The path '%s' contains too many \"..\"!"), 
 289                                GetFullPath().c_str()); 
 293                 m_dirs
.Remove(m_dirs
.GetCount() - 1); 
 298         if ( flags 
& wxPATH_NORM_ENV_VARS 
) 
 300             dir 
= wxExpandEnvVars(dir
); 
 303         if ( (flags 
& wxPATH_NORM_CASE
) && !IsCaseSensitive(format
) ) 
 311     if ( (flags 
& wxPATH_NORM_CASE
) && !IsCaseSensitive(format
) ) 
 313         // VZ: expand env vars here too? 
 322 // ---------------------------------------------------------------------------- 
 323 // filename kind tests 
 324 // ---------------------------------------------------------------------------- 
 326 bool wxFileName::SameAs( const wxFileName 
&filepath
, wxPathFormat format
) 
 328     wxFileName fn1 
= *this, 
 331     // get cwd only once - small time saving 
 332     wxString cwd 
= wxGetCwd(); 
 333     fn1
.Normalize(wxPATH_NORM_ALL
, cwd
, format
); 
 334     fn2
.Normalize(wxPATH_NORM_ALL
, cwd
, format
); 
 336     if ( fn1
.GetFullPath() == fn2
.GetFullPath() ) 
 339     // TODO: compare inodes for Unix, this works even when filenames are 
 340     //       different but files are the same (symlinks) (VZ) 
 346 bool wxFileName::IsCaseSensitive( wxPathFormat format 
) 
 348     // only DOS filenames are case-sensitive 
 349     return GetFormat(format
) != wxPATH_DOS
; 
 352 bool wxFileName::IsRelative( wxPathFormat format 
) 
 354     return !IsAbsolute(format
); 
 357 bool wxFileName::IsAbsolute( wxPathFormat format 
) 
 359     wxChar ch 
= m_dirs
.IsEmpty() ? _T('\0') : m_dirs
[0u][0u]; 
 361     // the path is absolute if it starts with a path separator or, only for 
 362     // Unix filenames, with "~" or "~user" 
 363     return IsPathSeparator(ch
, format
) || 
 364            (GetFormat(format
) == wxPATH_UNIX 
&& ch 
== _T('~') ); 
 368 wxString 
wxFileName::GetPathSeparators(wxPathFormat format
) 
 371     switch ( GetFormat(format
) ) 
 374             // accept both as native APIs do 
 375             seps 
<< wxFILE_SEP_PATH_UNIX 
<< wxFILE_SEP_PATH_DOS
; 
 379             wxFAIL_MSG( _T("unknown wxPATH_XXX style") ); 
 383             seps 
= wxFILE_SEP_PATH_UNIX
; 
 387             seps 
= wxFILE_SEP_PATH_MAC
; 
 395 bool wxFileName::IsPathSeparator(wxChar ch
, wxPathFormat format
) 
 397     return GetPathSeparators(format
).Find(ch
) != wxNOT_FOUND
; 
 400 bool wxFileName::IsWild( wxPathFormat format 
) 
 402     // FIXME: this is probably false for Mac and this is surely wrong for most 
 403     //        of Unix shells (think about "[...]") 
 404     return m_name
.find_first_of(_T("*?")) != wxString::npos
; 
 407 // ---------------------------------------------------------------------------- 
 408 // path components manipulation 
 409 // ---------------------------------------------------------------------------- 
 411 void wxFileName::AppendDir( const wxString 
&dir 
) 
 416 void wxFileName::PrependDir( const wxString 
&dir 
) 
 418     m_dirs
.Insert( dir
, 0 ); 
 421 void wxFileName::InsertDir( int before
, const wxString 
&dir 
) 
 423     m_dirs
.Insert( dir
, before 
); 
 426 void wxFileName::RemoveDir( int pos 
) 
 428     m_dirs
.Remove( (size_t)pos 
); 
 431 // ---------------------------------------------------------------------------- 
 433 // ---------------------------------------------------------------------------- 
 435 void wxFileName::SetFullName(const wxString
& fullname
) 
 437     SplitPath(fullname
, NULL 
/* no path */, &m_name
, &m_ext
); 
 440 wxString 
wxFileName::GetFullName() const 
 442     wxString fullname 
= m_name
; 
 443     if ( !m_ext
.empty() ) 
 445         fullname 
<< wxFILE_SEP_EXT 
<< m_ext
; 
 451 wxString 
wxFileName::GetPath( bool add_separator
, wxPathFormat format 
) const 
 453     format 
= GetFormat( format 
); 
 456     size_t count 
= m_dirs
.GetCount(); 
 457     for ( size_t i 
= 0; i 
< count
; i
++ ) 
 460         if ( add_separator 
|| (i 
< count
) ) 
 461             ret 
+= wxFILE_SEP_PATH
; 
 467 wxString 
wxFileName::GetFullPath( wxPathFormat format 
) const 
 469     return GetPathWithSep() + GetFullName(); 
 472 wxPathFormat 
wxFileName::GetFormat( wxPathFormat format 
) 
 474     if (format 
== wxPATH_NATIVE
) 
 476 #if defined(__WXMSW__) || defined(__WXPM__) 
 478 #elif defined(__WXMAC__) 
 481         format 
= wxPATH_UNIX
; 
 487 // ---------------------------------------------------------------------------- 
 488 // path splitting function 
 489 // ---------------------------------------------------------------------------- 
 491 void wxFileName::SplitPath(const wxString
& fullpath
, 
 497     format 
= GetFormat(format
); 
 499     // find the positions of the last dot and last path separator in the path 
 500     size_t posLastDot 
= fullpath
.find_last_of(wxFILE_SEP_EXT
); 
 501     size_t posLastSlash 
= fullpath
.find_last_of(GetPathSeparators(format
)); 
 503     if ( (posLastDot 
!= wxString::npos
) && (format 
== wxPATH_UNIX
) ) 
 505         if ( (posLastDot 
== 0) || 
 506              (fullpath
[posLastDot 
- 1] == wxFILE_SEP_PATH_UNIX
) ) 
 508             // under Unix, dot may be (and commonly is) the first character of 
 509             // the filename, don't treat the entire filename as extension in 
 511             posLastDot 
= wxString::npos
; 
 515     // if we do have a dot and a slash, check that the dot is in the name part 
 516     if ( (posLastDot 
!= wxString::npos
) && 
 517          (posLastSlash 
!= wxString::npos
) && 
 518          (posLastDot 
< posLastSlash
) ) 
 520         // the dot is part of the path, not the start of the extension 
 521         posLastDot 
= wxString::npos
; 
 524     // now fill in the variables provided by user 
 527         if ( posLastSlash 
== wxString::npos 
) 
 534             // take all until the separator 
 535             *pstrPath 
= fullpath
.Left(posLastSlash
); 
 541         // take all characters starting from the one after the last slash and 
 542         // up to, but excluding, the last dot 
 543         size_t nStart 
= posLastSlash 
== wxString::npos 
? 0 : posLastSlash 
+ 1; 
 545         if ( posLastDot 
== wxString::npos 
) 
 547             // take all until the end 
 548             count 
= wxString::npos
; 
 550         else if ( posLastSlash 
== wxString::npos 
) 
 554         else // have both dot and slash 
 556             count 
= posLastDot 
- posLastSlash 
- 1; 
 559         *pstrName 
= fullpath
.Mid(nStart
, count
); 
 564         if ( posLastDot 
== wxString::npos 
) 
 571             // take everything after the dot 
 572             *pstrExt 
= fullpath
.Mid(posLastDot 
+ 1);