]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/string.c
Load cups into easysw/current.
[thirdparty/cups.git] / cups / string.c
CommitLineData
ef416fc2 1/*
4400e98d 2 * "$Id: string.c 5047 2006-02-02 05:14:15Z mike $"
ef416fc2 3 *
4 * String functions for the Common UNIX Printing System (CUPS).
5 *
4400e98d 6 * Copyright 1997-2006 by Easy Software Products.
ef416fc2 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 *
4400e98d 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...
ef416fc2 39 */
40
41/*
42 * Include necessary headers...
43 */
44
4400e98d 45#include <stdlib.h>
46#include <limits.h>
47#include "debug.h"
ef416fc2 48#include "string.h"
4400e98d 49#include "globals.h"
50
51
52/*
53 * Local functions...
54 */
55
56static 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
63char * /* 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
138void
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
160void
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
217size_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}
ef416fc2 262
263
264/*
265 * '_cups_strcpy()' - Copy a string allowing for overlapping strings.
266 */
267
268void
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
284char * /* 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
306int /* 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
335int /* 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
369size_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
414size_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/*
4400e98d 446 * 'compare_sp_items()' - Compare two string pool items...
447 */
448
449static int /* O - Result of comparison */
450compare_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 $".
ef416fc2 459 */