aboutsummaryrefslogblamecommitdiff
path: root/flx/output.c
blob: 7898fc8baf38ce6c106d4d6877087f0dc51c70df (plain) (tree)




























































































































































                                                                                        
#include <string.h>
#include "utils.h"
#include "flx.h"
#include "output.h"
#include "source_type.h"
#include "flx_fcntl.h"

int   Sorted = (INPUT_SORTED|OUTPUT_SORTED); /* input/output sorted status */

t_file_desc   *free_file_desc(t_file_desc *desc) {
    if (!desc) return (NULL);
    if (desc->md5) FREE(desc->md5);
    if (desc->link) FREE(desc->link);
    FREE(desc);
    return (NULL);
}

t_file_desc   *fct_free_file_desc(void *data, t_file_desc *desc) {
    return (free_file_desc(desc));
}

/* this function free file tree and return 1 if the free is completed 
 * it doesn't free the element (base)
 */
int         ft_free(t_ft *tree, void *(*fct_free)(void *data, void *desc), void *data) {
    t_ft  *next;
    
    /* nothing have change, do not free */
    if (IS(Sorted, OUTPUT_SORTED) && !IS(Sorted, INPUT_SORTED)) return (0);

    /* remove description */
    if (IS(tree->status, FILLED)) {
	if (tree->desc && fct_free) tree->desc = fct_free(data, tree->desc);
	UNSET(tree->status, FILLED);
    }
    /* check for recursion */
    if (!IS(tree->status, CHANGED) || IS(tree->status, SORTING) || !tree->subtree) {
	UNSET(tree->status, CHANGED);
	return (1);
    }
    /* look for first soon */
    tree = tree->subtree->next;
    
    while (!IS(tree->status, BASE)) {
	
	/* pass unchanged elements */
	if (!IS(tree->status, CHANGED)) { tree = tree->next; continue ; }
	
	/* unset filled and remove data */
	if (IS(tree->status, FILLED)) {
	    if (tree->desc && fct_free) tree->desc = fct_free(data, tree->desc);
	    UNSET(tree->status, FILLED);
	}
	/* stop if necessary */
	if (IS(Sorted, OUTPUT_SORTED) && IS(tree->status, SORTING))
	    return (0);

	/* check if having to look at subtree */
	if (tree->subtree && !IS_PDOTF(tree)) {
	    if (ft_free(tree, fct_free, data)) {
		if (tree->subtree == tree->subtree->next)
		    POOL_FREE(t_file_tree, tree->subtree);
	    }
	    else return (0);
	}
	/* free filename memory */
	if (tree->filename) FREE(tree->filename);
	/* unchain and go to the next */
	next = tree->next;
	UNSET(tree->status, CHANGED);
	if (fct_free) {
	    LIST_UNCHAIN(tree);
	    POOL_FREE(t_file_tree, tree);
	}
	tree = next;
    }
    return (1);
}
    
int         output_write(t_db_output *out, void *data, int number) {
    t_device     *dst;
    void         *current;
    int          valid = 1;
    
    for (current = out->outputs; current ; current = SIMPLE_LIST_NEXT(current)) {
	dst = SIMPLE_LIST_PTR(current);
	if (dst->opened->write)
	    valid = dst->opened->write(dst->env, data, number) && valid;
    }
    return (valid);
}

int         output_add(t_db_output *out, char *desc, t_source_type *sourcestype) {
    char         tmp[BUFFER_LENGTH], *ptmp, *otmp = NULL;
    int          i;
    t_device     *new;
    
    strcpy(tmp, desc);
    if ((ptmp = backslashed_strchr(tmp, ':'))) {
	*ptmp++ = 0;

	/* look for options */
	if ((otmp = strchr(tmp, '+'))) *otmp++ = 0;
	
	/* find corresponding source */
	for (i = 0; sourcestype[i].name; i++)
	    if (!strcmp(tmp, sourcestype[i].name)) break;
	if (!sourcestype[i].name) {
	    /* not found, error */
	    error("can't find source type %s (%s:%s)", tmp, tmp, ptmp); 
	    return (0);
	}
    }
    else {
	error("no source type specified");
	return (0);
    }

    /* allocate memory for new device */
    new = MALLOC(sizeof(*new));
    new->opened = &sourcestype[i];
    if (new->opened->open) {
	if (!(new->env = new->opened->open(ptmp, otmp))) {
	    error("can't open '%s'", desc);
	    FREE(new);
	    return (0);
	}
	if (new->opened->fcntl)
	    Sorted |= (new->opened->fcntl(new->env, IS_SORTED) ? OUTPUT_SORTED : 0); 
    }
    else
	new->env = NULL;
    SIMPLE_LIST_PUSH(out->outputs, new);
    return (1);
}

t_db_output *output_alloc() {
    t_db_output *out;

    out = MALLOC(sizeof(*out));
    bzero(out, sizeof(*out));
    return (out);
}

t_db_output *output_free(t_db_output *old) {
    t_device   *dst;
    
    while (old->outputs) {
	dst = SIMPLE_LIST_POP(old->outputs);
	if (dst->opened->close)
	    dst->opened->close(dst->env);
	FREE(dst);
    }
    FREE(old);
    return (NULL);
}