]> Creatis software - cpPlugins.git/commitdiff
...
authorLeonardo Flórez-Valencia <florez-l@javeriana.edu.co>
Fri, 4 Nov 2016 23:22:40 +0000 (18:22 -0500)
committerLeonardo Flórez-Valencia <florez-l@javeriana.edu.co>
Fri, 4 Nov 2016 23:22:40 +0000 (18:22 -0500)
lib/CMakeLists.txt
lib/cpPlugins/Interface/Dirent.h [deleted file]
lib/cpPlugins/Interface/Plugins.cxx
lib/cpPlugins/OS/DirContents.cxx [new file with mode: 0644]
lib/cpPlugins/OS/DirContents.h [new file with mode: 0644]
lib/cpPlugins/OS/tinydir.h [new file with mode: 0644]
lib/cpPlugins/OS/tinydir_COPYING.txt [new file with mode: 0644]
lib/cpPlugins/OS/tinydir_README.md.txt [new file with mode: 0644]

index 0183e8ea86b203c74114d1efe08976e195e95230..a6a7f21e0361a5e506db4441fd748ba03f1d47ac 100644 (file)
@@ -72,20 +72,23 @@ ENDIF(USE_QT4)
 ## == Libraries to dynamically load ==
 ## ===================================
 
-SET(cpPlugins_DynLibs "${CMAKE_INSTALL_PREFIX}/bin|cpExtensions")
-LIST(APPEND cpPlugins_DynLibs "${CMAKE_INSTALL_PREFIX}/lib|cpExtensions")
-LIST(APPEND cpPlugins_DynLibs "${LIBRARY_OUTPUT_PATH}|cpExtensions")
+SET(_pre ${CMAKE_SHARED_LIBRARY_PREFIX})
+SET(_suf ${CMAKE_SHARED_LIBRARY_SUFFIX})
+
+SET(cpPlugins_DynLibs "${CMAKE_INSTALL_PREFIX}/bin/${_pre}cpExtensions${_suf}")
+LIST(APPEND cpPlugins_DynLibs "${CMAKE_INSTALL_PREFIX}/lib/${_pre}cpExtensions${_suf}")
+LIST(APPEND cpPlugins_DynLibs "${LIBRARY_OUTPUT_PATH}/${_pre}cpExtensions${_suf}")
 FOREACH(_lib ${cpPlugins_Instances})
-  LIST(APPEND cpPlugins_DynLibs "${CMAKE_INSTALL_PREFIX}/bin|${_lib}")
-  LIST(APPEND cpPlugins_DynLibs "${CMAKE_INSTALL_PREFIX}/lib|${_lib}")
-  LIST(APPEND cpPlugins_DynLibs "${LIBRARY_OUTPUT_PATH}|${_lib}")
+  LIST(APPEND cpPlugins_DynLibs "${CMAKE_INSTALL_PREFIX}/bin/${_pre}${_lib}${_suf}")
+  LIST(APPEND cpPlugins_DynLibs "${CMAKE_INSTALL_PREFIX}/lib/${_pre}${_lib}${_suf}")
+  LIST(APPEND cpPlugins_DynLibs "${LIBRARY_OUTPUT_PATH}/${_pre}${_lib}${_suf}")
 ENDFOREACH(_lib)
-LIST(APPEND cpPlugins_DynLibs "${VTK_INSTALL_PREFIX}/bin|vtk*")
-LIST(APPEND cpPlugins_DynLibs "${VTK_INSTALL_PREFIX}/lib|vtk*")
-LIST(APPEND cpPlugins_DynLibs "${ITK_INSTALL_PREFIX}/bin|itk*")
-LIST(APPEND cpPlugins_DynLibs "${ITK_INSTALL_PREFIX}/lib|itk*")
-LIST(APPEND cpPlugins_DynLibs "${ITK_INSTALL_PREFIX}/bin|ITK*")
-LIST(APPEND cpPlugins_DynLibs "${ITK_INSTALL_PREFIX}/lib|ITK*")
+LIST(APPEND cpPlugins_DynLibs "${VTK_INSTALL_PREFIX}/bin/*vtk*${_suf}")
+LIST(APPEND cpPlugins_DynLibs "${VTK_INSTALL_PREFIX}/lib/*vtk*${_suf}")
+LIST(APPEND cpPlugins_DynLibs "${ITK_INSTALL_PREFIX}/bin/*itk*${_suf}")
+LIST(APPEND cpPlugins_DynLibs "${ITK_INSTALL_PREFIX}/lib/*itk*${_suf}")
+LIST(APPEND cpPlugins_DynLibs "${ITK_INSTALL_PREFIX}/bin/*ITK*${_suf}")
+LIST(APPEND cpPlugins_DynLibs "${ITK_INSTALL_PREFIX}/lib/*ITK*${_suf}")
 FILE(WRITE ${PROJECT_BINARY_DIR}/cpPlugins_Libraries.config "")
 FOREACH(_lib ${cpPlugins_DynLibs})
   FILE(APPEND ${PROJECT_BINARY_DIR}/cpPlugins_Libraries.config "${_lib}\n")
