Platon Technologies
not logged in Login Registration
EnglishSlovak
open source software development celebrating 10 years of open source development! Thursday, March 28, 2024

File: [Platon] / games / 3do-view / dir.c (download)

Revision 1.11, Wed Nov 10 18:14:32 2004 UTC (19 years, 4 months ago) by nepto


Changes since 1.10: +5 -1 lines

Fixed several warnings.

/*
 * 3do-view - 3D objects (3DO) viewer for MS-Dos/Win32/SVGAlib/X11
 *
 * dir.c - files and directories handler
 * ____________________________________________________________
 *
 * Developed by Ondrej Jombik <nepto@platon.sk>
 * Copyright (c) 2003-2004 Platon SDG, http://platon.sk/
 * All rights reserved.
 *
 * See README file for more information about this software.
 * See COPYING file for license information.
 *
 * Download the latest version from
 * http://platon.sk/projects/games/
 *
 * Changelog:
 * 2003-05-19 - created
 * 2003-06-27 - added Win32 support
 * 2003-07-15 - smart memory allocation for files and directories data
 * 2003-08-12 - X11 adaptations
 */

/* $Platon: games/3do-view/dir.c,v 1.10 2004/04/06 09:54:15 nepto Exp $ */

#include <string.h>
#include <stdlib.h>
#include <system.h>

#define DIR_SMART_ALLOCATION            (1) /* 1 or 0 */
#define DIR_REALLOC_IDX_STEP            (15)
#if DIR_SMART_ALLOCATION
#  define DIR_REALLOC_DATA_STEP            (255)
#endif

#if PLATON_SYSTEM_SVGALIB || PLATON_SYSTEM_X11
#  include <unistd.h>
#  include <dirent.h>
#  include <sys/types.h>
#  include <sys/stat.h>
#  define    DIR_DIRECTORY_CONDITION        (S_ISDIR(st.st_mode))
#  define    DIR_FILENAME                (dp->d_name)
#  define    DIR_INIT_CONDITION            (! ((dirp = opendir(".")) == NULL \
                    && !chdir("/") && (dirp = opendir(".")) == NULL))
    /* If current directory cannot be opened, fallback to root directory. */
#endif

#if PLATON_SYSTEM_WIN32
#  include <windows.h>
#  define    DIR_DIRECTORY_CONDITION    (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
#  define    DIR_FILENAME            (FindFileData.cFileName)
#  define    DIR_NEXT_CONDITION        (FindNextFile(hFind, &FindFileData))
#  define    DIR_INIT_CONDITION        ((hFind = FindFirstFile("*.*", &FindFileData)) != INVALID_HANDLE_VALUE)
#endif

#if PLATON_SYSTEM_MSDOS
#  include <dos.h>
#  include <dir.h>
#  define    DIR_DIRECTORY_CONDITION        (ffblk.ff_attrib & FA_DIREC)
#  define    DIR_FILENAME                (ffblk.ff_name)
#  define    DIR_NEXT_CONDITION            (! findnext(&ffblk))
#  define    DIR_INIT_CONDITION            (! (findfirst("*.*", &ffblk, \
                    FA_DIREC + FA_HIDDEN + FA_RDONLY + FA_SYSTEM)))
#endif

#if DIR_SMART_ALLOCATION
    /* Sorting currently does not work in smart allocation mode. */
#else
static int compare_function(const void *ptr1, const void *ptr2) /* {{{ */
{
#if 0
    fprintf(stderr, "comparing %s[%p]:%s[%p]\n",
            *(char **) ptr1, ptr1, *(char **) ptr2, ptr2);
#endif
    return strcmp(*(char **) ptr1, *(char **) ptr2);
} /* }}} */
#endif

