]>
git.ipfire.org Git - thirdparty/cups.git/blob - cups/string.c
b92773da320bc8f92456958a12bd0a4df7712976
2 * "$Id: string.c 5238 2006-03-07 04:41:42Z mike $"
4 * String functions for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2006 by Easy Software Products.
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
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
24 * This file is subject to the Apple OS-Developed Software exception.
28 * _cupsStrAlloc() - Allocate/reference a string.
29 * _cupsStrFlush() - Flush the string pool...
30 * _cupsStrFormatd() - Format a floating-point number.
31 * _cupsStrFree() - Free/dereference a string.
32 * _cupsStrScand() - Scan a string for a floating-point number.
33 * _cupsStrStatistics() - Return allocation statistics for string pool.
34 * _cups_strcpy() - Copy a string allowing for overlapping strings.
35 * _cups_strdup() - Duplicate a string.
36 * _cups_strcasecmp() - Do a case-insensitive comparison.
37 * _cups_strncasecmp() - Do a case-insensitive comparison on up to N chars.
38 * _cups_strlcat() - Safely concatenate two strings.
39 * _cups_strlcpy() - Safely copy two strings.
40 * compare_sp_items() - Compare two string pool items...
44 * Include necessary headers...
58 static int compare_sp_items(_cups_sp_item_t
*a
, _cups_sp_item_t
*b
);
62 * '_cupsStrAlloc()' - Allocate/reference a string.
65 char * /* O - String pointer */
66 _cupsStrAlloc(const char *s
) /* I - String */
68 _cups_globals_t
*cg
; /* Global data */
69 _cups_sp_item_t
*item
, /* String pool item */
74 * Range check input...
81 * Get the string pool...
87 cg
->stringpool
= cupsArrayNew((cups_array_func_t
)compare_sp_items
, NULL
);
93 * See if the string is already in the pool...
98 if ((item
= (_cups_sp_item_t
*)cupsArrayFind(cg
->stringpool
, &key
)) != NULL
)
101 * Found it, return the cached string...
110 * Not found, so allocate a new one...
113 item
= (_cups_sp_item_t
*)calloc(1, sizeof(_cups_sp_item_t
));
118 item
->str
= strdup(s
);
127 * Add the string to the pool and return it...
130 cupsArrayAdd(cg
->stringpool
, item
);
137 * '_cupsStrFlush()' - Flush the string pool...
141 _cupsStrFlush(_cups_globals_t
*cg
) /* I - Global data */
143 _cups_sp_item_t
*item
; /* Current item */
146 for (item
= (_cups_sp_item_t
*)cupsArrayFirst(cg
->stringpool
);
148 item
= (_cups_sp_item_t
*)cupsArrayNext(cg
->stringpool
))
154 cupsArrayDelete(cg
->stringpool
);
159 * '_cupsStrFormatd()' - Format a floating-point number.
162 char * /* O - Pointer to end of string */
163 _cupsStrFormatd(char *buf
, /* I - String */
164 char *bufend
, /* I - End of string buffer */
165 double number
, /* I - Number to format */
166 struct lconv
*loc
) /* I - Locale data */
168 char *bufptr
, /* Pointer into buffer */
169 temp
[1024], /* Temporary string */
170 *tempdec
, /* Pointer to decimal point */
171 *tempptr
; /* Pointer into temporary string */
172 const char *dec
; /* Decimal point */
173 int declen
; /* Length of decimal point */
177 * Format the number using the "%.12f" format and then eliminate
178 * unnecessary trailing 0's.
181 snprintf(temp
, sizeof(temp
), "%.12f", number
);
182 for (tempptr
= temp
+ strlen(temp
) - 1;
183 tempptr
> temp
&& *tempptr
== '0';
187 * Next, find the decimal point...
190 if (loc
&& loc
->decimal_point
)
192 dec
= loc
->decimal_point
;
193 declen
= strlen(dec
);
202 tempdec
= strchr(temp
, *dec
);
204 tempdec
= strstr(temp
, dec
);
207 * Copy everything up to the decimal point...
212 for (tempptr
= temp
, bufptr
= buf
;
213 tempptr
< tempdec
&& bufptr
< bufend
;
214 *bufptr
++ = *tempptr
++);
218 if (*tempdec
&& bufptr
< bufend
)
222 while (*tempptr
&& bufptr
< bufend
)
223 *bufptr
++ = *tempptr
++;
230 strlcpy(buf
, temp
, bufend
- buf
+ 1);
231 bufptr
= buf
+ strlen(buf
);
239 * '_cupsStrFree()' - Free/dereference a string.
243 _cupsStrFree(const char *s
) /* I - String to free */
245 _cups_globals_t
*cg
; /* Global data */
246 _cups_sp_item_t
*item
, /* String pool item */
247 key
; /* Search key */
251 * Range check input...
258 * Get the string pool...
267 * See if the string is already in the pool...
272 if ((item
= (_cups_sp_item_t
*)cupsArrayFind(cg
->stringpool
, &key
)) != NULL
)
275 * Found it, dereference...
280 if (!item
->ref_count
)
286 cupsArrayRemove(cg
->stringpool
, item
);
296 * '_cupsStrScand()' - Scan a string for a floating-point number.
298 * This function handles the locale-specific BS so that a decimal
299 * point is always the period (".")...
302 double /* O - Number */
303 _cupsStrScand(const char *buf
, /* I - Pointer to number */
304 char **bufptr
, /* O - New pointer or NULL on error */
305 struct lconv
*loc
) /* I - Locale data */
307 char temp
[1024], /* Temporary buffer */
308 *tempptr
; /* Pointer into temporary buffer */
312 * Range check input...
319 * Skip leading whitespace...
322 while (isspace(*buf
& 255))
326 * Copy leading sign, numbers, period, and then numbers...
330 if (*buf
== '-' || *buf
== '+')
333 while (isdigit(*buf
& 255))
334 if (tempptr
< (temp
+ sizeof(temp
) - 1))
346 if (loc
&& loc
->decimal_point
)
348 strlcpy(tempptr
, loc
->decimal_point
, sizeof(temp
) - (tempptr
- temp
));
349 tempptr
+= strlen(tempptr
);
351 else if (tempptr
< (temp
+ sizeof(temp
) - 1))
361 while (isdigit(*buf
& 255))
362 if (tempptr
< (temp
+ sizeof(temp
) - 1))
374 * Nul-terminate the temporary string and return the value...
378 *bufptr
= (char *)buf
;
382 return (strtod(temp
, NULL
));
387 * '_cupsStrStatistics()' - Return allocation statistics for string pool.
390 size_t /* O - Number of strings */
391 _cupsStrStatistics(size_t *alloc_bytes
, /* O - Allocated bytes */
392 size_t *total_bytes
) /* O - Total string bytes */
394 size_t count
, /* Number of strings */
395 abytes
, /* Allocated string bytes */
396 tbytes
, /* Total string bytes */
397 len
; /* Length of string */
398 _cups_sp_item_t
*item
; /* Current item */
399 _cups_globals_t
*cg
; /* Global data */
403 * Loop through strings in pool, counting everything up...
408 for (count
= 0, abytes
= 0, tbytes
= 0,
409 item
= (_cups_sp_item_t
*)cupsArrayFirst(cg
->stringpool
);
411 item
= (_cups_sp_item_t
*)cupsArrayNext(cg
->stringpool
))
414 * Count allocated memory, using a 64-bit aligned buffer as a basis.
417 count
+= item
->ref_count
;
418 len
= (strlen(item
->str
) + 8) & ~7;
419 abytes
+= sizeof(_cups_sp_item_t
) + len
;
420 tbytes
+= item
->ref_count
* len
;
428 *alloc_bytes
= abytes
;
431 *total_bytes
= tbytes
;
438 * '_cups_strcpy()' - Copy a string allowing for overlapping strings.
442 _cups_strcpy(char *dst
, /* I - Destination string */
443 const char *src
) /* I - Source string */
453 * '_cups_strdup()' - Duplicate a string.
457 char * /* O - New string pointer */
458 _cups_strdup(const char *s
) /* I - String to duplicate */
460 char *t
; /* New string pointer */
466 if ((t
= malloc(strlen(s
) + 1)) == NULL
)
469 return (strcpy(t
, s
));
471 #endif /* !HAVE_STRDUP */
475 * '_cups_strcasecmp()' - Do a case-insensitive comparison.
478 #ifndef HAVE_STRCASECMP
479 int /* O - Result of comparison (-1, 0, or 1) */
480 _cups_strcasecmp(const char *s
, /* I - First string */
481 const char *t
) /* I - Second string */
483 while (*s
!= '\0' && *t
!= '\0')
485 if (tolower(*s
& 255) < tolower(*t
& 255))
487 else if (tolower(*s
& 255) > tolower(*t
& 255))
494 if (*s
== '\0' && *t
== '\0')
501 #endif /* !HAVE_STRCASECMP */
504 * '_cups_strncasecmp()' - Do a case-insensitive comparison on up to N chars.
507 #ifndef HAVE_STRNCASECMP
508 int /* O - Result of comparison (-1, 0, or 1) */
509 _cups_strncasecmp(const char *s
, /* I - First string */
510 vconst
char *t
, /* I - Second string */
511 size_t n
) /* I - Maximum number of characters to compare */
513 while (*s
!= '\0' && *t
!= '\0' && n
> 0)
515 if (tolower(*s
& 255) < tolower(*t
& 255))
517 else if (tolower(*s
& 255) > tolower(*t
& 255))
527 else if (*s
== '\0' && *t
== '\0')
534 #endif /* !HAVE_STRNCASECMP */
539 * '_cups_strlcat()' - Safely concatenate two strings.
542 size_t /* O - Length of string */
543 _cups_strlcat(char *dst
, /* O - Destination string */
544 const char *src
, /* I - Source string */
545 size_t size
) /* I - Size of destination string buffer */
547 size_t srclen
; /* Length of source string */
548 size_t dstlen
; /* Length of destination string */
552 * Figure out how much room is left...
555 dstlen
= strlen(dst
);
559 return (dstlen
); /* No room, return immediately... */
562 * Figure out how much room is needed...
565 srclen
= strlen(src
);
568 * Copy the appropriate amount...
574 memcpy(dst
+ dstlen
, src
, srclen
);
575 dst
[dstlen
+ srclen
] = '\0';
577 return (dstlen
+ srclen
);
579 #endif /* !HAVE_STRLCAT */
584 * '_cups_strlcpy()' - Safely copy two strings.
587 size_t /* O - Length of string */
588 _cups_strlcpy(char *dst
, /* O - Destination string */
589 const char *src
, /* I - Source string */
590 size_t size
) /* I - Size of destination string buffer */
592 size_t srclen
; /* Length of source string */
596 * Figure out how much room is needed...
601 srclen
= strlen(src
);
604 * Copy the appropriate amount...
610 memcpy(dst
, src
, srclen
);
615 #endif /* !HAVE_STRLCPY */
619 * 'compare_sp_items()' - Compare two string pool items...
622 static int /* O - Result of comparison */
623 compare_sp_items(_cups_sp_item_t
*a
, /* I - First item */
624 _cups_sp_item_t
*b
) /* I - Second item */
626 return (strcmp(a
->str
, b
->str
));
631 * End of "$Id: string.c 5238 2006-03-07 04:41:42Z mike $".