#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <cups/debug.h>
#include <cups/string.h>
#include "mime.h"
static int compare(mime_filter_t *, mime_filter_t *);
static mime_filter_t *lookup(mime_t *, mime_type_t *, mime_type_t *);
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 == NULL || src == NULL || dst == NULL || filter == NULL)
return (NULL);
if (strlen(filter) > (MIME_MAX_FILTER - 1))
return (NULL);
if ((temp = lookup(mime, src, dst)) != NULL)
{
if (temp->cost > cost)
{
temp->cost = cost;
strlcpy(temp->filter, filter, sizeof(temp->filter));
}
}
else
{
if (mime->num_filters == 0)
temp = malloc(sizeof(mime_filter_t));
else
temp = realloc(mime->filters, sizeof(mime_filter_t) * (mime->num_filters + 1));
if (temp == NULL)
return (NULL);
mime->filters = temp;
temp += mime->num_filters;
mime->num_filters ++;
temp->src = src;
temp->dst = dst;
temp->cost = cost;
strlcpy(temp->filter, filter, sizeof(temp->filter));
if (mime->num_filters > 1)
qsort(mime->filters, mime->num_filters, sizeof(mime_filter_t),
(int (*)(const void *, const void *))compare);
}
return (temp);
}
mime_filter_t *
mimeFilter(mime_t *mime,
mime_type_t *src,
mime_type_t *dst,
int *num_filters,
int max_depth)
{
int i, j,
num_temp,
num_mintemp,
cost,
mincost;
mime_filter_t *temp,
*mintemp,
*current;
DEBUG_printf(("mimeFilter(mime=%p, src=%p(%s/%s), dst=%p(%s/%s), num_filters=%p(%d))\n",
mime, src, src ? src->super : "?", src ? src->type : "?",
dst, dst ? dst->super : "?", dst ? dst->type : "?",
num_filters, num_filters ? *num_filters : 0));
if (mime == NULL || src == NULL || dst == NULL || num_filters == NULL ||
max_depth <= 0)
return (NULL);
*num_filters = 0;
if ((temp = lookup(mime, src, dst)) != NULL)
{
if ((mintemp = (mime_filter_t *)malloc(sizeof(mime_filter_t))) == NULL)
return (NULL);
memcpy(mintemp, temp, sizeof(mime_filter_t));
num_mintemp = 1;
mincost = mintemp->cost;
DEBUG_puts(" Found direct filter:");
DEBUG_printf((" %s (cost=%d)\n", mintemp->filter, mincost));
}
else
{
mincost = 9999999;
mintemp = NULL;
num_mintemp = 0;
}
for (i = mime->num_filters, current = mime->filters;
i > 0;
i --, current ++)
if (current->src == src)
{
if ((temp = mimeFilter(mime, current->dst, dst, &num_temp,
max_depth - 1)) == NULL)
continue;
for (j = 0, cost = 0; j < num_temp; j ++)
cost += temp[j].cost;
if (cost < mincost)
{
if (mintemp != NULL)
free(mintemp);
mintemp = (mime_filter_t *)realloc(temp, sizeof(mime_filter_t) *
(num_temp + 1));
if (mintemp == NULL)
{
*num_filters = 0;
return (NULL);
}
memmove(mintemp + 1, mintemp, num_temp * sizeof(mime_filter_t));
memcpy(mintemp, current, sizeof(mime_filter_t));
num_mintemp = num_temp + 1;
mincost = cost;
}
else
free(temp);
}
if (mintemp != NULL)
{
*num_filters = num_mintemp;
#ifdef DEBUG
printf(" Returning %d filters:\n", *num_filters);
for (i = 0; i < num_mintemp; i ++)
printf(" %s\n", mintemp[i].filter);
#endif
return (mintemp);
}
DEBUG_puts(" Returning zippo...");
return (NULL);
}
static int
compare(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 mime_filter_t *
lookup(mime_t *mime,
mime_type_t *src,
mime_type_t *dst)
{
mime_filter_t key;
if (mime->num_filters == 0)
return (NULL);
key.src = src;
key.dst = dst;
return ((mime_filter_t *)bsearch(&key, mime->filters, mime->num_filters,
sizeof(mime_filter_t),
(int (*)(const void *, const void *))compare));
}