diff --git a/lib/cpPlugins/Interface/Dirent.h b/lib/cpPlugins/Interface/Dirent.h
deleted file mode 100644 (file)
index 7461f91..0000000
+++ /dev/null
@@ -1,849 +0,0 @@
-/*
- * dirent.h - dirent API for Microsoft Visual Studio
- *
- * Copyright (C) 2006-2012 Toni Ronkko
- * Modified by Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * ``Software''), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * $Id: dirent.h,v 1.20 2014/03/19 17:52:23 tronkko Exp $
- */
-#ifndef __cpPlugins__dirent__h__
-#define __cpPlugins__dirent__h__
-
-// florez-l: use this file in windows environments
-#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ )
-
-/*
- * Define architecture flags so we don't need to include windows.h.
- * Avoiding windows.h makes it simpler to use windows sockets in conjunction
- * with dirent.h.
- */
-#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_IX86)
-#   define _X86_
-#endif
-#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_AMD64)
-#define _AMD64_
-#endif
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <windef.h>
-#include <winbase.h>
-#include <wchar.h>
-#include <string.h>
-#include <stdlib.h>
-#include <malloc.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-
-/* Indicates that d_type field is available in dirent structure */
-#define ___cpPlugins__dirent__h__AVE_D_TYPE
-
-/* Indicates that d_namlen field is available in dirent structure */
-#define ___cpPlugins__dirent__h__AVE_D_NAMLEN
-
-/* Entries missing from MSVC 6.0 */
-#if !defined(FILE_ATTRIBUTE_DEVICE)
-#   define FILE_ATTRIBUTE_DEVICE 0x40
-#endif
-
-/* File type and permission flags for stat() */
-#if !defined(S_IFMT)
-#   define S_IFMT   _S_IFMT                     /* File type mask */
-#endif
-#if !defined(S_IFDIR)
-#   define S_IFDIR  _S_IFDIR                    /* Directory */
-#endif
-#if !defined(S_IFCHR)
-#   define S_IFCHR  _S_IFCHR                    /* Character device */
-#endif
-#if !defined(S_IFFIFO)
-#   define S_IFFIFO _S_IFFIFO                   /* Pipe */
-#endif
-#if !defined(S_IFREG)
-#   define S_IFREG  _S_IFREG                    /* Regular file */
-#endif
-#if !defined(S_IREAD)
-#   define S_IREAD  _S_IREAD                    /* Read permission */
-#endif
-#if !defined(S_IWRITE)
-#   define S_IWRITE _S_IWRITE                   /* Write permission */
-#endif
-#if !defined(S_IEXEC)
-#   define S_IEXEC  _S_IEXEC                    /* Execute permission */
-#endif
-#if !defined(S_IFIFO)
-#   define S_IFIFO _S_IFIFO                     /* Pipe */
-#endif
-#if !defined(S_IFBLK)
-#   define S_IFBLK   0                          /* Block device */
-#endif
-#if !defined(S_IFLNK)
-#   define S_IFLNK   0                          /* Link */
-#endif
-#if !defined(S_IFSOCK)
-#   define S_IFSOCK  0                          /* Socket */
-#endif
-
-#if defined(_MSC_VER)
-#   define S_IRUSR  S_IREAD                     /* Read user */
-#   define S_IWUSR  S_IWRITE                    /* Write user */
-#   define S_IXUSR  0                           /* Execute user */
-#   define S_IRGRP  0                           /* Read group */
-#   define S_IWGRP  0                           /* Write group */
-#   define S_IXGRP  0                           /* Execute group */
-#   define S_IROTH  0                           /* Read others */
-#   define S_IWOTH  0                           /* Write others */
-#   define S_IXOTH  0                           /* Execute others */
-#endif
-
-/* Maximum length of file name */
-#if !defined(PATH_MAX)
-#   define PATH_MAX MAX_PATH
-#endif
-#if !defined(FILENAME_MAX)
-#   define FILENAME_MAX MAX_PATH
-#endif
-#if !defined(NAME_MAX)
-#   define NAME_MAX FILENAME_MAX
-#endif
-
-/* File type flags for d_type */
-#define DT_UNKNOWN  0
-#define DT_REG      S_IFREG
-#define DT_DIR      S_IFDIR
-#define DT_FIFO     S_IFIFO
-#define DT_SOCK     S_IFSOCK
-#define DT_CHR      S_IFCHR
-#define DT_BLK      S_IFBLK
-#define DT_LNK      S_IFLNK
-
-/* Macros for converting between st_mode and d_type */
-#define IFTODT(mode) ((mode) & S_IFMT)
-#define DTTOIF(type) (type)
-
-/*
- * File type macros.  Note that block devices, sockets and links cannot be
- * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
- * only defined for compatibility.  These macros should always return false
- * on Windows.
- */
-#define        S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
-#define        S_ISDIR(mode)  (((mode) & S_IFMT) == S_IFDIR)
-#define        S_ISREG(mode)  (((mode) & S_IFMT) == S_IFREG)
-#define        S_ISLNK(mode)  (((mode) & S_IFMT) == S_IFLNK)
-#define        S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
-#define        S_ISCHR(mode)  (((mode) & S_IFMT) == S_IFCHR)
-#define        S_ISBLK(mode)  (((mode) & S_IFMT) == S_IFBLK)
-
-/* Return the exact length of d_namlen without zero terminator */
-#define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
-
-/* Return number of bytes needed to store d_namlen */
-#define _D_ALLOC_NAMLEN(p) (PATH_MAX)
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/* Wide-character version */
-struct _wdirent {
-    long d_ino;                                 /* Always zero */
-    unsigned short d_reclen;                    /* Structure size */
-    size_t d_namlen;                            /* Length of name without \0 */
-    int d_type;                                 /* File type */
-    wchar_t d_name[PATH_MAX];                   /* File name */
-};
-typedef struct _wdirent _wdirent;
-
-struct _WDIR {
-    struct _wdirent ent;                        /* Current directory entry */
-    WIN32_FIND_DATAW data;                      /* Private file data */
-    int cached;                                 /* True if data is valid */
-    HANDLE handle;                              /* Win32 search handle */
-    wchar_t *patt;                              /* Initial directory name */
-};
-typedef struct _WDIR _WDIR;
-
-static _WDIR *_wopendir (const wchar_t *dirname);
-static struct _wdirent *_wreaddir (_WDIR *dirp);
-static int _wclosedir (_WDIR *dirp);
-static void _wrewinddir (_WDIR* dirp);
-
-
-/* For compatibility with Symbian */
-#define wdirent _wdirent
-#define WDIR _WDIR
-#define wopendir _wopendir
-#define wreaddir _wreaddir
-#define wclosedir _wclosedir
-#define wrewinddir _wrewinddir
-
-
-/* Multi-byte character versions */
-struct dirent {
-    long d_ino;                                 /* Always zero */
-    unsigned short d_reclen;                    /* Structure size */
-    size_t d_namlen;                            /* Length of name without \0 */
-    int d_type;                                 /* File type */
-    char d_name[PATH_MAX];                      /* File name */
-};
-typedef struct dirent dirent;
-
-struct DIR {
-    struct dirent ent;
-    struct _WDIR *wdirp;
-};
-typedef struct DIR DIR;
-
-static DIR *opendir (const char *dirname);
-static struct dirent *readdir (DIR *dirp);
-static int closedir (DIR *dirp);
-static void rewinddir (DIR* dirp);
-
-
-/* Internal utility functions */
-static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp);
-static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp);
-
-static int dirent_mbstowcs_s(
-    size_t *pReturnValue,
-    wchar_t *wcstr,
-    size_t sizeInWords,
-    const char *mbstr,
-    size_t count);
-
-static int dirent_wcstombs_s(
-    size_t *pReturnValue,
-    char *mbstr,
-    size_t sizeInBytes,
-    const wchar_t *wcstr,
-    size_t count);
-
-static void dirent_set_errno (int error);
-
-/*
- * Open directory stream DIRNAME for read and return a pointer to the
- * internal working area that is used to retrieve individual directory
- * entries.
- */
-static _WDIR*
-_wopendir(
-    const wchar_t *dirname)
-{
-    _WDIR *dirp = NULL;
-    int error;
-
-    /* Must have directory name */
-    if (dirname == NULL  ||  dirname[0] == '\0') {
-        dirent_set_errno (ENOENT);
-        return NULL;
-    }
-
-    /* Allocate new _WDIR structure */
-    dirp = (_WDIR*) malloc (sizeof (struct _WDIR));
-    if (dirp != NULL) {
-        DWORD n;
-
-        /* Reset _WDIR structure */
-        dirp->handle = INVALID_HANDLE_VALUE;
-        dirp->patt = NULL;
-        dirp->cached = 0;
-
-        /* Compute the length of full path plus zero terminator */
-        n = GetFullPathNameW (dirname, 0, NULL, NULL);
-
-        /* Allocate room for absolute directory name and search pattern */
-        dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16);
-        if (dirp->patt) {
-
-            /*
-             * Convert relative directory name to an absolute one.  This
-             * allows rewinddir() to function correctly even when current
-             * working directory is changed between opendir() and rewinddir().
-             */
-            n = GetFullPathNameW (dirname, n, dirp->patt, NULL);
-            if (n > 0) {
-                wchar_t *p;
-
-                /* Append search pattern \* to the directory name */
-                p = dirp->patt + n;
-                if (dirp->patt < p) {
-                    switch (p[-1]) {
-                    case '\\':
-                    case '/':
-                    case ':':
-                        /* Directory ends in path separator, e.g. c:\temp\ */
-                        /*NOP*/;
-                        break;
-
-                    default:
-                        /* Directory name doesn't end in path separator */
-                        *p++ = '\\';
-                    }
-                }
-                *p++ = '*';
-                *p = '\0';
-
-                /* Open directory stream and retrieve the first entry */
-                if (dirent_first (dirp)) {
-                    /* Directory stream opened successfully */
-                    error = 0;
-                } else {
-                    /* Cannot retrieve first entry */
-                    error = 1;
-                    dirent_set_errno (ENOENT);
-                }
-
-            } else {
-                /* Cannot retrieve full path name */
-                dirent_set_errno (ENOENT);
-                error = 1;
-            }
-
-        } else {
-            /* Cannot allocate memory for search pattern */
-            error = 1;
-        }
-
-    } else {
-        /* Cannot allocate _WDIR structure */
-        error = 1;
-    }
-
-    /* Clean up in case of error */
-    if (error  &&  dirp) {
-        _wclosedir (dirp);
-        dirp = NULL;
-    }
-
-    return dirp;
-}
-
-/*
- * Read next directory entry.  The directory entry is returned in dirent
- * structure in the d_name field.  Individual directory entries returned by
- * this function include regular files, sub-directories, pseudo-directories
- * "." and ".." as well as volume labels, hidden files and system files.
- */
-static struct _wdirent*
-_wreaddir(
-    _WDIR *dirp)
-{
-    WIN32_FIND_DATAW *datap;
-    struct _wdirent *entp;
-
-    /* Read next directory entry */
-    datap = dirent_next (dirp);
-    if (datap) {
-        size_t n;
-        DWORD attr;
-        
-        /* Pointer to directory entry to return */
-        entp = &dirp->ent;
-
-        /* 
-         * Copy file name as wide-character string.  If the file name is too
-         * long to fit in to the destination buffer, then truncate file name
-         * to PATH_MAX characters and zero-terminate the buffer.
-         */
-        n = 0;
-        while (n + 1 < PATH_MAX  &&  datap->cFileName[n] != 0) {
-            entp->d_name[n] = datap->cFileName[n];
-            n++;
-        }
-        dirp->ent.d_name[n] = 0;
-
-        /* Length of file name excluding zero terminator */
-        entp->d_namlen = n;
-
-        /* File type */
-        attr = datap->dwFileAttributes;
-        if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
-            entp->d_type = DT_CHR;
-        } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
-            entp->d_type = DT_DIR;
-        } else {
-            entp->d_type = DT_REG;
-        }
-
-        /* Reset dummy fields */
-        entp->d_ino = 0;
-        entp->d_reclen = sizeof (struct _wdirent);
-
-    } else {
-
-        /* Last directory entry read */
-        entp = NULL;
-
-    }
-
-    return entp;
-}
-
-/*
- * Close directory stream opened by opendir() function.  This invalidates the
- * DIR structure as well as any directory entry read previously by
- * _wreaddir().
- */
-static int
-_wclosedir(
-    _WDIR *dirp)
-{
-    int ok;
-    if (dirp) {
-
-        /* Release search handle */
-        if (dirp->handle != INVALID_HANDLE_VALUE) {
-            FindClose (dirp->handle);
-            dirp->handle = INVALID_HANDLE_VALUE;
-        }
-
-        /* Release search pattern */
-        if (dirp->patt) {
-            free (dirp->patt);
-            dirp->patt = NULL;
-        }
-
-        /* Release directory structure */
-        free (dirp);
-        ok = /*success*/0;
-
-    } else {
-        /* Invalid directory stream */
-        dirent_set_errno (EBADF);
-        ok = /*failure*/-1;
-    }
-    return ok;
-}
-
-/*
- * Rewind directory stream such that _wreaddir() returns the very first
- * file name again.
- */
-static void
-_wrewinddir(
-    _WDIR* dirp)
-{
-    if (dirp) {
-        /* Release existing search handle */
-        if (dirp->handle != INVALID_HANDLE_VALUE) {
-            FindClose (dirp->handle);
-        }
-
-        /* Open new search handle */
-        dirent_first (dirp);
-    }
-}
-
-/* Get first directory entry (internal) */
-static WIN32_FIND_DATAW*
-dirent_first(
-    _WDIR *dirp)
-{
-    WIN32_FIND_DATAW *datap;
-
-    /* Open directory and retrieve the first entry */
-    dirp->handle = FindFirstFileW (dirp->patt, &dirp->data);
-    if (dirp->handle != INVALID_HANDLE_VALUE) {
-
-        /* a directory entry is now waiting in memory */
-        datap = &dirp->data;
-        dirp->cached = 1;
-
-    } else {
-
-        /* Failed to re-open directory: no directory entry in memory */
-        dirp->cached = 0;
-        datap = NULL;
-
-    }
-    return datap;
-}
-
-/* Get next directory entry (internal) */
-static WIN32_FIND_DATAW*
-dirent_next(
-    _WDIR *dirp)
-{
-    WIN32_FIND_DATAW *p;
-
-    /* Get next directory entry */
-    if (dirp->cached != 0) {
-
-        /* A valid directory entry already in memory */
-        p = &dirp->data;
-        dirp->cached = 0;
-
-    } else if (dirp->handle != INVALID_HANDLE_VALUE) {
-
-        /* Get the next directory entry from stream */
-        if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) {
-            /* Got a file */
-            p = &dirp->data;
-        } else {
-            /* The very last entry has been processed or an error occured */
-            FindClose (dirp->handle);
-            dirp->handle = INVALID_HANDLE_VALUE;
-            p = NULL;
-        }
-
-    } else {
-
-        /* End of directory stream reached */
-        p = NULL;
-
-    }
-
-    return p;
-}
-
-/* 
- * Open directory stream using plain old C-string.
- */
-static DIR*
-opendir(
-    const char *dirname) 
-{
-    struct DIR *dirp;
-    int error;
-
-    /* Must have directory name */
-    if (dirname == NULL  ||  dirname[0] == '\0') {
-        dirent_set_errno (ENOENT);
-        return NULL;
-    }
-
-    /* Allocate memory for DIR structure */
-    dirp = (DIR*) malloc (sizeof (struct DIR));
-    if (dirp) {
-        wchar_t wname[PATH_MAX];
-        size_t n;
-
-        /* Convert directory name to wide-character string */
-        error = dirent_mbstowcs_s (&n, wname, PATH_MAX, dirname, PATH_MAX);
-        if (!error) {
-
-            /* Open directory stream using wide-character name */
-            dirp->wdirp = _wopendir (wname);
-            if (dirp->wdirp) {
-                /* Directory stream opened */
-                error = 0;
-            } else {
-                /* Failed to open directory stream */
-                error = 1;
-            }
-
-        } else {
-            /* 
-             * Cannot convert file name to wide-character string.  This
-             * occurs if the string contains invalid multi-byte sequences or
-             * the output buffer is too small to contain the resulting
-             * string.
-             */
-            error = 1;
-        }
-
-    } else {
-        /* Cannot allocate DIR structure */
-        error = 1;
-    }
-
-    /* Clean up in case of error */
-    if (error  &&  dirp) {
-        free (dirp);
-        dirp = NULL;
-    }
-
-    return dirp;
-}
-
-/*
- * Read next directory entry.
- *
- * When working with text consoles, please note that file names returned by
- * readdir() are represented in the default ANSI code page while any output to
- * console is typically formatted on another code page.  Thus, non-ASCII
- * characters in file names will not usually display correctly on console.  The
- * problem can be fixed in two ways: (1) change the character set of console
- * to 1252 using chcp utility and use Lucida Console font, or (2) use
- * _cprintf function when writing to console.  The _cprinf() will re-encode
- * ANSI strings to the console code page so many non-ASCII characters will
- * display correcly.
- */
-static struct dirent*
-readdir(
-    DIR *dirp) 
-{
-    WIN32_FIND_DATAW *datap;
-    struct dirent *entp;
-
-    /* Read next directory entry */
-    datap = dirent_next (dirp->wdirp);
-    if (datap) {
-        size_t n;
-        int error;
-
-        /* Attempt to convert file name to multi-byte string */
-        error = dirent_wcstombs_s(
-            &n, dirp->ent.d_name, PATH_MAX, datap->cFileName, PATH_MAX);
-
-        /* 
-         * If the file name cannot be represented by a multi-byte string,
-         * then attempt to use old 8+3 file name.  This allows traditional
-         * Unix-code to access some file names despite of unicode
-         * characters, although file names may seem unfamiliar to the user.
-         *
-         * Be ware that the code below cannot come up with a short file
-         * name unless the file system provides one.  At least
-         * VirtualBox shared folders fail to do this.
-         */
-        if (error  &&  datap->cAlternateFileName[0] != '\0') {
-            error = dirent_wcstombs_s(
-                &n, dirp->ent.d_name, PATH_MAX, 
-                datap->cAlternateFileName, PATH_MAX);
-        }
-
-        if (!error) {
-            DWORD attr;
-
-            /* Initialize directory entry for return */
-            entp = &dirp->ent;
-
-            /* Length of file name excluding zero terminator */
-            entp->d_namlen = n - 1;
-
-            /* File attributes */
-            attr = datap->dwFileAttributes;
-            if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
-                entp->d_type = DT_CHR;
-            } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
-                entp->d_type = DT_DIR;
-            } else {
-                entp->d_type = DT_REG;
-            }
-
-            /* Reset dummy fields */
-            entp->d_ino = 0;
-            entp->d_reclen = sizeof (struct dirent);
-
-        } else {
-            /* 
-             * Cannot convert file name to multi-byte string so construct
-             * an errornous directory entry and return that.  Note that
-             * we cannot return NULL as that would stop the processing
-             * of directory entries completely.
-             */
-            entp = &dirp->ent;
-            entp->d_name[0] = '?';
-            entp->d_name[1] = '\0';
-            entp->d_namlen = 1;
-            entp->d_type = DT_UNKNOWN;
-            entp->d_ino = 0;
-            entp->d_reclen = 0;
-        }
-
-    } else {
-        /* No more directory entries */
-        entp = NULL;
-    }
-
-    return entp;
-}
-
-/*
- * Close directory stream.
- */
-static int
-closedir(
-    DIR *dirp) 
-{
-    int ok;
-    if (dirp) {
-
-        /* Close wide-character directory stream */
-        ok = _wclosedir (dirp->wdirp);
-        dirp->wdirp = NULL;
-
-        /* Release multi-byte character version */
-        free (dirp);
-
-    } else {
-
-        /* Invalid directory stream */
-        dirent_set_errno (EBADF);
-        ok = /*failure*/-1;
-
-    }
-    return ok;
-}
-
-/*
- * Rewind directory stream to beginning.
- */
-static void
-rewinddir(
-    DIR* dirp) 
-{
-    /* Rewind wide-character string directory stream */
-    _wrewinddir (dirp->wdirp);
-}
-
-/* Convert multi-byte string to wide character string */
-static int
-dirent_mbstowcs_s(
-    size_t *pReturnValue,
-    wchar_t *wcstr,
-    size_t sizeInWords,
-    const char *mbstr,
-    size_t count)
-{
-    int error;
-
-#if defined(_MSC_VER)  &&  _MSC_VER >= 1400
-
-    /* Microsoft Visual Studio 2005 or later */
-    error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count);
-
-#else
-
-    /* Older Visual Studio or non-Microsoft compiler */
-    size_t n;
-
-    /* Convert to wide-character string (or count characters) */
-    n = mbstowcs (wcstr, mbstr, sizeInWords);
-    if (!wcstr  ||  n < count) {
-
-        /* Zero-terminate output buffer */
-        if (wcstr  &&  sizeInWords) {
-            if (n >= sizeInWords) {
-                n = sizeInWords - 1;
-            }
-            wcstr[n] = 0;
-        }
-
-        /* Length of resuting multi-byte string WITH zero terminator */
-        if (pReturnValue) {
-            *pReturnValue = n + 1;
-        }
-
-        /* Success */
-        error = 0;
-
-    } else {
-
-        /* Could not convert string */
-        error = 1;
-
-    }
-
-#endif
-
-    return error;
-}
-
-/* Convert wide-character string to multi-byte string */
-static int
-dirent_wcstombs_s(
-    size_t *pReturnValue,
-    char *mbstr,
-    size_t sizeInBytes, /* max size of mbstr */
-    const wchar_t *wcstr,
-    size_t count)
-{
-    int error;
-
-#if defined(_MSC_VER)  &&  _MSC_VER >= 1400
-
-    /* Microsoft Visual Studio 2005 or later */
-    error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count);
-
-#else
-
-    /* Older Visual Studio or non-Microsoft compiler */
-    size_t n;
-
-    /* Convert to multi-byte string (or count the number of bytes needed) */
-    n = wcstombs (mbstr, wcstr, sizeInBytes);
-    if (!mbstr  ||  n < count) {
-
-        /* Zero-terminate output buffer */
-        if (mbstr  &&  sizeInBytes) {
-            if (n >= sizeInBytes) {
-                n = sizeInBytes - 1;
-            }
-            mbstr[n] = '\0';
-        }
-
-        /* Lenght of resulting multi-bytes string WITH zero-terminator */
-        if (pReturnValue) {
-            *pReturnValue = n + 1;
-        }
-
-        /* Success */
-        error = 0;
-
-    } else {
-
-        /* Cannot convert string */
-        error = 1;
-
-    }
-
-#endif
-
-    return error;
-}
-
-/* Set errno variable */
-static void
-dirent_set_errno(
-    int error)
-{
-#if defined(_MSC_VER)  &&  _MSC_VER >= 1400
-
-    /* Microsoft Visual Studio 2005 and later */
-    _set_errno (error);
-
-#else
-
-    /* Non-Microsoft compiler or older Microsoft compiler */
-    errno = error;
-
-#endif
-}
-
-
-#ifdef __cplusplus
-}
-#endif
-
-// florez-l: use the standard linux header
-#else // defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ )
-#  include <sys/types.h>
-#  include <dirent.h>
-#endif // defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ )
-
-#endif /*__cpPlugins__dirent__h__*/
-
index c114404b1e332602749ebca4f24f045120e0c20c..eabd53ef905e45048dd4530530b360b014a2bb43 100644 (file)
@@ -1,8 +1,7 @@
 #include <cpPlugins/Interface/Plugins.h>
 #include <cpPlugins/OS/DLLManager.h>
