2 * "$Id: filter.c 6252 2007-02-10 15:34:18Z mike $"
4 * File type conversion routines for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
26 * mimeAddFilter() - Add a filter to the current MIME database.
27 * mimeFilter() - Find the fastest way to convert from one type to
29 * mimeFilterLookup() - Lookup a filter...
30 * compare_filters() - Compare two filters...
31 * find_filters() - Find the filters to convert from one type to another.
35 * Include necessary headers...
42 #include <cups/debug.h>
43 #include <cups/string.h>
51 typedef struct _mime_typelist_s
/**** List of source types ****/
53 struct _mime_typelist_s
*next
; /* Next source type */
54 mime_type_t
*src
; /* Source type */
62 static int compare_filters(mime_filter_t
*, mime_filter_t
*);
63 static int compare_srcs(mime_filter_t
*, mime_filter_t
*);
64 static cups_array_t
*find_filters(mime_t
*mime
, mime_type_t
*src
,
65 mime_type_t
*dst
, int *cost
,
66 _mime_typelist_t
*visited
);
70 * 'mimeAddFilter()' - Add a filter to the current MIME database.
73 mime_filter_t
* /* O - New filter */
74 mimeAddFilter(mime_t
*mime
, /* I - MIME database */
75 mime_type_t
*src
, /* I - Source type */
76 mime_type_t
*dst
, /* I - Destination type */
77 int cost
, /* I - Relative time/resource cost */
78 const char *filter
) /* I - Filter program to run */
80 mime_filter_t
*temp
; /* New filter */
84 * Range-check the input...
87 if (!mime
|| !src
|| !dst
|| !filter
)
91 * See if we already have an existing filter for the given source and
95 if ((temp
= mimeFilterLookup(mime
, src
, dst
)) != NULL
)
98 * Yup, does the existing filter have a higher cost? If so, copy the
99 * filter and cost to the existing filter entry and return it...
102 if (temp
->cost
> cost
)
105 strlcpy(temp
->filter
, filter
, sizeof(temp
->filter
));
111 * Nope, add a new one...
115 mime
->filters
= cupsArrayNew((cups_array_func_t
)compare_filters
, NULL
);
120 if ((temp
= calloc(1, sizeof(mime_filter_t
))) == NULL
)
124 * Copy the information over and sort if necessary...
130 strlcpy(temp
->filter
, filter
, sizeof(temp
->filter
));
132 cupsArrayAdd(mime
->filters
, temp
);
136 * Return the new/updated filter...
144 * 'mimeFilter()' - Find the fastest way to convert from one type to another.
147 cups_array_t
* /* O - Array of filters to run */
148 mimeFilter(mime_t
*mime
, /* I - MIME database */
149 mime_type_t
*src
, /* I - Source file type */
150 mime_type_t
*dst
, /* I - Destination file type */
151 int *cost
) /* O - Cost of filters */
154 * Range-check the input...
157 DEBUG_printf(("mimeFilter(mime=%p, src=%p(%s/%s), dst=%p(%s/%s), "
159 mime
, src
, src
? src
->super
: "?", src
? src
->type
: "?",
160 dst
, dst
? dst
->super
: "?", dst
? dst
->type
: "?",
161 cost
, cost
? *cost
: 0));
167 if (!mime
|| !src
|| !dst
)
171 * (Re)build the source lookup array as needed...
176 mime_filter_t
*current
; /* Current filter */
179 mime
->srcs
= cupsArrayNew((cups_array_func_t
)compare_srcs
, NULL
);
181 for (current
= mimeFirstFilter(mime
);
183 current
= mimeNextFilter(mime
))
184 cupsArrayAdd(mime
->srcs
, current
);
188 * Find the filters...
191 return (find_filters(mime
, src
, dst
, cost
, NULL
));
196 * 'mimeFilterLookup()' - Lookup a filter...
199 mime_filter_t
* /* O - Filter for src->dst */
200 mimeFilterLookup(mime_t
*mime
, /* I - MIME database */
201 mime_type_t
*src
, /* I - Source type */
202 mime_type_t
*dst
) /* I - Destination type */
204 mime_filter_t key
; /* Key record for filter search */
210 return ((mime_filter_t
*)cupsArrayFind(mime
->filters
, &key
));
215 * 'compare_filters()' - Compare two filters...
218 static int /* O - Comparison result */
219 compare_filters(mime_filter_t
*f0
, /* I - First filter */
220 mime_filter_t
*f1
) /* I - Second filter */
222 int i
; /* Result of comparison */
225 if ((i
= strcmp(f0
->src
->super
, f1
->src
->super
)) == 0)
226 if ((i
= strcmp(f0
->src
->type
, f1
->src
->type
)) == 0)
227 if ((i
= strcmp(f0
->dst
->super
, f1
->dst
->super
)) == 0)
228 i
= strcmp(f0
->dst
->type
, f1
->dst
->type
);
235 * 'compare_srcs()' - Compare two srcs...
238 static int /* O - Comparison result */
239 compare_srcs(mime_filter_t
*f0
, /* I - First filter */
240 mime_filter_t
*f1
) /* I - Second filter */
242 int i
; /* Result of comparison */
245 if ((i
= strcmp(f0
->src
->super
, f1
->src
->super
)) == 0)
246 i
= strcmp(f0
->src
->type
, f1
->src
->type
);
253 * 'find_filters()' - Find the filters to convert from one type to another.
256 static cups_array_t
* /* O - Array of filters to run */
257 find_filters(mime_t
*mime
, /* I - MIME database */
258 mime_type_t
*src
, /* I - Source file type */
259 mime_type_t
*dst
, /* I - Destination file type */
260 int *cost
, /* O - Cost of filters */
261 _mime_typelist_t
*list
) /* I - Source types we've used */
263 int tempcost
, /* Temporary cost */
264 mincost
; /* Current minimum */
265 cups_array_t
*temp
, /* Temporary filter */
266 *mintemp
; /* Current minimum */
267 mime_filter_t
*current
, /* Current filter */
268 srckey
; /* Source type key */
269 _mime_typelist_t listnode
, /* New list node */
270 *listptr
; /* Pointer in list */
273 DEBUG_printf(("find_filters(mime=%p, src=%p(%s/%s), dst=%p(%s/%s), "
274 "cost=%p, list=%p)\n", mime
, src
, src
->super
, src
->type
,
275 dst
, dst
->super
, dst
->type
, cost
, list
));
278 * See if there is a filter that can convert the files directly...
281 if ((current
= mimeFilterLookup(mime
, src
, dst
)) != NULL
)
284 * Got a direct filter!
287 DEBUG_puts("Direct filter found!");
289 if ((mintemp
= cupsArrayNew(NULL
, NULL
)) == NULL
)
292 cupsArrayAdd(mintemp
, current
);
294 mincost
= current
->cost
;
299 DEBUG_puts(" Found direct filter:");
300 DEBUG_printf((" %s (cost=%d)\n", current
->filter
, mincost
));
305 * No direct filter...
313 * Initialize this node in the type list...
316 listnode
.next
= list
;
319 * OK, now look for filters from the source type to any other type...
324 for (current
= (mime_filter_t
*)cupsArrayFind(mime
->srcs
, &srckey
);
325 current
&& current
->src
== src
;
326 current
= (mime_filter_t
*)cupsArrayNext(mime
->srcs
))
329 * See if we have already tried the destination type as a source
330 * type (this avoids extra filter looping...)
333 mime_type_t
*current_dst
; /* Current destination type */
336 for (listptr
= list
, current_dst
= current
->dst
;
338 listptr
= listptr
->next
)
339 if (current_dst
== listptr
->src
)
346 * See if we have any filters that can convert from the destination type
347 * of this filter to the final type...
350 listnode
.src
= current
->src
;
352 cupsArraySave(mime
->srcs
);
353 temp
= find_filters(mime
, current
->dst
, dst
, &tempcost
, &listnode
);
354 cupsArrayRestore(mime
->srcs
);
363 * Found a match; see if this one is less costly than the last (if
367 tempcost
+= current
->cost
;
369 if (tempcost
< mincost
)
371 cupsArrayDelete(mintemp
);
374 * Hey, we got a match! Add the current filter to the beginning of the
380 cupsArrayInsert(mintemp
, current
);
383 cupsArrayDelete(temp
);
389 * Hey, we got a match!
393 printf(" Returning %d filters:\n", cupsArrayCount(mintemp
));
394 for (current
= (mime_filter_t
*)cupsArrayFirst(mintemp
);
396 current
= (mime_filter_t
*)cupsArrayNext(mintemp
))
397 printf(" %s\n", current
->filter
);
406 DEBUG_puts(" Returning zippo...");
413 * End of "$Id: filter.c 6252 2007-02-10 15:34:18Z mike $".