diff options
Diffstat (limited to 'flx/output.c')
-rw-r--r-- | flx/output.c | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/flx/output.c b/flx/output.c new file mode 100644 index 0000000..7898fc8 --- /dev/null +++ b/flx/output.c @@ -0,0 +1,157 @@ +#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); +} + |