From dfecbee5795f4ecd50ece7dda7c1ff49f181a04d Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 28 Feb 2005 00:18:37 +0000 Subject: [PATCH] support filenames with empty extension (foo.) (bug 1078200) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@32436 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/latex/wx/filename.tex | 8 ++++++ include/wx/filename.h | 31 +++++++++++++++++++++-- src/common/filename.cpp | 56 +++++++++++++++++++++++++++-------------- tests/filename/filenametest.cpp | 4 +++ 4 files changed, 78 insertions(+), 21 deletions(-) diff --git a/docs/latex/wx/filename.tex b/docs/latex/wx/filename.tex index 96bb35e..feae4b9 100644 --- a/docs/latex/wx/filename.tex +++ b/docs/latex/wx/filename.tex @@ -197,6 +197,8 @@ assert failure in debug build). \func{void}{Assign}{\param{const wxString\& }{fullpath}, \param{wxPathFormat }{format = wxPATH\_NATIVE}} +\func{void}{Assign}{\param{const wxString\& }{volume}, \param{const wxString\& }{path}, \param{const wxString\& }{name}, \param{const wxString\& }{ext}, \param{bool }{hasExt}, \param{wxPathFormat }{format = wxPATH\_NATIVE}} + \func{void}{Assign}{\param{const wxString\& }{volume}, \param{const wxString\& }{path}, \param{const wxString\& }{name}, \param{const wxString\& }{ext}, \param{wxPathFormat }{format = wxPATH\_NATIVE}} \func{void}{Assign}{\param{const wxString\& }{path}, \param{const wxString\& }{name}, \param{wxPathFormat }{format = wxPATH\_NATIVE}} @@ -785,6 +787,8 @@ Sets the volume specifier. \membersection{wxFileName::SplitPath}\label{wxfilenamesplitpath} +\func{static void}{SplitPath}{\param{const wxString\& }{fullpath}, \param{wxString* }{volume}, \param{wxString* }{path}, \param{wxString* }{name}, \param{wxString* }{ext}, \param{bool }{*hasExt = \texttt{NULL}}, \param{wxPathFormat }{format = wxPATH\_NATIVE}} + \func{static void}{SplitPath}{\param{const wxString\& }{fullpath}, \param{wxString* }{volume}, \param{wxString* }{path}, \param{wxString* }{name}, \param{wxString* }{ext}, \param{wxPathFormat }{format = wxPATH\_NATIVE}} \func{static void}{SplitPath}{\param{const wxString\& }{fullpath}, \param{wxString* }{path}, \param{wxString* }{name}, \param{wxString* }{ext}, \param{wxPathFormat }{format = wxPATH\_NATIVE}} @@ -801,6 +805,10 @@ without leading dot. All three of them may be empty if the corresponding component is. The old contents of the strings pointed to by these parameters will be overwritten in any case (if the pointers are not {\tt NULL}). +Note that for a filename ``foo.'' the extension is present, as indicated by the +trailing dot, but empty. If you need to cope with such cases, you should use +\arg{hasExt} instead of relying on testing whether \arg{ext} is empty or not. + \membersection{wxFileName::SplitVolume}\label{wxfilenamesplitvolume} diff --git a/include/wx/filename.h b/include/wx/filename.h index 654ab52..131b6fc 100644 --- a/include/wx/filename.h +++ b/include/wx/filename.h @@ -142,8 +142,16 @@ public: const wxString& path, const wxString& name, const wxString& ext, + bool hasExt, wxPathFormat format = wxPATH_NATIVE); + void Assign(const wxString& volume, + const wxString& path, + const wxString& name, + const wxString& ext, + wxPathFormat format = wxPATH_NATIVE) + { Assign(volume, path, name, ext, !ext.empty(), format); } + void Assign(const wxString& path, const wxString& name, wxPathFormat format = wxPATH_NATIVE); @@ -178,7 +186,8 @@ public: bool IsOk() const { // we're fine if we have the path or the name or if we're a root dir - return m_dirs.size() != 0 || !m_name.IsEmpty() || !m_relative; + return m_dirs.size() != 0 || !m_name.IsEmpty() || !m_relative || + !m_ext.empty() || m_hasExt; } // does the file with this name exists? @@ -407,9 +416,20 @@ public: wxString *path, wxString *name, wxString *ext, + bool *hasExt = NULL, wxPathFormat format = wxPATH_NATIVE); - // compatibility version + static void SplitPath(const wxString& fullpath, + wxString *volume, + wxString *path, + wxString *name, + wxString *ext, + wxPathFormat format = wxPATH_NATIVE) + { + SplitPath(fullpath, volume, path, name, ext, NULL, format); + } + + // compatibility version: volume is part of path static void SplitPath(const wxString& fullpath, wxString *path, wxString *name, @@ -455,6 +475,13 @@ private: // NB: the path is not absolute just because m_relative is false, it still // needs the drive (i.e. volume) in some formats (Windows) bool m_relative; + + // when m_ext is empty, it may be because we don't have any extension or + // because we have an empty extension + // + // the difference is important as file with name "foo" and without + // extension has full name "foo" while with empty extension it is "foo." + bool m_hasExt; }; #endif // _WX_FILENAME_H_ diff --git a/src/common/filename.cpp b/src/common/filename.cpp index cdf66a8..46ce327 100644 --- a/src/common/filename.cpp +++ b/src/common/filename.cpp @@ -300,12 +300,14 @@ void wxFileName::Assign( const wxFileName &filepath ) 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 ); @@ -313,6 +315,8 @@ void wxFileName::Assign(const wxString& volume, m_volume = volume; m_ext = ext; m_name = name; + + m_hasExt = hasExt; } void wxFileName::SetPath( const wxString& pathOrig, wxPathFormat format ) @@ -411,9 +415,10 @@ void wxFileName::Assign(const wxString& fullpath, wxPathFormat format) { wxString volume, path, name, ext; - SplitPath(fullpath, &volume, &path, &name, &ext, format); + bool hasExt; + SplitPath(fullpath, &volume, &path, &name, &ext, &hasExt, format); - Assign(volume, path, name, ext, format); + Assign(volume, path, name, ext, hasExt, format); } void wxFileName::Assign(const wxString& fullpathOrig, @@ -429,15 +434,16 @@ void wxFileName::Assign(const wxString& fullpathOrig, } wxString volume, path, name, ext; + bool hasExt; // do some consistency checks in debug mode: the name should be really just // the filename and the path should be really just a path #ifdef __WXDEBUG__ - wxString pathDummy, nameDummy, extDummy; + wxString volDummy, pathDummy, nameDummy, extDummy; - SplitPath(fullname, &pathDummy, &name, &ext, format); + SplitPath(fullname, &volDummy, &pathDummy, &name, &ext, &hasExt, format); - wxASSERT_MSG( pathDummy.empty(), + wxASSERT_MSG( volDummy.empty() && pathDummy.empty(), _T("the file name shouldn't contain the path") ); SplitPath(fullpath, &volume, &path, &nameDummy, &extDummy, format); @@ -446,11 +452,11 @@ void wxFileName::Assign(const wxString& fullpathOrig, _T("the path shouldn't contain file name nor extension") ); #else // !__WXDEBUG__ - SplitPath(fullname, NULL /* no path */, &name, &ext, format); + SplitPath(fullname, NULL /* no path */, &name, &ext, &hasExt, format); SplitPath(fullpath, &volume, &path, NULL, NULL, format); #endif // __WXDEBUG__/!__WXDEBUG__ - Assign(volume, path, name, ext, format); + Assign(volume, path, name, ext, hasExt, format); } void wxFileName::Assign(const wxString& pathOrig, @@ -480,6 +486,9 @@ void wxFileName::Clear() // we don't have any absolute path for now m_relative = true; + + // nor any extension + m_hasExt = false; } /* static */ @@ -1352,13 +1361,14 @@ void wxFileName::RemoveDir(size_t pos) void wxFileName::SetFullName(const wxString& fullname) { - SplitPath(fullname, NULL /* no path */, &m_name, &m_ext); + SplitPath(fullname, NULL /* no volume */, NULL /* no path */, + &m_name, &m_ext, &m_hasExt); } wxString wxFileName::GetFullName() const { wxString fullname = m_name; - if ( !m_ext.empty() ) + if ( m_hasExt ) { fullname << wxFILE_SEP_EXT << m_ext; } @@ -1720,6 +1730,7 @@ void wxFileName::SplitPath(const wxString& fullpathWithVolume, wxString *pstrPath, wxString *pstrName, wxString *pstrExt, + bool *hasExt, wxPathFormat format) { format = GetFormat(format); @@ -1806,18 +1817,25 @@ void wxFileName::SplitPath(const wxString& fullpathWithVolume, *pstrName = fullpath.Mid(nStart, count); } - if ( pstrExt ) + // finally deal with the extension here: we have an added complication that + // extension may be empty (but present) as in "foo." where trailing dot + // indicates the empty extension at the end -- and hence we must remember + // that we have it independently of pstrExt + if ( posLastDot == wxString::npos ) { - if ( posLastDot == wxString::npos ) - { - // no extension - pstrExt->Empty(); - } - else - { - // take everything after the dot + // no extension + if ( pstrExt ) + pstrExt->clear(); + if ( hasExt ) + *hasExt = false; + } + else + { + // take everything after the dot + if ( pstrExt ) *pstrExt = fullpath.Mid(posLastDot + 1); - } + if ( hasExt ) + *hasExt = true; } } diff --git a/tests/filename/filenametest.cpp b/tests/filename/filenametest.cpp index 2ce261d..0e9681e 100644 --- a/tests/filename/filenametest.cpp +++ b/tests/filename/filenametest.cpp @@ -148,6 +148,10 @@ void FileNameTestCase::TestSplit() CPPUNIT_ASSERT( name == fni.name ); CPPUNIT_ASSERT( ext == fni.ext ); } + + // special case of empty extension + wxFileName fn(_T("foo.")); + CPPUNIT_ASSERT( fn.GetFullPath() == _T("foo.") ); } void FileNameTestCase::TestSetPath() -- 2.7.4