1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker * Option routines for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker *
4*5e7646d2SAndroid Build Coastguard Worker * Copyright 2007-2017 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker * Copyright 1997-2007 by Easy Software Products.
6*5e7646d2SAndroid Build Coastguard Worker *
7*5e7646d2SAndroid Build Coastguard Worker * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
8*5e7646d2SAndroid Build Coastguard Worker */
9*5e7646d2SAndroid Build Coastguard Worker
10*5e7646d2SAndroid Build Coastguard Worker /*
11*5e7646d2SAndroid Build Coastguard Worker * Include necessary headers...
12*5e7646d2SAndroid Build Coastguard Worker */
13*5e7646d2SAndroid Build Coastguard Worker
14*5e7646d2SAndroid Build Coastguard Worker #include "cups-private.h"
15*5e7646d2SAndroid Build Coastguard Worker #include "debug-internal.h"
16*5e7646d2SAndroid Build Coastguard Worker
17*5e7646d2SAndroid Build Coastguard Worker
18*5e7646d2SAndroid Build Coastguard Worker /*
19*5e7646d2SAndroid Build Coastguard Worker * Local functions...
20*5e7646d2SAndroid Build Coastguard Worker */
21*5e7646d2SAndroid Build Coastguard Worker
22*5e7646d2SAndroid Build Coastguard Worker static int cups_compare_options(cups_option_t *a, cups_option_t *b);
23*5e7646d2SAndroid Build Coastguard Worker static int cups_find_option(const char *name, int num_options,
24*5e7646d2SAndroid Build Coastguard Worker cups_option_t *option, int prev, int *rdiff);
25*5e7646d2SAndroid Build Coastguard Worker
26*5e7646d2SAndroid Build Coastguard Worker
27*5e7646d2SAndroid Build Coastguard Worker /*
28*5e7646d2SAndroid Build Coastguard Worker * 'cupsAddIntegerOption()' - Add an integer option to an option array.
29*5e7646d2SAndroid Build Coastguard Worker *
30*5e7646d2SAndroid Build Coastguard Worker * New option arrays can be initialized simply by passing 0 for the
31*5e7646d2SAndroid Build Coastguard Worker * "num_options" parameter.
32*5e7646d2SAndroid Build Coastguard Worker *
33*5e7646d2SAndroid Build Coastguard Worker * @since CUPS 2.2.4/macOS 10.13@
34*5e7646d2SAndroid Build Coastguard Worker */
35*5e7646d2SAndroid Build Coastguard Worker
36*5e7646d2SAndroid Build Coastguard Worker int /* O - Number of options */
cupsAddIntegerOption(const char * name,int value,int num_options,cups_option_t ** options)37*5e7646d2SAndroid Build Coastguard Worker cupsAddIntegerOption(
38*5e7646d2SAndroid Build Coastguard Worker const char *name, /* I - Name of option */
39*5e7646d2SAndroid Build Coastguard Worker int value, /* I - Value of option */
40*5e7646d2SAndroid Build Coastguard Worker int num_options, /* I - Number of options */
41*5e7646d2SAndroid Build Coastguard Worker cups_option_t **options) /* IO - Pointer to options */
42*5e7646d2SAndroid Build Coastguard Worker {
43*5e7646d2SAndroid Build Coastguard Worker char strvalue[32]; /* String value */
44*5e7646d2SAndroid Build Coastguard Worker
45*5e7646d2SAndroid Build Coastguard Worker
46*5e7646d2SAndroid Build Coastguard Worker snprintf(strvalue, sizeof(strvalue), "%d", value);
47*5e7646d2SAndroid Build Coastguard Worker
48*5e7646d2SAndroid Build Coastguard Worker return (cupsAddOption(name, strvalue, num_options, options));
49*5e7646d2SAndroid Build Coastguard Worker }
50*5e7646d2SAndroid Build Coastguard Worker
51*5e7646d2SAndroid Build Coastguard Worker
52*5e7646d2SAndroid Build Coastguard Worker /*
53*5e7646d2SAndroid Build Coastguard Worker * 'cupsAddOption()' - Add an option to an option array.
54*5e7646d2SAndroid Build Coastguard Worker *
55*5e7646d2SAndroid Build Coastguard Worker * New option arrays can be initialized simply by passing 0 for the
56*5e7646d2SAndroid Build Coastguard Worker * "num_options" parameter.
57*5e7646d2SAndroid Build Coastguard Worker */
58*5e7646d2SAndroid Build Coastguard Worker
59*5e7646d2SAndroid Build Coastguard Worker int /* O - Number of options */
cupsAddOption(const char * name,const char * value,int num_options,cups_option_t ** options)60*5e7646d2SAndroid Build Coastguard Worker cupsAddOption(const char *name, /* I - Name of option */
61*5e7646d2SAndroid Build Coastguard Worker const char *value, /* I - Value of option */
62*5e7646d2SAndroid Build Coastguard Worker int num_options,/* I - Number of options */
63*5e7646d2SAndroid Build Coastguard Worker cups_option_t **options) /* IO - Pointer to options */
64*5e7646d2SAndroid Build Coastguard Worker {
65*5e7646d2SAndroid Build Coastguard Worker cups_option_t *temp; /* Pointer to new option */
66*5e7646d2SAndroid Build Coastguard Worker int insert, /* Insertion point */
67*5e7646d2SAndroid Build Coastguard Worker diff; /* Result of search */
68*5e7646d2SAndroid Build Coastguard Worker
69*5e7646d2SAndroid Build Coastguard Worker
70*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("2cupsAddOption(name=\"%s\", value=\"%s\", num_options=%d, options=%p)", name, value, num_options, (void *)options));
71*5e7646d2SAndroid Build Coastguard Worker
72*5e7646d2SAndroid Build Coastguard Worker if (!name || !name[0] || !value || !options || num_options < 0)
73*5e7646d2SAndroid Build Coastguard Worker {
74*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("3cupsAddOption: Returning %d", num_options));
75*5e7646d2SAndroid Build Coastguard Worker return (num_options);
76*5e7646d2SAndroid Build Coastguard Worker }
77*5e7646d2SAndroid Build Coastguard Worker
78*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strcasecmp(name, "cupsPrintQuality"))
79*5e7646d2SAndroid Build Coastguard Worker num_options = cupsRemoveOption("print-quality", num_options, options);
80*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strcasecmp(name, "print-quality"))
81*5e7646d2SAndroid Build Coastguard Worker num_options = cupsRemoveOption("cupsPrintQuality", num_options, options);
82*5e7646d2SAndroid Build Coastguard Worker
83*5e7646d2SAndroid Build Coastguard Worker /*
84*5e7646d2SAndroid Build Coastguard Worker * Look for an existing option with the same name...
85*5e7646d2SAndroid Build Coastguard Worker */
86*5e7646d2SAndroid Build Coastguard Worker
87*5e7646d2SAndroid Build Coastguard Worker if (num_options == 0)
88*5e7646d2SAndroid Build Coastguard Worker {
89*5e7646d2SAndroid Build Coastguard Worker insert = 0;
90*5e7646d2SAndroid Build Coastguard Worker diff = 1;
91*5e7646d2SAndroid Build Coastguard Worker }
92*5e7646d2SAndroid Build Coastguard Worker else
93*5e7646d2SAndroid Build Coastguard Worker {
94*5e7646d2SAndroid Build Coastguard Worker insert = cups_find_option(name, num_options, *options, num_options - 1,
95*5e7646d2SAndroid Build Coastguard Worker &diff);
96*5e7646d2SAndroid Build Coastguard Worker
97*5e7646d2SAndroid Build Coastguard Worker if (diff > 0)
98*5e7646d2SAndroid Build Coastguard Worker insert ++;
99*5e7646d2SAndroid Build Coastguard Worker }
100*5e7646d2SAndroid Build Coastguard Worker
101*5e7646d2SAndroid Build Coastguard Worker if (diff)
102*5e7646d2SAndroid Build Coastguard Worker {
103*5e7646d2SAndroid Build Coastguard Worker /*
104*5e7646d2SAndroid Build Coastguard Worker * No matching option name...
105*5e7646d2SAndroid Build Coastguard Worker */
106*5e7646d2SAndroid Build Coastguard Worker
107*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("4cupsAddOption: New option inserted at index %d...",
108*5e7646d2SAndroid Build Coastguard Worker insert));
109*5e7646d2SAndroid Build Coastguard Worker
110*5e7646d2SAndroid Build Coastguard Worker if (num_options == 0)
111*5e7646d2SAndroid Build Coastguard Worker temp = (cups_option_t *)malloc(sizeof(cups_option_t));
112*5e7646d2SAndroid Build Coastguard Worker else
113*5e7646d2SAndroid Build Coastguard Worker temp = (cups_option_t *)realloc(*options, sizeof(cups_option_t) * (size_t)(num_options + 1));
114*5e7646d2SAndroid Build Coastguard Worker
115*5e7646d2SAndroid Build Coastguard Worker if (!temp)
116*5e7646d2SAndroid Build Coastguard Worker {
117*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("3cupsAddOption: Unable to expand option array, returning 0");
118*5e7646d2SAndroid Build Coastguard Worker return (0);
119*5e7646d2SAndroid Build Coastguard Worker }
120*5e7646d2SAndroid Build Coastguard Worker
121*5e7646d2SAndroid Build Coastguard Worker *options = temp;
122*5e7646d2SAndroid Build Coastguard Worker
123*5e7646d2SAndroid Build Coastguard Worker if (insert < num_options)
124*5e7646d2SAndroid Build Coastguard Worker {
125*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("4cupsAddOption: Shifting %d options...",
126*5e7646d2SAndroid Build Coastguard Worker (int)(num_options - insert)));
127*5e7646d2SAndroid Build Coastguard Worker memmove(temp + insert + 1, temp + insert, (size_t)(num_options - insert) * sizeof(cups_option_t));
128*5e7646d2SAndroid Build Coastguard Worker }
129*5e7646d2SAndroid Build Coastguard Worker
130*5e7646d2SAndroid Build Coastguard Worker temp += insert;
131*5e7646d2SAndroid Build Coastguard Worker temp->name = _cupsStrAlloc(name);
132*5e7646d2SAndroid Build Coastguard Worker num_options ++;
133*5e7646d2SAndroid Build Coastguard Worker }
134*5e7646d2SAndroid Build Coastguard Worker else
135*5e7646d2SAndroid Build Coastguard Worker {
136*5e7646d2SAndroid Build Coastguard Worker /*
137*5e7646d2SAndroid Build Coastguard Worker * Match found; free the old value...
138*5e7646d2SAndroid Build Coastguard Worker */
139*5e7646d2SAndroid Build Coastguard Worker
140*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("4cupsAddOption: Option already exists at index %d...",
141*5e7646d2SAndroid Build Coastguard Worker insert));
142*5e7646d2SAndroid Build Coastguard Worker
143*5e7646d2SAndroid Build Coastguard Worker temp = *options + insert;
144*5e7646d2SAndroid Build Coastguard Worker _cupsStrFree(temp->value);
145*5e7646d2SAndroid Build Coastguard Worker }
146*5e7646d2SAndroid Build Coastguard Worker
147*5e7646d2SAndroid Build Coastguard Worker temp->value = _cupsStrAlloc(value);
148*5e7646d2SAndroid Build Coastguard Worker
149*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("3cupsAddOption: Returning %d", num_options));
150*5e7646d2SAndroid Build Coastguard Worker
151*5e7646d2SAndroid Build Coastguard Worker return (num_options);
152*5e7646d2SAndroid Build Coastguard Worker }
153*5e7646d2SAndroid Build Coastguard Worker
154*5e7646d2SAndroid Build Coastguard Worker
155*5e7646d2SAndroid Build Coastguard Worker /*
156*5e7646d2SAndroid Build Coastguard Worker * 'cupsFreeOptions()' - Free all memory used by options.
157*5e7646d2SAndroid Build Coastguard Worker */
158*5e7646d2SAndroid Build Coastguard Worker
159*5e7646d2SAndroid Build Coastguard Worker void
cupsFreeOptions(int num_options,cups_option_t * options)160*5e7646d2SAndroid Build Coastguard Worker cupsFreeOptions(
161*5e7646d2SAndroid Build Coastguard Worker int num_options, /* I - Number of options */
162*5e7646d2SAndroid Build Coastguard Worker cups_option_t *options) /* I - Pointer to options */
163*5e7646d2SAndroid Build Coastguard Worker {
164*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
165*5e7646d2SAndroid Build Coastguard Worker
166*5e7646d2SAndroid Build Coastguard Worker
167*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("cupsFreeOptions(num_options=%d, options=%p)", num_options, (void *)options));
168*5e7646d2SAndroid Build Coastguard Worker
169*5e7646d2SAndroid Build Coastguard Worker if (num_options <= 0 || !options)
170*5e7646d2SAndroid Build Coastguard Worker return;
171*5e7646d2SAndroid Build Coastguard Worker
172*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < num_options; i ++)
173*5e7646d2SAndroid Build Coastguard Worker {
174*5e7646d2SAndroid Build Coastguard Worker _cupsStrFree(options[i].name);
175*5e7646d2SAndroid Build Coastguard Worker _cupsStrFree(options[i].value);
176*5e7646d2SAndroid Build Coastguard Worker }
177*5e7646d2SAndroid Build Coastguard Worker
178*5e7646d2SAndroid Build Coastguard Worker free(options);
179*5e7646d2SAndroid Build Coastguard Worker }
180*5e7646d2SAndroid Build Coastguard Worker
181*5e7646d2SAndroid Build Coastguard Worker
182*5e7646d2SAndroid Build Coastguard Worker /*
183*5e7646d2SAndroid Build Coastguard Worker * 'cupsGetIntegerOption()' - Get an integer option value.
184*5e7646d2SAndroid Build Coastguard Worker *
185*5e7646d2SAndroid Build Coastguard Worker * INT_MIN is returned when the option does not exist, is not an integer, or
186*5e7646d2SAndroid Build Coastguard Worker * exceeds the range of values for the "int" type.
187*5e7646d2SAndroid Build Coastguard Worker *
188*5e7646d2SAndroid Build Coastguard Worker * @since CUPS 2.2.4/macOS 10.13@
189*5e7646d2SAndroid Build Coastguard Worker */
190*5e7646d2SAndroid Build Coastguard Worker
191*5e7646d2SAndroid Build Coastguard Worker int /* O - Option value or @code INT_MIN@ */
cupsGetIntegerOption(const char * name,int num_options,cups_option_t * options)192*5e7646d2SAndroid Build Coastguard Worker cupsGetIntegerOption(
193*5e7646d2SAndroid Build Coastguard Worker const char *name, /* I - Name of option */
194*5e7646d2SAndroid Build Coastguard Worker int num_options, /* I - Number of options */
195*5e7646d2SAndroid Build Coastguard Worker cups_option_t *options) /* I - Options */
196*5e7646d2SAndroid Build Coastguard Worker {
197*5e7646d2SAndroid Build Coastguard Worker const char *value = cupsGetOption(name, num_options, options);
198*5e7646d2SAndroid Build Coastguard Worker /* String value of option */
199*5e7646d2SAndroid Build Coastguard Worker char *ptr; /* Pointer into string value */
200*5e7646d2SAndroid Build Coastguard Worker long intvalue; /* Integer value */
201*5e7646d2SAndroid Build Coastguard Worker
202*5e7646d2SAndroid Build Coastguard Worker
203*5e7646d2SAndroid Build Coastguard Worker if (!value || !*value)
204*5e7646d2SAndroid Build Coastguard Worker return (INT_MIN);
205*5e7646d2SAndroid Build Coastguard Worker
206*5e7646d2SAndroid Build Coastguard Worker intvalue = strtol(value, &ptr, 10);
207*5e7646d2SAndroid Build Coastguard Worker if (intvalue < INT_MIN || intvalue > INT_MAX || *ptr)
208*5e7646d2SAndroid Build Coastguard Worker return (INT_MIN);
209*5e7646d2SAndroid Build Coastguard Worker
210*5e7646d2SAndroid Build Coastguard Worker return ((int)intvalue);
211*5e7646d2SAndroid Build Coastguard Worker }
212*5e7646d2SAndroid Build Coastguard Worker
213*5e7646d2SAndroid Build Coastguard Worker
214*5e7646d2SAndroid Build Coastguard Worker /*
215*5e7646d2SAndroid Build Coastguard Worker * 'cupsGetOption()' - Get an option value.
216*5e7646d2SAndroid Build Coastguard Worker */
217*5e7646d2SAndroid Build Coastguard Worker
218*5e7646d2SAndroid Build Coastguard Worker const char * /* O - Option value or @code NULL@ */
cupsGetOption(const char * name,int num_options,cups_option_t * options)219*5e7646d2SAndroid Build Coastguard Worker cupsGetOption(const char *name, /* I - Name of option */
220*5e7646d2SAndroid Build Coastguard Worker int num_options,/* I - Number of options */
221*5e7646d2SAndroid Build Coastguard Worker cups_option_t *options) /* I - Options */
222*5e7646d2SAndroid Build Coastguard Worker {
223*5e7646d2SAndroid Build Coastguard Worker int diff, /* Result of comparison */
224*5e7646d2SAndroid Build Coastguard Worker match; /* Matching index */
225*5e7646d2SAndroid Build Coastguard Worker
226*5e7646d2SAndroid Build Coastguard Worker
227*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("2cupsGetOption(name=\"%s\", num_options=%d, options=%p)", name, num_options, (void *)options));
228*5e7646d2SAndroid Build Coastguard Worker
229*5e7646d2SAndroid Build Coastguard Worker if (!name || num_options <= 0 || !options)
230*5e7646d2SAndroid Build Coastguard Worker {
231*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("3cupsGetOption: Returning NULL");
232*5e7646d2SAndroid Build Coastguard Worker return (NULL);
233*5e7646d2SAndroid Build Coastguard Worker }
234*5e7646d2SAndroid Build Coastguard Worker
235*5e7646d2SAndroid Build Coastguard Worker match = cups_find_option(name, num_options, options, -1, &diff);
236*5e7646d2SAndroid Build Coastguard Worker
237*5e7646d2SAndroid Build Coastguard Worker if (!diff)
238*5e7646d2SAndroid Build Coastguard Worker {
239*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("3cupsGetOption: Returning \"%s\"", options[match].value));
240*5e7646d2SAndroid Build Coastguard Worker return (options[match].value);
241*5e7646d2SAndroid Build Coastguard Worker }
242*5e7646d2SAndroid Build Coastguard Worker
243*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("3cupsGetOption: Returning NULL");
244*5e7646d2SAndroid Build Coastguard Worker return (NULL);
245*5e7646d2SAndroid Build Coastguard Worker }
246*5e7646d2SAndroid Build Coastguard Worker
247*5e7646d2SAndroid Build Coastguard Worker
248*5e7646d2SAndroid Build Coastguard Worker /*
249*5e7646d2SAndroid Build Coastguard Worker * 'cupsParseOptions()' - Parse options from a command-line argument.
250*5e7646d2SAndroid Build Coastguard Worker *
251*5e7646d2SAndroid Build Coastguard Worker * This function converts space-delimited name/value pairs according
252*5e7646d2SAndroid Build Coastguard Worker * to the PAPI text option ABNF specification. Collection values
253*5e7646d2SAndroid Build Coastguard Worker * ("name={a=... b=... c=...}") are stored with the curley brackets
254*5e7646d2SAndroid Build Coastguard Worker * intact - use @code cupsParseOptions@ on the value to extract the
255*5e7646d2SAndroid Build Coastguard Worker * collection attributes.
256*5e7646d2SAndroid Build Coastguard Worker */
257*5e7646d2SAndroid Build Coastguard Worker
258*5e7646d2SAndroid Build Coastguard Worker int /* O - Number of options found */
cupsParseOptions(const char * arg,int num_options,cups_option_t ** options)259*5e7646d2SAndroid Build Coastguard Worker cupsParseOptions(
260*5e7646d2SAndroid Build Coastguard Worker const char *arg, /* I - Argument to parse */
261*5e7646d2SAndroid Build Coastguard Worker int num_options, /* I - Number of options */
262*5e7646d2SAndroid Build Coastguard Worker cups_option_t **options) /* O - Options found */
263*5e7646d2SAndroid Build Coastguard Worker {
264*5e7646d2SAndroid Build Coastguard Worker char *copyarg, /* Copy of input string */
265*5e7646d2SAndroid Build Coastguard Worker *ptr, /* Pointer into string */
266*5e7646d2SAndroid Build Coastguard Worker *name, /* Pointer to name */
267*5e7646d2SAndroid Build Coastguard Worker *value, /* Pointer to value */
268*5e7646d2SAndroid Build Coastguard Worker sep, /* Separator character */
269*5e7646d2SAndroid Build Coastguard Worker quote; /* Quote character */
270*5e7646d2SAndroid Build Coastguard Worker
271*5e7646d2SAndroid Build Coastguard Worker
272*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("cupsParseOptions(arg=\"%s\", num_options=%d, options=%p)", arg, num_options, (void *)options));
273*5e7646d2SAndroid Build Coastguard Worker
274*5e7646d2SAndroid Build Coastguard Worker /*
275*5e7646d2SAndroid Build Coastguard Worker * Range check input...
276*5e7646d2SAndroid Build Coastguard Worker */
277*5e7646d2SAndroid Build Coastguard Worker
278*5e7646d2SAndroid Build Coastguard Worker if (!arg)
279*5e7646d2SAndroid Build Coastguard Worker {
280*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1cupsParseOptions: Returning %d", num_options));
281*5e7646d2SAndroid Build Coastguard Worker return (num_options);
282*5e7646d2SAndroid Build Coastguard Worker }
283*5e7646d2SAndroid Build Coastguard Worker
284*5e7646d2SAndroid Build Coastguard Worker if (!options || num_options < 0)
285*5e7646d2SAndroid Build Coastguard Worker {
286*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("1cupsParseOptions: Returning 0");
287*5e7646d2SAndroid Build Coastguard Worker return (0);
288*5e7646d2SAndroid Build Coastguard Worker }
289*5e7646d2SAndroid Build Coastguard Worker
290*5e7646d2SAndroid Build Coastguard Worker /*
291*5e7646d2SAndroid Build Coastguard Worker * Make a copy of the argument string and then divide it up...
292*5e7646d2SAndroid Build Coastguard Worker */
293*5e7646d2SAndroid Build Coastguard Worker
294*5e7646d2SAndroid Build Coastguard Worker if ((copyarg = strdup(arg)) == NULL)
295*5e7646d2SAndroid Build Coastguard Worker {
296*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("1cupsParseOptions: Unable to copy arg string");
297*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1cupsParseOptions: Returning %d", num_options));
298*5e7646d2SAndroid Build Coastguard Worker return (num_options);
299*5e7646d2SAndroid Build Coastguard Worker }
300*5e7646d2SAndroid Build Coastguard Worker
301*5e7646d2SAndroid Build Coastguard Worker if (*copyarg == '{')
302*5e7646d2SAndroid Build Coastguard Worker {
303*5e7646d2SAndroid Build Coastguard Worker /*
304*5e7646d2SAndroid Build Coastguard Worker * Remove surrounding {} so we can parse "{name=value ... name=value}"...
305*5e7646d2SAndroid Build Coastguard Worker */
306*5e7646d2SAndroid Build Coastguard Worker
307*5e7646d2SAndroid Build Coastguard Worker if ((ptr = copyarg + strlen(copyarg) - 1) > copyarg && *ptr == '}')
308*5e7646d2SAndroid Build Coastguard Worker {
309*5e7646d2SAndroid Build Coastguard Worker *ptr = '\0';
310*5e7646d2SAndroid Build Coastguard Worker ptr = copyarg + 1;
311*5e7646d2SAndroid Build Coastguard Worker }
312*5e7646d2SAndroid Build Coastguard Worker else
313*5e7646d2SAndroid Build Coastguard Worker ptr = copyarg;
314*5e7646d2SAndroid Build Coastguard Worker }
315*5e7646d2SAndroid Build Coastguard Worker else
316*5e7646d2SAndroid Build Coastguard Worker ptr = copyarg;
317*5e7646d2SAndroid Build Coastguard Worker
318*5e7646d2SAndroid Build Coastguard Worker /*
319*5e7646d2SAndroid Build Coastguard Worker * Skip leading spaces...
320*5e7646d2SAndroid Build Coastguard Worker */
321*5e7646d2SAndroid Build Coastguard Worker
322*5e7646d2SAndroid Build Coastguard Worker while (_cups_isspace(*ptr))
323*5e7646d2SAndroid Build Coastguard Worker ptr ++;
324*5e7646d2SAndroid Build Coastguard Worker
325*5e7646d2SAndroid Build Coastguard Worker /*
326*5e7646d2SAndroid Build Coastguard Worker * Loop through the string...
327*5e7646d2SAndroid Build Coastguard Worker */
328*5e7646d2SAndroid Build Coastguard Worker
329*5e7646d2SAndroid Build Coastguard Worker while (*ptr != '\0')
330*5e7646d2SAndroid Build Coastguard Worker {
331*5e7646d2SAndroid Build Coastguard Worker /*
332*5e7646d2SAndroid Build Coastguard Worker * Get the name up to a SPACE, =, or end-of-string...
333*5e7646d2SAndroid Build Coastguard Worker */
334*5e7646d2SAndroid Build Coastguard Worker
335*5e7646d2SAndroid Build Coastguard Worker name = ptr;
336*5e7646d2SAndroid Build Coastguard Worker while (!strchr("\f\n\r\t\v =", *ptr) && *ptr)
337*5e7646d2SAndroid Build Coastguard Worker ptr ++;
338*5e7646d2SAndroid Build Coastguard Worker
339*5e7646d2SAndroid Build Coastguard Worker /*
340*5e7646d2SAndroid Build Coastguard Worker * Avoid an empty name...
341*5e7646d2SAndroid Build Coastguard Worker */
342*5e7646d2SAndroid Build Coastguard Worker
343*5e7646d2SAndroid Build Coastguard Worker if (ptr == name)
344*5e7646d2SAndroid Build Coastguard Worker break;
345*5e7646d2SAndroid Build Coastguard Worker
346*5e7646d2SAndroid Build Coastguard Worker /*
347*5e7646d2SAndroid Build Coastguard Worker * Skip trailing spaces...
348*5e7646d2SAndroid Build Coastguard Worker */
349*5e7646d2SAndroid Build Coastguard Worker
350*5e7646d2SAndroid Build Coastguard Worker while (_cups_isspace(*ptr))
351*5e7646d2SAndroid Build Coastguard Worker *ptr++ = '\0';
352*5e7646d2SAndroid Build Coastguard Worker
353*5e7646d2SAndroid Build Coastguard Worker if ((sep = *ptr) == '=')
354*5e7646d2SAndroid Build Coastguard Worker *ptr++ = '\0';
355*5e7646d2SAndroid Build Coastguard Worker
356*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("2cupsParseOptions: name=\"%s\"", name));
357*5e7646d2SAndroid Build Coastguard Worker
358*5e7646d2SAndroid Build Coastguard Worker if (sep != '=')
359*5e7646d2SAndroid Build Coastguard Worker {
360*5e7646d2SAndroid Build Coastguard Worker /*
361*5e7646d2SAndroid Build Coastguard Worker * Boolean option...
362*5e7646d2SAndroid Build Coastguard Worker */
363*5e7646d2SAndroid Build Coastguard Worker
364*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strncasecmp(name, "no", 2))
365*5e7646d2SAndroid Build Coastguard Worker num_options = cupsAddOption(name + 2, "false", num_options,
366*5e7646d2SAndroid Build Coastguard Worker options);
367*5e7646d2SAndroid Build Coastguard Worker else
368*5e7646d2SAndroid Build Coastguard Worker num_options = cupsAddOption(name, "true", num_options, options);
369*5e7646d2SAndroid Build Coastguard Worker
370*5e7646d2SAndroid Build Coastguard Worker continue;
371*5e7646d2SAndroid Build Coastguard Worker }
372*5e7646d2SAndroid Build Coastguard Worker
373*5e7646d2SAndroid Build Coastguard Worker /*
374*5e7646d2SAndroid Build Coastguard Worker * Remove = and parse the value...
375*5e7646d2SAndroid Build Coastguard Worker */
376*5e7646d2SAndroid Build Coastguard Worker
377*5e7646d2SAndroid Build Coastguard Worker value = ptr;
378*5e7646d2SAndroid Build Coastguard Worker
379*5e7646d2SAndroid Build Coastguard Worker while (*ptr && !_cups_isspace(*ptr))
380*5e7646d2SAndroid Build Coastguard Worker {
381*5e7646d2SAndroid Build Coastguard Worker if (*ptr == ',')
382*5e7646d2SAndroid Build Coastguard Worker ptr ++;
383*5e7646d2SAndroid Build Coastguard Worker else if (*ptr == '\'' || *ptr == '\"')
384*5e7646d2SAndroid Build Coastguard Worker {
385*5e7646d2SAndroid Build Coastguard Worker /*
386*5e7646d2SAndroid Build Coastguard Worker * Quoted string constant...
387*5e7646d2SAndroid Build Coastguard Worker */
388*5e7646d2SAndroid Build Coastguard Worker
389*5e7646d2SAndroid Build Coastguard Worker quote = *ptr;
390*5e7646d2SAndroid Build Coastguard Worker _cups_strcpy(ptr, ptr + 1);
391*5e7646d2SAndroid Build Coastguard Worker
392*5e7646d2SAndroid Build Coastguard Worker while (*ptr != quote && *ptr)
393*5e7646d2SAndroid Build Coastguard Worker {
394*5e7646d2SAndroid Build Coastguard Worker if (*ptr == '\\' && ptr[1])
395*5e7646d2SAndroid Build Coastguard Worker _cups_strcpy(ptr, ptr + 1);
396*5e7646d2SAndroid Build Coastguard Worker
397*5e7646d2SAndroid Build Coastguard Worker ptr ++;
398*5e7646d2SAndroid Build Coastguard Worker }
399*5e7646d2SAndroid Build Coastguard Worker
400*5e7646d2SAndroid Build Coastguard Worker if (*ptr)
401*5e7646d2SAndroid Build Coastguard Worker _cups_strcpy(ptr, ptr + 1);
402*5e7646d2SAndroid Build Coastguard Worker }
403*5e7646d2SAndroid Build Coastguard Worker else if (*ptr == '{')
404*5e7646d2SAndroid Build Coastguard Worker {
405*5e7646d2SAndroid Build Coastguard Worker /*
406*5e7646d2SAndroid Build Coastguard Worker * Collection value...
407*5e7646d2SAndroid Build Coastguard Worker */
408*5e7646d2SAndroid Build Coastguard Worker
409*5e7646d2SAndroid Build Coastguard Worker int depth;
410*5e7646d2SAndroid Build Coastguard Worker
411*5e7646d2SAndroid Build Coastguard Worker for (depth = 0; *ptr; ptr ++)
412*5e7646d2SAndroid Build Coastguard Worker {
413*5e7646d2SAndroid Build Coastguard Worker if (*ptr == '{')
414*5e7646d2SAndroid Build Coastguard Worker depth ++;
415*5e7646d2SAndroid Build Coastguard Worker else if (*ptr == '}')
416*5e7646d2SAndroid Build Coastguard Worker {
417*5e7646d2SAndroid Build Coastguard Worker depth --;
418*5e7646d2SAndroid Build Coastguard Worker if (!depth)
419*5e7646d2SAndroid Build Coastguard Worker {
420*5e7646d2SAndroid Build Coastguard Worker ptr ++;
421*5e7646d2SAndroid Build Coastguard Worker break;
422*5e7646d2SAndroid Build Coastguard Worker }
423*5e7646d2SAndroid Build Coastguard Worker }
424*5e7646d2SAndroid Build Coastguard Worker else if (*ptr == '\\' && ptr[1])
425*5e7646d2SAndroid Build Coastguard Worker _cups_strcpy(ptr, ptr + 1);
426*5e7646d2SAndroid Build Coastguard Worker }
427*5e7646d2SAndroid Build Coastguard Worker }
428*5e7646d2SAndroid Build Coastguard Worker else
429*5e7646d2SAndroid Build Coastguard Worker {
430*5e7646d2SAndroid Build Coastguard Worker /*
431*5e7646d2SAndroid Build Coastguard Worker * Normal space-delimited string...
432*5e7646d2SAndroid Build Coastguard Worker */
433*5e7646d2SAndroid Build Coastguard Worker
434*5e7646d2SAndroid Build Coastguard Worker while (*ptr && !_cups_isspace(*ptr))
435*5e7646d2SAndroid Build Coastguard Worker {
436*5e7646d2SAndroid Build Coastguard Worker if (*ptr == '\\' && ptr[1])
437*5e7646d2SAndroid Build Coastguard Worker _cups_strcpy(ptr, ptr + 1);
438*5e7646d2SAndroid Build Coastguard Worker
439*5e7646d2SAndroid Build Coastguard Worker ptr ++;
440*5e7646d2SAndroid Build Coastguard Worker }
441*5e7646d2SAndroid Build Coastguard Worker }
442*5e7646d2SAndroid Build Coastguard Worker }
443*5e7646d2SAndroid Build Coastguard Worker
444*5e7646d2SAndroid Build Coastguard Worker if (*ptr != '\0')
445*5e7646d2SAndroid Build Coastguard Worker *ptr++ = '\0';
446*5e7646d2SAndroid Build Coastguard Worker
447*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("2cupsParseOptions: value=\"%s\"", value));
448*5e7646d2SAndroid Build Coastguard Worker
449*5e7646d2SAndroid Build Coastguard Worker /*
450*5e7646d2SAndroid Build Coastguard Worker * Skip trailing whitespace...
451*5e7646d2SAndroid Build Coastguard Worker */
452*5e7646d2SAndroid Build Coastguard Worker
453*5e7646d2SAndroid Build Coastguard Worker while (_cups_isspace(*ptr))
454*5e7646d2SAndroid Build Coastguard Worker ptr ++;
455*5e7646d2SAndroid Build Coastguard Worker
456*5e7646d2SAndroid Build Coastguard Worker /*
457*5e7646d2SAndroid Build Coastguard Worker * Add the string value...
458*5e7646d2SAndroid Build Coastguard Worker */
459*5e7646d2SAndroid Build Coastguard Worker
460*5e7646d2SAndroid Build Coastguard Worker num_options = cupsAddOption(name, value, num_options, options);
461*5e7646d2SAndroid Build Coastguard Worker }
462*5e7646d2SAndroid Build Coastguard Worker
463*5e7646d2SAndroid Build Coastguard Worker /*
464*5e7646d2SAndroid Build Coastguard Worker * Free the copy of the argument we made and return the number of options
465*5e7646d2SAndroid Build Coastguard Worker * found.
466*5e7646d2SAndroid Build Coastguard Worker */
467*5e7646d2SAndroid Build Coastguard Worker
468*5e7646d2SAndroid Build Coastguard Worker free(copyarg);
469*5e7646d2SAndroid Build Coastguard Worker
470*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1cupsParseOptions: Returning %d", num_options));
471*5e7646d2SAndroid Build Coastguard Worker
472*5e7646d2SAndroid Build Coastguard Worker return (num_options);
473*5e7646d2SAndroid Build Coastguard Worker }
474*5e7646d2SAndroid Build Coastguard Worker
475*5e7646d2SAndroid Build Coastguard Worker
476*5e7646d2SAndroid Build Coastguard Worker /*
477*5e7646d2SAndroid Build Coastguard Worker * 'cupsRemoveOption()' - Remove an option from an option array.
478*5e7646d2SAndroid Build Coastguard Worker *
479*5e7646d2SAndroid Build Coastguard Worker * @since CUPS 1.2/macOS 10.5@
480*5e7646d2SAndroid Build Coastguard Worker */
481*5e7646d2SAndroid Build Coastguard Worker
482*5e7646d2SAndroid Build Coastguard Worker int /* O - New number of options */
cupsRemoveOption(const char * name,int num_options,cups_option_t ** options)483*5e7646d2SAndroid Build Coastguard Worker cupsRemoveOption(
484*5e7646d2SAndroid Build Coastguard Worker const char *name, /* I - Option name */
485*5e7646d2SAndroid Build Coastguard Worker int num_options, /* I - Current number of options */
486*5e7646d2SAndroid Build Coastguard Worker cups_option_t **options) /* IO - Options */
487*5e7646d2SAndroid Build Coastguard Worker {
488*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
489*5e7646d2SAndroid Build Coastguard Worker cups_option_t *option; /* Current option */
490*5e7646d2SAndroid Build Coastguard Worker
491*5e7646d2SAndroid Build Coastguard Worker
492*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("2cupsRemoveOption(name=\"%s\", num_options=%d, options=%p)", name, num_options, (void *)options));
493*5e7646d2SAndroid Build Coastguard Worker
494*5e7646d2SAndroid Build Coastguard Worker /*
495*5e7646d2SAndroid Build Coastguard Worker * Range check input...
496*5e7646d2SAndroid Build Coastguard Worker */
497*5e7646d2SAndroid Build Coastguard Worker
498*5e7646d2SAndroid Build Coastguard Worker if (!name || num_options < 1 || !options)
499*5e7646d2SAndroid Build Coastguard Worker {
500*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("3cupsRemoveOption: Returning %d", num_options));
501*5e7646d2SAndroid Build Coastguard Worker return (num_options);
502*5e7646d2SAndroid Build Coastguard Worker }
503*5e7646d2SAndroid Build Coastguard Worker
504*5e7646d2SAndroid Build Coastguard Worker /*
505*5e7646d2SAndroid Build Coastguard Worker * Loop for the option...
506*5e7646d2SAndroid Build Coastguard Worker */
507*5e7646d2SAndroid Build Coastguard Worker
508*5e7646d2SAndroid Build Coastguard Worker for (i = num_options, option = *options; i > 0; i --, option ++)
509*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strcasecmp(name, option->name))
510*5e7646d2SAndroid Build Coastguard Worker break;
511*5e7646d2SAndroid Build Coastguard Worker
512*5e7646d2SAndroid Build Coastguard Worker if (i)
513*5e7646d2SAndroid Build Coastguard Worker {
514*5e7646d2SAndroid Build Coastguard Worker /*
515*5e7646d2SAndroid Build Coastguard Worker * Remove this option from the array...
516*5e7646d2SAndroid Build Coastguard Worker */
517*5e7646d2SAndroid Build Coastguard Worker
518*5e7646d2SAndroid Build Coastguard Worker DEBUG_puts("4cupsRemoveOption: Found option, removing it...");
519*5e7646d2SAndroid Build Coastguard Worker
520*5e7646d2SAndroid Build Coastguard Worker num_options --;
521*5e7646d2SAndroid Build Coastguard Worker i --;
522*5e7646d2SAndroid Build Coastguard Worker
523*5e7646d2SAndroid Build Coastguard Worker _cupsStrFree(option->name);
524*5e7646d2SAndroid Build Coastguard Worker _cupsStrFree(option->value);
525*5e7646d2SAndroid Build Coastguard Worker
526*5e7646d2SAndroid Build Coastguard Worker if (i > 0)
527*5e7646d2SAndroid Build Coastguard Worker memmove(option, option + 1, (size_t)i * sizeof(cups_option_t));
528*5e7646d2SAndroid Build Coastguard Worker }
529*5e7646d2SAndroid Build Coastguard Worker
530*5e7646d2SAndroid Build Coastguard Worker /*
531*5e7646d2SAndroid Build Coastguard Worker * Return the new number of options...
532*5e7646d2SAndroid Build Coastguard Worker */
533*5e7646d2SAndroid Build Coastguard Worker
534*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("3cupsRemoveOption: Returning %d", num_options));
535*5e7646d2SAndroid Build Coastguard Worker return (num_options);
536*5e7646d2SAndroid Build Coastguard Worker }
537*5e7646d2SAndroid Build Coastguard Worker
538*5e7646d2SAndroid Build Coastguard Worker
539*5e7646d2SAndroid Build Coastguard Worker /*
540*5e7646d2SAndroid Build Coastguard Worker * '_cupsGet1284Values()' - Get 1284 device ID keys and values.
541*5e7646d2SAndroid Build Coastguard Worker *
542*5e7646d2SAndroid Build Coastguard Worker * The returned dictionary is a CUPS option array that can be queried with
543*5e7646d2SAndroid Build Coastguard Worker * cupsGetOption and freed with cupsFreeOptions.
544*5e7646d2SAndroid Build Coastguard Worker */
545*5e7646d2SAndroid Build Coastguard Worker
546*5e7646d2SAndroid Build Coastguard Worker int /* O - Number of key/value pairs */
_cupsGet1284Values(const char * device_id,cups_option_t ** values)547*5e7646d2SAndroid Build Coastguard Worker _cupsGet1284Values(
548*5e7646d2SAndroid Build Coastguard Worker const char *device_id, /* I - IEEE-1284 device ID string */
549*5e7646d2SAndroid Build Coastguard Worker cups_option_t **values) /* O - Array of key/value pairs */
550*5e7646d2SAndroid Build Coastguard Worker {
551*5e7646d2SAndroid Build Coastguard Worker int num_values; /* Number of values */
552*5e7646d2SAndroid Build Coastguard Worker char key[256], /* Key string */
553*5e7646d2SAndroid Build Coastguard Worker value[256], /* Value string */
554*5e7646d2SAndroid Build Coastguard Worker *ptr; /* Pointer into key/value */
555*5e7646d2SAndroid Build Coastguard Worker
556*5e7646d2SAndroid Build Coastguard Worker
557*5e7646d2SAndroid Build Coastguard Worker /*
558*5e7646d2SAndroid Build Coastguard Worker * Range check input...
559*5e7646d2SAndroid Build Coastguard Worker */
560*5e7646d2SAndroid Build Coastguard Worker
561*5e7646d2SAndroid Build Coastguard Worker if (values)
562*5e7646d2SAndroid Build Coastguard Worker *values = NULL;
563*5e7646d2SAndroid Build Coastguard Worker
564*5e7646d2SAndroid Build Coastguard Worker if (!device_id || !values)
565*5e7646d2SAndroid Build Coastguard Worker return (0);
566*5e7646d2SAndroid Build Coastguard Worker
567*5e7646d2SAndroid Build Coastguard Worker /*
568*5e7646d2SAndroid Build Coastguard Worker * Parse the 1284 device ID value into keys and values. The format is
569*5e7646d2SAndroid Build Coastguard Worker * repeating sequences of:
570*5e7646d2SAndroid Build Coastguard Worker *
571*5e7646d2SAndroid Build Coastguard Worker * [whitespace]key:value[whitespace];
572*5e7646d2SAndroid Build Coastguard Worker */
573*5e7646d2SAndroid Build Coastguard Worker
574*5e7646d2SAndroid Build Coastguard Worker num_values = 0;
575*5e7646d2SAndroid Build Coastguard Worker while (*device_id)
576*5e7646d2SAndroid Build Coastguard Worker {
577*5e7646d2SAndroid Build Coastguard Worker while (_cups_isspace(*device_id))
578*5e7646d2SAndroid Build Coastguard Worker device_id ++;
579*5e7646d2SAndroid Build Coastguard Worker
580*5e7646d2SAndroid Build Coastguard Worker if (!*device_id)
581*5e7646d2SAndroid Build Coastguard Worker break;
582*5e7646d2SAndroid Build Coastguard Worker
583*5e7646d2SAndroid Build Coastguard Worker for (ptr = key; *device_id && *device_id != ':'; device_id ++)
584*5e7646d2SAndroid Build Coastguard Worker if (ptr < (key + sizeof(key) - 1))
585*5e7646d2SAndroid Build Coastguard Worker *ptr++ = *device_id;
586*5e7646d2SAndroid Build Coastguard Worker
587*5e7646d2SAndroid Build Coastguard Worker if (!*device_id)
588*5e7646d2SAndroid Build Coastguard Worker break;
589*5e7646d2SAndroid Build Coastguard Worker
590*5e7646d2SAndroid Build Coastguard Worker while (ptr > key && _cups_isspace(ptr[-1]))
591*5e7646d2SAndroid Build Coastguard Worker ptr --;
592*5e7646d2SAndroid Build Coastguard Worker
593*5e7646d2SAndroid Build Coastguard Worker *ptr = '\0';
594*5e7646d2SAndroid Build Coastguard Worker device_id ++;
595*5e7646d2SAndroid Build Coastguard Worker
596*5e7646d2SAndroid Build Coastguard Worker while (_cups_isspace(*device_id))
597*5e7646d2SAndroid Build Coastguard Worker device_id ++;
598*5e7646d2SAndroid Build Coastguard Worker
599*5e7646d2SAndroid Build Coastguard Worker if (!*device_id)
600*5e7646d2SAndroid Build Coastguard Worker break;
601*5e7646d2SAndroid Build Coastguard Worker
602*5e7646d2SAndroid Build Coastguard Worker for (ptr = value; *device_id && *device_id != ';'; device_id ++)
603*5e7646d2SAndroid Build Coastguard Worker if (ptr < (value + sizeof(value) - 1))
604*5e7646d2SAndroid Build Coastguard Worker *ptr++ = *device_id;
605*5e7646d2SAndroid Build Coastguard Worker
606*5e7646d2SAndroid Build Coastguard Worker while (ptr > value && _cups_isspace(ptr[-1]))
607*5e7646d2SAndroid Build Coastguard Worker ptr --;
608*5e7646d2SAndroid Build Coastguard Worker
609*5e7646d2SAndroid Build Coastguard Worker *ptr = '\0';
610*5e7646d2SAndroid Build Coastguard Worker num_values = cupsAddOption(key, value, num_values, values);
611*5e7646d2SAndroid Build Coastguard Worker
612*5e7646d2SAndroid Build Coastguard Worker if (!*device_id)
613*5e7646d2SAndroid Build Coastguard Worker break;
614*5e7646d2SAndroid Build Coastguard Worker device_id ++;
615*5e7646d2SAndroid Build Coastguard Worker }
616*5e7646d2SAndroid Build Coastguard Worker
617*5e7646d2SAndroid Build Coastguard Worker return (num_values);
618*5e7646d2SAndroid Build Coastguard Worker }
619*5e7646d2SAndroid Build Coastguard Worker
620*5e7646d2SAndroid Build Coastguard Worker
621*5e7646d2SAndroid Build Coastguard Worker /*
622*5e7646d2SAndroid Build Coastguard Worker * 'cups_compare_options()' - Compare two options.
623*5e7646d2SAndroid Build Coastguard Worker */
624*5e7646d2SAndroid Build Coastguard Worker
625*5e7646d2SAndroid Build Coastguard Worker static int /* O - Result of comparison */
cups_compare_options(cups_option_t * a,cups_option_t * b)626*5e7646d2SAndroid Build Coastguard Worker cups_compare_options(cups_option_t *a, /* I - First option */
627*5e7646d2SAndroid Build Coastguard Worker cups_option_t *b) /* I - Second option */
628*5e7646d2SAndroid Build Coastguard Worker {
629*5e7646d2SAndroid Build Coastguard Worker return (_cups_strcasecmp(a->name, b->name));
630*5e7646d2SAndroid Build Coastguard Worker }
631*5e7646d2SAndroid Build Coastguard Worker
632*5e7646d2SAndroid Build Coastguard Worker
633*5e7646d2SAndroid Build Coastguard Worker /*
634*5e7646d2SAndroid Build Coastguard Worker * 'cups_find_option()' - Find an option using a binary search.
635*5e7646d2SAndroid Build Coastguard Worker */
636*5e7646d2SAndroid Build Coastguard Worker
637*5e7646d2SAndroid Build Coastguard Worker static int /* O - Index of match */
cups_find_option(const char * name,int num_options,cups_option_t * options,int prev,int * rdiff)638*5e7646d2SAndroid Build Coastguard Worker cups_find_option(
639*5e7646d2SAndroid Build Coastguard Worker const char *name, /* I - Option name */
640*5e7646d2SAndroid Build Coastguard Worker int num_options, /* I - Number of options */
641*5e7646d2SAndroid Build Coastguard Worker cups_option_t *options, /* I - Options */
642*5e7646d2SAndroid Build Coastguard Worker int prev, /* I - Previous index */
643*5e7646d2SAndroid Build Coastguard Worker int *rdiff) /* O - Difference of match */
644*5e7646d2SAndroid Build Coastguard Worker {
645*5e7646d2SAndroid Build Coastguard Worker int left, /* Low mark for binary search */
646*5e7646d2SAndroid Build Coastguard Worker right, /* High mark for binary search */
647*5e7646d2SAndroid Build Coastguard Worker current, /* Current index */
648*5e7646d2SAndroid Build Coastguard Worker diff; /* Result of comparison */
649*5e7646d2SAndroid Build Coastguard Worker cups_option_t key; /* Search key */
650*5e7646d2SAndroid Build Coastguard Worker
651*5e7646d2SAndroid Build Coastguard Worker
652*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("7cups_find_option(name=\"%s\", num_options=%d, options=%p, prev=%d, rdiff=%p)", name, num_options, (void *)options, prev, (void *)rdiff));
653*5e7646d2SAndroid Build Coastguard Worker
654*5e7646d2SAndroid Build Coastguard Worker #ifdef DEBUG
655*5e7646d2SAndroid Build Coastguard Worker for (left = 0; left < num_options; left ++)
656*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("9cups_find_option: options[%d].name=\"%s\", .value=\"%s\"",
657*5e7646d2SAndroid Build Coastguard Worker left, options[left].name, options[left].value));
658*5e7646d2SAndroid Build Coastguard Worker #endif /* DEBUG */
659*5e7646d2SAndroid Build Coastguard Worker
660*5e7646d2SAndroid Build Coastguard Worker key.name = (char *)name;
661*5e7646d2SAndroid Build Coastguard Worker
662*5e7646d2SAndroid Build Coastguard Worker if (prev >= 0)
663*5e7646d2SAndroid Build Coastguard Worker {
664*5e7646d2SAndroid Build Coastguard Worker /*
665*5e7646d2SAndroid Build Coastguard Worker * Start search on either side of previous...
666*5e7646d2SAndroid Build Coastguard Worker */
667*5e7646d2SAndroid Build Coastguard Worker
668*5e7646d2SAndroid Build Coastguard Worker if ((diff = cups_compare_options(&key, options + prev)) == 0 ||
669*5e7646d2SAndroid Build Coastguard Worker (diff < 0 && prev == 0) ||
670*5e7646d2SAndroid Build Coastguard Worker (diff > 0 && prev == (num_options - 1)))
671*5e7646d2SAndroid Build Coastguard Worker {
672*5e7646d2SAndroid Build Coastguard Worker *rdiff = diff;
673*5e7646d2SAndroid Build Coastguard Worker return (prev);
674*5e7646d2SAndroid Build Coastguard Worker }
675*5e7646d2SAndroid Build Coastguard Worker else if (diff < 0)
676*5e7646d2SAndroid Build Coastguard Worker {
677*5e7646d2SAndroid Build Coastguard Worker /*
678*5e7646d2SAndroid Build Coastguard Worker * Start with previous on right side...
679*5e7646d2SAndroid Build Coastguard Worker */
680*5e7646d2SAndroid Build Coastguard Worker
681*5e7646d2SAndroid Build Coastguard Worker left = 0;
682*5e7646d2SAndroid Build Coastguard Worker right = prev;
683*5e7646d2SAndroid Build Coastguard Worker }
684*5e7646d2SAndroid Build Coastguard Worker else
685*5e7646d2SAndroid Build Coastguard Worker {
686*5e7646d2SAndroid Build Coastguard Worker /*
687*5e7646d2SAndroid Build Coastguard Worker * Start wih previous on left side...
688*5e7646d2SAndroid Build Coastguard Worker */
689*5e7646d2SAndroid Build Coastguard Worker
690*5e7646d2SAndroid Build Coastguard Worker left = prev;
691*5e7646d2SAndroid Build Coastguard Worker right = num_options - 1;
692*5e7646d2SAndroid Build Coastguard Worker }
693*5e7646d2SAndroid Build Coastguard Worker }
694*5e7646d2SAndroid Build Coastguard Worker else
695*5e7646d2SAndroid Build Coastguard Worker {
696*5e7646d2SAndroid Build Coastguard Worker /*
697*5e7646d2SAndroid Build Coastguard Worker * Start search in the middle...
698*5e7646d2SAndroid Build Coastguard Worker */
699*5e7646d2SAndroid Build Coastguard Worker
700*5e7646d2SAndroid Build Coastguard Worker left = 0;
701*5e7646d2SAndroid Build Coastguard Worker right = num_options - 1;
702*5e7646d2SAndroid Build Coastguard Worker }
703*5e7646d2SAndroid Build Coastguard Worker
704*5e7646d2SAndroid Build Coastguard Worker do
705*5e7646d2SAndroid Build Coastguard Worker {
706*5e7646d2SAndroid Build Coastguard Worker current = (left + right) / 2;
707*5e7646d2SAndroid Build Coastguard Worker diff = cups_compare_options(&key, options + current);
708*5e7646d2SAndroid Build Coastguard Worker
709*5e7646d2SAndroid Build Coastguard Worker if (diff == 0)
710*5e7646d2SAndroid Build Coastguard Worker break;
711*5e7646d2SAndroid Build Coastguard Worker else if (diff < 0)
712*5e7646d2SAndroid Build Coastguard Worker right = current;
713*5e7646d2SAndroid Build Coastguard Worker else
714*5e7646d2SAndroid Build Coastguard Worker left = current;
715*5e7646d2SAndroid Build Coastguard Worker }
716*5e7646d2SAndroid Build Coastguard Worker while ((right - left) > 1);
717*5e7646d2SAndroid Build Coastguard Worker
718*5e7646d2SAndroid Build Coastguard Worker if (diff != 0)
719*5e7646d2SAndroid Build Coastguard Worker {
720*5e7646d2SAndroid Build Coastguard Worker /*
721*5e7646d2SAndroid Build Coastguard Worker * Check the last 1 or 2 elements...
722*5e7646d2SAndroid Build Coastguard Worker */
723*5e7646d2SAndroid Build Coastguard Worker
724*5e7646d2SAndroid Build Coastguard Worker if ((diff = cups_compare_options(&key, options + left)) <= 0)
725*5e7646d2SAndroid Build Coastguard Worker current = left;
726*5e7646d2SAndroid Build Coastguard Worker else
727*5e7646d2SAndroid Build Coastguard Worker {
728*5e7646d2SAndroid Build Coastguard Worker diff = cups_compare_options(&key, options + right);
729*5e7646d2SAndroid Build Coastguard Worker current = right;
730*5e7646d2SAndroid Build Coastguard Worker }
731*5e7646d2SAndroid Build Coastguard Worker }
732*5e7646d2SAndroid Build Coastguard Worker
733*5e7646d2SAndroid Build Coastguard Worker /*
734*5e7646d2SAndroid Build Coastguard Worker * Return the closest destination and the difference...
735*5e7646d2SAndroid Build Coastguard Worker */
736*5e7646d2SAndroid Build Coastguard Worker
737*5e7646d2SAndroid Build Coastguard Worker *rdiff = diff;
738*5e7646d2SAndroid Build Coastguard Worker
739*5e7646d2SAndroid Build Coastguard Worker return (current);
740*5e7646d2SAndroid Build Coastguard Worker }
741