]>
git.ipfire.org Git - thirdparty/cups.git/blob - cups/options.c
2 * "$Id: options.c 8181 2008-12-10 17:29:57Z mike $"
4 * Option routines for CUPS.
6 * Copyright 2007-2010 by Apple Inc.
7 * Copyright 1997-2007 by Easy Software Products.
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
15 * This file is subject to the Apple OS-Developed Software exception.
19 * cupsAddOption() - Add an option to an option array.
20 * cupsFreeOptions() - Free all memory used by options.
21 * cupsGetOption() - Get an option value.
22 * cupsParseOptions() - Parse options from a command-line argument.
23 * cupsRemoveOption() - Remove an option from an option array.
24 * _cupsGet1284Values() - Get 1284 device ID keys and values.
25 * cups_compare_options() - Compare two options.
26 * cups_find_option() - Find an option using a binary search.
30 * Include necessary headers...
34 #include "string-private.h"
35 #include "debug-private.h"
42 static int cups_compare_options(cups_option_t
*a
, cups_option_t
*b
);
43 static int cups_find_option(const char *name
, int num_options
,
44 cups_option_t
*option
, int prev
, int *rdiff
);
48 * 'cupsAddOption()' - Add an option to an option array.
50 * New option arrays can be initialized simply by passing 0 for the
51 * "num_options" parameter.
54 int /* O - Number of options */
55 cupsAddOption(const char *name
, /* I - Name of option */
56 const char *value
, /* I - Value of option */
57 int num_options
,/* I - Number of options */
58 cups_option_t
**options
) /* IO - Pointer to options */
60 cups_option_t
*temp
; /* Pointer to new option */
61 int insert
, /* Insertion point */
62 diff
; /* Result of search */
65 DEBUG_printf(("2cupsAddOption(name=\"%s\", value=\"%s\", num_options=%d, "
66 "options=%p)", name
, value
, num_options
, options
));
68 if (!name
|| !name
[0] || !value
|| !options
|| num_options
< 0)
70 DEBUG_printf(("3cupsAddOption: Returning %d", num_options
));
75 * Look for an existing option with the same name...
85 insert
= cups_find_option(name
, num_options
, *options
, num_options
- 1,
95 * No matching option name...
98 DEBUG_printf(("4cupsAddOption: New option inserted at index %d...",
101 if (num_options
== 0)
102 temp
= (cups_option_t
*)malloc(sizeof(cups_option_t
));
104 temp
= (cups_option_t
*)realloc(*options
, sizeof(cups_option_t
) *
109 DEBUG_puts("3cupsAddOption: Unable to expand option array, returning 0");
115 if (insert
< num_options
)
117 DEBUG_printf(("4cupsAddOption: Shifting %d options...",
118 (int)(num_options
- insert
)));
119 memmove(temp
+ insert
+ 1, temp
+ insert
,
120 (num_options
- insert
) * sizeof(cups_option_t
));
124 temp
->name
= _cupsStrAlloc(name
);
130 * Match found; free the old value...
133 DEBUG_printf(("4cupsAddOption: Option already exists at index %d...",
136 temp
= *options
+ insert
;
137 _cupsStrFree(temp
->value
);
140 temp
->value
= _cupsStrAlloc(value
);
142 DEBUG_printf(("3cupsAddOption: Returning %d", num_options
));
144 return (num_options
);
149 * 'cupsFreeOptions()' - Free all memory used by options.
154 int num_options
, /* I - Number of options */
155 cups_option_t
*options
) /* I - Pointer to options */
157 int i
; /* Looping var */
160 DEBUG_printf(("cupsFreeOptions(num_options=%d, options=%p)", num_options
,
163 if (num_options
<= 0 || !options
)
166 for (i
= 0; i
< num_options
; i
++)
168 _cupsStrFree(options
[i
].name
);
169 _cupsStrFree(options
[i
].value
);
177 * 'cupsGetOption()' - Get an option value.
180 const char * /* O - Option value or @code NULL@ */
181 cupsGetOption(const char *name
, /* I - Name of option */
182 int num_options
,/* I - Number of options */
183 cups_option_t
*options
) /* I - Options */
185 int diff
, /* Result of comparison */
186 match
; /* Matching index */
189 DEBUG_printf(("2cupsGetOption(name=\"%s\", num_options=%d, options=%p)",
190 name
, num_options
, options
));
192 if (!name
|| num_options
<= 0 || !options
)
194 DEBUG_puts("3cupsGetOption: Returning NULL");
198 match
= cups_find_option(name
, num_options
, options
, -1, &diff
);
202 DEBUG_printf(("3cupsGetOption: Returning \"%s\"", options
[match
].value
));
203 return (options
[match
].value
);
206 DEBUG_puts("3cupsGetOption: Returning NULL");
212 * 'cupsParseOptions()' - Parse options from a command-line argument.
214 * This function converts space-delimited name/value pairs according
215 * to the PAPI text option ABNF specification. Collection values
216 * ("name={a=... b=... c=...}") are stored with the curley brackets
217 * intact - use @code cupsParseOptions@ on the value to extract the
218 * collection attributes.
221 int /* O - Number of options found */
223 const char *arg
, /* I - Argument to parse */
224 int num_options
, /* I - Number of options */
225 cups_option_t
**options
) /* O - Options found */
227 char *copyarg
, /* Copy of input string */
228 *ptr
, /* Pointer into string */
229 *name
, /* Pointer to name */
230 *value
, /* Pointer to value */
231 sep
, /* Separator character */
232 quote
; /* Quote character */
235 DEBUG_printf(("cupsParseOptions(arg=\"%s\", num_options=%d, options=%p)",
236 arg
, num_options
, options
));
239 * Range check input...
244 DEBUG_printf(("1cupsParseOptions: Returning %d", num_options
));
245 return (num_options
);
248 if (!options
|| num_options
< 0)
250 DEBUG_puts("1cupsParseOptions: Returning 0");
255 * Make a copy of the argument string and then divide it up...
258 if ((copyarg
= strdup(arg
)) == NULL
)
260 DEBUG_puts("1cupsParseOptions: Unable to copy arg string");
261 DEBUG_printf(("1cupsParseOptions: Returning %d", num_options
));
262 return (num_options
);
268 * Remove surrounding {} so we can parse "{name=value ... name=value}"...
271 if ((ptr
= copyarg
+ strlen(copyarg
) - 1) > copyarg
&& *ptr
== '}')
283 * Skip leading spaces...
286 while (isspace(*ptr
& 255))
290 * Loop through the string...
296 * Get the name up to a SPACE, =, or end-of-string...
300 while (!isspace(*ptr
& 255) && *ptr
!= '=' && *ptr
)
304 * Avoid an empty name...
311 * Skip trailing spaces...
314 while (isspace(*ptr
& 255))
317 if ((sep
= *ptr
) == '=')
320 DEBUG_printf(("2cupsParseOptions: name=\"%s\"", name
));
328 if (!strncasecmp(name
, "no", 2))
329 num_options
= cupsAddOption(name
+ 2, "false", num_options
,
332 num_options
= cupsAddOption(name
, "true", num_options
, options
);
338 * Remove = and parse the value...
343 while (*ptr
&& !isspace(*ptr
& 255))
347 else if (*ptr
== '\'' || *ptr
== '\"')
350 * Quoted string constant...
354 _cups_strcpy(ptr
, ptr
+ 1);
356 while (*ptr
!= quote
&& *ptr
)
358 if (*ptr
== '\\' && ptr
[1])
359 _cups_strcpy(ptr
, ptr
+ 1);
365 _cups_strcpy(ptr
, ptr
+ 1);
367 else if (*ptr
== '{')
370 * Collection value...
375 for (depth
= 0; *ptr
; ptr
++)
379 else if (*ptr
== '}')
388 else if (*ptr
== '\\' && ptr
[1])
389 _cups_strcpy(ptr
, ptr
+ 1);
395 * Normal space-delimited string...
398 while (!isspace(*ptr
& 255) && *ptr
)
400 if (*ptr
== '\\' && ptr
[1])
401 _cups_strcpy(ptr
, ptr
+ 1);
411 DEBUG_printf(("2cupsParseOptions: value=\"%s\"", value
));
414 * Skip trailing whitespace...
417 while (isspace(*ptr
& 255))
421 * Add the string value...
424 num_options
= cupsAddOption(name
, value
, num_options
, options
);
428 * Free the copy of the argument we made and return the number of options
434 DEBUG_printf(("1cupsParseOptions: Returning %d", num_options
));
436 return (num_options
);
441 * 'cupsRemoveOption()' - Remove an option from an option array.
443 * @since CUPS 1.2/Mac OS X 10.5@
446 int /* O - New number of options */
448 const char *name
, /* I - Option name */
449 int num_options
, /* I - Current number of options */
450 cups_option_t
**options
) /* IO - Options */
452 int i
; /* Looping var */
453 cups_option_t
*option
; /* Current option */
456 DEBUG_printf(("2cupsRemoveOption(name=\"%s\", num_options=%d, options=%p)",
457 name
, num_options
, options
));
460 * Range check input...
463 if (!name
|| num_options
< 1 || !options
)
465 DEBUG_printf(("3cupsRemoveOption: Returning %d", num_options
));
466 return (num_options
);
470 * Loop for the option...
473 for (i
= num_options
, option
= *options
; i
> 0; i
--, option
++)
474 if (!strcasecmp(name
, option
->name
))
480 * Remove this option from the array...
483 DEBUG_puts("4cupsRemoveOption: Found option, removing it...");
488 _cupsStrFree(option
->name
);
489 _cupsStrFree(option
->value
);
492 memmove(option
, option
+ 1, i
* sizeof(cups_option_t
));
496 * Return the new number of options...
499 DEBUG_printf(("3cupsRemoveOption: Returning %d", num_options
));
500 return (num_options
);
505 * '_cupsGet1284Values()' - Get 1284 device ID keys and values.
507 * The returned dictionary is a CUPS option array that can be queried with
508 * cupsGetOption and freed with cupsFreeOptions.
511 int /* O - Number of key/value pairs */
513 const char *device_id
, /* I - IEEE-1284 device ID string */
514 cups_option_t
**values
) /* O - Array of key/value pairs */
516 int num_values
; /* Number of values */
517 char key
[256], /* Key string */
518 value
[256], /* Value string */
519 *ptr
; /* Pointer into key/value */
523 * Range check input...
529 if (!device_id
|| !values
)
533 * Parse the 1284 device ID value into keys and values. The format is
534 * repeating sequences of:
536 * [whitespace]key:value[whitespace];
542 while (isspace(*device_id
& 255))
548 for (ptr
= key
; *device_id
&& *device_id
!= ':'; device_id
++)
549 if (ptr
< (key
+ sizeof(key
) - 1))
555 while (ptr
> key
&& isspace(ptr
[-1] & 255))
561 while (isspace(*device_id
& 255))
567 for (ptr
= value
; *device_id
&& *device_id
!= ';'; device_id
++)
568 if (ptr
< (value
+ sizeof(value
) - 1))
574 while (ptr
> value
&& isspace(ptr
[-1] & 255))
580 num_values
= cupsAddOption(key
, value
, num_values
, values
);
588 * 'cups_compare_options()' - Compare two options.
591 static int /* O - Result of comparison */
592 cups_compare_options(cups_option_t
*a
, /* I - First option */
593 cups_option_t
*b
) /* I - Second option */
595 return (strcasecmp(a
->name
, b
->name
));
600 * 'cups_find_option()' - Find an option using a binary search.
603 static int /* O - Index of match */
605 const char *name
, /* I - Option name */
606 int num_options
, /* I - Number of options */
607 cups_option_t
*options
, /* I - Options */
608 int prev
, /* I - Previous index */
609 int *rdiff
) /* O - Difference of match */
611 int left
, /* Low mark for binary search */
612 right
, /* High mark for binary search */
613 current
, /* Current index */
614 diff
; /* Result of comparison */
615 cups_option_t key
; /* Search key */
618 DEBUG_printf(("7cups_find_option(name=\"%s\", num_options=%d, options=%p, "
619 "prev=%d, rdiff=%p)", name
, num_options
, options
, prev
,
623 for (left
= 0; left
< num_options
; left
++)
624 DEBUG_printf(("9cups_find_option: options[%d].name=\"%s\", .value=\"%s\"",
625 left
, options
[left
].name
, options
[left
].value
));
628 key
.name
= (char *)name
;
633 * Start search on either side of previous...
636 if ((diff
= cups_compare_options(&key
, options
+ prev
)) == 0 ||
637 (diff
< 0 && prev
== 0) ||
638 (diff
> 0 && prev
== (num_options
- 1)))
646 * Start with previous on right side...
655 * Start wih previous on left side...
659 right
= num_options
- 1;
665 * Start search in the middle...
669 right
= num_options
- 1;
674 current
= (left
+ right
) / 2;
675 diff
= cups_compare_options(&key
, options
+ current
);
684 while ((right
- left
) > 1);
689 * Check the last 1 or 2 elements...
692 if ((diff
= cups_compare_options(&key
, options
+ left
)) <= 0)
696 diff
= cups_compare_options(&key
, options
+ right
);
702 * Return the closest destination and the difference...
712 * End of "$Id: options.c 8181 2008-12-10 17:29:57Z mike $".