]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/string.c
Load cups into easysw/current.
[thirdparty/cups.git] / cups / string.c
1 /*
2 * "$Id: string.c 5047 2006-02-02 05:14:15Z mike $"
3 *
4 * String functions for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1997-2006 by Easy Software Products.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
13 * at:
14 *
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
19 *
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * This file is subject to the Apple OS-Developed Software exception.
25 *
26 * Contents:
27 *
28 * _cups_sp_alloc() - Allocate/reference a string.
29 * _cups_sp_flush() - Flush the string pool...
30 * _cups_sp_free() - Free/dereference a string.
31 * _cups_sp_statistics() - Return allocation statistics for string pool.
32 * _cups_strcpy() - Copy a string allowing for overlapping strings.
33 * _cups_strdup() - Duplicate a string.
34 * _cups_strcasecmp() - Do a case-insensitive comparison.
35 * _cups_strncasecmp() - Do a case-insensitive comparison on up to N chars.
36 * _cups_strlcat() - Safely concatenate two strings.
37 * _cups_strlcpy() - Safely copy two strings.
38 * compare_sp_items() - Compare two string pool items...
39 */
40
41 /*
42 * Include necessary headers...
43 */
44
45 #include <stdlib.h>
46 #include <limits.h>
47 #include "debug.h"
48 #include "string.h"
49 #include "globals.h"
50
51
52 /*
53 * Local functions...
54 */
55
56 static int compare_sp_items(_cups_sp_item_t *a, _cups_sp_item_t *b);
57
58
59 /*
60 * '_cups_sp_alloc()' - Allocate/reference a string.
61 */
62
63 char * /* O - String pointer */
64 _cups_sp_alloc(const char *s) /* I - String */
65 {
66 _cups_globals_t *cg; /* Global data */
67 _cups_sp_item_t *item, /* String pool item */
68 key; /* Search key */
69
70
71 /*
72 * Range check input...
73 */
74
75 if (!s)
76 return (NULL);
77
78 /*
79 * Get the string pool...
80 */
81
82 cg = _cupsGlobals();
83
84 if (!cg->stringpool)
85 cg->stringpool = cupsArrayNew((cups_array_func_t)compare_sp_items, NULL);
86
87 if (!cg->stringpool)
88 return (NULL);
89
90 /*
91 * See if the string is already in the pool...
92 */
93
94 key.str = (char *)s;
95
96 if ((item = (_cups_sp_item_t *)cupsArrayFind(cg->stringpool, &key)) != NULL)
97 {
98 /*
99 * Found it, return the cached string...
100 */
101
102 item->ref_count ++;
103
104 return (item->str);
105 }
106
107 /*
108 * Not found, so allocate a new one...
109 */
110
111 item = (_cups_sp_item_t *)calloc(1, sizeof(_cups_sp_item_t));
112 if (!item)
113 return (NULL);
114
115 item->ref_count = 1;
116 item->str = strdup(s);
117
118 if (!item->str)
119 {
120 free(item);
121 return (NULL);
122 }
123
124 /*
125 * Add the string to the pool and return it...
126 */
127
128 cupsArrayAdd(cg->stringpool, item);
129
130 return (item->str);
131 }
132
133
134 /*
135 * '_cups_sp_flush()' - Flush the string pool...
136 */
137
138 void
139 _cups_sp_flush(_cups_globals_t *cg) /* I - Global data */
140 {
141 _cups_sp_item_t *item; /* Current item */
142
143
144 for (item = (_cups_sp_item_t *)cupsArrayFirst(cg->stringpool);
145 item;
146 item = (_cups_sp_item_t *)cupsArrayNext(cg->stringpool))
147 {
148 free(item->str);
149 free(item);
150 }
151
152 cupsArrayDelete(cg->stringpool);
153 }
154
155
156 /*
157 * '_cups_sp_free()' - Free/dereference a string.
158 */
159
160 void
161 _cups_sp_free(const char *s)
162 {
163 _cups_globals_t *cg; /* Global data */
164 _cups_sp_item_t *item, /* String pool item */
165 key; /* Search key */
166
167
168 /*
169 * Range check input...
170 */
171
172 if (!s)
173 return;
174
175 /*
176 * Get the string pool...
177 */
178
179 cg = _cupsGlobals();
180
181 if (!cg->stringpool)
182 return;
183
184 /*
185 * See if the string is already in the pool...
186 */
187
188 key.str = (char *)s;
189
190 if ((item = (_cups_sp_item_t *)cupsArrayFind(cg->stringpool, &key)) != NULL)
191 {
192 /*
193 * Found it, dereference...
194 */
195
196 item->ref_count --;
197
198 if (!item->ref_count)
199 {
200 /*
201 * Remove and free...
202 */
203
204 cupsArrayRemove(cg->stringpool, item);
205
206 free(item->str);
207 free(item);
208 }
209 }
210 }
211
212
213 /*
214 * '_cups_sp_statistics()' - Return allocation statistics for string pool.
215 */
216
217 size_t /* O - Number of strings */
218 _cups_sp_statistics(size_t *alloc_bytes,/* O - Allocated bytes */
219 size_t *total_bytes)/* O - Total string bytes */
220 {
221 size_t count, /* Number of strings */
222 abytes, /* Allocated string bytes */
223 tbytes, /* Total string bytes */
224 len; /* Length of string */
225 _cups_sp_item_t *item; /* Current item */
226 _cups_globals_t *cg; /* Global data */
227
228
229 /*
230 * Loop through strings in pool, counting everything up...
231 */
232
233 cg = _cupsGlobals();
234
235 for (count = 0, abytes = 0, tbytes = 0,
236 item = (_cups_sp_item_t *)cupsArrayFirst(cg->stringpool);
237 item;
238 item = (_cups_sp_item_t *)cupsArrayNext(cg->stringpool))
239 {
240 /*
241 * Count allocated memory, using a 64-bit aligned buffer as a basis.
242 */
243
244 count += item->ref_count;
245 len = (strlen(item->str) + 8) & ~7;
246 abytes += sizeof(_cups_sp_item_t) + len;
247 tbytes += item->ref_count * len;
248 }
249
250 /*
251 * Return values...
252 */
253
254 if (alloc_bytes)
255 *alloc_bytes = abytes;
256
257 if (total_bytes)
258 *total_bytes = tbytes;
259
260 return (count);
261 }
262
263
264 /*
265 * '_cups_strcpy()' - Copy a string allowing for overlapping strings.
266 */
267
268 void
269 _cups_strcpy(char *dst, /* I - Destination string */
270 const char *src) /* I - Source string */
271 {
272 while (*src)
273 *dst++ = *src++;
274
275 *dst = '\0';
276 }
277
278
279 /*
280 * '_cups_strdup()' - Duplicate a string.
281 */
282
283 #ifndef HAVE_STRDUP
284 char * /* O - New string pointer */
285 _cups_strdup(const char *s) /* I - String to duplicate */
286 {
287 char *t; /* New string pointer */
288
289
290 if (s == NULL)
291 return (NULL);
292
293 if ((t = malloc(strlen(s) + 1)) == NULL)
294 return (NULL);
295
296 return (strcpy(t, s));
297 }
298 #endif /* !HAVE_STRDUP */
299
300
301 /*
302 * '_cups_strcasecmp()' - Do a case-insensitive comparison.
303 */
304
305 #ifndef HAVE_STRCASECMP
306 int /* O - Result of comparison (-1, 0, or 1) */
307 _cups_strcasecmp(const char *s, /* I - First string */
308 const char *t) /* I - Second string */
309 {
310 while (*s != '\0' && *t != '\0')
311 {
312 if (tolower(*s & 255) < tolower(*t & 255))
313 return (-1);
314 else if (tolower(*s & 255) > tolower(*t & 255))
315 return (1);
316
317 s ++;
318 t ++;
319 }
320
321 if (*s == '\0' && *t == '\0')
322 return (0);
323 else if (*s != '\0')
324 return (1);
325 else
326 return (-1);
327 }
328 #endif /* !HAVE_STRCASECMP */
329
330 /*
331 * '_cups_strncasecmp()' - Do a case-insensitive comparison on up to N chars.
332 */
333
334 #ifndef HAVE_STRNCASECMP
335 int /* O - Result of comparison (-1, 0, or 1) */
336 _cups_strncasecmp(const char *s, /* I - First string */
337 vconst char *t, /* I - Second string */
338 size_t n) /* I - Maximum number of characters to compare */
339 {
340 while (*s != '\0' && *t != '\0' && n > 0)
341 {
342 if (tolower(*s & 255) < tolower(*t & 255))
343 return (-1);
344 else if (tolower(*s & 255) > tolower(*t & 255))
345 return (1);
346
347 s ++;
348 t ++;
349 n --;
350 }
351
352 if (n == 0)
353 return (0);
354 else if (*s == '\0' && *t == '\0')
355 return (0);
356 else if (*s != '\0')
357 return (1);
358 else
359 return (-1);
360 }
361 #endif /* !HAVE_STRNCASECMP */
362
363
364 #ifndef HAVE_STRLCAT
365 /*
366 * '_cups_strlcat()' - Safely concatenate two strings.
367 */
368
369 size_t /* O - Length of string */
370 _cups_strlcat(char *dst, /* O - Destination string */
371 const char *src, /* I - Source string */
372 size_t size) /* I - Size of destination string buffer */
373 {
374 size_t srclen; /* Length of source string */
375 size_t dstlen; /* Length of destination string */
376
377
378 /*
379 * Figure out how much room is left...
380 */
381
382 dstlen = strlen(dst);
383 size -= dstlen + 1;
384
385 if (!size)
386 return (dstlen); /* No room, return immediately... */
387
388 /*
389 * Figure out how much room is needed...
390 */
391
392 srclen = strlen(src);
393
394 /*
395 * Copy the appropriate amount...
396 */
397
398 if (srclen > size)
399 srclen = size;
400
401 memcpy(dst + dstlen, src, srclen);
402 dst[dstlen + srclen] = '\0';
403
404 return (dstlen + srclen);
405 }
406 #endif /* !HAVE_STRLCAT */
407
408
409 #ifndef HAVE_STRLCPY
410 /*
411 * '_cups_strlcpy()' - Safely copy two strings.
412 */
413
414 size_t /* O - Length of string */
415 _cups_strlcpy(char *dst, /* O - Destination string */
416 const char *src, /* I - Source string */
417 size_t size) /* I - Size of destination string buffer */
418 {
419 size_t srclen; /* Length of source string */
420
421
422 /*
423 * Figure out how much room is needed...
424 */
425
426 size --;
427
428 srclen = strlen(src);
429
430 /*
431 * Copy the appropriate amount...
432 */
433
434 if (srclen > size)
435 srclen = size;
436
437 memcpy(dst, src, srclen);
438 dst[srclen] = '\0';
439
440 return (srclen);
441 }
442 #endif /* !HAVE_STRLCPY */
443
444
445 /*
446 * 'compare_sp_items()' - Compare two string pool items...
447 */
448
449 static int /* O - Result of comparison */
450 compare_sp_items(_cups_sp_item_t *a, /* I - First item */
451 _cups_sp_item_t *b) /* I - Second item */
452 {
453 return (strcmp(a->str, b->str));
454 }
455
456
457 /*
458 * End of "$Id: string.c 5047 2006-02-02 05:14:15Z mike $".
459 */