From 1944c6bdd0daa0a9793e9a57f0800c169fec958b Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 8 Dec 1999 14:16:53 +0000 Subject: [PATCH] wxDir class added git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@4873 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/dir.h | 109 ++++++++++++++ samples/console/console.cpp | 84 ++++++++++- src/msw/dir.cpp | 281 ++++++++++++++++++++++++++++++++++++ src/unix/dir.cpp | 261 +++++++++++++++++++++++++++++++++ 4 files changed, 734 insertions(+), 1 deletion(-) create mode 100644 include/wx/dir.h create mode 100644 src/msw/dir.cpp create mode 100644 src/unix/dir.cpp diff --git a/include/wx/dir.h b/include/wx/dir.h new file mode 100644 index 0000000000..f8b0b67f3c --- /dev/null +++ b/include/wx/dir.h @@ -0,0 +1,109 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: wx/dir.h +// Purpose: wxDir is a class for enumerating the files in a directory +// Author: Vadim Zeitlin +// Modified by: +// Created: 08.12.99 +// RCS-ID: $Id$ +// Copyright: (c) 1999 Vadim Zeitlin +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_DIR_H_ +#define _WX_DIR_H_ + +#ifdef __GNUG__ + #pragma interface "dir.h" +#endif + +#ifndef WX_PRECOMP + #include "wx/string.h" +#endif + +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +// these flags define what kind of filenames is included in the list of files +// enumerated by GetFirst/GetNext +enum +{ + wxDIR_FILES = 0x0001, // include files + wxDIR_DIRS = 0x0002, // include directories + wxDIR_HIDDEN = 0x0004, // include hidden files + wxDIR_DOTDOT = 0x0008, // include '.' and '..' + + // by default, enumerate everything except '.' and '..' + wxDIR_DEFAULT = wxDIR_FILES | wxDIR_DIRS | wxDIR_HIDDEN +}; + +// ---------------------------------------------------------------------------- +// wxDir: portable equivalent of {open/read/close}dir functions +// ---------------------------------------------------------------------------- + +class WXDLLEXPORT wxDir +{ +public: + // test for existence of a directory with the given name + static bool Exists(const wxString& dir); + + // ctors + // ----- + + // default, use Open() + wxDir() { m_data = NULL; } + + // opens the directory for enumeration, use IsOpened() to test success + wxDir(const wxString& dir); + + // dtor cleans up the associated ressources + ~wxDir(); + + // open the directory for enumerating + bool Open(const wxString& dir); + + // returns TRUE if the directory was successfully opened + bool IsOpened() const; + + // file enumeration routines + // ------------------------- + + // start enumerating all files matching filespec (or all files if it is + // empty) and flags, return TRUE on success + bool GetFirst(wxString *filename, + const wxString& filespec = wxEmptyString, + int flags = wxDIR_DEFAULT) const; + + // get next file in the enumeration started with either GetFirst() or + // GetFirstNormal() + bool GetNext(wxString *filename) const; + + // TODO using scandir() when available later, emulating it otherwise +#if 0 + // get all files in the directory into an array, return TRUE on success + // + // this function uses Select() function to select the files + // unless the filespec is explicitly given and Compare() function to sort + // them + bool Read(wxArrayString& filenames, + const wxString& filespec = wxEmptyString) const; + +protected: + // this function is called by Read() if filespec is not specified in + // Read(): it should return TRUE if the file matches our selection + // criteria and FALSE otherwise + virtual bool Select(const wxChar* filename); + + // This function is called by Read() to sort the array: it should return + // -1, 0 or +1 if the first file is less than, equal to or greater than + // the second. The base class version does + virtual int Compare(const wxChar *filename1, const wxChar *filename2); +#endif // 0 + +private: + friend class WXDLLEXPORT wxDirData; + + wxDirData *m_data; +}; + +#endif // _WX_DIR_H_ diff --git a/samples/console/console.cpp b/samples/console/console.cpp index eaaf0a945e..ecbaeeda4f 100644 --- a/samples/console/console.cpp +++ b/samples/console/console.cpp @@ -30,8 +30,9 @@ // what to test? //#define TEST_ARRAYS +#define TEST_DIR //#define TEST_LOG -#define TEST_MIME +//#define TEST_MIME //#define TEST_STRINGS //#define TEST_THREADS //#define TEST_TIME @@ -41,6 +42,83 @@ // implementation // ============================================================================ +// ---------------------------------------------------------------------------- +// wxDir +// ---------------------------------------------------------------------------- + +#ifdef TEST_DIR + +#include + +static void TestDirEnumHelper(wxDir& dir, + int flags = wxDIR_DEFAULT, + const wxString& filespec = wxEmptyString) +{ + wxString filename; + + if ( !dir.IsOpened() ) + return; + + bool cont = dir.GetFirst(&filename, filespec, flags); + while ( cont ) + { + printf("\t%s\n", filename.c_str()); + + cont = dir.GetNext(&filename); + } + + puts(""); +} + +static void TestDirEnum() +{ + wxDir dir(wxGetCwd()); + + puts("Enumerating everything in current directory:"); + TestDirEnumHelper(dir); + + puts("Enumerating really everything in current directory:"); + TestDirEnumHelper(dir, wxDIR_DEFAULT | wxDIR_DOTDOT); + + puts("Enumerating object files in current directory:"); + TestDirEnumHelper(dir, wxDIR_DEFAULT, "*.o"); + + puts("Enumerating directories in current directory:"); + TestDirEnumHelper(dir, wxDIR_DIRS); + + puts("Enumerating files in current directory:"); + TestDirEnumHelper(dir, wxDIR_FILES); + + puts("Enumerating files including hidden in current directory:"); + TestDirEnumHelper(dir, wxDIR_FILES | wxDIR_HIDDEN); + +#ifdef __UNIX__ + dir.Open("/"); +#elif defined(__WXMSW__) + dir.Open("c:\\"); +#else + #error "don't know where the root directory is" +#endif + + puts("Enumerating everything in root directory:"); + TestDirEnumHelper(dir, wxDIR_DEFAULT); + + puts("Enumerating directories in root directory:"); + TestDirEnumHelper(dir, wxDIR_DIRS); + + puts("Enumerating files in root directory:"); + TestDirEnumHelper(dir, wxDIR_FILES); + + puts("Enumerating files including hidden in root directory:"); + TestDirEnumHelper(dir, wxDIR_FILES | wxDIR_HIDDEN); + + puts("Enumerating files in non existing directory:"); + wxDir dirNo("nosuchdir"); + TestDirEnumHelper(dirNo); +} + +#endif // TEST_DIR + // ---------------------------------------------------------------------------- // MIME types // ---------------------------------------------------------------------------- @@ -676,6 +754,10 @@ int main(int argc, char **argv) PrintArray("a3", a3); #endif // TEST_ARRAYS +#ifdef TEST_DIR + TestDirEnum(); +#endif // TEST_DIR + #ifdef TEST_LOG wxString s; for ( size_t n = 0; n < 8000; n++ ) diff --git a/src/msw/dir.cpp b/src/msw/dir.cpp new file mode 100644 index 0000000000..8e993552a5 --- /dev/null +++ b/src/msw/dir.cpp @@ -0,0 +1,281 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: msw/dir.cpp +// Purpose: wxDir implementation for Win32 +// Author: Vadim Zeitlin +// Modified by: +// Created: 08.12.99 +// RCS-ID: $Id$ +// Copyright: (c) 1999 Vadim Zeitlin +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +#ifdef __GNUG__ + #pragma implementation "dir.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" +#endif // PCH + +#include "wx/dir.h" +#include "wx/filefn.h" // for wxPathExists() + +#include + +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +#ifndef MAX_PATH + #define MAX_PATH 260 // from VC++ headers +#endif + +// ---------------------------------------------------------------------------- +// macros +// ---------------------------------------------------------------------------- + +#define M_DIR ((wxDirData *)m_data) + +// ---------------------------------------------------------------------------- +// private classes +// ---------------------------------------------------------------------------- + +// this class stores everything we need to enumerate the files +class wxDirData +{ +public: + wxDirData(const wxString& dirname); + ~wxDirData(); + + void SetFileSpec(const wxString& filespec) { m_filespec = filespec; } + void SetFlags(int flags) { m_flags = flags; } + + void Close(); + void Rewind(); + bool Read(wxString *filename); + +private: + HANDLE m_handle; + + wxString m_dirname; + wxString m_filespec; + + int m_flags; +}; + +// ============================================================================ +// implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// wxDirData +// ---------------------------------------------------------------------------- + +wxDirData::wxDirData(const wxString& dirname) + : m_dirname(dirname) +{ + m_handle = INVALID_HANDLE_VALUE; + + // throw away the trailing slashes + size_t n = m_dirname.length(); + wxCHECK_RET( n, _T("empty dir name in wxDir") ); + + while ( n > 0 && wxIsPathSeparator(m_dirname[--n]) ) + ; + + m_dirname.Truncate(n + 1); +} + +wxDirData::~wxDirData() +{ + Close(); +} + +void wxDirData::Close() +{ + if ( m_handle != INVALID_HANDLE_VALUE ) + { + if ( !::FindClose(m_handle) ) + { + wxLogLastError(_T("FindClose")); + } + } +} + +void wxDirData::Rewind() +{ + Close(); +} + +bool wxDirData::Read(wxString *filename) +{ + bool first = FALSE; + + WIN32_FIND_DATA finddata; + if ( m_handle == INVALID_HANDLE_VALUE ) + { + // open first + m_handle = ::FindFirstFile(!m_filespec ? _T("*.*") : m_filespec.c_str(), + &finddata); + + first = TRUE; + } + + if ( m_handle == INVALID_HANDLE_VALUE ) + { + DWORD err = ::GetLastError(); + + if ( err != ERROR_NO_MORE_FILES ) + { + wxLogSysError(err, _("Can not enumerate files in directory '%s'"), + m_dirname.c_str()); + } + //else: not an error, just no (such) files + + return FALSE; + } + + bool matches = FALSE; + + const wxChar *name; + DWORD attr; + + while ( !matches ) + { + if ( first ) + { + first = FALSE; + } + else + { + if ( !::FindNextFile(m_handle, &finddata) ) + { + DWORD err = ::GetLastError(); + + if ( err != ERROR_NO_MORE_FILES ) + { + wxLogLastError(_T("FindNext")); + } + //else: not an error, just no more (such) files + + return FALSE; + } + } + + name = finddata.cFileName; + attr = finddata.dwFileAttributes; + + // don't return "." and ".." unless asked for + if ( name[0] == _T('.') && + ((name[1] == _T('.') && name[2] == _T('\0')) || + (name[1] == _T('\0'))) ) + { + if ( !(m_flags & wxDIR_DOTDOT) ) + continue; + } + + // check the type now + if ( !(m_flags & wxDIR_FILES) && !(attr & FILE_ATTRIBUTE_DIRECTORY) ) + { + // it's a file, but we don't want them + continue; + } + else if ( !(m_flags & wxDIR_DIRS) && (attr & FILE_ATTRIBUTE_DIRECTORY) ) + { + // it's a dir, and we don't want it + continue; + } + + // finally, check whether it's a hidden file + if ( !(m_flags & wxDIR_HIDDEN) ) + { + matches = !(attr & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)); + } + } + + *filename = name; + + return TRUE; +} + +// ---------------------------------------------------------------------------- +// wxDir helpers +// ---------------------------------------------------------------------------- + +/* static */ +bool wxDir::Exists(const wxString& dir) +{ + return wxPathExists(dir); +} + +// ---------------------------------------------------------------------------- +// wxDir construction/destruction +// ---------------------------------------------------------------------------- + +wxDir::wxDir(const wxString& dirname) +{ + m_data = NULL; + + (void)Open(dirname); +} + +bool wxDir::Open(const wxString& dirname) +{ + delete M_DIR; + m_data = new wxDirData(dirname); + + return TRUE; +} + +bool wxDir::IsOpened() const +{ + return m_data != NULL; +} + +wxDir::~wxDir() +{ + delete M_DIR; +} + +// ---------------------------------------------------------------------------- +// wxDir enumerating +// ---------------------------------------------------------------------------- + +bool wxDir::GetFirst(wxString *filename, + const wxString& filespec, + int flags) const +{ + wxCHECK_MSG( IsOpened(), FALSE, _T("must wxDir::Open() first") ); + + M_DIR->Rewind(); + + M_DIR->SetFileSpec(filespec); + M_DIR->SetFlags(flags); + + return GetNext(filename); +} + +bool wxDir::GetNext(wxString *filename) const +{ + wxCHECK_MSG( IsOpened(), FALSE, _T("must wxDir::Open() first") ); + + wxCHECK_MSG( filename, FALSE, _T("bad pointer in wxDir::GetNext()") ); + + return M_DIR->Read(filename); +} diff --git a/src/unix/dir.cpp b/src/unix/dir.cpp new file mode 100644 index 0000000000..188e93c6e5 --- /dev/null +++ b/src/unix/dir.cpp @@ -0,0 +1,261 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: unix/dir.cpp +// Purpose: wxDir implementation for Unix/POSIX systems +// Author: Vadim Zeitlin +// Modified by: +// Created: 08.12.99 +// RCS-ID: $Id$ +// Copyright: (c) 1999 Vadim Zeitlin +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +#ifdef __GNUG__ + #pragma implementation "dir.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" +#endif // PCH + +#include "wx/dir.h" +#include "wx/filefn.h" // for wxMatchWild + +#include + +#include + +// ---------------------------------------------------------------------------- +// macros +// ---------------------------------------------------------------------------- + +#define M_DIR ((wxDirData *)m_data) + +// ---------------------------------------------------------------------------- +// private classes +// ---------------------------------------------------------------------------- + +// this class stores everything we need to enumerate the files +class wxDirData +{ +public: + wxDirData(const wxString& dirname); + ~wxDirData(); + + bool IsOk() const { return m_dir != NULL; } + + void SetFileSpec(const wxString& filespec) { m_filespec = filespec; } + void SetFlags(int flags) { m_flags = flags; } + + void Rewind() { rewinddir(m_dir); } + bool Read(wxString *filename); + +private: + DIR *m_dir; + + wxString m_dirname; + wxString m_filespec; + + int m_flags; +}; + +// ============================================================================ +// implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// wxDirData +// ---------------------------------------------------------------------------- + +#if !defined( __VMS__ ) || ( __VMS_VER >= 70000000 ) + +wxDirData::wxDirData(const wxString& dirname) + : m_dirname(dirname) +{ + m_dir = NULL; + + // throw away the trailing slashes + size_t n = m_dirname.length(); + wxCHECK_RET( n, _T("empty dir name in wxDir") ); + + while ( n > 0 && m_dirname[--n] == '/' ) + ; + + m_dirname.Truncate(n + 1); + + // do open the dir + m_dir = opendir(m_dirname.fn_str()); +} + +wxDirData::~wxDirData() +{ + if ( m_dir ) + { + if ( closedir(m_dir) != 0 ) + { + wxLogLastError(_T("closedir")); + } + } +} + +bool wxDirData::Read(wxString *filename) +{ + dirent *de; + bool matches = FALSE; + + while ( !matches ) + { + de = readdir(m_dir); + if ( !de ) + return FALSE; + + // don't return "." and ".." unless asked for + if ( de->d_name[0] == '.' && + ((de->d_name[1] == '.' && de->d_name[2] == '\0') || + (de->d_name[1] == '\0')) ) + { + if ( !(m_flags & wxDIR_DOTDOT) ) + continue; + } + + // check the type now + if ( !(m_flags & wxDIR_FILES) && + !wxDir::Exists(m_dirname + _T('/') + de->d_name) ) + { + // it's a file, but we don't want them + continue; + } + else if ( !(m_flags & wxDIR_DIRS) && + wxDir::Exists(m_dirname + _T('/') + de->d_name) ) + { + // it's a dir, and we don't want it + continue; + } + + // finally, check the name + if ( !m_filespec ) + { + matches = m_flags & wxDIR_HIDDEN ? TRUE : de->d_name[0] != '.'; + } + else + { + // test against the pattern + matches = wxMatchWild(m_filespec, de->d_name, + !(m_flags & wxDIR_HIDDEN)); + } + } + + *filename = de->d_name; + + return TRUE; +} + +#else // old VMS (TODO) + +wxDirData::wxDirData(const wxString& WXUNUSED(dirname)) +{ + wxFAIL_MSG(_T("not implemented")); +} + +wxDirData::~wxDirData() +{ +} + +bool wxDirData::Read(wxString * WXUNUSED(filename)) +{ + return FALSE; +} + +#endif // not or new VMS/old VMS + +// ---------------------------------------------------------------------------- +// wxDir helpers +// ---------------------------------------------------------------------------- + +/* static */ +bool wxDir::Exists(const wxString& dir) +{ + return wxPathExists(dir); +} + +// ---------------------------------------------------------------------------- +// wxDir construction/destruction +// ---------------------------------------------------------------------------- + +wxDir::wxDir(const wxString& dirname) +{ + m_data = NULL; + + (void)Open(dirname); +} + +bool wxDir::Open(const wxString& dirname) +{ + delete M_DIR; + m_data = new wxDirData(dirname); + + if ( !M_DIR->IsOk() ) + { + wxLogSysError(_("Can not enumerate files in directory '%s'"), + dirname.c_str()); + + delete M_DIR; + m_data = NULL; + + return FALSE; + } + + return TRUE; +} + +bool wxDir::IsOpened() const +{ + return m_data != NULL; +} + +wxDir::~wxDir() +{ + delete M_DIR; +} + +// ---------------------------------------------------------------------------- +// wxDir enumerating +// ---------------------------------------------------------------------------- + +bool wxDir::GetFirst(wxString *filename, + const wxString& filespec, + int flags) const +{ + wxCHECK_MSG( IsOpened(), FALSE, _T("must wxDir::Open() first") ); + + M_DIR->Rewind(); + + M_DIR->SetFileSpec(filespec); + M_DIR->SetFlags(flags); + + return GetNext(filename); +} + +bool wxDir::GetNext(wxString *filename) const +{ + wxCHECK_MSG( IsOpened(), FALSE, _T("must wxDir::Open() first") ); + + wxCHECK_MSG( filename, FALSE, _T("bad pointer in wxDir::GetNext()") ); + + return M_DIR->Read(filename); +} -- 2.45.2