xref: /aosp_15_r20/external/libcups/cups/string.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker  * String functions for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker  *
4*5e7646d2SAndroid Build Coastguard Worker  * Copyright © 2007-2019 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
8*5e7646d2SAndroid Build Coastguard Worker  * information.
9*5e7646d2SAndroid Build Coastguard Worker  */
10*5e7646d2SAndroid Build Coastguard Worker 
11*5e7646d2SAndroid Build Coastguard Worker /*
12*5e7646d2SAndroid Build Coastguard Worker  * Include necessary headers...
13*5e7646d2SAndroid Build Coastguard Worker  */
14*5e7646d2SAndroid Build Coastguard Worker 
15*5e7646d2SAndroid Build Coastguard Worker #define _CUPS_STRING_C_
16*5e7646d2SAndroid Build Coastguard Worker #include "cups-private.h"
17*5e7646d2SAndroid Build Coastguard Worker #include "debug-internal.h"
18*5e7646d2SAndroid Build Coastguard Worker #include <stddef.h>
19*5e7646d2SAndroid Build Coastguard Worker #include <limits.h>
20*5e7646d2SAndroid Build Coastguard Worker 
21*5e7646d2SAndroid Build Coastguard Worker 
22*5e7646d2SAndroid Build Coastguard Worker /*
23*5e7646d2SAndroid Build Coastguard Worker  * Local globals...
24*5e7646d2SAndroid Build Coastguard Worker  */
25*5e7646d2SAndroid Build Coastguard Worker 
26*5e7646d2SAndroid Build Coastguard Worker static _cups_mutex_t	sp_mutex = _CUPS_MUTEX_INITIALIZER;
27*5e7646d2SAndroid Build Coastguard Worker 					/* Mutex to control access to pool */
28*5e7646d2SAndroid Build Coastguard Worker static cups_array_t	*stringpool = NULL;
29*5e7646d2SAndroid Build Coastguard Worker 					/* Global string pool */
30*5e7646d2SAndroid Build Coastguard Worker 
31*5e7646d2SAndroid Build Coastguard Worker 
32*5e7646d2SAndroid Build Coastguard Worker /*
33*5e7646d2SAndroid Build Coastguard Worker  * Local functions...
34*5e7646d2SAndroid Build Coastguard Worker  */
35*5e7646d2SAndroid Build Coastguard Worker 
36*5e7646d2SAndroid Build Coastguard Worker static int	compare_sp_items(_cups_sp_item_t *a, _cups_sp_item_t *b);
37*5e7646d2SAndroid Build Coastguard Worker 
38*5e7646d2SAndroid Build Coastguard Worker 
39*5e7646d2SAndroid Build Coastguard Worker /*
40*5e7646d2SAndroid Build Coastguard Worker  * '_cupsStrAlloc()' - Allocate/reference a string.
41*5e7646d2SAndroid Build Coastguard Worker  */
42*5e7646d2SAndroid Build Coastguard Worker 
43*5e7646d2SAndroid Build Coastguard Worker char *					/* O - String pointer */
_cupsStrAlloc(const char * s)44*5e7646d2SAndroid Build Coastguard Worker _cupsStrAlloc(const char *s)		/* I - String */
45*5e7646d2SAndroid Build Coastguard Worker {
46*5e7646d2SAndroid Build Coastguard Worker   size_t		slen;		/* Length of string */
47*5e7646d2SAndroid Build Coastguard Worker   _cups_sp_item_t	*item,		/* String pool item */
48*5e7646d2SAndroid Build Coastguard Worker 			*key;		/* Search key */
49*5e7646d2SAndroid Build Coastguard Worker 
50*5e7646d2SAndroid Build Coastguard Worker 
51*5e7646d2SAndroid Build Coastguard Worker  /*
52*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
53*5e7646d2SAndroid Build Coastguard Worker   */
54*5e7646d2SAndroid Build Coastguard Worker 
55*5e7646d2SAndroid Build Coastguard Worker   if (!s)
56*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
57*5e7646d2SAndroid Build Coastguard Worker 
58*5e7646d2SAndroid Build Coastguard Worker  /*
59*5e7646d2SAndroid Build Coastguard Worker   * Get the string pool...
60*5e7646d2SAndroid Build Coastguard Worker   */
61*5e7646d2SAndroid Build Coastguard Worker 
62*5e7646d2SAndroid Build Coastguard Worker   _cupsMutexLock(&sp_mutex);
63*5e7646d2SAndroid Build Coastguard Worker 
64*5e7646d2SAndroid Build Coastguard Worker   if (!stringpool)
65*5e7646d2SAndroid Build Coastguard Worker     stringpool = cupsArrayNew((cups_array_func_t)compare_sp_items, NULL);
66*5e7646d2SAndroid Build Coastguard Worker 
67*5e7646d2SAndroid Build Coastguard Worker   if (!stringpool)
68*5e7646d2SAndroid Build Coastguard Worker   {
69*5e7646d2SAndroid Build Coastguard Worker     _cupsMutexUnlock(&sp_mutex);
70*5e7646d2SAndroid Build Coastguard Worker 
71*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
72*5e7646d2SAndroid Build Coastguard Worker   }
73*5e7646d2SAndroid Build Coastguard Worker 
74*5e7646d2SAndroid Build Coastguard Worker  /*
75*5e7646d2SAndroid Build Coastguard Worker   * See if the string is already in the pool...
76*5e7646d2SAndroid Build Coastguard Worker   */
77*5e7646d2SAndroid Build Coastguard Worker 
78*5e7646d2SAndroid Build Coastguard Worker   key = (_cups_sp_item_t *)(s - offsetof(_cups_sp_item_t, str));
79*5e7646d2SAndroid Build Coastguard Worker 
80*5e7646d2SAndroid Build Coastguard Worker   if ((item = (_cups_sp_item_t *)cupsArrayFind(stringpool, key)) != NULL)
81*5e7646d2SAndroid Build Coastguard Worker   {
82*5e7646d2SAndroid Build Coastguard Worker    /*
83*5e7646d2SAndroid Build Coastguard Worker     * Found it, return the cached string...
84*5e7646d2SAndroid Build Coastguard Worker     */
85*5e7646d2SAndroid Build Coastguard Worker 
86*5e7646d2SAndroid Build Coastguard Worker     item->ref_count ++;
87*5e7646d2SAndroid Build Coastguard Worker 
88*5e7646d2SAndroid Build Coastguard Worker #ifdef DEBUG_GUARDS
89*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("5_cupsStrAlloc: Using string %p(%s) for \"%s\", guard=%08x, "
90*5e7646d2SAndroid Build Coastguard Worker                   "ref_count=%d", item, item->str, s, item->guard,
91*5e7646d2SAndroid Build Coastguard Worker 		  item->ref_count));
92*5e7646d2SAndroid Build Coastguard Worker 
93*5e7646d2SAndroid Build Coastguard Worker     if (item->guard != _CUPS_STR_GUARD)
94*5e7646d2SAndroid Build Coastguard Worker       abort();
95*5e7646d2SAndroid Build Coastguard Worker #endif /* DEBUG_GUARDS */
96*5e7646d2SAndroid Build Coastguard Worker 
97*5e7646d2SAndroid Build Coastguard Worker     _cupsMutexUnlock(&sp_mutex);
98*5e7646d2SAndroid Build Coastguard Worker 
99*5e7646d2SAndroid Build Coastguard Worker     return (item->str);
100*5e7646d2SAndroid Build Coastguard Worker   }
101*5e7646d2SAndroid Build Coastguard Worker 
102*5e7646d2SAndroid Build Coastguard Worker  /*
103*5e7646d2SAndroid Build Coastguard Worker   * Not found, so allocate a new one...
104*5e7646d2SAndroid Build Coastguard Worker   */
105*5e7646d2SAndroid Build Coastguard Worker 
106*5e7646d2SAndroid Build Coastguard Worker   slen = strlen(s);
107*5e7646d2SAndroid Build Coastguard Worker   item = (_cups_sp_item_t *)calloc(1, sizeof(_cups_sp_item_t) + slen);
108*5e7646d2SAndroid Build Coastguard Worker   if (!item)
109*5e7646d2SAndroid Build Coastguard Worker   {
110*5e7646d2SAndroid Build Coastguard Worker     _cupsMutexUnlock(&sp_mutex);
111*5e7646d2SAndroid Build Coastguard Worker 
112*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
113*5e7646d2SAndroid Build Coastguard Worker   }
114*5e7646d2SAndroid Build Coastguard Worker 
115*5e7646d2SAndroid Build Coastguard Worker   item->ref_count = 1;
116*5e7646d2SAndroid Build Coastguard Worker   memcpy(item->str, s, slen + 1);
117*5e7646d2SAndroid Build Coastguard Worker 
118*5e7646d2SAndroid Build Coastguard Worker #ifdef DEBUG_GUARDS
119*5e7646d2SAndroid Build Coastguard Worker   item->guard = _CUPS_STR_GUARD;
120*5e7646d2SAndroid Build Coastguard Worker 
121*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("5_cupsStrAlloc: Created string %p(%s) for \"%s\", guard=%08x, "
122*5e7646d2SAndroid Build Coastguard Worker 		"ref_count=%d", item, item->str, s, item->guard,
123*5e7646d2SAndroid Build Coastguard Worker 		item->ref_count));
124*5e7646d2SAndroid Build Coastguard Worker #endif /* DEBUG_GUARDS */
125*5e7646d2SAndroid Build Coastguard Worker 
126*5e7646d2SAndroid Build Coastguard Worker  /*
127*5e7646d2SAndroid Build Coastguard Worker   * Add the string to the pool and return it...
128*5e7646d2SAndroid Build Coastguard Worker   */
129*5e7646d2SAndroid Build Coastguard Worker 
130*5e7646d2SAndroid Build Coastguard Worker   cupsArrayAdd(stringpool, item);
131*5e7646d2SAndroid Build Coastguard Worker 
132*5e7646d2SAndroid Build Coastguard Worker   _cupsMutexUnlock(&sp_mutex);
133*5e7646d2SAndroid Build Coastguard Worker 
134*5e7646d2SAndroid Build Coastguard Worker   return (item->str);
135*5e7646d2SAndroid Build Coastguard Worker }
136*5e7646d2SAndroid Build Coastguard Worker 
137*5e7646d2SAndroid Build Coastguard Worker 
138*5e7646d2SAndroid Build Coastguard Worker /*
139*5e7646d2SAndroid Build Coastguard Worker  * '_cupsStrDate()' - Return a localized date for a given time value.
140*5e7646d2SAndroid Build Coastguard Worker  *
141*5e7646d2SAndroid Build Coastguard Worker  * This function works around the locale encoding issues of strftime...
142*5e7646d2SAndroid Build Coastguard Worker  */
143*5e7646d2SAndroid Build Coastguard Worker 
144*5e7646d2SAndroid Build Coastguard Worker char *					/* O - Buffer */
_cupsStrDate(char * buf,size_t bufsize,time_t timeval)145*5e7646d2SAndroid Build Coastguard Worker _cupsStrDate(char   *buf,		/* I - Buffer */
146*5e7646d2SAndroid Build Coastguard Worker              size_t bufsize,		/* I - Size of buffer */
147*5e7646d2SAndroid Build Coastguard Worker 	     time_t timeval)		/* I - Time value */
148*5e7646d2SAndroid Build Coastguard Worker {
149*5e7646d2SAndroid Build Coastguard Worker   struct tm	date;			/* Local date/time */
150*5e7646d2SAndroid Build Coastguard Worker   char		temp[1024];		/* Temporary buffer */
151*5e7646d2SAndroid Build Coastguard Worker   _cups_globals_t *cg = _cupsGlobals();	/* Per-thread globals */
152*5e7646d2SAndroid Build Coastguard Worker 
153*5e7646d2SAndroid Build Coastguard Worker 
154*5e7646d2SAndroid Build Coastguard Worker   if (!cg->lang_default)
155*5e7646d2SAndroid Build Coastguard Worker     cg->lang_default = cupsLangDefault();
156*5e7646d2SAndroid Build Coastguard Worker 
157*5e7646d2SAndroid Build Coastguard Worker   localtime_r(&timeval, &date);
158*5e7646d2SAndroid Build Coastguard Worker 
159*5e7646d2SAndroid Build Coastguard Worker   if (cg->lang_default->encoding != CUPS_UTF8)
160*5e7646d2SAndroid Build Coastguard Worker   {
161*5e7646d2SAndroid Build Coastguard Worker     strftime(temp, sizeof(temp), "%c", &date);
162*5e7646d2SAndroid Build Coastguard Worker     cupsCharsetToUTF8((cups_utf8_t *)buf, temp, (int)bufsize, cg->lang_default->encoding);
163*5e7646d2SAndroid Build Coastguard Worker   }
164*5e7646d2SAndroid Build Coastguard Worker   else
165*5e7646d2SAndroid Build Coastguard Worker     strftime(buf, bufsize, "%c", &date);
166*5e7646d2SAndroid Build Coastguard Worker 
167*5e7646d2SAndroid Build Coastguard Worker   return (buf);
168*5e7646d2SAndroid Build Coastguard Worker }
169*5e7646d2SAndroid Build Coastguard Worker 
170*5e7646d2SAndroid Build Coastguard Worker 
171*5e7646d2SAndroid Build Coastguard Worker /*
172*5e7646d2SAndroid Build Coastguard Worker  * '_cupsStrFlush()' - Flush the string pool.
173*5e7646d2SAndroid Build Coastguard Worker  */
174*5e7646d2SAndroid Build Coastguard Worker 
175*5e7646d2SAndroid Build Coastguard Worker void
_cupsStrFlush(void)176*5e7646d2SAndroid Build Coastguard Worker _cupsStrFlush(void)
177*5e7646d2SAndroid Build Coastguard Worker {
178*5e7646d2SAndroid Build Coastguard Worker   _cups_sp_item_t	*item;		/* Current item */
179*5e7646d2SAndroid Build Coastguard Worker 
180*5e7646d2SAndroid Build Coastguard Worker 
181*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("4_cupsStrFlush: %d strings in array",
182*5e7646d2SAndroid Build Coastguard Worker                 cupsArrayCount(stringpool)));
183*5e7646d2SAndroid Build Coastguard Worker 
184*5e7646d2SAndroid Build Coastguard Worker   _cupsMutexLock(&sp_mutex);
185*5e7646d2SAndroid Build Coastguard Worker 
186*5e7646d2SAndroid Build Coastguard Worker   for (item = (_cups_sp_item_t *)cupsArrayFirst(stringpool);
187*5e7646d2SAndroid Build Coastguard Worker        item;
188*5e7646d2SAndroid Build Coastguard Worker        item = (_cups_sp_item_t *)cupsArrayNext(stringpool))
189*5e7646d2SAndroid Build Coastguard Worker     free(item);
190*5e7646d2SAndroid Build Coastguard Worker 
191*5e7646d2SAndroid Build Coastguard Worker   cupsArrayDelete(stringpool);
192*5e7646d2SAndroid Build Coastguard Worker   stringpool = NULL;
193*5e7646d2SAndroid Build Coastguard Worker 
194*5e7646d2SAndroid Build Coastguard Worker   _cupsMutexUnlock(&sp_mutex);
195*5e7646d2SAndroid Build Coastguard Worker }
196*5e7646d2SAndroid Build Coastguard Worker 
197*5e7646d2SAndroid Build Coastguard Worker 
198*5e7646d2SAndroid Build Coastguard Worker /*
199*5e7646d2SAndroid Build Coastguard Worker  * '_cupsStrFormatd()' - Format a floating-point number.
200*5e7646d2SAndroid Build Coastguard Worker  */
201*5e7646d2SAndroid Build Coastguard Worker 
202*5e7646d2SAndroid Build Coastguard Worker char *					/* O - Pointer to end of string */
_cupsStrFormatd(char * buf,char * bufend,double number,struct lconv * loc)203*5e7646d2SAndroid Build Coastguard Worker _cupsStrFormatd(char         *buf,	/* I - String */
204*5e7646d2SAndroid Build Coastguard Worker                 char         *bufend,	/* I - End of string buffer */
205*5e7646d2SAndroid Build Coastguard Worker 		double       number,	/* I - Number to format */
206*5e7646d2SAndroid Build Coastguard Worker                 struct lconv *loc)	/* I - Locale data */
207*5e7646d2SAndroid Build Coastguard Worker {
208*5e7646d2SAndroid Build Coastguard Worker   char		*bufptr,		/* Pointer into buffer */
209*5e7646d2SAndroid Build Coastguard Worker 		temp[1024],		/* Temporary string */
210*5e7646d2SAndroid Build Coastguard Worker 		*tempdec,		/* Pointer to decimal point */
211*5e7646d2SAndroid Build Coastguard Worker 		*tempptr;		/* Pointer into temporary string */
212*5e7646d2SAndroid Build Coastguard Worker   const char	*dec;			/* Decimal point */
213*5e7646d2SAndroid Build Coastguard Worker   int		declen;			/* Length of decimal point */
214*5e7646d2SAndroid Build Coastguard Worker 
215*5e7646d2SAndroid Build Coastguard Worker 
216*5e7646d2SAndroid Build Coastguard Worker  /*
217*5e7646d2SAndroid Build Coastguard Worker   * Format the number using the "%.12f" format and then eliminate
218*5e7646d2SAndroid Build Coastguard Worker   * unnecessary trailing 0's.
219*5e7646d2SAndroid Build Coastguard Worker   */
220*5e7646d2SAndroid Build Coastguard Worker 
221*5e7646d2SAndroid Build Coastguard Worker   snprintf(temp, sizeof(temp), "%.12f", number);
222*5e7646d2SAndroid Build Coastguard Worker   for (tempptr = temp + strlen(temp) - 1;
223*5e7646d2SAndroid Build Coastguard Worker        tempptr > temp && *tempptr == '0';
224*5e7646d2SAndroid Build Coastguard Worker        *tempptr-- = '\0');
225*5e7646d2SAndroid Build Coastguard Worker 
226*5e7646d2SAndroid Build Coastguard Worker  /*
227*5e7646d2SAndroid Build Coastguard Worker   * Next, find the decimal point...
228*5e7646d2SAndroid Build Coastguard Worker   */
229*5e7646d2SAndroid Build Coastguard Worker 
230*5e7646d2SAndroid Build Coastguard Worker   if (loc && loc->decimal_point)
231*5e7646d2SAndroid Build Coastguard Worker   {
232*5e7646d2SAndroid Build Coastguard Worker     dec    = loc->decimal_point;
233*5e7646d2SAndroid Build Coastguard Worker     declen = (int)strlen(dec);
234*5e7646d2SAndroid Build Coastguard Worker   }
235*5e7646d2SAndroid Build Coastguard Worker   else
236*5e7646d2SAndroid Build Coastguard Worker   {
237*5e7646d2SAndroid Build Coastguard Worker     dec    = ".";
238*5e7646d2SAndroid Build Coastguard Worker     declen = 1;
239*5e7646d2SAndroid Build Coastguard Worker   }
240*5e7646d2SAndroid Build Coastguard Worker 
241*5e7646d2SAndroid Build Coastguard Worker   if (declen == 1)
242*5e7646d2SAndroid Build Coastguard Worker     tempdec = strchr(temp, *dec);
243*5e7646d2SAndroid Build Coastguard Worker   else
244*5e7646d2SAndroid Build Coastguard Worker     tempdec = strstr(temp, dec);
245*5e7646d2SAndroid Build Coastguard Worker 
246*5e7646d2SAndroid Build Coastguard Worker  /*
247*5e7646d2SAndroid Build Coastguard Worker   * Copy everything up to the decimal point...
248*5e7646d2SAndroid Build Coastguard Worker   */
249*5e7646d2SAndroid Build Coastguard Worker 
250*5e7646d2SAndroid Build Coastguard Worker   if (tempdec)
251*5e7646d2SAndroid Build Coastguard Worker   {
252*5e7646d2SAndroid Build Coastguard Worker     for (tempptr = temp, bufptr = buf;
253*5e7646d2SAndroid Build Coastguard Worker          tempptr < tempdec && bufptr < bufend;
254*5e7646d2SAndroid Build Coastguard Worker 	 *bufptr++ = *tempptr++);
255*5e7646d2SAndroid Build Coastguard Worker 
256*5e7646d2SAndroid Build Coastguard Worker     tempptr += declen;
257*5e7646d2SAndroid Build Coastguard Worker 
258*5e7646d2SAndroid Build Coastguard Worker     if (*tempptr && bufptr < bufend)
259*5e7646d2SAndroid Build Coastguard Worker     {
260*5e7646d2SAndroid Build Coastguard Worker       *bufptr++ = '.';
261*5e7646d2SAndroid Build Coastguard Worker 
262*5e7646d2SAndroid Build Coastguard Worker       while (*tempptr && bufptr < bufend)
263*5e7646d2SAndroid Build Coastguard Worker         *bufptr++ = *tempptr++;
264*5e7646d2SAndroid Build Coastguard Worker     }
265*5e7646d2SAndroid Build Coastguard Worker 
266*5e7646d2SAndroid Build Coastguard Worker     *bufptr = '\0';
267*5e7646d2SAndroid Build Coastguard Worker   }
268*5e7646d2SAndroid Build Coastguard Worker   else
269*5e7646d2SAndroid Build Coastguard Worker   {
270*5e7646d2SAndroid Build Coastguard Worker     strlcpy(buf, temp, (size_t)(bufend - buf + 1));
271*5e7646d2SAndroid Build Coastguard Worker     bufptr = buf + strlen(buf);
272*5e7646d2SAndroid Build Coastguard Worker   }
273*5e7646d2SAndroid Build Coastguard Worker 
274*5e7646d2SAndroid Build Coastguard Worker   return (bufptr);
275*5e7646d2SAndroid Build Coastguard Worker }
276*5e7646d2SAndroid Build Coastguard Worker 
277*5e7646d2SAndroid Build Coastguard Worker 
278*5e7646d2SAndroid Build Coastguard Worker /*
279*5e7646d2SAndroid Build Coastguard Worker  * '_cupsStrFree()' - Free/dereference a string.
280*5e7646d2SAndroid Build Coastguard Worker  */
281*5e7646d2SAndroid Build Coastguard Worker 
282*5e7646d2SAndroid Build Coastguard Worker void
_cupsStrFree(const char * s)283*5e7646d2SAndroid Build Coastguard Worker _cupsStrFree(const char *s)		/* I - String to free */
284*5e7646d2SAndroid Build Coastguard Worker {
285*5e7646d2SAndroid Build Coastguard Worker   _cups_sp_item_t	*item,		/* String pool item */
286*5e7646d2SAndroid Build Coastguard Worker 			*key;		/* Search key */
287*5e7646d2SAndroid Build Coastguard Worker 
288*5e7646d2SAndroid Build Coastguard Worker 
289*5e7646d2SAndroid Build Coastguard Worker  /*
290*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
291*5e7646d2SAndroid Build Coastguard Worker   */
292*5e7646d2SAndroid Build Coastguard Worker 
293*5e7646d2SAndroid Build Coastguard Worker   if (!s)
294*5e7646d2SAndroid Build Coastguard Worker     return;
295*5e7646d2SAndroid Build Coastguard Worker 
296*5e7646d2SAndroid Build Coastguard Worker  /*
297*5e7646d2SAndroid Build Coastguard Worker   * Check the string pool...
298*5e7646d2SAndroid Build Coastguard Worker   *
299*5e7646d2SAndroid Build Coastguard Worker   * We don't need to lock the mutex yet, as we only want to know if
300*5e7646d2SAndroid Build Coastguard Worker   * the stringpool is initialized.  The rest of the code will still
301*5e7646d2SAndroid Build Coastguard Worker   * work if it is initialized before we lock...
302*5e7646d2SAndroid Build Coastguard Worker   */
303*5e7646d2SAndroid Build Coastguard Worker 
304*5e7646d2SAndroid Build Coastguard Worker   if (!stringpool)
305*5e7646d2SAndroid Build Coastguard Worker     return;
306*5e7646d2SAndroid Build Coastguard Worker 
307*5e7646d2SAndroid Build Coastguard Worker  /*
308*5e7646d2SAndroid Build Coastguard Worker   * See if the string is already in the pool...
309*5e7646d2SAndroid Build Coastguard Worker   */
310*5e7646d2SAndroid Build Coastguard Worker 
311*5e7646d2SAndroid Build Coastguard Worker   _cupsMutexLock(&sp_mutex);
312*5e7646d2SAndroid Build Coastguard Worker 
313*5e7646d2SAndroid Build Coastguard Worker   key = (_cups_sp_item_t *)(s - offsetof(_cups_sp_item_t, str));
314*5e7646d2SAndroid Build Coastguard Worker 
315*5e7646d2SAndroid Build Coastguard Worker   if ((item = (_cups_sp_item_t *)cupsArrayFind(stringpool, key)) != NULL &&
316*5e7646d2SAndroid Build Coastguard Worker       item == key)
317*5e7646d2SAndroid Build Coastguard Worker   {
318*5e7646d2SAndroid Build Coastguard Worker    /*
319*5e7646d2SAndroid Build Coastguard Worker     * Found it, dereference...
320*5e7646d2SAndroid Build Coastguard Worker     */
321*5e7646d2SAndroid Build Coastguard Worker 
322*5e7646d2SAndroid Build Coastguard Worker #ifdef DEBUG_GUARDS
323*5e7646d2SAndroid Build Coastguard Worker     if (key->guard != _CUPS_STR_GUARD)
324*5e7646d2SAndroid Build Coastguard Worker     {
325*5e7646d2SAndroid Build Coastguard Worker       DEBUG_printf(("5_cupsStrFree: Freeing string %p(%s), guard=%08x, ref_count=%d", key, key->str, key->guard, key->ref_count));
326*5e7646d2SAndroid Build Coastguard Worker       abort();
327*5e7646d2SAndroid Build Coastguard Worker     }
328*5e7646d2SAndroid Build Coastguard Worker #endif /* DEBUG_GUARDS */
329*5e7646d2SAndroid Build Coastguard Worker 
330*5e7646d2SAndroid Build Coastguard Worker     item->ref_count --;
331*5e7646d2SAndroid Build Coastguard Worker 
332*5e7646d2SAndroid Build Coastguard Worker     if (!item->ref_count)
333*5e7646d2SAndroid Build Coastguard Worker     {
334*5e7646d2SAndroid Build Coastguard Worker      /*
335*5e7646d2SAndroid Build Coastguard Worker       * Remove and free...
336*5e7646d2SAndroid Build Coastguard Worker       */
337*5e7646d2SAndroid Build Coastguard Worker 
338*5e7646d2SAndroid Build Coastguard Worker       cupsArrayRemove(stringpool, item);
339*5e7646d2SAndroid Build Coastguard Worker 
340*5e7646d2SAndroid Build Coastguard Worker       free(item);
341*5e7646d2SAndroid Build Coastguard Worker     }
342*5e7646d2SAndroid Build Coastguard Worker   }
343*5e7646d2SAndroid Build Coastguard Worker 
344*5e7646d2SAndroid Build Coastguard Worker   _cupsMutexUnlock(&sp_mutex);
345*5e7646d2SAndroid Build Coastguard Worker }
346*5e7646d2SAndroid Build Coastguard Worker 
347*5e7646d2SAndroid Build Coastguard Worker 
348*5e7646d2SAndroid Build Coastguard Worker /*
349*5e7646d2SAndroid Build Coastguard Worker  * '_cupsStrRetain()' - Increment the reference count of a string.
350*5e7646d2SAndroid Build Coastguard Worker  *
351*5e7646d2SAndroid Build Coastguard Worker  * Note: This function does not verify that the passed pointer is in the
352*5e7646d2SAndroid Build Coastguard Worker  *       string pool, so any calls to it MUST know they are passing in a
353*5e7646d2SAndroid Build Coastguard Worker  *       good pointer.
354*5e7646d2SAndroid Build Coastguard Worker  */
355*5e7646d2SAndroid Build Coastguard Worker 
356*5e7646d2SAndroid Build Coastguard Worker char *					/* O - Pointer to string */
_cupsStrRetain(const char * s)357*5e7646d2SAndroid Build Coastguard Worker _cupsStrRetain(const char *s)		/* I - String to retain */
358*5e7646d2SAndroid Build Coastguard Worker {
359*5e7646d2SAndroid Build Coastguard Worker   _cups_sp_item_t	*item;		/* Pointer to string pool item */
360*5e7646d2SAndroid Build Coastguard Worker 
361*5e7646d2SAndroid Build Coastguard Worker 
362*5e7646d2SAndroid Build Coastguard Worker   if (s)
363*5e7646d2SAndroid Build Coastguard Worker   {
364*5e7646d2SAndroid Build Coastguard Worker     item = (_cups_sp_item_t *)(s - offsetof(_cups_sp_item_t, str));
365*5e7646d2SAndroid Build Coastguard Worker 
366*5e7646d2SAndroid Build Coastguard Worker #ifdef DEBUG_GUARDS
367*5e7646d2SAndroid Build Coastguard Worker     if (item->guard != _CUPS_STR_GUARD)
368*5e7646d2SAndroid Build Coastguard Worker     {
369*5e7646d2SAndroid Build Coastguard Worker       DEBUG_printf(("5_cupsStrRetain: Retaining string %p(%s), guard=%08x, "
370*5e7646d2SAndroid Build Coastguard Worker                     "ref_count=%d", item, s, item->guard, item->ref_count));
371*5e7646d2SAndroid Build Coastguard Worker       abort();
372*5e7646d2SAndroid Build Coastguard Worker     }
373*5e7646d2SAndroid Build Coastguard Worker #endif /* DEBUG_GUARDS */
374*5e7646d2SAndroid Build Coastguard Worker 
375*5e7646d2SAndroid Build Coastguard Worker     _cupsMutexLock(&sp_mutex);
376*5e7646d2SAndroid Build Coastguard Worker 
377*5e7646d2SAndroid Build Coastguard Worker     item->ref_count ++;
378*5e7646d2SAndroid Build Coastguard Worker 
379*5e7646d2SAndroid Build Coastguard Worker     _cupsMutexUnlock(&sp_mutex);
380*5e7646d2SAndroid Build Coastguard Worker   }
381*5e7646d2SAndroid Build Coastguard Worker 
382*5e7646d2SAndroid Build Coastguard Worker   return ((char *)s);
383*5e7646d2SAndroid Build Coastguard Worker }
384*5e7646d2SAndroid Build Coastguard Worker 
385*5e7646d2SAndroid Build Coastguard Worker 
386*5e7646d2SAndroid Build Coastguard Worker /*
387*5e7646d2SAndroid Build Coastguard Worker  * '_cupsStrScand()' - Scan a string for a floating-point number.
388*5e7646d2SAndroid Build Coastguard Worker  *
389*5e7646d2SAndroid Build Coastguard Worker  * This function handles the locale-specific BS so that a decimal
390*5e7646d2SAndroid Build Coastguard Worker  * point is always the period (".")...
391*5e7646d2SAndroid Build Coastguard Worker  */
392*5e7646d2SAndroid Build Coastguard Worker 
393*5e7646d2SAndroid Build Coastguard Worker double					/* O - Number */
_cupsStrScand(const char * buf,char ** bufptr,struct lconv * loc)394*5e7646d2SAndroid Build Coastguard Worker _cupsStrScand(const char   *buf,	/* I - Pointer to number */
395*5e7646d2SAndroid Build Coastguard Worker               char         **bufptr,	/* O - New pointer or NULL on error */
396*5e7646d2SAndroid Build Coastguard Worker               struct lconv *loc)	/* I - Locale data */
397*5e7646d2SAndroid Build Coastguard Worker {
398*5e7646d2SAndroid Build Coastguard Worker   char	temp[1024],			/* Temporary buffer */
399*5e7646d2SAndroid Build Coastguard Worker 	*tempptr;			/* Pointer into temporary buffer */
400*5e7646d2SAndroid Build Coastguard Worker 
401*5e7646d2SAndroid Build Coastguard Worker 
402*5e7646d2SAndroid Build Coastguard Worker  /*
403*5e7646d2SAndroid Build Coastguard Worker   * Range check input...
404*5e7646d2SAndroid Build Coastguard Worker   */
405*5e7646d2SAndroid Build Coastguard Worker 
406*5e7646d2SAndroid Build Coastguard Worker   if (!buf)
407*5e7646d2SAndroid Build Coastguard Worker     return (0.0);
408*5e7646d2SAndroid Build Coastguard Worker 
409*5e7646d2SAndroid Build Coastguard Worker  /*
410*5e7646d2SAndroid Build Coastguard Worker   * Skip leading whitespace...
411*5e7646d2SAndroid Build Coastguard Worker   */
412*5e7646d2SAndroid Build Coastguard Worker 
413*5e7646d2SAndroid Build Coastguard Worker   while (_cups_isspace(*buf))
414*5e7646d2SAndroid Build Coastguard Worker     buf ++;
415*5e7646d2SAndroid Build Coastguard Worker 
416*5e7646d2SAndroid Build Coastguard Worker  /*
417*5e7646d2SAndroid Build Coastguard Worker   * Copy leading sign, numbers, period, and then numbers...
418*5e7646d2SAndroid Build Coastguard Worker   */
419*5e7646d2SAndroid Build Coastguard Worker 
420*5e7646d2SAndroid Build Coastguard Worker   tempptr = temp;
421*5e7646d2SAndroid Build Coastguard Worker   if (*buf == '-' || *buf == '+')
422*5e7646d2SAndroid Build Coastguard Worker     *tempptr++ = *buf++;
423*5e7646d2SAndroid Build Coastguard Worker 
424*5e7646d2SAndroid Build Coastguard Worker   while (isdigit(*buf & 255))
425*5e7646d2SAndroid Build Coastguard Worker     if (tempptr < (temp + sizeof(temp) - 1))
426*5e7646d2SAndroid Build Coastguard Worker       *tempptr++ = *buf++;
427*5e7646d2SAndroid Build Coastguard Worker     else
428*5e7646d2SAndroid Build Coastguard Worker     {
429*5e7646d2SAndroid Build Coastguard Worker       if (bufptr)
430*5e7646d2SAndroid Build Coastguard Worker 	*bufptr = NULL;
431*5e7646d2SAndroid Build Coastguard Worker 
432*5e7646d2SAndroid Build Coastguard Worker       return (0.0);
433*5e7646d2SAndroid Build Coastguard Worker     }
434*5e7646d2SAndroid Build Coastguard Worker 
435*5e7646d2SAndroid Build Coastguard Worker   if (*buf == '.')
436*5e7646d2SAndroid Build Coastguard Worker   {
437*5e7646d2SAndroid Build Coastguard Worker    /*
438*5e7646d2SAndroid Build Coastguard Worker     * Read fractional portion of number...
439*5e7646d2SAndroid Build Coastguard Worker     */
440*5e7646d2SAndroid Build Coastguard Worker 
441*5e7646d2SAndroid Build Coastguard Worker     buf ++;
442*5e7646d2SAndroid Build Coastguard Worker 
443*5e7646d2SAndroid Build Coastguard Worker     if (loc && loc->decimal_point)
444*5e7646d2SAndroid Build Coastguard Worker     {
445*5e7646d2SAndroid Build Coastguard Worker       strlcpy(tempptr, loc->decimal_point, sizeof(temp) - (size_t)(tempptr - temp));
446*5e7646d2SAndroid Build Coastguard Worker       tempptr += strlen(tempptr);
447*5e7646d2SAndroid Build Coastguard Worker     }
448*5e7646d2SAndroid Build Coastguard Worker     else if (tempptr < (temp + sizeof(temp) - 1))
449*5e7646d2SAndroid Build Coastguard Worker       *tempptr++ = '.';
450*5e7646d2SAndroid Build Coastguard Worker     else
451*5e7646d2SAndroid Build Coastguard Worker     {
452*5e7646d2SAndroid Build Coastguard Worker       if (bufptr)
453*5e7646d2SAndroid Build Coastguard Worker         *bufptr = NULL;
454*5e7646d2SAndroid Build Coastguard Worker 
455*5e7646d2SAndroid Build Coastguard Worker       return (0.0);
456*5e7646d2SAndroid Build Coastguard Worker     }
457*5e7646d2SAndroid Build Coastguard Worker 
458*5e7646d2SAndroid Build Coastguard Worker     while (isdigit(*buf & 255))
459*5e7646d2SAndroid Build Coastguard Worker       if (tempptr < (temp + sizeof(temp) - 1))
460*5e7646d2SAndroid Build Coastguard Worker 	*tempptr++ = *buf++;
461*5e7646d2SAndroid Build Coastguard Worker       else
462*5e7646d2SAndroid Build Coastguard Worker       {
463*5e7646d2SAndroid Build Coastguard Worker 	if (bufptr)
464*5e7646d2SAndroid Build Coastguard Worker 	  *bufptr = NULL;
465*5e7646d2SAndroid Build Coastguard Worker 
466*5e7646d2SAndroid Build Coastguard Worker 	return (0.0);
467*5e7646d2SAndroid Build Coastguard Worker       }
468*5e7646d2SAndroid Build Coastguard Worker   }
469*5e7646d2SAndroid Build Coastguard Worker 
470*5e7646d2SAndroid Build Coastguard Worker   if (*buf == 'e' || *buf == 'E')
471*5e7646d2SAndroid Build Coastguard Worker   {
472*5e7646d2SAndroid Build Coastguard Worker    /*
473*5e7646d2SAndroid Build Coastguard Worker     * Read exponent...
474*5e7646d2SAndroid Build Coastguard Worker     */
475*5e7646d2SAndroid Build Coastguard Worker 
476*5e7646d2SAndroid Build Coastguard Worker     if (tempptr < (temp + sizeof(temp) - 1))
477*5e7646d2SAndroid Build Coastguard Worker       *tempptr++ = *buf++;
478*5e7646d2SAndroid Build Coastguard Worker     else
479*5e7646d2SAndroid Build Coastguard Worker     {
480*5e7646d2SAndroid Build Coastguard Worker       if (bufptr)
481*5e7646d2SAndroid Build Coastguard Worker 	*bufptr = NULL;
482*5e7646d2SAndroid Build Coastguard Worker 
483*5e7646d2SAndroid Build Coastguard Worker       return (0.0);
484*5e7646d2SAndroid Build Coastguard Worker     }
485*5e7646d2SAndroid Build Coastguard Worker 
486*5e7646d2SAndroid Build Coastguard Worker     if (*buf == '+' || *buf == '-')
487*5e7646d2SAndroid Build Coastguard Worker     {
488*5e7646d2SAndroid Build Coastguard Worker       if (tempptr < (temp + sizeof(temp) - 1))
489*5e7646d2SAndroid Build Coastguard Worker 	*tempptr++ = *buf++;
490*5e7646d2SAndroid Build Coastguard Worker       else
491*5e7646d2SAndroid Build Coastguard Worker       {
492*5e7646d2SAndroid Build Coastguard Worker 	if (bufptr)
493*5e7646d2SAndroid Build Coastguard Worker 	  *bufptr = NULL;
494*5e7646d2SAndroid Build Coastguard Worker 
495*5e7646d2SAndroid Build Coastguard Worker 	return (0.0);
496*5e7646d2SAndroid Build Coastguard Worker       }
497*5e7646d2SAndroid Build Coastguard Worker     }
498*5e7646d2SAndroid Build Coastguard Worker 
499*5e7646d2SAndroid Build Coastguard Worker     while (isdigit(*buf & 255))
500*5e7646d2SAndroid Build Coastguard Worker       if (tempptr < (temp + sizeof(temp) - 1))
501*5e7646d2SAndroid Build Coastguard Worker 	*tempptr++ = *buf++;
502*5e7646d2SAndroid Build Coastguard Worker       else
503*5e7646d2SAndroid Build Coastguard Worker       {
504*5e7646d2SAndroid Build Coastguard Worker 	if (bufptr)
505*5e7646d2SAndroid Build Coastguard Worker 	  *bufptr = NULL;
506*5e7646d2SAndroid Build Coastguard Worker 
507*5e7646d2SAndroid Build Coastguard Worker 	return (0.0);
508*5e7646d2SAndroid Build Coastguard Worker       }
509*5e7646d2SAndroid Build Coastguard Worker   }
510*5e7646d2SAndroid Build Coastguard Worker 
511*5e7646d2SAndroid Build Coastguard Worker  /*
512*5e7646d2SAndroid Build Coastguard Worker   * Nul-terminate the temporary string and return the value...
513*5e7646d2SAndroid Build Coastguard Worker   */
514*5e7646d2SAndroid Build Coastguard Worker 
515*5e7646d2SAndroid Build Coastguard Worker   if (bufptr)
516*5e7646d2SAndroid Build Coastguard Worker     *bufptr = (char *)buf;
517*5e7646d2SAndroid Build Coastguard Worker 
518*5e7646d2SAndroid Build Coastguard Worker   *tempptr = '\0';
519*5e7646d2SAndroid Build Coastguard Worker 
520*5e7646d2SAndroid Build Coastguard Worker   return (strtod(temp, NULL));
521*5e7646d2SAndroid Build Coastguard Worker }
522*5e7646d2SAndroid Build Coastguard Worker 
523*5e7646d2SAndroid Build Coastguard Worker 
524*5e7646d2SAndroid Build Coastguard Worker /*
525*5e7646d2SAndroid Build Coastguard Worker  * '_cupsStrStatistics()' - Return allocation statistics for string pool.
526*5e7646d2SAndroid Build Coastguard Worker  */
527*5e7646d2SAndroid Build Coastguard Worker 
528*5e7646d2SAndroid Build Coastguard Worker size_t					/* O - Number of strings */
_cupsStrStatistics(size_t * alloc_bytes,size_t * total_bytes)529*5e7646d2SAndroid Build Coastguard Worker _cupsStrStatistics(size_t *alloc_bytes,	/* O - Allocated bytes */
530*5e7646d2SAndroid Build Coastguard Worker                    size_t *total_bytes)	/* O - Total string bytes */
531*5e7646d2SAndroid Build Coastguard Worker {
532*5e7646d2SAndroid Build Coastguard Worker   size_t		count,		/* Number of strings */
533*5e7646d2SAndroid Build Coastguard Worker 			abytes,		/* Allocated string bytes */
534*5e7646d2SAndroid Build Coastguard Worker 			tbytes,		/* Total string bytes */
535*5e7646d2SAndroid Build Coastguard Worker 			len;		/* Length of string */
536*5e7646d2SAndroid Build Coastguard Worker   _cups_sp_item_t	*item;		/* Current item */
537*5e7646d2SAndroid Build Coastguard Worker 
538*5e7646d2SAndroid Build Coastguard Worker 
539*5e7646d2SAndroid Build Coastguard Worker  /*
540*5e7646d2SAndroid Build Coastguard Worker   * Loop through strings in pool, counting everything up...
541*5e7646d2SAndroid Build Coastguard Worker   */
542*5e7646d2SAndroid Build Coastguard Worker 
543*5e7646d2SAndroid Build Coastguard Worker   _cupsMutexLock(&sp_mutex);
544*5e7646d2SAndroid Build Coastguard Worker 
545*5e7646d2SAndroid Build Coastguard Worker   for (count = 0, abytes = 0, tbytes = 0,
546*5e7646d2SAndroid Build Coastguard Worker            item = (_cups_sp_item_t *)cupsArrayFirst(stringpool);
547*5e7646d2SAndroid Build Coastguard Worker        item;
548*5e7646d2SAndroid Build Coastguard Worker        item = (_cups_sp_item_t *)cupsArrayNext(stringpool))
549*5e7646d2SAndroid Build Coastguard Worker   {
550*5e7646d2SAndroid Build Coastguard Worker    /*
551*5e7646d2SAndroid Build Coastguard Worker     * Count allocated memory, using a 64-bit aligned buffer as a basis.
552*5e7646d2SAndroid Build Coastguard Worker     */
553*5e7646d2SAndroid Build Coastguard Worker 
554*5e7646d2SAndroid Build Coastguard Worker     count  += item->ref_count;
555*5e7646d2SAndroid Build Coastguard Worker     len    = (strlen(item->str) + 8) & (size_t)~7;
556*5e7646d2SAndroid Build Coastguard Worker     abytes += sizeof(_cups_sp_item_t) + len;
557*5e7646d2SAndroid Build Coastguard Worker     tbytes += item->ref_count * len;
558*5e7646d2SAndroid Build Coastguard Worker   }
559*5e7646d2SAndroid Build Coastguard Worker 
560*5e7646d2SAndroid Build Coastguard Worker   _cupsMutexUnlock(&sp_mutex);
561*5e7646d2SAndroid Build Coastguard Worker 
562*5e7646d2SAndroid Build Coastguard Worker  /*
563*5e7646d2SAndroid Build Coastguard Worker   * Return values...
564*5e7646d2SAndroid Build Coastguard Worker   */
565*5e7646d2SAndroid Build Coastguard Worker 
566*5e7646d2SAndroid Build Coastguard Worker   if (alloc_bytes)
567*5e7646d2SAndroid Build Coastguard Worker     *alloc_bytes = abytes;
568*5e7646d2SAndroid Build Coastguard Worker 
569*5e7646d2SAndroid Build Coastguard Worker   if (total_bytes)
570*5e7646d2SAndroid Build Coastguard Worker     *total_bytes = tbytes;
571*5e7646d2SAndroid Build Coastguard Worker 
572*5e7646d2SAndroid Build Coastguard Worker   return (count);
573*5e7646d2SAndroid Build Coastguard Worker }
574*5e7646d2SAndroid Build Coastguard Worker 
575*5e7646d2SAndroid Build Coastguard Worker 
576*5e7646d2SAndroid Build Coastguard Worker /*
577*5e7646d2SAndroid Build Coastguard Worker  * '_cups_strcpy()' - Copy a string allowing for overlapping strings.
578*5e7646d2SAndroid Build Coastguard Worker  */
579*5e7646d2SAndroid Build Coastguard Worker 
580*5e7646d2SAndroid Build Coastguard Worker void
_cups_strcpy(char * dst,const char * src)581*5e7646d2SAndroid Build Coastguard Worker _cups_strcpy(char       *dst,		/* I - Destination string */
582*5e7646d2SAndroid Build Coastguard Worker              const char *src)		/* I - Source string */
583*5e7646d2SAndroid Build Coastguard Worker {
584*5e7646d2SAndroid Build Coastguard Worker   while (*src)
585*5e7646d2SAndroid Build Coastguard Worker     *dst++ = *src++;
586*5e7646d2SAndroid Build Coastguard Worker 
587*5e7646d2SAndroid Build Coastguard Worker   *dst = '\0';
588*5e7646d2SAndroid Build Coastguard Worker }
589*5e7646d2SAndroid Build Coastguard Worker 
590*5e7646d2SAndroid Build Coastguard Worker 
591*5e7646d2SAndroid Build Coastguard Worker /*
592*5e7646d2SAndroid Build Coastguard Worker  * '_cups_strdup()' - Duplicate a string.
593*5e7646d2SAndroid Build Coastguard Worker  */
594*5e7646d2SAndroid Build Coastguard Worker 
595*5e7646d2SAndroid Build Coastguard Worker #ifndef HAVE_STRDUP
596*5e7646d2SAndroid Build Coastguard Worker char 	*				/* O - New string pointer */
_cups_strdup(const char * s)597*5e7646d2SAndroid Build Coastguard Worker _cups_strdup(const char *s)		/* I - String to duplicate */
598*5e7646d2SAndroid Build Coastguard Worker {
599*5e7646d2SAndroid Build Coastguard Worker   char		*t;			/* New string pointer */
600*5e7646d2SAndroid Build Coastguard Worker   size_t	slen;			/* Length of string */
601*5e7646d2SAndroid Build Coastguard Worker 
602*5e7646d2SAndroid Build Coastguard Worker 
603*5e7646d2SAndroid Build Coastguard Worker   if (!s)
604*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
605*5e7646d2SAndroid Build Coastguard Worker 
606*5e7646d2SAndroid Build Coastguard Worker   slen = strlen(s);
607*5e7646d2SAndroid Build Coastguard Worker   if ((t = malloc(slen + 1)) == NULL)
608*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
609*5e7646d2SAndroid Build Coastguard Worker 
610*5e7646d2SAndroid Build Coastguard Worker   return (memcpy(t, s, slen + 1));
611*5e7646d2SAndroid Build Coastguard Worker }
612*5e7646d2SAndroid Build Coastguard Worker #endif /* !HAVE_STRDUP */
613*5e7646d2SAndroid Build Coastguard Worker 
614*5e7646d2SAndroid Build Coastguard Worker 
615*5e7646d2SAndroid Build Coastguard Worker /*
616*5e7646d2SAndroid Build Coastguard Worker  * '_cups_strcasecmp()' - Do a case-insensitive comparison.
617*5e7646d2SAndroid Build Coastguard Worker  */
618*5e7646d2SAndroid Build Coastguard Worker 
619*5e7646d2SAndroid Build Coastguard Worker int				/* O - Result of comparison (-1, 0, or 1) */
_cups_strcasecmp(const char * s,const char * t)620*5e7646d2SAndroid Build Coastguard Worker _cups_strcasecmp(const char *s,	/* I - First string */
621*5e7646d2SAndroid Build Coastguard Worker                  const char *t)	/* I - Second string */
622*5e7646d2SAndroid Build Coastguard Worker {
623*5e7646d2SAndroid Build Coastguard Worker   while (*s != '\0' && *t != '\0')
624*5e7646d2SAndroid Build Coastguard Worker   {
625*5e7646d2SAndroid Build Coastguard Worker     if (_cups_tolower(*s) < _cups_tolower(*t))
626*5e7646d2SAndroid Build Coastguard Worker       return (-1);
627*5e7646d2SAndroid Build Coastguard Worker     else if (_cups_tolower(*s) > _cups_tolower(*t))
628*5e7646d2SAndroid Build Coastguard Worker       return (1);
629*5e7646d2SAndroid Build Coastguard Worker 
630*5e7646d2SAndroid Build Coastguard Worker     s ++;
631*5e7646d2SAndroid Build Coastguard Worker     t ++;
632*5e7646d2SAndroid Build Coastguard Worker   }
633*5e7646d2SAndroid Build Coastguard Worker 
634*5e7646d2SAndroid Build Coastguard Worker   if (*s == '\0' && *t == '\0')
635*5e7646d2SAndroid Build Coastguard Worker     return (0);
636*5e7646d2SAndroid Build Coastguard Worker   else if (*s != '\0')
637*5e7646d2SAndroid Build Coastguard Worker     return (1);
638*5e7646d2SAndroid Build Coastguard Worker   else
639*5e7646d2SAndroid Build Coastguard Worker     return (-1);
640*5e7646d2SAndroid Build Coastguard Worker }
641*5e7646d2SAndroid Build Coastguard Worker 
642*5e7646d2SAndroid Build Coastguard Worker /*
643*5e7646d2SAndroid Build Coastguard Worker  * '_cups_strncasecmp()' - Do a case-insensitive comparison on up to N chars.
644*5e7646d2SAndroid Build Coastguard Worker  */
645*5e7646d2SAndroid Build Coastguard Worker 
646*5e7646d2SAndroid Build Coastguard Worker int					/* O - Result of comparison (-1, 0, or 1) */
_cups_strncasecmp(const char * s,const char * t,size_t n)647*5e7646d2SAndroid Build Coastguard Worker _cups_strncasecmp(const char *s,	/* I - First string */
648*5e7646d2SAndroid Build Coastguard Worker                   const char *t,	/* I - Second string */
649*5e7646d2SAndroid Build Coastguard Worker 		  size_t     n)		/* I - Maximum number of characters to compare */
650*5e7646d2SAndroid Build Coastguard Worker {
651*5e7646d2SAndroid Build Coastguard Worker   while (*s != '\0' && *t != '\0' && n > 0)
652*5e7646d2SAndroid Build Coastguard Worker   {
653*5e7646d2SAndroid Build Coastguard Worker     if (_cups_tolower(*s) < _cups_tolower(*t))
654*5e7646d2SAndroid Build Coastguard Worker       return (-1);
655*5e7646d2SAndroid Build Coastguard Worker     else if (_cups_tolower(*s) > _cups_tolower(*t))
656*5e7646d2SAndroid Build Coastguard Worker       return (1);
657*5e7646d2SAndroid Build Coastguard Worker 
658*5e7646d2SAndroid Build Coastguard Worker     s ++;
659*5e7646d2SAndroid Build Coastguard Worker     t ++;
660*5e7646d2SAndroid Build Coastguard Worker     n --;
661*5e7646d2SAndroid Build Coastguard Worker   }
662*5e7646d2SAndroid Build Coastguard Worker 
663*5e7646d2SAndroid Build Coastguard Worker   if (n == 0)
664*5e7646d2SAndroid Build Coastguard Worker     return (0);
665*5e7646d2SAndroid Build Coastguard Worker   else if (*s == '\0' && *t == '\0')
666*5e7646d2SAndroid Build Coastguard Worker     return (0);
667*5e7646d2SAndroid Build Coastguard Worker   else if (*s != '\0')
668*5e7646d2SAndroid Build Coastguard Worker     return (1);
669*5e7646d2SAndroid Build Coastguard Worker   else
670*5e7646d2SAndroid Build Coastguard Worker     return (-1);
671*5e7646d2SAndroid Build Coastguard Worker }
672*5e7646d2SAndroid Build Coastguard Worker 
673*5e7646d2SAndroid Build Coastguard Worker 
674*5e7646d2SAndroid Build Coastguard Worker #ifndef HAVE_STRLCAT
675*5e7646d2SAndroid Build Coastguard Worker /*
676*5e7646d2SAndroid Build Coastguard Worker  * '_cups_strlcat()' - Safely concatenate two strings.
677*5e7646d2SAndroid Build Coastguard Worker  */
678*5e7646d2SAndroid Build Coastguard Worker 
679*5e7646d2SAndroid Build Coastguard Worker size_t					/* O - Length of string */
_cups_strlcat(char * dst,const char * src,size_t size)680*5e7646d2SAndroid Build Coastguard Worker _cups_strlcat(char       *dst,		/* O - Destination string */
681*5e7646d2SAndroid Build Coastguard Worker               const char *src,		/* I - Source string */
682*5e7646d2SAndroid Build Coastguard Worker 	      size_t     size)		/* I - Size of destination string buffer */
683*5e7646d2SAndroid Build Coastguard Worker {
684*5e7646d2SAndroid Build Coastguard Worker   size_t	srclen;			/* Length of source string */
685*5e7646d2SAndroid Build Coastguard Worker   size_t	dstlen;			/* Length of destination string */
686*5e7646d2SAndroid Build Coastguard Worker 
687*5e7646d2SAndroid Build Coastguard Worker 
688*5e7646d2SAndroid Build Coastguard Worker  /*
689*5e7646d2SAndroid Build Coastguard Worker   * Figure out how much room is left...
690*5e7646d2SAndroid Build Coastguard Worker   */
691*5e7646d2SAndroid Build Coastguard Worker 
692*5e7646d2SAndroid Build Coastguard Worker   dstlen = strlen(dst);
693*5e7646d2SAndroid Build Coastguard Worker 
694*5e7646d2SAndroid Build Coastguard Worker   if (size < (dstlen + 1))
695*5e7646d2SAndroid Build Coastguard Worker     return (dstlen);		        /* No room, return immediately... */
696*5e7646d2SAndroid Build Coastguard Worker 
697*5e7646d2SAndroid Build Coastguard Worker   size -= dstlen + 1;
698*5e7646d2SAndroid Build Coastguard Worker 
699*5e7646d2SAndroid Build Coastguard Worker  /*
700*5e7646d2SAndroid Build Coastguard Worker   * Figure out how much room is needed...
701*5e7646d2SAndroid Build Coastguard Worker   */
702*5e7646d2SAndroid Build Coastguard Worker 
703*5e7646d2SAndroid Build Coastguard Worker   srclen = strlen(src);
704*5e7646d2SAndroid Build Coastguard Worker 
705*5e7646d2SAndroid Build Coastguard Worker  /*
706*5e7646d2SAndroid Build Coastguard Worker   * Copy the appropriate amount...
707*5e7646d2SAndroid Build Coastguard Worker   */
708*5e7646d2SAndroid Build Coastguard Worker 
709*5e7646d2SAndroid Build Coastguard Worker   if (srclen > size)
710*5e7646d2SAndroid Build Coastguard Worker     srclen = size;
711*5e7646d2SAndroid Build Coastguard Worker 
712*5e7646d2SAndroid Build Coastguard Worker   memmove(dst + dstlen, src, srclen);
713*5e7646d2SAndroid Build Coastguard Worker   dst[dstlen + srclen] = '\0';
714*5e7646d2SAndroid Build Coastguard Worker 
715*5e7646d2SAndroid Build Coastguard Worker   return (dstlen + srclen);
716*5e7646d2SAndroid Build Coastguard Worker }
717*5e7646d2SAndroid Build Coastguard Worker #endif /* !HAVE_STRLCAT */
718*5e7646d2SAndroid Build Coastguard Worker 
719*5e7646d2SAndroid Build Coastguard Worker 
720*5e7646d2SAndroid Build Coastguard Worker #ifndef HAVE_STRLCPY
721*5e7646d2SAndroid Build Coastguard Worker /*
722*5e7646d2SAndroid Build Coastguard Worker  * '_cups_strlcpy()' - Safely copy two strings.
723*5e7646d2SAndroid Build Coastguard Worker  */
724*5e7646d2SAndroid Build Coastguard Worker 
725*5e7646d2SAndroid Build Coastguard Worker size_t					/* O - Length of string */
_cups_strlcpy(char * dst,const char * src,size_t size)726*5e7646d2SAndroid Build Coastguard Worker _cups_strlcpy(char       *dst,		/* O - Destination string */
727*5e7646d2SAndroid Build Coastguard Worker               const char *src,		/* I - Source string */
728*5e7646d2SAndroid Build Coastguard Worker 	      size_t      size)		/* I - Size of destination string buffer */
729*5e7646d2SAndroid Build Coastguard Worker {
730*5e7646d2SAndroid Build Coastguard Worker   size_t	srclen;			/* Length of source string */
731*5e7646d2SAndroid Build Coastguard Worker 
732*5e7646d2SAndroid Build Coastguard Worker 
733*5e7646d2SAndroid Build Coastguard Worker  /*
734*5e7646d2SAndroid Build Coastguard Worker   * Figure out how much room is needed...
735*5e7646d2SAndroid Build Coastguard Worker   */
736*5e7646d2SAndroid Build Coastguard Worker 
737*5e7646d2SAndroid Build Coastguard Worker   size --;
738*5e7646d2SAndroid Build Coastguard Worker 
739*5e7646d2SAndroid Build Coastguard Worker   srclen = strlen(src);
740*5e7646d2SAndroid Build Coastguard Worker 
741*5e7646d2SAndroid Build Coastguard Worker  /*
742*5e7646d2SAndroid Build Coastguard Worker   * Copy the appropriate amount...
743*5e7646d2SAndroid Build Coastguard Worker   */
744*5e7646d2SAndroid Build Coastguard Worker 
745*5e7646d2SAndroid Build Coastguard Worker   if (srclen > size)
746*5e7646d2SAndroid Build Coastguard Worker     srclen = size;
747*5e7646d2SAndroid Build Coastguard Worker 
748*5e7646d2SAndroid Build Coastguard Worker   memmove(dst, src, srclen);
749*5e7646d2SAndroid Build Coastguard Worker   dst[srclen] = '\0';
750*5e7646d2SAndroid Build Coastguard Worker 
751*5e7646d2SAndroid Build Coastguard Worker   return (srclen);
752*5e7646d2SAndroid Build Coastguard Worker }
753*5e7646d2SAndroid Build Coastguard Worker #endif /* !HAVE_STRLCPY */
754*5e7646d2SAndroid Build Coastguard Worker 
755*5e7646d2SAndroid Build Coastguard Worker 
756*5e7646d2SAndroid Build Coastguard Worker /*
757*5e7646d2SAndroid Build Coastguard Worker  * 'compare_sp_items()' - Compare two string pool items...
758*5e7646d2SAndroid Build Coastguard Worker  */
759*5e7646d2SAndroid Build Coastguard Worker 
760*5e7646d2SAndroid Build Coastguard Worker static int				/* O - Result of comparison */
compare_sp_items(_cups_sp_item_t * a,_cups_sp_item_t * b)761*5e7646d2SAndroid Build Coastguard Worker compare_sp_items(_cups_sp_item_t *a,	/* I - First item */
762*5e7646d2SAndroid Build Coastguard Worker                  _cups_sp_item_t *b)	/* I - Second item */
763*5e7646d2SAndroid Build Coastguard Worker {
764*5e7646d2SAndroid Build Coastguard Worker   return (strcmp(a->str, b->str));
765*5e7646d2SAndroid Build Coastguard Worker }
766