-#include <cpPlugins/Interface/Dirent.h>
+#include <cpPlugins/OS/DirContents.h>
 #include <cpExtensions/Utility.h>
-#include <regex>
 
 // -------------------------------------------------------------------------
 cpPlugins::Interface::Plugins::
@@ -106,63 +105,24 @@ LoadEnvironments( )
       std::istringstream input( buffer );
       for( std::string line; std::getline( input, line ); )
       {
-        std::vector< std::string > tokens;
-        cpExtensions::Tokenize( tokens, line, "|" );
-        if( tokens.size( ) == 2 )
+        auto pos = line.find( "*" );
+        if( pos != std::string::npos )
         {
-          std::string pth = tokens[ 0 ];
-          std::string lib = tokens[ 1 ];
-          if( lib.find( "*" ) != std::string::npos )
-          {
-            std::string ext( cpPlugins_LIB_EXT );
-            DIR* dir;
-            struct dirent* ent;
-            if( ( dir = opendir( pth.c_str( ) ) ) != NULL )
-            {
-              while( ( ent = readdir( dir ) ) != NULL )
-              {
-                std::string fname( ent->d_name );
-                long pos = long( fname.size( ) ) - long( ext.size( ) );
-                if( pos > 0 )
-                {
-                  if( fname.substr( pos ) == ext )
-                  {
-                    std::regex re( lib );
-                    std::smatch match;
-                    if( std::regex_search( fname, match, re ) && match.size( ) >= 1 )
-                    {
-                      std::stringstream str;
-                      str
-                        << pth << cpPlugins_PATH_SEPARATOR << fname;
-                      libs.insert( str.str( ) );
-                    } // fi
-
-                  } // fi
-
-                } // fi
-
-              } // elihw
-              closedir( dir );
-
-            } // fi
-          }
-          else
-          {
-            std::stringstream str;
-            str
-              << pth << cpPlugins_PATH_SEPARATOR << cpPlugins_LIB_PREFIX
-              << lib << cpPlugins_LIB_EXT;
-            libs.insert( str.str( ) );
-
-          } // fi
-
-        } // fi
+          std::string dname, fname;
+          cpPlugins::OS::SplitPath( dname, fname, line );
+          auto files = cpPlugins::OS::LoadDirContents( dname, false, fname );
+          for( auto fIt = files.begin( ); fIt != files.end( ); ++fIt )
+            libs.insert( *fIt );
+        }
+        else
+          libs.insert( line );
 
       } // rof
 
     } // fi
 
   } // rof
