]> git.ipfire.org Git - thirdparty/cups.git/blame - scheduler/filter.c
Load cups into easysw/current.
[thirdparty/cups.git] / scheduler / filter.c
CommitLineData
ef416fc2 1/*
f7deaa1a 2 * "$Id: filter.c 6252 2007-02-10 15:34:18Z mike $"
ef416fc2 3 *
4 * File type conversion routines for the Common UNIX Printing System (CUPS).
5 *
f7deaa1a 6 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
ef416fc2 7 *
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
13 * at:
14 *
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
19 *
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * Contents:
25 *
f7deaa1a 26 * mimeAddFilter() - Add a filter to the current MIME database.
27 * mimeFilter() - Find the fastest way to convert from one type to
28 * another.
29 * mimeFilterLookup() - Lookup a filter...
30 * compare_filters() - Compare two filters...
31 * find_filters() - Find the filters to convert from one type to another.
ef416fc2 32 */
33
34/*
35 * Include necessary headers...
36 */
37
38#include <stdio.h>
39#include <stdlib.h>
40#include <ctype.h>
41
42#include <cups/debug.h>
43#include <cups/string.h>
44#include "mime.h"
45
46
bd7854cb 47/*
48 * Local types...
49 */
50
51typedef struct _mime_typelist_s /**** List of source types ****/
52{
53 struct _mime_typelist_s *next; /* Next source type */
54 mime_type_t *src; /* Source type */
55} _mime_typelist_t;
56
57
ef416fc2 58/*
59 * Local functions...
60 */
61
fa73b229 62static int compare_filters(mime_filter_t *, mime_filter_t *);
a74454a7 63static int compare_srcs(mime_filter_t *, mime_filter_t *);
bd7854cb 64static cups_array_t *find_filters(mime_t *mime, mime_type_t *src,
65 mime_type_t *dst, int *cost,
66 _mime_typelist_t *visited);
ef416fc2 67
68
69/*
70 * 'mimeAddFilter()' - Add a filter to the current MIME database.
71 */
72
73mime_filter_t * /* O - New filter */
74mimeAddFilter(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 */
79{
80 mime_filter_t *temp; /* New filter */
81
82
83 /*
84 * Range-check the input...
85 */
86
fa73b229 87 if (!mime || !src || !dst || !filter)
ef416fc2 88 return (NULL);
89
90 /*
91 * See if we already have an existing filter for the given source and
92 * destination...
93 */
94
f7deaa1a 95 if ((temp = mimeFilterLookup(mime, src, dst)) != NULL)
ef416fc2 96 {
97 /*
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...
100 */
101
102 if (temp->cost > cost)
103 {
104 temp->cost = cost;
105 strlcpy(temp->filter, filter, sizeof(temp->filter));
106 }
107 }
108 else
109 {
110 /*
111 * Nope, add a new one...
112 */
113
fa73b229 114 if (!mime->filters)
115 mime->filters = cupsArrayNew((cups_array_func_t)compare_filters, NULL);
ef416fc2 116
fa73b229 117 if (!mime->filters)
ef416fc2 118 return (NULL);
119
fa73b229 120 if ((temp = calloc(1, sizeof(mime_filter_t))) == NULL)
121 return (NULL);
ef416fc2 122
123 /*
124 * Copy the information over and sort if necessary...
125 */
126
127 temp->src = src;
128 temp->dst = dst;
129 temp->cost = cost;
130 strlcpy(temp->filter, filter, sizeof(temp->filter));
131
fa73b229 132 cupsArrayAdd(mime->filters, temp);
ef416fc2 133 }
134
135 /*
136 * Return the new/updated filter...
137 */
138
139 return (temp);
140}
141
142
143/*
144 * 'mimeFilter()' - Find the fastest way to convert from one type to another.
145 */
146
fa73b229 147cups_array_t * /* O - Array of filters to run */
ef416fc2 148mimeFilter(mime_t *mime, /* I - MIME database */
149 mime_type_t *src, /* I - Source file type */
150 mime_type_t *dst, /* I - Destination file type */
bd7854cb 151 int *cost) /* O - Cost of filters */
ef416fc2 152{
ef416fc2 153 /*
154 * Range-check the input...
155 */
156
fa73b229 157 DEBUG_printf(("mimeFilter(mime=%p, src=%p(%s/%s), dst=%p(%s/%s), "
bd7854cb 158 "cost=%p(%d))\n",
ef416fc2 159 mime, src, src ? src->super : "?", src ? src->type : "?",
160 dst, dst ? dst->super : "?", dst ? dst->type : "?",
bd7854cb 161 cost, cost ? *cost : 0));
162
ef416fc2 163
fa73b229 164 if (cost)
165 *cost = 0;
ef416fc2 166
bd7854cb 167 if (!mime || !src || !dst)
fa73b229 168 return (NULL);
ef416fc2 169
a74454a7 170 /*
171 * (Re)build the source lookup array as needed...
172 */
173
174 if (!mime->srcs)
175 {
176 mime_filter_t *current; /* Current filter */
177
178
179 mime->srcs = cupsArrayNew((cups_array_func_t)compare_srcs, NULL);
180
181 for (current = mimeFirstFilter(mime);
182 current;
183 current = mimeNextFilter(mime))
184 cupsArrayAdd(mime->srcs, current);
185 }
186
bd7854cb 187 /*
188 * Find the filters...
189 */
190
191 return (find_filters(mime, src, dst, cost, NULL));
192}
193
194
f7deaa1a 195/*
196 * 'mimeFilterLookup()' - Lookup a filter...
197 */
198
199mime_filter_t * /* O - Filter for src->dst */
200mimeFilterLookup(mime_t *mime, /* I - MIME database */
201 mime_type_t *src, /* I - Source type */
202 mime_type_t *dst) /* I - Destination type */
203{
204 mime_filter_t key; /* Key record for filter search */
205
206
207 key.src = src;
208 key.dst = dst;
209
210 return ((mime_filter_t *)cupsArrayFind(mime->filters, &key));
211}
212
213
bd7854cb 214/*
215 * 'compare_filters()' - Compare two filters...
216 */
217
218static int /* O - Comparison result */
219compare_filters(mime_filter_t *f0, /* I - First filter */
220 mime_filter_t *f1) /* I - Second filter */
221{
222 int i; /* Result of comparison */
223
224
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);
229
230 return (i);
231}
232
233
a74454a7 234/*
235 * 'compare_srcs()' - Compare two srcs...
236 */
237
238static int /* O - Comparison result */
239compare_srcs(mime_filter_t *f0, /* I - First filter */
240 mime_filter_t *f1) /* I - Second filter */
241{
242 int i; /* Result of comparison */
243
244
245 if ((i = strcmp(f0->src->super, f1->src->super)) == 0)
246 i = strcmp(f0->src->type, f1->src->type);
247
248 return (i);
249}
250
251
bd7854cb 252/*
253 * 'find_filters()' - Find the filters to convert from one type to another.
254 */
255
b423cd4c 256static cups_array_t * /* O - Array of filters to run */
bd7854cb 257find_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 */
262{
263 int tempcost, /* Temporary cost */
264 mincost; /* Current minimum */
265 cups_array_t *temp, /* Temporary filter */
266 *mintemp; /* Current minimum */
a74454a7 267 mime_filter_t *current, /* Current filter */
268 srckey; /* Source type key */
bd7854cb 269 _mime_typelist_t listnode, /* New list node */
270 *listptr; /* Pointer in list */
271
272
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));
276
ef416fc2 277 /*
278 * See if there is a filter that can convert the files directly...
279 */
280
f7deaa1a 281 if ((current = mimeFilterLookup(mime, src, dst)) != NULL)
ef416fc2 282 {
283 /*
284 * Got a direct filter!
285 */
286
bd7854cb 287 DEBUG_puts("Direct filter found!");
288
fa73b229 289 if ((mintemp = cupsArrayNew(NULL, NULL)) == NULL)
ef416fc2 290 return (NULL);
291
fa73b229 292 cupsArrayAdd(mintemp, current);
293
294 mincost = current->cost;
ef416fc2 295
a74454a7 296 if (!cost)
297 return (mintemp);
298
ef416fc2 299 DEBUG_puts(" Found direct filter:");
bd7854cb 300 DEBUG_printf((" %s (cost=%d)\n", current->filter, mincost));
ef416fc2 301 }
302 else
303 {
304 /*
305 * No direct filter...
306 */
307
fa73b229 308 mintemp = NULL;
309 mincost = 9999999;
ef416fc2 310 }
311
bd7854cb 312 /*
313 * Initialize this node in the type list...
314 */
315
316 listnode.next = list;
317
ef416fc2 318 /*
319 * OK, now look for filters from the source type to any other type...
320 */
321
a74454a7 322 srckey.src = src;
bd7854cb 323
a74454a7 324 for (current = (mime_filter_t *)cupsArrayFind(mime->srcs, &srckey);
325 current && current->src == src;
326 current = (mime_filter_t *)cupsArrayNext(mime->srcs))
327 {
328 /*
329 * See if we have already tried the destination type as a source
330 * type (this avoids extra filter looping...)
331 */
bd7854cb 332
a74454a7 333 mime_type_t *current_dst; /* Current destination type */
bd7854cb 334
ef416fc2 335
a74454a7 336 for (listptr = list, current_dst = current->dst;
337 listptr;
338 listptr = listptr->next)
339 if (current_dst == listptr->src)
340 break;
341
342 if (listptr)
343 continue;
bd7854cb 344
a74454a7 345 /*
346 * See if we have any filters that can convert from the destination type
347 * of this filter to the final type...
348 */
349
350 listnode.src = current->src;
fa73b229 351
a74454a7 352 cupsArraySave(mime->srcs);
353 temp = find_filters(mime, current->dst, dst, &tempcost, &listnode);
354 cupsArrayRestore(mime->srcs);
355
356 if (!temp)
357 continue;
358
359 if (!cost)
360 return (temp);
361
362 /*
363 * Found a match; see if this one is less costly than the last (if
364 * any...)
365 */
366
ed486911 367 tempcost += current->cost;
368
a74454a7 369 if (tempcost < mincost)
370 {
371 cupsArrayDelete(mintemp);
ef416fc2 372
373 /*
a74454a7 374 * Hey, we got a match! Add the current filter to the beginning of the
375 * filter list...
ef416fc2 376 */
377
a74454a7 378 mintemp = temp;
ed486911 379 mincost = tempcost;
a74454a7 380 cupsArrayInsert(mintemp, current);
ef416fc2 381 }
a74454a7 382 else
383 cupsArrayDelete(temp);
384 }
ef416fc2 385
fa73b229 386 if (mintemp)
ef416fc2 387 {
388 /*
389 * Hey, we got a match!
390 */
391
ef416fc2 392#ifdef DEBUG
fa73b229 393 printf(" Returning %d filters:\n", cupsArrayCount(mintemp));
394 for (current = (mime_filter_t *)cupsArrayFirst(mintemp);
395 current;
396 current = (mime_filter_t *)cupsArrayNext(mintemp))
397 printf(" %s\n", current->filter);
ef416fc2 398#endif /* DEBUG */
399
bd7854cb 400 if (cost)
401 *cost = mincost;
fa73b229 402
ef416fc2 403 return (mintemp);
404 }
405
406 DEBUG_puts(" Returning zippo...");
407
408 return (NULL);
409}
410
411
ef416fc2 412/*
f7deaa1a 413 * End of "$Id: filter.c 6252 2007-02-10 15:34:18Z mike $".
ef416fc2 414 */