void get_directories_and_files(char ***directories, char ***files) /* {{{ */
{
#if DIR_SMART_ALLOCATION
    register int *alloc_bytes;
    register int *free_bytes;
    int directories_alloc_bytes = 0;
    int directories_free_bytes  = 0;
    int files_alloc_bytes       = 0;
    int files_free_bytes        = 0;
#endif
#if PLATON_SYSTEM_SVGALIB || PLATON_SYSTEM_X11
    DIR *dirp;
    struct dirent *dp;
    struct stat st;
#endif
#if PLATON_SYSTEM_WIN32
    WIN32_FIND_DATA FindFileData;
    HANDLE hFind;
#endif
#if PLATON_SYSTEM_MSDOS
    struct ffblk ffblk;
#endif
    register char ***ptr;
    int directories_size, files_size, *size;

    if (directories != NULL) *directories = NULL;
    if (files       != NULL) *files       = NULL;

    if (! DIR_INIT_CONDITION)
        return;

    directories_size = 0;
    files_size       = 0;

#if PLATON_SYSTEM_SVGALIB || PLATON_SYSTEM_X11
    for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
        if (stat(DIR_FILENAME, &st))
            continue;
#endif
#if PLATON_SYSTEM_MSDOS || PLATON_SYSTEM_WIN32
    do {
#endif

        if (DIR_DIRECTORY_CONDITION) {
            if (directories == NULL || ! strcmp(DIR_FILENAME, "."))
                continue;
            ptr  = directories;
            size = &directories_size;
#if DIR_SMART_ALLOCATION
            alloc_bytes = &directories_alloc_bytes;
            free_bytes  = &directories_free_bytes;
#endif
        } else {
            if (files == NULL)
                continue;
            ptr  = files;
            size = &files_size;
#if DIR_SMART_ALLOCATION
            alloc_bytes = &files_alloc_bytes;
            free_bytes  = &files_free_bytes;
#endif
        }
        if (! *size || !((*size + 1) % DIR_REALLOC_IDX_STEP)) {
            register char **new_ptr;
            new_ptr = (char **) realloc((void *) *ptr,
                    sizeof(char *) * (*size + 1 + DIR_REALLOC_IDX_STEP));
            if (new_ptr == NULL)
                break; /* take what we recentry have and go away
                          if memory allocation failed */
            *ptr = new_ptr;
            if (! *size)
                (*ptr)[0] = NULL;
        }
#if DIR_SMART_ALLOCATION
        while (strlen(DIR_FILENAME) + 1 > *free_bytes) {
            register char *new_ptr;
            register int i, diff;
            new_ptr = (char *) realloc((void *) **ptr,
                    sizeof(char) * (*alloc_bytes + DIR_REALLOC_DATA_STEP));
            if (new_ptr == NULL)
                break; /* skip this entry if memory allocation failed */
            diff = new_ptr - **ptr;
            for (i = 0; i <= *size; i++)
                (*ptr)[i] += diff;
            *free_bytes  += DIR_REALLOC_DATA_STEP;
            *alloc_bytes += DIR_REALLOC_DATA_STEP;
        }
        if (strlen(DIR_FILENAME) + 1 <= *free_bytes) {
            (*ptr)[*size] = **ptr + *alloc_bytes - *free_bytes;
            strcpy((*ptr)[*size], DIR_FILENAME);
            *free_bytes -= (strlen(DIR_FILENAME) + 1);
        }
#else
        if (((*ptr)[*size] = strdup(DIR_FILENAME)) == NULL)
            break;
#endif
        (*size)++;
        (*ptr)[*size] = NULL;
#if PLATON_SYSTEM_SVGALIB || PLATON_SYSTEM_X11
    }
    closedir(dirp);
#endif
#if PLATON_SYSTEM_MSDOS || PLATON_SYSTEM_WIN32
    } while (DIR_NEXT_CONDITION);
#endif

#if DIR_SMART_ALLOCATION
    /* Sorting currently does not work in smart allocation mode. */
#else
    if (*directories != NULL)
        qsort(*directories, directories_size, sizeof(char *), compare_function);
    if (*files != NULL)
        qsort(*files, files_size, sizeof(char *), compare_function);
#endif
} /* }}} */

void free_directories_or_files(char **ar) /* {{{ */
{
#if DIR_SMART_ALLOCATION
    if (ar[0] != NULL)
        free(ar[0]);
#else
    register int i;
    for (i = 0; ar[i] != NULL; i++)
        free(ar[i]);
#endif
    free(ar);
} /* }}} */

#if defined(SELF) || defined(SELFTEST) || defined(SELF_DIR)

#include <stdio.h>

int main(int argc, char **argv) /* {{{ */
{
    register int k;
    char **dirs, **files;

    get_directories_and_files(&dirs, &files);

    printf("Directories: [%p]\n", dirs);
    for (k = 0; dirs != NULL && dirs[k] != NULL; k++)
        printf("%03d: %s\n", k, dirs[k]);

    printf("Files: [%p]\n", files);
    for (k = 0; files != NULL && files[k] != NULL; k++)
        printf("%03d: %s\n", k, files[k]);

    if (dirs != NULL)
        free_directories_or_files(dirs);
    if (files != NULL)
        free_directories_or_files(files);

    return 0;
} /* }}} */

#endif /* #if defined(SELF) || defined(SELFTEST) || defined(SELF_DIR) */

/* Modeline for ViM {{{
 * vim: set ts=4:
 * vim600: fdm=marker fdl=0 fdc=0:
 * }}} */


Platon Group <platon@platon.org> http://platon.org/
Copyright © 2002-2006 Platon Group
Site powered by Metafox CMS
Go to Top