]> git.ipfire.org Git - thirdparty/cups.git/blame - scheduler/filter.c
To prepare to load cups into easysw/current, perform 4 renames.
[thirdparty/cups.git] / scheduler / filter.c
CommitLineData
ef416fc2 1/*
2 * "$Id: filter.c 4833 2005-11-12 21:46:52Z mike $"
3 *
4 * File type conversion routines for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1997-2005 by Easy Software Products, all rights reserved.
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 *
26 * mimeAddFilter() - Add a filter to the current MIME database.
27 * mimeFilter() - Find the fastest way to convert from one type to another.
28 * compare() - Compare two filter types...
29 * lookup() - Lookup a filter...
30 */
31
32/*
33 * Include necessary headers...
34 */
35
36#include <stdio.h>
37#include <stdlib.h>
38#include <ctype.h>
39
40#include <cups/debug.h>
41#include <cups/string.h>
42#include "mime.h"
43
44
45/*
46 * Local functions...
47 */
48
49static int compare(mime_filter_t *, mime_filter_t *);
50static mime_filter_t *lookup(mime_t *, mime_type_t *, mime_type_t *);
51
52
53/*
54 * 'mimeAddFilter()' - Add a filter to the current MIME database.
55 */
56
57mime_filter_t * /* O - New filter */
58mimeAddFilter(mime_t *mime, /* I - MIME database */
59 mime_type_t *src, /* I - Source type */
60 mime_type_t *dst, /* I - Destination type */
61 int cost, /* I - Relative time/resource cost */
62 const char *filter) /* I - Filter program to run */
63{
64 mime_filter_t *temp; /* New filter */
65
66
67 /*
68 * Range-check the input...
69 */
70
71 if (mime == NULL || src == NULL || dst == NULL || filter == NULL)
72 return (NULL);
73
74 if (strlen(filter) > (MIME_MAX_FILTER - 1))
75 return (NULL);
76
77 /*
78 * See if we already have an existing filter for the given source and
79 * destination...
80 */
81
82 if ((temp = lookup(mime, src, dst)) != NULL)
83 {
84 /*
85 * Yup, does the existing filter have a higher cost? If so, copy the
86 * filter and cost to the existing filter entry and return it...
87 */
88
89 if (temp->cost > cost)
90 {
91 temp->cost = cost;
92 strlcpy(temp->filter, filter, sizeof(temp->filter));
93 }
94 }
95 else
96 {
97 /*
98 * Nope, add a new one...
99 */
100
101 if (mime->num_filters == 0)
102 temp = malloc(sizeof(mime_filter_t));
103 else
104 temp = realloc(mime->filters, sizeof(mime_filter_t) * (mime->num_filters + 1));
105
106 if (temp == NULL)
107 return (NULL);
108
109 mime->filters = temp;
110 temp += mime->num_filters;
111 mime->num_filters ++;
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
122 if (mime->num_filters > 1)
123 qsort(mime->filters, mime->num_filters, sizeof(mime_filter_t),
124 (int (*)(const void *, const void *))compare);
125 }
126
127 /*
128 * Return the new/updated filter...
129 */
130
131 return (temp);
132}
133
134
135/*
136 * 'mimeFilter()' - Find the fastest way to convert from one type to another.
137 */
138
139mime_filter_t * /* O - Array of filters to run */
140mimeFilter(mime_t *mime, /* I - MIME database */
141 mime_type_t *src, /* I - Source file type */
142 mime_type_t *dst, /* I - Destination file type */
143 int *num_filters, /* O - Number of filters to run */
144 int max_depth) /* I - Maximum depth of search */
145{
146 int i, j, /* Looping vars */
147 num_temp, /* Number of temporary filters */
148 num_mintemp, /* Number of filters in the minimum */
149 cost, /* Current cost */
150 mincost; /* Current minimum */
151 mime_filter_t *temp, /* Temporary filter */
152 *mintemp, /* Current minimum */
153 *current; /* Current filter */
154
155
156 /*
157 * Range-check the input...
158 */
159
160 DEBUG_printf(("mimeFilter(mime=%p, src=%p(%s/%s), dst=%p(%s/%s), num_filters=%p(%d))\n",
161 mime, src, src ? src->super : "?", src ? src->type : "?",
162 dst, dst ? dst->super : "?", dst ? dst->type : "?",
163 num_filters, num_filters ? *num_filters : 0));
164
165 if (mime == NULL || src == NULL || dst == NULL || num_filters == NULL ||
166 max_depth <= 0)
167 return (NULL);
168
169 *num_filters = 0;
170
171 /*
172 * See if there is a filter that can convert the files directly...
173 */
174
175 if ((temp = lookup(mime, src, dst)) != NULL)
176 {
177 /*
178 * Got a direct filter!
179 */
180
181 if ((mintemp = (mime_filter_t *)malloc(sizeof(mime_filter_t))) == NULL)
182 return (NULL);
183
184 memcpy(mintemp, temp, sizeof(mime_filter_t));
185 num_mintemp = 1;
186 mincost = mintemp->cost;
187
188 DEBUG_puts(" Found direct filter:");
189 DEBUG_printf((" %s (cost=%d)\n", mintemp->filter, mincost));
190 }
191 else
192 {
193 /*
194 * No direct filter...
195 */
196
197 mincost = 9999999;
198 mintemp = NULL;
199 num_mintemp = 0;
200 }
201
202 /*
203 * OK, now look for filters from the source type to any other type...
204 */
205
206 for (i = mime->num_filters, current = mime->filters;
207 i > 0;
208 i --, current ++)
209 if (current->src == src)
210 {
211 /*
212 * See if we have any filters that can convert from the destination type
213 * of this filter to the final type...
214 */
215
216 if ((temp = mimeFilter(mime, current->dst, dst, &num_temp,
217 max_depth - 1)) == NULL)
218 continue;
219
220 /*
221 * Found a match; see if this one is less costly than the last (if
222 * any...)
223 */
224
225 for (j = 0, cost = current->cost; j < num_temp; j ++)
226 cost += temp[j].cost;
227
228 if (cost < mincost)
229 {
230 if (mintemp != NULL)
231 free(mintemp);
232
233 /*
234 * Hey, we got a match! Add the current filter to the beginning of the
235 * filter list...
236 */
237
238 mintemp = (mime_filter_t *)realloc(temp, sizeof(mime_filter_t) *
239 (num_temp + 1));
240
241 if (mintemp == NULL)
242 {
243 *num_filters = 0;
244 return (NULL);
245 }
246
247 memmove(mintemp + 1, mintemp, num_temp * sizeof(mime_filter_t));
248 memcpy(mintemp, current, sizeof(mime_filter_t));
249
250 num_mintemp = num_temp + 1;
251 mincost = cost;
252 }
253 else
254 free(temp);
255 }
256
257 if (mintemp != NULL)
258 {
259 /*
260 * Hey, we got a match!
261 */
262
263 *num_filters = num_mintemp;
264
265#ifdef DEBUG
266 printf(" Returning %d filters:\n", *num_filters);
267 for (i = 0; i < num_mintemp; i ++)
268 printf(" %s\n", mintemp[i].filter);
269#endif /* DEBUG */
270
271 return (mintemp);
272 }
273
274 DEBUG_puts(" Returning zippo...");
275
276 return (NULL);
277}
278
279
280/*
281 * 'compare()' - Compare two filter types...
282 */
283
284static int /* O - Comparison result */
285compare(mime_filter_t *f0, /* I - First filter */
286 mime_filter_t *f1) /* I - Second filter */
287{
288 int i; /* Result of comparison */
289
290
291 if ((i = strcmp(f0->src->super, f1->src->super)) == 0)
292 if ((i = strcmp(f0->src->type, f1->src->type)) == 0)
293 if ((i = strcmp(f0->dst->super, f1->dst->super)) == 0)
294 i = strcmp(f0->dst->type, f1->dst->type);
295
296 return (i);
297}
298
299
300/*
301 * 'lookup()' - Lookup a filter...
302 */
303
304static mime_filter_t * /* O - Filter for src->dst */
305lookup(mime_t *mime, /* I - MIME database */
306 mime_type_t *src, /* I - Source type */
307 mime_type_t *dst) /* I - Destination type */
308{
309 mime_filter_t key; /* Key record for filter search */
310
311
312 if (mime->num_filters == 0)
313 return (NULL);
314
315 key.src = src;
316 key.dst = dst;
317
318 return ((mime_filter_t *)bsearch(&key, mime->filters, mime->num_filters,
319 sizeof(mime_filter_t),
320 (int (*)(const void *, const void *))compare));
321}
322
323
324/*
325 * End of "$Id: filter.c 4833 2005-11-12 21:46:52Z mike $".
326 */