]> git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/filter.c
50d50e5b7309f05fbfc888c7f681d11944988c6e
[thirdparty/cups.git] / scheduler / filter.c
1 /*
2 * "$Id: filter.c,v 1.4 2002/01/02 17:59:15 mike Exp $"
3 *
4 * File type conversion routines for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1997-2002 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-3111 USA
19 *
20 * Voice: (301) 373-9603
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/string.h>
41 #include "mime.h"
42
43
44 /*
45 * Local functions...
46 */
47
48 static int compare(mime_filter_t *, mime_filter_t *);
49 static mime_filter_t *lookup(mime_t *, mime_type_t *, mime_type_t *);
50
51
52 /*
53 * 'mimeAddFilter()' - Add a filter to the current MIME database.
54 */
55
56 mime_filter_t * /* O - New filter */
57 mimeAddFilter(mime_t *mime, /* I - MIME database */
58 mime_type_t *src, /* I - Source type */
59 mime_type_t *dst, /* I - Destination type */
60 int cost, /* I - Relative time/resource cost */
61 const char *filter) /* I - Filter program to run */
62 {
63 mime_filter_t *temp; /* New filter */
64
65
66 /*
67 * Range-check the input...
68 */
69
70 if (mime == NULL || src == NULL || dst == NULL || filter == NULL)
71 return (NULL);
72
73 if (strlen(filter) > (MIME_MAX_FILTER - 1))
74 return (NULL);
75
76 /*
77 * See if we already have an existing filter for the given source and
78 * destination...
79 */
80
81 if ((temp = lookup(mime, src, dst)) != NULL)
82 {
83 /*
84 * Yup, does the existing filter have a higher cost? If so, copy the
85 * filter and cost to the existing filter entry and return it...
86 */
87
88 if (temp->cost > cost)
89 {
90 temp->cost = cost;
91 strncpy(temp->filter, filter, sizeof(temp->filter) - 1);
92 temp->filter[sizeof(temp->filter) - 1] = '\0';
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 strncpy(temp->filter, filter, sizeof(temp->filter) - 1);
121 temp->filter[sizeof(temp->filter) - 1] = '\0';
122
123 if (mime->num_filters > 1)
124 qsort(mime->filters, mime->num_filters, sizeof(mime_filter_t),
125 (int (*)(const void *, const void *))compare);
126 }
127
128 /*
129 * Return the new/updated filter...
130 */
131
132 return (temp);
133 }
134
135
136 /*
137 * 'mimeFilter()' - Find the fastest way to convert from one type to another.
138 */
139
140 mime_filter_t * /* O - Array of filters to run */
141 mimeFilter(mime_t *mime, /* I - MIME database */
142 mime_type_t *src, /* I - Source file type */
143 mime_type_t *dst, /* I - Destination file type */
144 int *num_filters) /* O - Number of filters to run */
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 *mincurrent, /* Current filter for minimum */
154 *current, /* Current filter */
155 *filters; /* Filters to use */
156
157
158 /*
159 * Range-check the input...
160 */
161
162 if (mime == NULL || src == NULL || dst == NULL || num_filters == NULL)
163 return (NULL);
164
165 *num_filters = 0;
166
167 /*
168 * See if there is a filter that can convert the files directly...
169 */
170
171 if ((temp = lookup(mime, src, dst)) != NULL)
172 {
173 /*
174 * Got a direct filter!
175 */
176
177 if ((filters = (mime_filter_t *)malloc(sizeof(mime_filter_t))) == NULL)
178 return (NULL);
179
180 memcpy(filters, temp, sizeof(mime_filter_t));
181 *num_filters = 1;
182 return (filters);
183 }
184
185 /*
186 * OK, now look for filters from the source type to any other type...
187 */
188
189 mincost = 9999999;
190 mintemp = NULL;
191 num_mintemp = 0;
192 mincurrent = NULL;
193
194 for (i = mime->num_filters, current = mime->filters; i > 0; i --, current ++)
195 if (current->src == src)
196 {
197 /*
198 * See if we have any filters that can convert from the destination type
199 * of this filter to the final type...
200 */
201
202 if ((temp = mimeFilter(mime, current->dst, dst, &num_temp)) == NULL)
203 continue;
204
205 /*
206 * Found a match; see if this one is less costly than the last (if
207 * any...)
208 */
209
210 for (j = 0, cost = 0; j < num_temp; j ++)
211 cost += temp->cost;
212
213 if (cost < mincost)
214 {
215 if (mintemp != NULL)
216 free(mintemp);
217
218 mincost = cost;
219 mintemp = temp;
220 num_mintemp = num_temp;
221 mincurrent = current;
222 }
223 else
224 free(temp);
225 }
226
227 if (mintemp != NULL)
228 {
229 /*
230 * Hey, we got a match! Add the current filter to the beginning of the
231 * filter list...
232 */
233
234 filters = (mime_filter_t *)realloc(mintemp, sizeof(mime_filter_t) *
235 (num_mintemp + 1));
236
237 if (filters == NULL)
238 {
239 *num_filters = 0;
240 return (NULL);
241 }
242
243 memmove(filters + 1, filters, num_mintemp * sizeof(mime_filter_t));
244 memcpy(filters, mincurrent, sizeof(mime_filter_t));
245
246 *num_filters = num_mintemp + 1;
247
248 return (filters);
249 }
250
251 return (NULL);
252 }
253
254
255 /*
256 * 'compare()' - Compare two filter types...
257 */
258
259 static int /* O - Comparison result */
260 compare(mime_filter_t *f0, /* I - First filter */
261 mime_filter_t *f1) /* I - Second filter */
262 {
263 int i; /* Result of comparison */
264
265
266 if ((i = strcmp(f0->src->super, f1->src->super)) == 0)
267 if ((i = strcmp(f0->src->type, f1->src->type)) == 0)
268 if ((i = strcmp(f0->dst->super, f1->dst->super)) == 0)
269 i = strcmp(f0->dst->type, f1->dst->type);
270
271 return (i);
272 }
273
274
275 /*
276 * 'lookup()' - Lookup a filter...
277 */
278
279 static mime_filter_t * /* O - Filter for src->dst */
280 lookup(mime_t *mime, /* I - MIME database */
281 mime_type_t *src, /* I - Source type */
282 mime_type_t *dst) /* I - Destination type */
283 {
284 mime_filter_t key; /* Key record for filter search */
285
286
287 if (mime->num_filters == 0)
288 return (NULL);
289
290 key.src = src;
291 key.dst = dst;
292
293 return ((mime_filter_t *)bsearch(&key, mime->filters, mime->num_filters,
294 sizeof(mime_filter_t),
295 (int (*)(const void *, const void *))compare));
296 }
297
298
299 /*
300 * End of "$Id: filter.c,v 1.4 2002/01/02 17:59:15 mike Exp $".
301 */