#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <cups/debug.h>
#include <cups/string.h>
#include "mime.h"
typedef struct _mime_typelist_s
{
struct _mime_typelist_s *next;
mime_type_t *src;
} _mime_typelist_t;
static int compare_filters(mime_filter_t *, mime_filter_t *);
static int compare_srcs(mime_filter_t *, mime_filter_t *);
static cups_array_t *find_filters(mime_t *mime, mime_type_t *src,
mime_type_t *dst, int *cost,
_mime_typelist_t *visited);
mime_filter_t *
mimeAddFilter(mime_t *mime,
mime_type_t *src,
mime_type_t *dst,
int cost,
const char *filter)
{
mime_filter_t *temp;
if (!mime || !src || !dst || !filter)
return (NULL);
if ((temp = mimeFilterLookup(mime, src, dst)) != NULL)
{
if (temp->cost > cost)
{
temp->cost = cost;
strlcpy(temp->filter, filter, sizeof(temp->filter));
}
}
else
{
if (!mime->filters)
mime->filters = cupsArrayNew((cups_array_func_t)compare_filters, NULL);
if (!mime->filters)
return (NULL);
if ((temp = calloc(1, sizeof(mime_filter_t))) == NULL)
return (NULL);
temp->src = src;
temp->dst = dst;
temp->cost = cost;
strlcpy(temp->filter, filter, sizeof(temp->filter));
cupsArrayAdd(mime->filters, temp);
}
return (temp);
}
cups_array_t *
mimeFilter(mime_t *mime,
mime_type_t *src,
mime_type_t *dst,
int *cost)
{
DEBUG_printf(("mimeFilter(mime=%p, src=%p(%s/%s), dst=%p(%s/%s), "
"cost=%p(%d))\n",
mime, src, src ? src->super : "?", src ? src->type : "?",
dst, dst ? dst->super : "?", dst ? dst->type : "?",
cost, cost ? *cost : 0));
if (cost)
*cost = 0;
if (!mime || !src || !dst)
return (NULL);
if (!mime->srcs)
{
mime_filter_t *current;
mime->srcs = cupsArrayNew((cups_array_func_t)compare_srcs, NULL);
for (current = mimeFirstFilter(mime);
current;
current = mimeNextFilter(mime))
cupsArrayAdd(mime->srcs, current);
}
return (find_filters(mime, src, dst, cost, NULL));
}
mime_filter_t *
mimeFilterLookup(mime_t *mime,
mime_type_t *src,
mime_type_t *dst)
{
mime_filter_t key;
key.src = src;
key.dst = dst;
return ((mime_filter_t *)cupsArrayFind(mime->filters, &key));
}
static int
compare_filters(mime_filter_t *f0,
mime_filter_t *f1)
{
int i;
if ((i = strcmp(f0->src->super, f1->src->super)) == 0)
if ((i = strcmp(f0->src->type, f1->src->type)) == 0)
if ((i = strcmp(f0->dst->super, f1->dst->super)) == 0)
i = strcmp(f0->dst->type, f1->dst->type);
return (i);
}
static int
compare_srcs(mime_filter_t *f0,
mime_filter_t *f1)
{
int i;
if ((i = strcmp(f0->src->super, f1->src->super)) == 0)
i = strcmp(f0->src->type, f1->src->type);
return (i);
}
static cups_array_t *
find_filters(mime_t *mime,
mime_type_t *src,
mime_type_t *dst,
int *cost,
_mime_typelist_t *list)
{
int tempcost,
mincost;
cups_array_t *temp,
*mintemp;
mime_filter_t *current,
srckey;
_mime_typelist_t listnode,
*listptr;
DEBUG_printf(("find_filters(mime=%p, src=%p(%s/%s), dst=%p(%s/%s), "
"cost=%p, list=%p)\n", mime, src, src->super, src->type,
dst, dst->super, dst->type, cost, list));
if ((current = mimeFilterLookup(mime, src, dst)) != NULL)
{
DEBUG_puts("find_filters: Direct filter found!");
if ((mintemp = cupsArrayNew(NULL, NULL)) == NULL)
return (NULL);
cupsArrayAdd(mintemp, current);
mincost = current->cost;
if (!cost)
return (mintemp);
DEBUG_puts("find_filters: Found direct filter:");
DEBUG_printf(("find_filters: %s (cost=%d)\n", current->filter, mincost));
}
else
{
mintemp = NULL;
mincost = 9999999;
}
listnode.next = list;
srckey.src = src;
for (current = (mime_filter_t *)cupsArrayFind(mime->srcs, &srckey);
current && current->src == src;
current = (mime_filter_t *)cupsArrayNext(mime->srcs))
{
mime_type_t *current_dst;
for (listptr = list, current_dst = current->dst;
listptr;
listptr = listptr->next)
if (current_dst == listptr->src)
break;
if (listptr)
continue;
listnode.src = current->src;
cupsArraySave(mime->srcs);
temp = find_filters(mime, current->dst, dst, &tempcost, &listnode);
cupsArrayRestore(mime->srcs);
if (!temp)
continue;
if (!cost)
return (temp);
tempcost += current->cost;
if (tempcost < mincost)
{
cupsArrayDelete(mintemp);
mintemp = temp;
mincost = tempcost;
cupsArrayInsert(mintemp, current);
}
else
cupsArrayDelete(temp);
}
if (mintemp)
{
#ifdef DEBUG
DEBUG_printf(("find_filters: Returning %d filters:\n",
cupsArrayCount(mintemp)));
for (current = (mime_filter_t *)cupsArrayFirst(mintemp);
current;
current = (mime_filter_t *)cupsArrayNext(mintemp))
DEBUG_printf(("find_filters: %s\n", current->filter));
#endif
if (cost)
*cost = mincost;
return (mintemp);
}
DEBUG_puts("find_filters: Returning zippo...");
return (NULL);
}