+
   for( auto l = libs.begin( ); l != libs.end( ); ++l )
   {
     std::string lib = cpExtensions::CanonicalPath( *l );
@@ -306,7 +266,9 @@ LoadFile( const std::string& fname )
 
     // Get filter creator
     TCreator creator = ( TCreator )(
-      cpPlugins::OS::DLLManager::GetFunctionHandle( hnd, category + "_" + name )
+      cpPlugins::OS::DLLManager::GetFunctionHandle(
+        hnd, category + "_" + name
+        )
       );
     if( creator == NULL )
     {
@@ -373,28 +335,18 @@ LoadPlugin( const std::string& pname )
 void cpPlugins::Interface::Plugins::
 LoadDirectory( const std::string& dirname )
 {
-  DIR* dir;
-  struct dirent* ent;
-  if( ( dir = opendir( dirname.c_str( ) ) ) != NULL )
+  std::stringstream pat;
+  pat << "*" << cpPlugins_LIB_EXT;
+  auto libs = cpPlugins::OS::LoadDirContents( dirname, false, pat.str( ) );
+  for( auto lIt = libs.begin( ); lIt != libs.end( ); ++lIt )
   {
-    while( ( ent = readdir( dir ) ) != NULL )
+    try
     {
-      try
-      {
-        std::stringstream fname;
-        fname << dirname << cpExtensions_PATH_SEPARATOR << ent->d_name;
-        this->LoadFile( fname.str( ) );
-      }
-      catch( ... ) { }
-
-    } // elihw
-    closedir( dir );
-  }
-  else
-    throw std::runtime_error(
-      std::string( "Could not load directory " ) +
-      std::string( "\"" ) +  dirname + std::string( "\"" )
-      );
+      this->LoadFile( *lIt );
+    }
+    catch( ... ) { }
+
+  } // rof
 }
 
 // -------------------------------------------------------------------------
