merged the modularization branch (credentials) back to trunk
This commit is contained in:
@@ -1,10 +1,3 @@
|
||||
/**
|
||||
* @file enumerator.c
|
||||
*
|
||||
* @brief Implementation of enumerator_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2007 Martin Willi
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
@@ -18,10 +11,20 @@
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "enumerator.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
/**
|
||||
* Implementation of enumerator_create_empty().enumerate
|
||||
@@ -42,3 +45,350 @@ enumerator_t* enumerator_create_empty()
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumerator implementation for directory enumerator
|
||||
*/
|
||||
typedef struct {
|
||||
/** implements enumerator_t */
|
||||
enumerator_t public;
|
||||
/** directory handle */
|
||||
DIR *dir;
|
||||
/** absolute path of current file */
|
||||
char full[PATH_MAX];
|
||||
/** where directory part of full ends and relative file gets written */
|
||||
char *full_end;
|
||||
} dir_enum_t;
|
||||
|
||||
/**
|
||||
* Implementation of enumerator_create_directory().destroy
|
||||
*/
|
||||
static void destroy_dir_enum(dir_enum_t *this)
|
||||
{
|
||||
closedir(this->dir);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of enumerator_create_directory().enumerate
|
||||
*/
|
||||
static bool enumerate_dir_enum(dir_enum_t *this, char **relative,
|
||||
char **absolute, struct stat *st)
|
||||
{
|
||||
struct dirent *entry = readdir(this->dir);
|
||||
size_t len, remaining;
|
||||
|
||||
if (!entry)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (streq(entry->d_name, ".") || streq(entry->d_name, ".."))
|
||||
{
|
||||
return enumerate_dir_enum(this, relative, absolute, st);
|
||||
}
|
||||
if (relative)
|
||||
{
|
||||
*relative = entry->d_name;
|
||||
}
|
||||
if (absolute || st)
|
||||
{
|
||||
remaining = sizeof(this->full) - (this->full_end - this->full);
|
||||
len = snprintf(this->full_end, remaining, "%s", entry->d_name);
|
||||
if (len < 0 || len >= remaining)
|
||||
{
|
||||
DBG1("buffer too small to enumerate file '%s'", entry->d_name);
|
||||
return FALSE;
|
||||
}
|
||||
if (absolute)
|
||||
{
|
||||
*absolute = this->full;
|
||||
}
|
||||
if (st)
|
||||
{
|
||||
if (stat(this->full, st))
|
||||
{
|
||||
DBG1("stat() on '%s' failed: %s", this->full, strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
enumerator_t* enumerator_create_directory(char *path)
|
||||
{
|
||||
size_t len;
|
||||
dir_enum_t *this = malloc_thing(dir_enum_t);
|
||||
this->public.enumerate = (void*)enumerate_dir_enum;
|
||||
this->public.destroy = (void*)destroy_dir_enum;
|
||||
|
||||
if (*path == '\0')
|
||||
{
|
||||
path = "./";
|
||||
}
|
||||
len = snprintf(this->full, sizeof(this->full)-1, "%s", path);
|
||||
if (len < 0 || len >= sizeof(this->full)-1)
|
||||
{
|
||||
DBG1("path string %s too long", path);
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
/* append a '/' if not already done */
|
||||
if (this->full[len-1] != '/')
|
||||
{
|
||||
this->full[len++] = '/';
|
||||
this->full[len] = '\0';
|
||||
}
|
||||
this->full_end = &this->full[len];
|
||||
|
||||
this->dir = opendir(path);
|
||||
if (this->dir == NULL)
|
||||
{
|
||||
DBG1("opening directory %s failed: %s", path, strerror(errno));
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/**
|
||||
* enumerator for nested enumerations
|
||||
*/
|
||||
typedef struct {
|
||||
/* implements enumerator_t */
|
||||
enumerator_t public;
|
||||
/* outer enumerator */
|
||||
enumerator_t *outer;
|
||||
/* inner enumerator */
|
||||
enumerator_t *inner;
|
||||
/* constructor for inner enumerator */
|
||||
enumerator_t *(*create_inner)(void *outer, void *data);
|
||||
/* data to pass to constructor above */
|
||||
void *data;
|
||||
/* destructor for data */
|
||||
void (*destroy_data)(void *data);
|
||||
} nested_enumerator_t;
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of enumerator_create_nested().enumerate()
|
||||
*/
|
||||
static bool enumerate_nested(nested_enumerator_t *this, void *v1, void *v2,
|
||||
void *v3, void *v4, void *v5)
|
||||
{
|
||||
while (TRUE)
|
||||
{
|
||||
while (this->inner == NULL)
|
||||
{
|
||||
void *outer;
|
||||
|
||||
if (!this->outer->enumerate(this->outer, &outer))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
this->inner = this->create_inner(outer, this->data);
|
||||
}
|
||||
if (this->inner->enumerate(this->inner, v1, v2, v3, v4, v5))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
this->inner->destroy(this->inner);
|
||||
this->inner = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of enumerator_create_nested().destroy()
|
||||
**/
|
||||
static void destroy_nested(nested_enumerator_t *this)
|
||||
{
|
||||
if (this->destroy_data)
|
||||
{
|
||||
this->destroy_data(this->data);
|
||||
}
|
||||
DESTROY_IF(this->inner);
|
||||
this->outer->destroy(this->outer);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
enumerator_t *enumerator_create_nested(enumerator_t *outer,
|
||||
enumerator_t *(inner_constructor)(void *outer, void *data),
|
||||
void *data, void (*destroy_data)(void *data))
|
||||
{
|
||||
nested_enumerator_t *enumerator = malloc_thing(nested_enumerator_t);
|
||||
|
||||
enumerator->public.enumerate = (void*)enumerate_nested;
|
||||
enumerator->public.destroy = (void*)destroy_nested;
|
||||
enumerator->outer = outer;
|
||||
enumerator->inner = NULL;
|
||||
enumerator->create_inner = (void*)inner_constructor;
|
||||
enumerator->data = data;
|
||||
enumerator->destroy_data = destroy_data;
|
||||
|
||||
return &enumerator->public;
|
||||
}
|
||||
|
||||
/**
|
||||
* enumerator for filtered enumerator
|
||||
*/
|
||||
typedef struct {
|
||||
enumerator_t public;
|
||||
enumerator_t *unfiltered;
|
||||
void *data;
|
||||
bool (*filter)(void *data, ...);
|
||||
void (*destructor)(void *data);
|
||||
} filter_enumerator_t;
|
||||
|
||||
/**
|
||||
* Implementation of enumerator_create_filter().destroy
|
||||
*/
|
||||
void destroy_filter(filter_enumerator_t *this)
|
||||
{
|
||||
if (this->destructor)
|
||||
{
|
||||
this->destructor(this->data);
|
||||
}
|
||||
this->unfiltered->destroy(this->unfiltered);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of enumerator_create_filter().enumerate
|
||||
*/
|
||||
bool enumerate_filter(filter_enumerator_t *this, void *o1, void *o2,
|
||||
void *o3, void *o4, void *o5)
|
||||
{
|
||||
void *i1, *i2, *i3, *i4, *i5;
|
||||
|
||||
while (this->unfiltered->enumerate(this->unfiltered, &i1, &i2, &i3, &i4, &i5))
|
||||
{
|
||||
if (this->filter(this->data, &i1, o1, &i2, o2, &i3, o3, &i4, o4, &i5, o5))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* see header
|
||||
*/
|
||||
enumerator_t *enumerator_create_filter(enumerator_t *unfiltered,
|
||||
bool (*filter)(void *data, ...),
|
||||
void *data, void (*destructor)(void *data))
|
||||
{
|
||||
filter_enumerator_t *this = malloc_thing(filter_enumerator_t);
|
||||
|
||||
this->public.enumerate = (void*)enumerate_filter;
|
||||
this->public.destroy = (void*)destroy_filter;
|
||||
this->unfiltered = unfiltered;
|
||||
this->filter = filter;
|
||||
this->data = data;
|
||||
this->destructor = destructor;
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/**
|
||||
* enumerator for cleaner enumerator
|
||||
*/
|
||||
typedef struct {
|
||||
enumerator_t public;
|
||||
enumerator_t *wrapped;
|
||||
void (*cleanup)(void *data);
|
||||
void *data;
|
||||
} cleaner_enumerator_t;
|
||||
|
||||
/**
|
||||
* Implementation of enumerator_create_cleanup().destroy
|
||||
*/
|
||||
static void destroy_cleaner(cleaner_enumerator_t *this)
|
||||
{
|
||||
this->cleanup(this->data);
|
||||
this->wrapped->destroy(this->wrapped);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of enumerator_create_cleaner().enumerate
|
||||
*/
|
||||
static bool enumerate_cleaner(cleaner_enumerator_t *this, void *v1, void *v2,
|
||||
void *v3, void *v4, void *v5)
|
||||
{
|
||||
return this->wrapped->enumerate(this->wrapped, v1, v2, v3, v4, v5);
|
||||
}
|
||||
|
||||
/**
|
||||
* see header
|
||||
*/
|
||||
enumerator_t *enumerator_create_cleaner(enumerator_t *wrapped,
|
||||
void (*cleanup)(void *data), void *data)
|
||||
{
|
||||
cleaner_enumerator_t *this = malloc_thing(cleaner_enumerator_t);
|
||||
|
||||
this->public.enumerate = (void*)enumerate_cleaner;
|
||||
this->public.destroy = (void*)destroy_cleaner;
|
||||
this->wrapped = wrapped;
|
||||
this->cleanup = cleanup;
|
||||
this->data = data;
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/**
|
||||
* enumerator for single enumerator
|
||||
*/
|
||||
typedef struct {
|
||||
enumerator_t public;
|
||||
void *item;
|
||||
void (*cleanup)(void *item);
|
||||
bool done;
|
||||
} single_enumerator_t;
|
||||
|
||||
/**
|
||||
* Implementation of enumerator_create_single().destroy
|
||||
*/
|
||||
static void destroy_single(single_enumerator_t *this)
|
||||
{
|
||||
if (this->cleanup)
|
||||
{
|
||||
this->cleanup(this->item);
|
||||
}
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of enumerator_create_single().enumerate
|
||||
*/
|
||||
static bool enumerate_single(single_enumerator_t *this, void **item)
|
||||
{
|
||||
if (this->done)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
*item = this->item;
|
||||
this->done = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* see header
|
||||
*/
|
||||
enumerator_t *enumerator_create_single(void *item, void (*cleanup)(void *item))
|
||||
{
|
||||
single_enumerator_t *this = malloc_thing(single_enumerator_t);
|
||||
|
||||
this->public.enumerate = (void*)enumerate_single;
|
||||
this->public.destroy = (void*)destroy_single;
|
||||
this->item = item;
|
||||
this->cleanup = cleanup;
|
||||
this->done = FALSE;
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user