filename.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 2,162 行 · 第 1/5 页
CPP
2,162 行
/////////////////////////////////////////////////////////////////////////////
// Name: src/common/filename.cpp
// Purpose: wxFileName - encapsulates a file path
// Author: Robert Roebling, Vadim Zeitlin
// Modified by:
// Created: 28.12.2000
// RCS-ID: $Id: filename.cpp,v 1.158.2.6 2006/03/02 12:46:06 JS Exp $
// Copyright: (c) 2000 Robert Roebling
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
/*
Here are brief descriptions of the filename formats supported by this class:
wxPATH_UNIX: standard Unix format, used under Darwin as well, absolute file
names have the form:
/dir1/dir2/.../dirN/filename, "." and ".." stand for the
current and parent directory respectively, "~" is parsed as the
user HOME and "~username" as the HOME of that user
wxPATH_DOS: DOS/Windows format, absolute file names have the form:
drive:\dir1\dir2\...\dirN\filename.ext where drive is a single
letter. "." and ".." as for Unix but no "~".
There are also UNC names of the form \\share\fullpath
wxPATH_MAC: Mac OS 8/9 and Mac OS X under CodeWarrior 7 format, absolute file
names have the form
volume:dir1:...:dirN:filename
and the relative file names are either
:dir1:...:dirN:filename
or just
filename
(although :filename works as well).
Since the volume is just part of the file path, it is not
treated like a separate entity as it is done under DOS and
VMS, it is just treated as another dir.
wxPATH_VMS: VMS native format, absolute file names have the form
<device>:[dir1.dir2.dir3]file.txt
or
<device>:[000000.dir1.dir2.dir3]file.txt
the <device> is the physical device (i.e. disk). 000000 is the
root directory on the device which can be omitted.
Note that VMS uses different separators unlike Unix:
: always after the device. If the path does not contain : than
the default (the device of the current directory) is assumed.
[ start of directory specification
. separator between directory and subdirectory
] between directory and file
*/
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
#pragma implementation "filename.h"
#endif
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/intl.h"
#include "wx/log.h"
#include "wx/file.h"
#endif
#include "wx/filename.h"
#include "wx/tokenzr.h"
#include "wx/config.h" // for wxExpandEnvVars
#include "wx/utils.h"
#include "wx/file.h"
#include "wx/dynlib.h"
// For GetShort/LongPathName
#ifdef __WIN32__
#include "wx/msw/wrapwin.h"
#if defined(__MINGW32__)
#include "wx/msw/gccpriv.h"
#endif
#endif
#ifdef __WXWINCE__
#include "wx/msw/private.h"
#endif
#if defined(__WXMAC__)
#include "wx/mac/private.h" // includes mac headers
#endif
// utime() is POSIX so should normally be available on all Unices
#ifdef __UNIX_LIKE__
#include <sys/types.h>
#include <utime.h>
#include <sys/stat.h>
#include <unistd.h>
#endif
#ifdef __DJGPP__
#include <unistd.h>
#endif
#ifdef __MWERKS__
#ifdef __MACH__
#include <sys/types.h>
#include <utime.h>
#include <sys/stat.h>
#include <unistd.h>
#else
#include <stat.h>
#include <unistd.h>
#include <unix.h>
#endif
#endif
#ifdef __WATCOMC__
#include <io.h>
#include <sys/utime.h>
#include <sys/stat.h>
#endif
#ifdef __VISAGECPP__
#ifndef MAX_PATH
#define MAX_PATH 256
#endif
#endif
#ifdef __EMX__
#include <os2.h>
#define MAX_PATH _MAX_PATH
#endif
// ----------------------------------------------------------------------------
// private classes
// ----------------------------------------------------------------------------
// small helper class which opens and closes the file - we use it just to get
// a file handle for the given file name to pass it to some Win32 API function
#if defined(__WIN32__) && !defined(__WXMICROWIN__)
class wxFileHandle
{
public:
enum OpenMode
{
Read,
Write
};
wxFileHandle(const wxString& filename, OpenMode mode)
{
m_hFile = ::CreateFile
(
filename, // name
mode == Read ? GENERIC_READ // access mask
: GENERIC_WRITE,
FILE_SHARE_READ | // sharing mode
FILE_SHARE_WRITE, // (allow everything)
NULL, // no secutity attr
OPEN_EXISTING, // creation disposition
0, // no flags
NULL // no template file
);
if ( m_hFile == INVALID_HANDLE_VALUE )
{
wxLogSysError(_("Failed to open '%s' for %s"),
filename.c_str(),
mode == Read ? _("reading") : _("writing"));
}
}
~wxFileHandle()
{
if ( m_hFile != INVALID_HANDLE_VALUE )
{
if ( !::CloseHandle(m_hFile) )
{
wxLogSysError(_("Failed to close file handle"));
}
}
}
// return true only if the file could be opened successfully
bool IsOk() const { return m_hFile != INVALID_HANDLE_VALUE; }
// get the handle
operator HANDLE() const { return m_hFile; }
private:
HANDLE m_hFile;
};
#endif // __WIN32__
// ----------------------------------------------------------------------------
// private functions
// ----------------------------------------------------------------------------
#if wxUSE_DATETIME && defined(__WIN32__) && !defined(__WXMICROWIN__)
// convert between wxDateTime and FILETIME which is a 64-bit value representing
// the number of 100-nanosecond intervals since January 1, 1601.
static void ConvertFileTimeToWx(wxDateTime *dt, const FILETIME &ft)
{
FILETIME ftcopy = ft;
FILETIME ftLocal;
if ( !::FileTimeToLocalFileTime(&ftcopy, &ftLocal) )
{
wxLogLastError(_T("FileTimeToLocalFileTime"));
}
SYSTEMTIME st;
if ( !::FileTimeToSystemTime(&ftLocal, &st) )
{
wxLogLastError(_T("FileTimeToSystemTime"));
}
dt->Set(st.wDay, wxDateTime::Month(st.wMonth - 1), st.wYear,
st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
}
static void ConvertWxToFileTime(FILETIME *ft, const wxDateTime& dt)
{
SYSTEMTIME st;
st.wDay = dt.GetDay();
st.wMonth = (WORD)(dt.GetMonth() + 1);
st.wYear = (WORD)dt.GetYear();
st.wHour = dt.GetHour();
st.wMinute = dt.GetMinute();
st.wSecond = dt.GetSecond();
st.wMilliseconds = dt.GetMillisecond();
FILETIME ftLocal;
if ( !::SystemTimeToFileTime(&st, &ftLocal) )
{
wxLogLastError(_T("SystemTimeToFileTime"));
}
if ( !::LocalFileTimeToFileTime(&ftLocal, ft) )
{
wxLogLastError(_T("LocalFileTimeToFileTime"));
}
}
#endif // wxUSE_DATETIME && __WIN32__
// return a string with the volume par
static wxString wxGetVolumeString(const wxString& volume, wxPathFormat format)
{
wxString path;
if ( !volume.empty() )
{
format = wxFileName::GetFormat(format);
// Special Windows UNC paths hack, part 2: undo what we did in
// SplitPath() and make an UNC path if we have a drive which is not a
// single letter (hopefully the network shares can't be one letter only
// although I didn't find any authoritative docs on this)
if ( format == wxPATH_DOS && volume.length() > 1 )
{
path << wxFILE_SEP_PATH_DOS << wxFILE_SEP_PATH_DOS << volume;
}
else if ( format == wxPATH_DOS || format == wxPATH_VMS )
{
path << volume << wxFileName::GetVolumeSeparator(format);
}
// else ignore
}
return path;
}
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// wxFileName construction
// ----------------------------------------------------------------------------
void wxFileName::Assign( const wxFileName &filepath )
{
m_volume = filepath.GetVolume();
m_dirs = filepath.GetDirs();
m_name = filepath.GetName();
m_ext = filepath.GetExt();
m_relative = filepath.m_relative;
m_hasExt = filepath.m_hasExt;
}
void wxFileName::Assign(const wxString& volume,
const wxString& path,
const wxString& name,
const wxString& ext,
bool hasExt,
wxPathFormat format )
{
SetPath( path, format );
m_volume = volume;
m_ext = ext;
m_name = name;
m_hasExt = hasExt;
}
void wxFileName::SetPath( const wxString& pathOrig, wxPathFormat format )
{
m_dirs.Clear();
if ( pathOrig.empty() )
{
// no path at all
m_relative = true;
return;
}
format = GetFormat( format );
// 0) deal with possible volume part first
wxString volume,
path;
SplitVolume(pathOrig, &volume, &path, format);
if ( !volume.empty() )
{
m_relative = false;
SetVolume(volume);
}
// 1) Determine if the path is relative or absolute.
wxChar leadingChar = path[0u];
switch (format)
{
case wxPATH_MAC:
m_relative = leadingChar == wxT(':');
// We then remove a leading ":". The reason is in our
// storage form for relative paths:
// ":dir:file.txt" actually means "./dir/file.txt" in
// DOS notation and should get stored as
// (relative) (dir) (file.txt)
// "::dir:file.txt" actually means "../dir/file.txt"
// stored as (relative) (..) (dir) (file.txt)
// This is important only for the Mac as an empty dir
// actually means <UP>, whereas under DOS, double
// slashes can be ignored: "\\\\" is the same as "\\".
if (m_relative)
path.erase( 0, 1 );
break;
case wxPATH_VMS:
// TODO: what is the relative path format here?
m_relative = false;
break;
default:
wxFAIL_MSG( _T("Unknown path format") );
// !! Fall through !!
case wxPATH_UNIX:
// the paths of the form "~" or "~username" are absolute
m_relative = leadingChar != wxT('/') && leadingChar != _T('~');
break;
case wxPATH_DOS:
m_relative = !IsPathSeparator(leadingChar, format);
break;
}
// 2) Break up the path into its members. If the original path
// was just "/" or "\\", m_dirs will be empty. We know from
// the m_relative field, if this means "nothing" or "root dir".
wxStringTokenizer tn( path, GetPathSeparators(format) );
while ( tn.HasMoreTokens() )
{
wxString token = tn.GetNextToken();
// Remove empty token under DOS and Unix, interpret them
// as .. under Mac.
if (token.empty())
{
if (format == wxPATH_MAC)
m_dirs.Add( wxT("..") );
// else ignore
}
else
{
m_dirs.Add( token );
}
}
}
void wxFileName::Assign(const wxString& fullpath,
wxPathFormat format)
{
wxString volume, path, name, ext;
bool hasExt;
SplitPath(fullpath, &volume, &path, &name, &ext, &hasExt, format);
Assign(volume, path, name, ext, hasExt, format);
}
void wxFileName::Assign(const wxString& fullpathOrig,
const wxString& fullname,
wxPathFormat format)
{
// always recognize fullpath as directory, even if it doesn't end with a
// slash
wxString fullpath = fullpathOrig;
if ( !wxEndsWithPathSeparator(fullpath) )
{
fullpath += GetPathSeparator(format);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?