]> git.saurik.com Git - wxWidgets.git/commitdiff
wxDir class added
authorVadim Zeitlin <vadim@wxwidgets.org>
Wed, 8 Dec 1999 14:16:53 +0000 (14:16 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Wed, 8 Dec 1999 14:16:53 +0000 (14:16 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@4873 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/dir.h [new file with mode: 0644]
samples/console/console.cpp
src/msw/dir.cpp [new file with mode: 0644]
src/unix/dir.cpp [new file with mode: 0644]

diff --git a/include/wx/dir.h b/include/wx/dir.h
new file mode 100644 (file)
index 0000000..f8b0b67
--- /dev/null
@@ -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 <zeitlin@dptmaths.ens-cachan.fr>
+// 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_
index eaaf0a945eeff1c537b72b4b8b89b7dde674ace7..ecbaeeda4f704ac91f0ebc25c7a6dc45760d4b27 100644 (file)
@@ -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
 // implementation
 // ============================================================================
 
+// ----------------------------------------------------------------------------
+// wxDir
+// ----------------------------------------------------------------------------
+
+#ifdef TEST_DIR
+
+#include <wx/dir.h>
+
+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 (file)
index 0000000..8e99355
--- /dev/null
@@ -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 <zeitlin@dptmaths.ens-cachan.fr>
+// 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 <windows.h>
+
+// ----------------------------------------------------------------------------
+// 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 (file)
index 0000000..188e93c
--- /dev/null
@@ -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 <zeitlin@dptmaths.ens-cachan.fr>
+// 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 <sys/types.h>
+
+#include <dirent.h>
+
+// ----------------------------------------------------------------------------
+// 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);
+}