]> git.ipfire.org Git - thirdparty/cups.git/blame - scheduler/filter.c
Move debug printfs to internal usage only.
[thirdparty/cups.git] / scheduler / filter.c
CommitLineData
ef416fc2 1/*
503b54c9 2 * File type conversion routines for CUPS.
ef416fc2 3 *
503b54c9
MS
4 * Copyright 2007-2011 by Apple Inc.
5 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
ef416fc2 6 *
e3101897 7 * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
ef416fc2 8 */
9
10/*
11 * Include necessary headers...
12 */
13
71e16022 14#include <cups/string-private.h>
ef416fc2 15#include "mime.h"
16
17
fb863569
MS
18/*
19 * Debug macros that used to be private API...
20 */
21
22#define DEBUG_puts(x)
23#define DEBUG_printf(...)
24
25
bd7854cb 26/*
27 * Local types...
28 */
29
30typedef struct _mime_typelist_s /**** List of source types ****/
31{
32 struct _mime_typelist_s *next; /* Next source type */
33 mime_type_t *src; /* Source type */
34} _mime_typelist_t;
35
36
ef416fc2 37/*
38 * Local functions...
39 */
40
22c9029b
MS
41static int mime_compare_filters(mime_filter_t *, mime_filter_t *);
42static int mime_compare_srcs(mime_filter_t *, mime_filter_t *);
43static cups_array_t *mime_find_filters(mime_t *mime, mime_type_t *src,
07ed0e9a
MS
44 size_t srcsize, mime_type_t *dst,
45 int *cost, _mime_typelist_t *visited);
ef416fc2 46
47
48/*
49 * 'mimeAddFilter()' - Add a filter to the current MIME database.
50 */
51
52mime_filter_t * /* O - New filter */
53mimeAddFilter(mime_t *mime, /* I - MIME database */
54 mime_type_t *src, /* I - Source type */
55 mime_type_t *dst, /* I - Destination type */
56 int cost, /* I - Relative time/resource cost */
57 const char *filter) /* I - Filter program to run */
58{
59 mime_filter_t *temp; /* New filter */
60
61
22c9029b
MS
62 DEBUG_printf(("mimeAddFilter(mime=%p, src=%p(%s/%s), dst=%p(%s/%s), cost=%d, "
63 "filter=\"%s\")", mime,
64 src, src ? src->super : "???", src ? src->type : "???",
65 dst, dst ? dst->super : "???", dst ? dst->type : "???",
66 cost, filter));
57b7b66b 67
ef416fc2 68 /*
69 * Range-check the input...
70 */
71
fa73b229 72 if (!mime || !src || !dst || !filter)
22c9029b
MS
73 {
74 DEBUG_puts("1mimeAddFilter: Returning NULL.");
ef416fc2 75 return (NULL);
22c9029b 76 }
ef416fc2 77
78 /*
79 * See if we already have an existing filter for the given source and
80 * destination...
81 */
82
f7deaa1a 83 if ((temp = mimeFilterLookup(mime, src, dst)) != NULL)
ef416fc2 84 {
85 /*
86 * Yup, does the existing filter have a higher cost? If so, copy the
87 * filter and cost to the existing filter entry and return it...
88 */
89
90 if (temp->cost > cost)
91 {
22c9029b
MS
92 DEBUG_printf(("1mimeAddFilter: Replacing filter \"%s\", cost %d.",
93 temp->filter, temp->cost));
ef416fc2 94 temp->cost = cost;
95 strlcpy(temp->filter, filter, sizeof(temp->filter));
96 }
97 }
98 else
99 {
100 /*
101 * Nope, add a new one...
102 */
103
fa73b229 104 if (!mime->filters)
22c9029b 105 mime->filters = cupsArrayNew((cups_array_func_t)mime_compare_filters, NULL);
ef416fc2 106
fa73b229 107 if (!mime->filters)
ef416fc2 108 return (NULL);
109
fa73b229 110 if ((temp = calloc(1, sizeof(mime_filter_t))) == NULL)
111 return (NULL);
ef416fc2 112
113 /*
114 * Copy the information over and sort if necessary...
115 */
116
117 temp->src = src;
118 temp->dst = dst;
119 temp->cost = cost;
120 strlcpy(temp->filter, filter, sizeof(temp->filter));
121
22c9029b 122 DEBUG_puts("1mimeAddFilter: Adding new filter.");
fa73b229 123 cupsArrayAdd(mime->filters, temp);
22c9029b 124 cupsArrayAdd(mime->srcs, temp);
ef416fc2 125 }
126
127 /*
128 * Return the new/updated filter...
129 */
130
22c9029b
MS
131 DEBUG_printf(("1mimeAddFilter: Returning %p.", temp));
132
ef416fc2 133 return (temp);
134}
135
136
137/*
138 * 'mimeFilter()' - Find the fastest way to convert from one type to another.
139 */
140
fa73b229 141cups_array_t * /* O - Array of filters to run */
ef416fc2 142mimeFilter(mime_t *mime, /* I - MIME database */
143 mime_type_t *src, /* I - Source file type */
144 mime_type_t *dst, /* I - Destination file type */
bd7854cb 145 int *cost) /* O - Cost of filters */
ef416fc2 146{
fa73b229 147 DEBUG_printf(("mimeFilter(mime=%p, src=%p(%s/%s), dst=%p(%s/%s), "
22c9029b
MS
148 "cost=%p(%d))", mime,
149 src, src ? src->super : "???", src ? src->type : "???",
150 dst, dst ? dst->super : "???", dst ? dst->type : "???",
bd7854cb 151 cost, cost ? *cost : 0));
152
07ed0e9a
MS
153 return (mimeFilter2(mime, src, 0, dst, cost));
154}
155
156
157/*
158 * 'mimeFilter2()' - Find the fastest way to convert from one type to another,
159 * including file size.
160 */
161
162cups_array_t * /* O - Array of filters to run */
163mimeFilter2(mime_t *mime, /* I - MIME database */
164 mime_type_t *src, /* I - Source file type */
165 size_t srcsize, /* I - Size of source file */
166 mime_type_t *dst, /* I - Destination file type */
167 int *cost) /* O - Cost of filters */
168{
22c9029b
MS
169 cups_array_t *filters; /* Array of filters to run */
170
171
07ed0e9a
MS
172 /*
173 * Range-check the input...
174 */
175
176 DEBUG_printf(("mimeFilter2(mime=%p, src=%p(%s/%s), srcsize=" CUPS_LLFMT
22c9029b
MS
177 ", dst=%p(%s/%s), cost=%p(%d))", mime,
178 src, src ? src->super : "???", src ? src->type : "???",
179 CUPS_LLCAST srcsize,
180 dst, dst ? dst->super : "???", dst ? dst->type : "???",
181 cost, cost ? *cost : 0));
ef416fc2 182
fa73b229 183 if (cost)
184 *cost = 0;
ef416fc2 185
bd7854cb 186 if (!mime || !src || !dst)
fa73b229 187 return (NULL);
ef416fc2 188
a74454a7 189 /*
190 * (Re)build the source lookup array as needed...
191 */
192
193 if (!mime->srcs)
194 {
195 mime_filter_t *current; /* Current filter */
196
22c9029b 197 mime->srcs = cupsArrayNew((cups_array_func_t)mime_compare_srcs, NULL);
a74454a7 198
199 for (current = mimeFirstFilter(mime);
200 current;
201 current = mimeNextFilter(mime))
202 cupsArrayAdd(mime->srcs, current);
203 }
204
bd7854cb 205 /*
206 * Find the filters...
207 */
208
22c9029b
MS
209 filters = mime_find_filters(mime, src, srcsize, dst, cost, NULL);
210
211 DEBUG_printf(("1mimeFilter2: Returning %d filter(s), cost %d:",
212 cupsArrayCount(filters), cost ? *cost : -1));
213#ifdef DEBUG
214 {
215 mime_filter_t *filter; /* Current filter */
216
217 for (filter = (mime_filter_t *)cupsArrayFirst(filters);
218 filter;
219 filter = (mime_filter_t *)cupsArrayNext(filters))
220 DEBUG_printf(("1mimeFilter2: %s/%s %s/%s %d %s", filter->src->super,
221 filter->src->type, filter->dst->super, filter->dst->type,
222 filter->cost, filter->filter));
223 }
224#endif /* DEBUG */
225
226 return (filters);
bd7854cb 227}
228
229
f7deaa1a 230/*
07ed0e9a 231 * 'mimeFilterLookup()' - Lookup a filter.
f7deaa1a 232 */
233
234mime_filter_t * /* O - Filter for src->dst */
235mimeFilterLookup(mime_t *mime, /* I - MIME database */
236 mime_type_t *src, /* I - Source type */
237 mime_type_t *dst) /* I - Destination type */
238{
22c9029b
MS
239 mime_filter_t key, /* Key record for filter search */
240 *filter; /* Matching filter */
241
f7deaa1a 242
22c9029b
MS
243 DEBUG_printf(("2mimeFilterLookup(mime=%p, src=%p(%s/%s), dst=%p(%s/%s))", mime,
244 src, src ? src->super : "???", src ? src->type : "???",
245 dst, dst ? dst->super : "???", dst ? dst->type : "???"));
f7deaa1a 246
247 key.src = src;
248 key.dst = dst;
249
22c9029b
MS
250 filter = (mime_filter_t *)cupsArrayFind(mime->filters, &key);
251 DEBUG_printf(("3mimeFilterLookup: Returning %p(%s).", filter,
252 filter ? filter->filter : "???"));
253 return (filter);
f7deaa1a 254}
255
256
bd7854cb 257/*
22c9029b 258 * 'mime_compare_filters()' - Compare two filters.
bd7854cb 259 */
260
261static int /* O - Comparison result */
22c9029b
MS
262mime_compare_filters(mime_filter_t *f0, /* I - First filter */
263 mime_filter_t *f1) /* I - Second filter */
bd7854cb 264{
265 int i; /* Result of comparison */
266
267
268 if ((i = strcmp(f0->src->super, f1->src->super)) == 0)
269 if ((i = strcmp(f0->src->type, f1->src->type)) == 0)
270 if ((i = strcmp(f0->dst->super, f1->dst->super)) == 0)
271 i = strcmp(f0->dst->type, f1->dst->type);
272
273 return (i);
274}
275
276
a74454a7 277/*
22c9029b 278 * 'mime_compare_srcs()' - Compare two filter source types.
a74454a7 279 */
280
281static int /* O - Comparison result */
22c9029b
MS
282mime_compare_srcs(mime_filter_t *f0, /* I - First filter */
283 mime_filter_t *f1) /* I - Second filter */
a74454a7 284{
285 int i; /* Result of comparison */
286
287
288 if ((i = strcmp(f0->src->super, f1->src->super)) == 0)
289 i = strcmp(f0->src->type, f1->src->type);
290
291 return (i);
292}
293
294
bd7854cb 295/*
22c9029b 296 * 'mime_find_filters()' - Find the filters to convert from one type to another.
bd7854cb 297 */
298
b423cd4c 299static cups_array_t * /* O - Array of filters to run */
22c9029b
MS
300mime_find_filters(
301 mime_t *mime, /* I - MIME database */
302 mime_type_t *src, /* I - Source file type */
303 size_t srcsize, /* I - Size of source file */
304 mime_type_t *dst, /* I - Destination file type */
305 int *cost, /* O - Cost of filters */
306 _mime_typelist_t *list) /* I - Source types we've used */
bd7854cb 307{
308 int tempcost, /* Temporary cost */
309 mincost; /* Current minimum */
310 cups_array_t *temp, /* Temporary filter */
311 *mintemp; /* Current minimum */
a74454a7 312 mime_filter_t *current, /* Current filter */
313 srckey; /* Source type key */
bd7854cb 314 _mime_typelist_t listnode, /* New list node */
315 *listptr; /* Pointer in list */
316
317
22c9029b 318 DEBUG_printf(("2mime_find_filters(mime=%p, src=%p(%s/%s), srcsize=" CUPS_LLFMT
07ed0e9a
MS
319 ", dst=%p(%s/%s), cost=%p, list=%p)", mime, src, src->super,
320 src->type, CUPS_LLCAST srcsize, dst, dst->super, dst->type,
321 cost, list));
bd7854cb 322
ef416fc2 323 /*
324 * See if there is a filter that can convert the files directly...
325 */
326
07ed0e9a
MS
327 if ((current = mimeFilterLookup(mime, src, dst)) != NULL &&
328 (current->maxsize == 0 || srcsize <= current->maxsize))
ef416fc2 329 {
330 /*
331 * Got a direct filter!
332 */
333
22c9029b 334 DEBUG_puts("3mime_find_filters: Direct filter found.");
bd7854cb 335
fa73b229 336 if ((mintemp = cupsArrayNew(NULL, NULL)) == NULL)
22c9029b
MS
337 {
338 DEBUG_puts("3mime_find_filters: Returning NULL (out of memory).");
ef416fc2 339 return (NULL);
22c9029b 340 }
ef416fc2 341
fa73b229 342 cupsArrayAdd(mintemp, current);
343
344 mincost = current->cost;
ef416fc2 345
a74454a7 346 if (!cost)
22c9029b
MS
347 {
348 DEBUG_printf(("3mime_find_filters: Returning 1 filter, cost %d:",
349 mincost));
350 DEBUG_printf(("3mime_find_filters: %s/%s %s/%s %d %s",
351 current->src->super, current->src->type,
352 current->dst->super, current->dst->type,
353 current->cost, current->filter));
a74454a7 354 return (mintemp);
22c9029b 355 }
ef416fc2 356 }
357 else
358 {
359 /*
360 * No direct filter...
361 */
362
fa73b229 363 mintemp = NULL;
364 mincost = 9999999;
ef416fc2 365 }
366
bd7854cb 367 /*
368 * Initialize this node in the type list...
369 */
370
371 listnode.next = list;
372
ef416fc2 373 /*
374 * OK, now look for filters from the source type to any other type...
375 */
376
a74454a7 377 srckey.src = src;
bd7854cb 378
a74454a7 379 for (current = (mime_filter_t *)cupsArrayFind(mime->srcs, &srckey);
380 current && current->src == src;
381 current = (mime_filter_t *)cupsArrayNext(mime->srcs))
382 {
383 /*
384 * See if we have already tried the destination type as a source
385 * type (this avoids extra filter looping...)
386 */
bd7854cb 387
a74454a7 388 mime_type_t *current_dst; /* Current destination type */
bd7854cb 389
07ed0e9a
MS
390 if (current->maxsize > 0 && srcsize > current->maxsize)
391 continue;
ef416fc2 392
a74454a7 393 for (listptr = list, current_dst = current->dst;
394 listptr;
395 listptr = listptr->next)
396 if (current_dst == listptr->src)
397 break;
398
399 if (listptr)
400 continue;
bd7854cb 401
a74454a7 402 /*
403 * See if we have any filters that can convert from the destination type
404 * of this filter to the final type...
405 */
406
407 listnode.src = current->src;
fa73b229 408
a74454a7 409 cupsArraySave(mime->srcs);
22c9029b
MS
410 temp = mime_find_filters(mime, current->dst, srcsize, dst, &tempcost,
411 &listnode);
a74454a7 412 cupsArrayRestore(mime->srcs);
413
414 if (!temp)
415 continue;
416
417 if (!cost)
22c9029b
MS
418 {
419 DEBUG_printf(("3mime_find_filters: Returning %d filter(s), cost %d:",
420 cupsArrayCount(temp), tempcost));
421
422#ifdef DEBUG
423 for (current = (mime_filter_t *)cupsArrayFirst(temp);
424 current;
425 current = (mime_filter_t *)cupsArrayNext(temp))
426 DEBUG_printf(("3mime_find_filters: %s/%s %s/%s %d %s",
427 current->src->super, current->src->type,
428 current->dst->super, current->dst->type,
429 current->cost, current->filter));
430#endif /* DEBUG */
431
a74454a7 432 return (temp);
22c9029b 433 }
a74454a7 434
435 /*
436 * Found a match; see if this one is less costly than the last (if
437 * any...)
438 */
439
ed486911 440 tempcost += current->cost;
441
a74454a7 442 if (tempcost < mincost)
443 {
444 cupsArrayDelete(mintemp);
ef416fc2 445
446 /*
a74454a7 447 * Hey, we got a match! Add the current filter to the beginning of the
448 * filter list...
ef416fc2 449 */
450
a74454a7 451 mintemp = temp;
ed486911 452 mincost = tempcost;
a74454a7 453 cupsArrayInsert(mintemp, current);
ef416fc2 454 }
a74454a7 455 else
456 cupsArrayDelete(temp);
457 }
ef416fc2 458
fa73b229 459 if (mintemp)
ef416fc2 460 {
461 /*
462 * Hey, we got a match!
463 */
464
22c9029b
MS
465 DEBUG_printf(("3mime_find_filters: Returning %d filter(s), cost %d:",
466 cupsArrayCount(mintemp), mincost));
ae71f5de 467
22c9029b 468#ifdef DEBUG
fa73b229 469 for (current = (mime_filter_t *)cupsArrayFirst(mintemp);
470 current;
471 current = (mime_filter_t *)cupsArrayNext(mintemp))
22c9029b
MS
472 DEBUG_printf(("3mime_find_filters: %s/%s %s/%s %d %s",
473 current->src->super, current->src->type,
474 current->dst->super, current->dst->type,
475 current->cost, current->filter));
ef416fc2 476#endif /* DEBUG */
477
bd7854cb 478 if (cost)
479 *cost = mincost;
fa73b229 480
ef416fc2 481 return (mintemp);
482 }
483
22c9029b 484 DEBUG_puts("3mime_find_filters: Returning NULL (no matches).");
ef416fc2 485
486 return (NULL);
487}