diff --git a/lib/cpPlugins/OS/DirContents.cxx b/lib/cpPlugins/OS/DirContents.cxx
new file mode 100644 (file)
index 0000000..9a801e8
--- /dev/null
@@ -0,0 +1,145 @@
+#include <cpPlugins/OS/DirContents.h>
+#include <cpPlugins/OS/tinydir.h>
+#include <sstream>
+
+// -------------------------------------------------------------------------
+std::set< std::string > cpPlugins::OS::
+LoadDirContents(
+  const std::string& path, bool recursive, const std::string& pattern
+  )
+{
+  // Prepare inputs and outputs
+  std::stringstream path_stream;
+  path_stream << path << cpPlugins_PATH_SEPARATOR;
+  std::string path_str = path_stream.str( );
+  std::set< std::string > output;
+
+  // Process data
+  tinydir_dir dir;
+  if( tinydir_open_sorted( &dir, path.c_str( ) ) != -1 )
+  {
+    for( auto i = 0; i < dir.n_files; i++ )
+    {
+      tinydir_file file;
+      if( tinydir_readfile_n( &dir, &file , i ) != -1 )
+      {
+        std::string fname = path_str + file.name;
+        if( file.is_dir )
+        {
+          if( recursive )
+          {
+            if( fname != "." && fname != ".." )
+            {
+              auto tmp = cpPlugins::OS::LoadDirContents( fname, true );
+              output.insert( tmp.begin( ), tmp.end( ) );
+
+            } // fi
+
+          } // fi
+        }
+        else
+        {
+          if( pattern != "" )
+          {
+            if( cpPlugins::OS::Glob( fname, pattern ) )
+              output.insert( fname );
+          }
+          else
+            output.insert( fname );
+
+        } // fi
+
+      } // fi
+
+    } // rof
+
+  } // fi
+  tinydir_close( &dir );
+  return( output );
+}
+
+// ------------------------------------------------------------------------
+void cpPlugins::OS::
+SplitPath( std::string& dname, std::string& fname, const std::string& path )
+{
+  auto found = path.find_last_of( "/\\" );
+  dname = path.substr( 0, found );
+  fname = path.substr( found + 1 );
+}
+
+// ------------------------------------------------------------------------
+int cpPlugins::OS::
+GlobMatch( const char* target, const char* pattern )
+{
+  char* pat = const_cast< char* >( pattern );
+  char* end = strchr( pat, ']' );
+  char* ptr;
+  if( *pat == '[' && end != NULL )
+  {
+    if( end == pat + 1 )
+    {
+      end = strchr( pat + 2, ']' );
+      if( end == NULL )
+        return( 0 );
+
+    } // fi
+
+    if( end - pat == 4 && pat[ 2 ] == '-' && pat[ 1 ] <= pattern[ 3 ] )
+    {
+      if( *target >= pat[ 1 ] && *target <= pat[ 3 ] )
+        return( 5 );
+      else
+        return( 0 );
+
+    } // fi
+
+    ptr = strchr( pat + 1, *target );
+    if( ptr != NULL && ptr < end )
+      return( end - pat + 1 );
+    else
+      return( 0 );
+
+  } // fi
+
+  if( *pat == '?' && *target != 0 )
+    return( 1 );
+  if( *pat == '*' )
+    return( 0 );
+  if( *target == 0 || *pat == 0 )
+    return( 0 );
+  if( *target == *pat )
+    return( 1 );
+  return( 0 );
+}
+
+// ------------------------------------------------------------------------
+bool cpPlugins::OS::
+Glob( const std::string& line, const std::string& pattern )
+{
+  const char* target = line.c_str( );
+  const char* pat = pattern.c_str( );
+  int gobble;
+
+  while( ( gobble = GlobMatch( target, pat ) ) )
+  {
+    target++;
+    pat += gobble;
+
+  } // elihw
+  if( *target == 0 && *pat == 0 )
+    return( true );
+  else if( *pat == '*' )
+  {
+    while( pat[ 1 ] == '*' )
+      pat++;
+    if( pat[ 1 ] == 0 )
+      return( true );
+    while( *target )
+      if( Glob( target++, pat + 1 ) )
+        return( 1 );
+
+  } // fi
+  return( false );
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/OS/DirContents.h b/lib/cpPlugins/OS/DirContents.h
new file mode 100644 (file)
index 0000000..e569ee3
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef __cpPlugins__OS__DirContents__h__
+#define __cpPlugins__OS__DirContents__h__
+
+#include <cpPlugins/Config.h>
+#include <set>
+#include <string>
+
+namespace cpPlugins
+{
+  namespace OS
+  {
+    /**
+     */
+    std::set< std::string > cpPlugins_EXPORT LoadDirContents(
+      const std::string& path, bool recursive,
+      const std::string& pattern = ""
+      );
+
+    /**
+     */
+    void cpPlugins_EXPORT SplitPath(
+      std::string& dname, std::string& fname,
+      const std::string& path
+      );
+
+    /**
+     */
+    int cpPlugins_EXPORT GlobMatch( const char* target, const char* pattern );
+
+    /**
+     */
+    bool cpPlugins_EXPORT Glob(
+      const std::string& line, const std::string& pattern
+      );
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpPlugins__OS__DirContents__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/OS/tinydir.h b/lib/cpPlugins/OS/tinydir.h
new file mode 100644 (file)
index 0000000..2d4418b
--- /dev/null
@@ -0,0 +1,804 @@
+/*
+Copyright (c) 2013-2016, tinydir authors:
+- Cong Xu
+- Lautis Sun
+- Baudouin Feildel
+- Andargor <andargor@yahoo.com>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef TINYDIR_H
+#define TINYDIR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if ((defined _UNICODE) && !(defined UNICODE))
+#define UNICODE
+#endif
+
+#if ((defined UNICODE) && !(defined _UNICODE))
+#define _UNICODE
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef _MSC_VER
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+# include <tchar.h>
+# pragma warning(push)
+# pragma warning (disable : 4996)
+#else
+# include <dirent.h>
+# include <libgen.h>
+# include <sys/stat.h>
+# include <stddef.h>
+#endif
+#ifdef __MINGW32__
+# include <tchar.h>
+#endif
+
+
+/* types */
+
+/* Windows UNICODE wide character support */
+#if defined _MSC_VER || defined __MINGW32__
+#define _tinydir_char_t TCHAR
+#define TINYDIR_STRING(s) _TEXT(s)
+#define _tinydir_strlen _tcslen
+#define _tinydir_strcpy _tcscpy
+#define _tinydir_strcat _tcscat
+#define _tinydir_strcmp _tcscmp
+#define _tinydir_strrchr _tcsrchr
+#define _tinydir_strncmp _tcsncmp
+#else
+#define _tinydir_char_t char
+#define TINYDIR_STRING(s) s
+#define _tinydir_strlen strlen
+#define _tinydir_strcpy strcpy
+#define _tinydir_strcat strcat
+#define _tinydir_strcmp strcmp
+#define _tinydir_strrchr strrchr
+#define _tinydir_strncmp strncmp
+#endif
+
+#if (defined _MSC_VER || defined __MINGW32__)
+#include <windows.h>
+#define _TINYDIR_PATH_MAX MAX_PATH
+#elif defined  __linux__
+#include <linux/limits.h>
+#define _TINYDIR_PATH_MAX PATH_MAX
+#else
+#define _TINYDIR_PATH_MAX 4096
+#endif
+
+#ifdef _MSC_VER
+/* extra chars for the "\\*" mask */
+# define _TINYDIR_PATH_EXTRA 2
+#else
+# define _TINYDIR_PATH_EXTRA 0
+#endif
+
+#define _TINYDIR_FILENAME_MAX 256
+
+#if (defined _MSC_VER || defined __MINGW32__)
+#define _TINYDIR_DRIVE_MAX 3
+#endif
+
+#ifdef _MSC_VER
+# define _TINYDIR_FUNC static __inline
+#elif !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
+# define _TINYDIR_FUNC static __inline__
+#else
+# define _TINYDIR_FUNC static inline
+#endif
+
+/* readdir_r usage; define TINYDIR_USE_READDIR_R to use it (if supported) */
+#ifdef TINYDIR_USE_READDIR_R
+
+/* readdir_r is a POSIX-only function, and may not be available under various
+ * environments/settings, e.g. MinGW. Use readdir fallback */
+#if _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _BSD_SOURCE || _SVID_SOURCE ||\
+       _POSIX_SOURCE
+# define _TINYDIR_HAS_READDIR_R
+#endif
+#if _POSIX_C_SOURCE >= 200112L
+# define _TINYDIR_HAS_FPATHCONF
+# include <unistd.h>
+#endif
+#if _BSD_SOURCE || _SVID_SOURCE || \
+       (_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700)
+# define _TINYDIR_HAS_DIRFD
+# include <sys/types.h>
+#endif
+#if defined _TINYDIR_HAS_FPATHCONF && defined _TINYDIR_HAS_DIRFD &&\
+       defined _PC_NAME_MAX
+# define _TINYDIR_USE_FPATHCONF
+#endif
+#if defined __MINGW32__ || !defined _TINYDIR_HAS_READDIR_R ||\
+       !(defined _TINYDIR_USE_FPATHCONF || defined NAME_MAX)
+# define _TINYDIR_USE_READDIR
+#endif
+
+/* Use readdir by default */
+#else
+# define _TINYDIR_USE_READDIR
+#endif
+
+/* MINGW32 has two versions of dirent, ASCII and UNICODE*/
+#ifndef _MSC_VER
+#if (defined __MINGW32__) && (defined _UNICODE)
+#define _TINYDIR_DIR _WDIR
+#define _tinydir_dirent _wdirent
+#define _tinydir_opendir _wopendir
+#define _tinydir_readdir _wreaddir
+#define _tinydir_closedir _wclosedir
+#else
+#define _TINYDIR_DIR DIR
+#define _tinydir_dirent dirent
+#define _tinydir_opendir opendir
+#define _tinydir_readdir readdir
+#define _tinydir_closedir closedir
+#endif
+#endif
+
+/* Allow user to use a custom allocator by defining _TINYDIR_MALLOC and _TINYDIR_FREE. */
+#if    defined(_TINYDIR_MALLOC) &&  defined(_TINYDIR_FREE)
+#elif !defined(_TINYDIR_MALLOC) && !defined(_TINYDIR_FREE)
+#else
+#error "Either define both alloc and free or none of them!"
+#endif
+
+#if !defined(_TINYDIR_MALLOC)
+       #define _TINYDIR_MALLOC(_size) malloc(_size)
+       #define _TINYDIR_FREE(_ptr)    free(_ptr)
+#endif /* !defined(_TINYDIR_MALLOC) */
+
+typedef struct tinydir_file
+{
+       _tinydir_char_t path[_TINYDIR_PATH_MAX];
+       _tinydir_char_t name[_TINYDIR_FILENAME_MAX];
+       _tinydir_char_t *extension;
+       int is_dir;
+       int is_reg;
+
+#ifndef _MSC_VER
+#ifdef __MINGW32__
+       struct _stat _s;
+#else
+       struct stat _s;
+#endif
+#endif
+} tinydir_file;
+
+typedef struct tinydir_dir
+{
+       _tinydir_char_t path[_TINYDIR_PATH_MAX];
+       int has_next;
+       size_t n_files;
+
+       tinydir_file *_files;
+#ifdef _MSC_VER
+       HANDLE _h;
+       WIN32_FIND_DATA _f;
+#else
+       _TINYDIR_DIR *_d;
+       struct _tinydir_dirent *_e;
+#ifndef _TINYDIR_USE_READDIR
+       struct _tinydir_dirent *_ep;
+#endif
+#endif
+} tinydir_dir;
+
+
+/* declarations */
+
+_TINYDIR_FUNC
+int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path);
+_TINYDIR_FUNC
+int tinydir_open_sorted(tinydir_dir *dir, const _tinydir_char_t *path);
+_TINYDIR_FUNC
+void tinydir_close(tinydir_dir *dir);
+
+_TINYDIR_FUNC
+int tinydir_next(tinydir_dir *dir);
+_TINYDIR_FUNC
+int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file);
+_TINYDIR_FUNC
+int tinydir_readfile_n(const tinydir_dir *dir, tinydir_file *file, size_t i);
+_TINYDIR_FUNC
+int tinydir_open_subdir_n(tinydir_dir *dir, size_t i);
+
+_TINYDIR_FUNC
+int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path);
+_TINYDIR_FUNC
+void _tinydir_get_ext(tinydir_file *file);
+_TINYDIR_FUNC
+int _tinydir_file_cmp(const void *a, const void *b);
+#ifndef _MSC_VER
+#ifndef _TINYDIR_USE_READDIR
+_TINYDIR_FUNC
+size_t _tinydir_dirent_buf_size(_TINYDIR_DIR *dirp);
+#endif
+#endif
+
+
+/* definitions*/
+
+_TINYDIR_FUNC
+int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path)
+{
+#ifndef _MSC_VER
+#ifndef _TINYDIR_USE_READDIR
+       int error;
+       int size;       /* using int size */
+#endif
+#else
+       _tinydir_char_t path_buf[_TINYDIR_PATH_MAX];
+#endif
+       _tinydir_char_t *pathp;
+
+       if (dir == NULL || path == NULL || _tinydir_strlen(path) == 0)
+       {
+               errno = EINVAL;
+               return -1;
+       }
+       if (_tinydir_strlen(path) + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX)
+       {
+               errno = ENAMETOOLONG;
+               return -1;
+       }
+
+       /* initialise dir */
+       dir->_files = NULL;
+#ifdef _MSC_VER
+       dir->_h = INVALID_HANDLE_VALUE;
+#else
+       dir->_d = NULL;
+#ifndef _TINYDIR_USE_READDIR
+       dir->_ep = NULL;
+#endif
+#endif
+       tinydir_close(dir);
+
+       _tinydir_strcpy(dir->path, path);
+       /* Remove trailing slashes */
+       pathp = &dir->path[_tinydir_strlen(dir->path) - 1];
+       while (pathp != dir->path && (*pathp == TINYDIR_STRING('\\') || *pathp == TINYDIR_STRING('/')))
+       {
+               *pathp = TINYDIR_STRING('\0');
+               pathp++;
+       }
+#ifdef _MSC_VER
+       _tinydir_strcpy(path_buf, dir->path);
+       _tinydir_strcat(path_buf, TINYDIR_STRING("\\*"));
+       dir->_h = FindFirstFile(path_buf, &dir->_f);
+       if (dir->_h == INVALID_HANDLE_VALUE)
+       {
+               errno = ENOENT;
+#else
+       dir->_d = _tinydir_opendir(path);
+       if (dir->_d == NULL)
+       {
+#endif
+               goto bail;
+       }
+
+       /* read first file */
+       dir->has_next = 1;
+#ifndef _MSC_VER
+#ifdef _TINYDIR_USE_READDIR
+       dir->_e = _tinydir_readdir(dir->_d);
+#else
+       /* allocate dirent buffer for readdir_r */
+       size = _tinydir_dirent_buf_size(dir->_d); /* conversion to int */
+       if (size == -1) return -1;
+       dir->_ep = (struct _tinydir_dirent*)_TINYDIR_MALLOC(size);
+       if (dir->_ep == NULL) return -1;
+
+       error = readdir_r(dir->_d, dir->_ep, &dir->_e);
+       if (error != 0) return -1;
+#endif
+       if (dir->_e == NULL)
+       {
+               dir->has_next = 0;
+       }
+#endif
+
+       return 0;
+
+bail:
+       tinydir_close(dir);
+       return -1;
+}
+
+_TINYDIR_FUNC
+int tinydir_open_sorted(tinydir_dir *dir, const _tinydir_char_t *path)
+{
+       /* Count the number of files first, to pre-allocate the files array */
+       size_t n_files = 0;
+       if (tinydir_open(dir, path) == -1)
+       {
+               return -1;
+       }
+       while (dir->has_next)
+       {
+               n_files++;
+               if (tinydir_next(dir) == -1)
+               {
+                       goto bail;
+               }
+       }
+       tinydir_close(dir);
+
+       if (tinydir_open(dir, path) == -1)
+       {
+               return -1;
+       }
+
+       dir->n_files = 0;
+       dir->_files = (tinydir_file *)_TINYDIR_MALLOC(sizeof *dir->_files * n_files);
+       if (dir->_files == NULL)
+       {
+               goto bail;
+       }
+       while (dir->has_next)
+       {
+               tinydir_file *p_file;
+               dir->n_files++;
+
+               p_file = &dir->_files[dir->n_files - 1];
+               if (tinydir_readfile(dir, p_file) == -1)
+               {
+                       goto bail;
+               }
+
+               if (tinydir_next(dir) == -1)
+               {
+                       goto bail;
+               }
+
+               /* Just in case the number of files has changed between the first and
+               second reads, terminate without writing into unallocated memory */
+               if (dir->n_files == n_files)
+               {
+                       break;
+               }
+       }
+
+       qsort(dir->_files, dir->n_files, sizeof(tinydir_file), _tinydir_file_cmp);
+
+       return 0;
+
+bail:
+       tinydir_close(dir);
+       return -1;
+}
+
+_TINYDIR_FUNC
+void tinydir_close(tinydir_dir *dir)
+{
+       if (dir == NULL)
+       {
+               return;
+       }
+
+       memset(dir->path, 0, sizeof(dir->path));
+       dir->has_next = 0;
+       dir->n_files = 0;
+       _TINYDIR_FREE(dir->_files);
+       dir->_files = NULL;
+#ifdef _MSC_VER
+       if (dir->_h != INVALID_HANDLE_VALUE)
+       {
+               FindClose(dir->_h);
+       }
+       dir->_h = INVALID_HANDLE_VALUE;
+#else
+       if (dir->_d)
+       {
+               _tinydir_closedir(dir->_d);
+       }
+       dir->_d = NULL;
+       dir->_e = NULL;
+#ifndef _TINYDIR_USE_READDIR
+       _TINYDIR_FREE(dir->_ep);
+       dir->_ep = NULL;
+#endif
+#endif
+}
+
+_TINYDIR_FUNC
+int tinydir_next(tinydir_dir *dir)
+{
+       if (dir == NULL)
+       {
+               errno = EINVAL;
+               return -1;
+       }
+       if (!dir->has_next)
+       {
+               errno = ENOENT;
+               return -1;
+       }
+
+#ifdef _MSC_VER
+       if (FindNextFile(dir->_h, &dir->_f) == 0)
+#else
+#ifdef _TINYDIR_USE_READDIR
+       dir->_e = _tinydir_readdir(dir->_d);
+#else
+       if (dir->_ep == NULL)
+       {
+               return -1;
+       }
+       if (readdir_r(dir->_d, dir->_ep, &dir->_e) != 0)
+       {
+               return -1;
+       }
+#endif
+       if (dir->_e == NULL)
+#endif
+       {
+               dir->has_next = 0;
+#ifdef _MSC_VER
+               if (GetLastError() != ERROR_SUCCESS &&
+                       GetLastError() != ERROR_NO_MORE_FILES)
+               {
+                       tinydir_close(dir);
+                       errno = EIO;
+                       return -1;
+               }
+#endif
+       }
+
+       return 0;
+}
+
+_TINYDIR_FUNC
+int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file)
+{
+       if (dir == NULL || file == NULL)
+       {
+               errno = EINVAL;
+               return -1;
+       }
+#ifdef _MSC_VER
+       if (dir->_h == INVALID_HANDLE_VALUE)
+#else
+       if (dir->_e == NULL)
+#endif
+       {
+               errno = ENOENT;
+               return -1;
+       }
+       if (_tinydir_strlen(dir->path) +
+               _tinydir_strlen(
+#ifdef _MSC_VER
+                       dir->_f.cFileName
+#else
+                       dir->_e->d_name
+#endif
+               ) + 1 + _TINYDIR_PATH_EXTRA >=
+               _TINYDIR_PATH_MAX)
+       {
+               /* the path for the file will be too long */
+               errno = ENAMETOOLONG;
+               return -1;
+       }
+       if (_tinydir_strlen(
+#ifdef _MSC_VER
+                       dir->_f.cFileName
+#else
+                       dir->_e->d_name
+#endif
+               ) >= _TINYDIR_FILENAME_MAX)
+       {
+               errno = ENAMETOOLONG;
+               return -1;
+       }
+
+       _tinydir_strcpy(file->path, dir->path);
+       _tinydir_strcat(file->path, TINYDIR_STRING("/"));
+       _tinydir_strcpy(file->name,
+#ifdef _MSC_VER
+               dir->_f.cFileName
+#else
+               dir->_e->d_name
+#endif
+       );
+       _tinydir_strcat(file->path, file->name);
+#ifndef _MSC_VER
+#ifdef __MINGW32__
+       if (_tstat(
+#else
+       if (stat(
+#endif
+               file->path, &file->_s) == -1)
+       {
+               return -1;
+       }
+#endif
+       _tinydir_get_ext(file);
+
+       file->is_dir =
+#ifdef _MSC_VER
+               !!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
+#else
+               S_ISDIR(file->_s.st_mode);
+#endif
+       file->is_reg =
+#ifdef _MSC_VER
+               !!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) ||
+               (
+                       !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) &&
+                       !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
+                       !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) &&
+#ifdef FILE_ATTRIBUTE_INTEGRITY_STREAM
+                       !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_INTEGRITY_STREAM) &&
+#endif
+#ifdef FILE_ATTRIBUTE_NO_SCRUB_DATA
+                       !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_NO_SCRUB_DATA) &&
+#endif
+                       !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE) &&
+                       !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY));
+#else
+               S_ISREG(file->_s.st_mode);
+#endif
+
+       return 0;
+}
+
+_TINYDIR_FUNC
+int tinydir_readfile_n(const tinydir_dir *dir, tinydir_file *file, size_t i)
+{
+       if (dir == NULL || file == NULL)
+       {
+               errno = EINVAL;
+               return -1;
+       }
+       if (i >= dir->n_files)
+       {
+               errno = ENOENT;
+               return -1;
+       }
+
+       memcpy(file, &dir->_files[i], sizeof(tinydir_file));
+       _tinydir_get_ext(file);
+
+       return 0;
+}
+
+_TINYDIR_FUNC
+int tinydir_open_subdir_n(tinydir_dir *dir, size_t i)
+{
+       _tinydir_char_t path[_TINYDIR_PATH_MAX];
+       if (dir == NULL)
+       {
+               errno = EINVAL;
+               return -1;
+       }
+       if (i >= dir->n_files || !dir->_files[i].is_dir)
+       {
+               errno = ENOENT;
+               return -1;
+       }
+
+       _tinydir_strcpy(path, dir->_files[i].path);
+       tinydir_close(dir);
+       if (tinydir_open_sorted(dir, path) == -1)
+       {
+               return -1;
+       }
+
+       return 0;
+}
+
+/* Open a single file given its path */
+_TINYDIR_FUNC
+int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path)
+{
+       tinydir_dir dir;
+       int result = 0;
+       int found = 0;
+       _tinydir_char_t dir_name_buf[_TINYDIR_PATH_MAX];
+       _tinydir_char_t file_name_buf[_TINYDIR_FILENAME_MAX];
+       _tinydir_char_t *dir_name;
+       _tinydir_char_t *base_name;
+#if (defined _MSC_VER || defined __MINGW32__)
+       _tinydir_char_t drive_buf[_TINYDIR_DRIVE_MAX];
+       _tinydir_char_t ext_buf[_TINYDIR_FILENAME_MAX];
+#endif
+
+       if (file == NULL || path == NULL || _tinydir_strlen(path) == 0)
+       {
+               errno = EINVAL;
+               return -1;
+       }
+       if (_tinydir_strlen(path) + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX)
+       {
+               errno = ENAMETOOLONG;
+               return -1;
+       }
+
+       /* Get the parent path */
+#if (defined _MSC_VER || defined __MINGW32__)
+#if ((defined _MSC_VER) && (_MSC_VER >= 1400))
+               _tsplitpath_s(
+                       path,
+                       drive_buf, _TINYDIR_DRIVE_MAX,
+                       dir_name_buf, _TINYDIR_FILENAME_MAX,
+                       file_name_buf, _TINYDIR_FILENAME_MAX,
+                       ext_buf, _TINYDIR_FILENAME_MAX);
+#else
+               _tsplitpath(
+                       path,
+                       drive_buf,
+                       dir_name_buf,
+                       file_name_buf,
+                       ext_buf);
+#endif
+
+/* _splitpath_s not work fine with only filename and widechar support */
+#ifdef _UNICODE
+               if (drive_buf[0] == L'\xFEFE')
+                       drive_buf[0] = '\0';
+               if (dir_name_buf[0] == L'\xFEFE')
+                       dir_name_buf[0] = '\0';
+#endif
+
+       if (errno)
+       {
+               errno = EINVAL;
+               return -1;
+       }
+       /* Emulate the behavior of dirname by returning "." for dir name if it's
+       empty */
+       if (drive_buf[0] == '\0' && dir_name_buf[0] == '\0')
+       {
+               _tinydir_strcpy(dir_name_buf, TINYDIR_STRING("."));
+       }
+       /* Concatenate the drive letter and dir name to form full dir name */
+       _tinydir_strcat(drive_buf, dir_name_buf);
+       dir_name = drive_buf;
+       /* Concatenate the file name and extension to form base name */
+       _tinydir_strcat(file_name_buf, ext_buf);
+       base_name = file_name_buf;
+#else
+       _tinydir_strcpy(dir_name_buf, path);
+       dir_name = dirname(dir_name_buf);
+       _tinydir_strcpy(file_name_buf, path);
+       base_name =basename(file_name_buf);
+#endif
+
+       /* Open the parent directory */
+       if (tinydir_open(&dir, dir_name) == -1)
+       {
+               return -1;
+       }
+
+       /* Read through the parent directory and look for the file */
+       while (dir.has_next)
+       {
+               if (tinydir_readfile(&dir, file) == -1)
+               {
+                       result = -1;
+                       goto bail;
+               }
+               if (_tinydir_strcmp(file->name, base_name) == 0)
+               {
+                       /* File found */
+                       found = 1;
+                       break;
+               }
+               tinydir_next(&dir);
+       }
+       if (!found)
+       {
+               result = -1;
+               errno = ENOENT;
+       }
+
+bail:
+       tinydir_close(&dir);
+       return result;
+}
+
+_TINYDIR_FUNC
+void _tinydir_get_ext(tinydir_file *file)
+{
+       _tinydir_char_t *period = _tinydir_strrchr(file->name, TINYDIR_STRING('.'));
+       if (period == NULL)
+       {
+               file->extension = &(file->name[_tinydir_strlen(file->name)]);
+       }
+       else
+       {
+               file->extension = period + 1;
+       }
+}
+
+_TINYDIR_FUNC
+int _tinydir_file_cmp(const void *a, const void *b)
+{
+       const tinydir_file *fa = (const tinydir_file *)a;
+       const tinydir_file *fb = (const tinydir_file *)b;
+       if (fa->is_dir != fb->is_dir)
+       {
+               return -(fa->is_dir - fb->is_dir);
+       }
+       return _tinydir_strncmp(fa->name, fb->name, _TINYDIR_FILENAME_MAX);
+}
+
+#ifndef _MSC_VER
+#ifndef _TINYDIR_USE_READDIR
+/*
+The following authored by Ben Hutchings <ben@decadent.org.uk>
+from https://womble.decadent.org.uk/readdir_r-advisory.html
+*/
+/* Calculate the required buffer size (in bytes) for directory      *
+* entries read from the given directory handle.  Return -1 if this  *
+* this cannot be done.                                              *
+*                                                                   *
+* This code does not trust values of NAME_MAX that are less than    *
+* 255, since some systems (including at least HP-UX) incorrectly    *
+* define it to be a smaller value.                                  */
+_TINYDIR_FUNC
+size_t _tinydir_dirent_buf_size(_TINYDIR_DIR *dirp)
+{
+       long name_max;
+       size_t name_end;
+       /* parameter may be unused */
+       (void)dirp;
+
+#if defined _TINYDIR_USE_FPATHCONF
+       name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX);
+       if (name_max == -1)
+#if defined(NAME_MAX)
+               name_max = (NAME_MAX > 255) ? NAME_MAX : 255;
+#else
+               return (size_t)(-1);
+#endif
+#elif defined(NAME_MAX)
+       name_max = (NAME_MAX > 255) ? NAME_MAX : 255;
+#else
+#error "buffer size for readdir_r cannot be determined"
+#endif
+       name_end = (size_t)offsetof(struct _tinydir_dirent, d_name) + name_max + 1;
+       return (name_end > sizeof(struct _tinydir_dirent) ?
+               name_end : sizeof(struct _tinydir_dirent));
+}
+#endif
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+# if defined (_MSC_VER)
+# pragma warning(pop)
+# endif
+
+#endif
diff --git a/lib/cpPlugins/OS/tinydir_COPYING.txt b/lib/cpPlugins/OS/tinydir_COPYING.txt
new file mode 100644 (file)
index 0000000..0d31329
--- /dev/null
@@ -0,0 +1,26 @@
+Copyright (c) 2013-2016, tinydir authors:
+- Cong Xu
+- Lautis Sun
+- Baudouin Feildel
+- Andargor <andargor@yahoo.com>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met: 
+
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer. 
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/lib/cpPlugins/OS/tinydir_README.md.txt b/lib/cpPlugins/OS/tinydir_README.md.txt
new file mode 100644 (file)
index 0000000..3fab002
--- /dev/null
@@ -0,0 +1,78 @@
+TinyDir
+=======
+[![Build Status](https://travis-ci.org/cxong/tinydir.svg?branch=master)](https://travis-ci.org/cxong/tinydir)[![Project Stats](https://www.openhub.net/p/tinydir/widgets/project_thin_badge.gif)](https://www.openhub.net/p/tinydir)
+
+Lightweight, portable and easy to integrate C directory and file reader. TinyDir wraps dirent for POSIX and FindFirstFile for Windows.
+
+Windows unicode is supported by defining `UNICODE` and `_UNICODE` before including `tinydir.h`.
+
+Example
+=======
+
+There are two methods. Error checking omitted:
+
+```C
+tinydir_dir dir;
+tinydir_open(&dir, "/path/to/dir");
+
+while (dir.has_next)
+{
+       tinydir_file file;
+       tinydir_readfile(&dir, &file);
+
+       printf("%s", file.name);
+       if (file.is_dir)
+       {
+               printf("/");
+       }
+       printf("\n");
+
+       tinydir_next(&dir);
+}
+
+tinydir_close(&dir);
+```
+
+```C
+tinydir_dir dir;
+int i;
+tinydir_open_sorted(&dir, "/path/to/dir");
+
+for (i = 0; i < dir.n_files; i++)
+{
+       tinydir_file file;
+       tinydir_readfile_n(&dir, &file, i);
+
+       printf("%s", file.name);
+       if (file.is_dir)
+       {
+               printf("/");
+       }
+       printf("\n");
+}
+
+tinydir_close(&dir);
+```
+
+See the `/samples` folder for more examples, including an interactive command-line directory navigator.
+
+Language
+========
+
+ANSI C, or C90.
+
+Platforms
+=========
+
+POSIX and Windows supported. Open to the possibility of supporting other platforms.
+
+License
+=======
+
+Simplified BSD; if you use tinydir you can comply by including `tinydir.h` or `COPYING` somewhere in your package.
+
+Known Limitations
+=================
+
+- Limited path and filename sizes
+- [Possible race condition bug if folder being read has changing content](https://github.com/cxong/tinydir/issues/13)