X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=cups%2Fstring.c;h=e91ba40d4660490e0b2f5862b5f03525cb9beb57;hb=bfc73dc326f5c93f1df7dcb357d0c8bfcd610636;hp=b92773da320bc8f92456958a12bd0a4df7712976;hpb=757d2cad8f3f75c420ad2e462b787cd9cf8a7a62;p=thirdparty%2Fcups.git diff --git a/cups/string.c b/cups/string.c index b92773da3..e91ba40d4 100644 --- a/cups/string.c +++ b/cups/string.c @@ -1,54 +1,31 @@ /* - * "$Id: string.c 5238 2006-03-07 04:41:42Z mike $" + * String functions for CUPS. * - * String functions for the Common UNIX Printing System (CUPS). + * Copyright 2007-2014 by Apple Inc. + * Copyright 1997-2007 by Easy Software Products. * - * Copyright 1997-2006 by Easy Software Products. - * - * These coded instructions, statements, and computer programs are the - * property of Easy Software Products and are protected by Federal - * copyright law. Distribution and use rights are outlined in the file - * "LICENSE.txt" which should have been included with this file. If this - * file is missing or damaged please contact Easy Software Products - * at: - * - * Attn: CUPS Licensing Information - * Easy Software Products - * 44141 Airport View Drive, Suite 204 - * Hollywood, Maryland 20636 USA - * - * Voice: (301) 373-9600 - * EMail: cups-info@cups.org - * WWW: http://www.cups.org - * - * This file is subject to the Apple OS-Developed Software exception. - * - * Contents: - * - * _cupsStrAlloc() - Allocate/reference a string. - * _cupsStrFlush() - Flush the string pool... - * _cupsStrFormatd() - Format a floating-point number. - * _cupsStrFree() - Free/dereference a string. - * _cupsStrScand() - Scan a string for a floating-point number. - * _cupsStrStatistics() - Return allocation statistics for string pool. - * _cups_strcpy() - Copy a string allowing for overlapping strings. - * _cups_strdup() - Duplicate a string. - * _cups_strcasecmp() - Do a case-insensitive comparison. - * _cups_strncasecmp() - Do a case-insensitive comparison on up to N chars. - * _cups_strlcat() - Safely concatenate two strings. - * _cups_strlcpy() - Safely copy two strings. - * compare_sp_items() - Compare two string pool items... + * Licensed under Apache License v2.0. See the file "LICENSE" for more information. */ /* * Include necessary headers... */ -#include +#define _CUPS_STRING_C_ +#include "cups-private.h" +#include "debug-internal.h" +#include #include -#include "debug.h" -#include "string.h" -#include "globals.h" + + +/* + * Local globals... + */ + +static _cups_mutex_t sp_mutex = _CUPS_MUTEX_INITIALIZER; + /* Mutex to control access to pool */ +static cups_array_t *stringpool = NULL; + /* Global string pool */ /* @@ -65,9 +42,9 @@ static int compare_sp_items(_cups_sp_item_t *a, _cups_sp_item_t *b); char * /* O - String pointer */ _cupsStrAlloc(const char *s) /* I - String */ { - _cups_globals_t *cg; /* Global data */ + size_t slen; /* Length of string */ _cups_sp_item_t *item, /* String pool item */ - key; /* Search key */ + *key; /* Search key */ /* @@ -81,21 +58,25 @@ _cupsStrAlloc(const char *s) /* I - String */ * Get the string pool... */ - cg = _cupsGlobals(); + _cupsMutexLock(&sp_mutex); + + if (!stringpool) + stringpool = cupsArrayNew((cups_array_func_t)compare_sp_items, NULL); - if (!cg->stringpool) - cg->stringpool = cupsArrayNew((cups_array_func_t)compare_sp_items, NULL); + if (!stringpool) + { + _cupsMutexUnlock(&sp_mutex); - if (!cg->stringpool) return (NULL); + } /* * See if the string is already in the pool... */ - key.str = (char *)s; + key = (_cups_sp_item_t *)(s - offsetof(_cups_sp_item_t, str)); - if ((item = (_cups_sp_item_t *)cupsArrayFind(cg->stringpool, &key)) != NULL) + if ((item = (_cups_sp_item_t *)cupsArrayFind(stringpool, key)) != NULL) { /* * Found it, return the cached string... @@ -103,6 +84,17 @@ _cupsStrAlloc(const char *s) /* I - String */ item->ref_count ++; +#ifdef DEBUG_GUARDS + DEBUG_printf(("5_cupsStrAlloc: Using string %p(%s) for \"%s\", guard=%08x, " + "ref_count=%d", item, item->str, s, item->guard, + item->ref_count)); + + if (item->guard != _CUPS_STR_GUARD) + abort(); +#endif /* DEBUG_GUARDS */ + + _cupsMutexUnlock(&sp_mutex); + return (item->str); } @@ -110,48 +102,95 @@ _cupsStrAlloc(const char *s) /* I - String */ * Not found, so allocate a new one... */ - item = (_cups_sp_item_t *)calloc(1, sizeof(_cups_sp_item_t)); + slen = strlen(s); + item = (_cups_sp_item_t *)calloc(1, sizeof(_cups_sp_item_t) + slen); if (!item) + { + _cupsMutexUnlock(&sp_mutex); + return (NULL); + } item->ref_count = 1; - item->str = strdup(s); + memcpy(item->str, s, slen + 1); - if (!item->str) - { - free(item); - return (NULL); - } +#ifdef DEBUG_GUARDS + item->guard = _CUPS_STR_GUARD; + + DEBUG_printf(("5_cupsStrAlloc: Created string %p(%s) for \"%s\", guard=%08x, " + "ref_count=%d", item, item->str, s, item->guard, + item->ref_count)); +#endif /* DEBUG_GUARDS */ /* * Add the string to the pool and return it... */ - cupsArrayAdd(cg->stringpool, item); + cupsArrayAdd(stringpool, item); + + _cupsMutexUnlock(&sp_mutex); return (item->str); } /* - * '_cupsStrFlush()' - Flush the string pool... + * '_cupsStrDate()' - Return a localized date for a given time value. + * + * This function works around the locale encoding issues of strftime... + */ + +char * /* O - Buffer */ +_cupsStrDate(char *buf, /* I - Buffer */ + size_t bufsize, /* I - Size of buffer */ + time_t timeval) /* I - Time value */ +{ + struct tm *dateval; /* Local date/time */ + char temp[1024]; /* Temporary buffer */ + _cups_globals_t *cg = _cupsGlobals(); /* Per-thread globals */ + + + if (!cg->lang_default) + cg->lang_default = cupsLangDefault(); + + dateval = localtime(&timeval); + + if (cg->lang_default->encoding != CUPS_UTF8) + { + strftime(temp, sizeof(temp), "%c", dateval); + cupsCharsetToUTF8((cups_utf8_t *)buf, temp, (int)bufsize, cg->lang_default->encoding); + } + else + strftime(buf, bufsize, "%c", dateval); + + return (buf); +} + + +/* + * '_cupsStrFlush()' - Flush the string pool. */ void -_cupsStrFlush(_cups_globals_t *cg) /* I - Global data */ +_cupsStrFlush(void) { _cups_sp_item_t *item; /* Current item */ - for (item = (_cups_sp_item_t *)cupsArrayFirst(cg->stringpool); + DEBUG_printf(("4_cupsStrFlush: %d strings in array", + cupsArrayCount(stringpool))); + + _cupsMutexLock(&sp_mutex); + + for (item = (_cups_sp_item_t *)cupsArrayFirst(stringpool); item; - item = (_cups_sp_item_t *)cupsArrayNext(cg->stringpool)) - { - free(item->str); + item = (_cups_sp_item_t *)cupsArrayNext(stringpool)) free(item); - } - cupsArrayDelete(cg->stringpool); + cupsArrayDelete(stringpool); + stringpool = NULL; + + _cupsMutexUnlock(&sp_mutex); } @@ -190,7 +229,7 @@ _cupsStrFormatd(char *buf, /* I - String */ if (loc && loc->decimal_point) { dec = loc->decimal_point; - declen = strlen(dec); + declen = (int)strlen(dec); } else { @@ -213,9 +252,9 @@ _cupsStrFormatd(char *buf, /* I - String */ tempptr < tempdec && bufptr < bufend; *bufptr++ = *tempptr++); - tempdec += declen; + tempptr += declen; - if (*tempdec && bufptr < bufend) + if (*tempptr && bufptr < bufend) { *bufptr++ = '.'; @@ -227,7 +266,7 @@ _cupsStrFormatd(char *buf, /* I - String */ } else { - strlcpy(buf, temp, bufend - buf + 1); + strlcpy(buf, temp, (size_t)(bufend - buf + 1)); bufptr = buf + strlen(buf); } @@ -242,9 +281,8 @@ _cupsStrFormatd(char *buf, /* I - String */ void _cupsStrFree(const char *s) /* I - String to free */ { - _cups_globals_t *cg; /* Global data */ _cups_sp_item_t *item, /* String pool item */ - key; /* Search key */ + *key; /* Search key */ /* @@ -255,21 +293,35 @@ _cupsStrFree(const char *s) /* I - String to free */ return; /* - * Get the string pool... + * Check the string pool... + * + * We don't need to lock the mutex yet, as we only want to know if + * the stringpool is initialized. The rest of the code will still + * work if it is initialized before we lock... */ - cg = _cupsGlobals(); - - if (!cg->stringpool) + if (!stringpool) return; /* * See if the string is already in the pool... */ - key.str = (char *)s; + _cupsMutexLock(&sp_mutex); + + key = (_cups_sp_item_t *)(s - offsetof(_cups_sp_item_t, str)); + +#ifdef DEBUG_GUARDS + if (key->guard != _CUPS_STR_GUARD) + { + DEBUG_printf(("5_cupsStrFree: Freeing string %p(%s), guard=%08x, " + "ref_count=%d", key, key->str, key->guard, key->ref_count)); + abort(); + } +#endif /* DEBUG_GUARDS */ - if ((item = (_cups_sp_item_t *)cupsArrayFind(cg->stringpool, &key)) != NULL) + if ((item = (_cups_sp_item_t *)cupsArrayFind(stringpool, key)) != NULL && + item == key) { /* * Found it, dereference... @@ -283,12 +335,51 @@ _cupsStrFree(const char *s) /* I - String to free */ * Remove and free... */ - cupsArrayRemove(cg->stringpool, item); + cupsArrayRemove(stringpool, item); - free(item->str); free(item); } } + + _cupsMutexUnlock(&sp_mutex); +} + + +/* + * '_cupsStrRetain()' - Increment the reference count of a string. + * + * Note: This function does not verify that the passed pointer is in the + * string pool, so any calls to it MUST know they are passing in a + * good pointer. + */ + +char * /* O - Pointer to string */ +_cupsStrRetain(const char *s) /* I - String to retain */ +{ + _cups_sp_item_t *item; /* Pointer to string pool item */ + + + if (s) + { + item = (_cups_sp_item_t *)(s - offsetof(_cups_sp_item_t, str)); + +#ifdef DEBUG_GUARDS + if (item->guard != _CUPS_STR_GUARD) + { + DEBUG_printf(("5_cupsStrRetain: Retaining string %p(%s), guard=%08x, " + "ref_count=%d", item, s, item->guard, item->ref_count)); + abort(); + } +#endif /* DEBUG_GUARDS */ + + _cupsMutexLock(&sp_mutex); + + item->ref_count ++; + + _cupsMutexUnlock(&sp_mutex); + } + + return ((char *)s); } @@ -319,7 +410,7 @@ _cupsStrScand(const char *buf, /* I - Pointer to number */ * Skip leading whitespace... */ - while (isspace(*buf & 255)) + while (_cups_isspace(*buf)) buf ++; /* @@ -343,9 +434,15 @@ _cupsStrScand(const char *buf, /* I - Pointer to number */ if (*buf == '.') { + /* + * Read fractional portion of number... + */ + + buf ++; + if (loc && loc->decimal_point) { - strlcpy(tempptr, loc->decimal_point, sizeof(temp) - (tempptr - temp)); + strlcpy(tempptr, loc->decimal_point, sizeof(temp) - (size_t)(tempptr - temp)); tempptr += strlen(tempptr); } else if (tempptr < (temp + sizeof(temp) - 1)) @@ -370,6 +467,47 @@ _cupsStrScand(const char *buf, /* I - Pointer to number */ } } + if (*buf == 'e' || *buf == 'E') + { + /* + * Read exponent... + */ + + if (tempptr < (temp + sizeof(temp) - 1)) + *tempptr++ = *buf++; + else + { + if (bufptr) + *bufptr = NULL; + + return (0.0); + } + + if (*buf == '+' || *buf == '-') + { + if (tempptr < (temp + sizeof(temp) - 1)) + *tempptr++ = *buf++; + else + { + if (bufptr) + *bufptr = NULL; + + return (0.0); + } + } + + while (isdigit(*buf & 255)) + if (tempptr < (temp + sizeof(temp) - 1)) + *tempptr++ = *buf++; + else + { + if (bufptr) + *bufptr = NULL; + + return (0.0); + } + } + /* * Nul-terminate the temporary string and return the value... */ @@ -396,30 +534,31 @@ _cupsStrStatistics(size_t *alloc_bytes, /* O - Allocated bytes */ tbytes, /* Total string bytes */ len; /* Length of string */ _cups_sp_item_t *item; /* Current item */ - _cups_globals_t *cg; /* Global data */ /* * Loop through strings in pool, counting everything up... */ - cg = _cupsGlobals(); + _cupsMutexLock(&sp_mutex); for (count = 0, abytes = 0, tbytes = 0, - item = (_cups_sp_item_t *)cupsArrayFirst(cg->stringpool); + item = (_cups_sp_item_t *)cupsArrayFirst(stringpool); item; - item = (_cups_sp_item_t *)cupsArrayNext(cg->stringpool)) + item = (_cups_sp_item_t *)cupsArrayNext(stringpool)) { /* * Count allocated memory, using a 64-bit aligned buffer as a basis. */ count += item->ref_count; - len = (strlen(item->str) + 8) & ~7; + len = (strlen(item->str) + 8) & (size_t)~7; abytes += sizeof(_cups_sp_item_t) + len; tbytes += item->ref_count * len; } + _cupsMutexUnlock(&sp_mutex); + /* * Return values... */ @@ -440,7 +579,7 @@ _cupsStrStatistics(size_t *alloc_bytes, /* O - Allocated bytes */ void _cups_strcpy(char *dst, /* I - Destination string */ - const char *src) /* I - Source string */ + const char *src) /* I - Source string */ { while (*src) *dst++ = *src++; @@ -457,16 +596,18 @@ _cups_strcpy(char *dst, /* I - Destination string */ char * /* O - New string pointer */ _cups_strdup(const char *s) /* I - String to duplicate */ { - char *t; /* New string pointer */ + char *t; /* New string pointer */ + size_t slen; /* Length of string */ - if (s == NULL) + if (!s) return (NULL); - if ((t = malloc(strlen(s) + 1)) == NULL) + slen = strlen(s); + if ((t = malloc(slen + 1)) == NULL) return (NULL); - return (strcpy(t, s)); + return (memcpy(t, s, slen + 1)); } #endif /* !HAVE_STRDUP */ @@ -475,16 +616,15 @@ _cups_strdup(const char *s) /* I - String to duplicate */ * '_cups_strcasecmp()' - Do a case-insensitive comparison. */ -#ifndef HAVE_STRCASECMP int /* O - Result of comparison (-1, 0, or 1) */ _cups_strcasecmp(const char *s, /* I - First string */ - const char *t) /* I - Second string */ + const char *t) /* I - Second string */ { while (*s != '\0' && *t != '\0') { - if (tolower(*s & 255) < tolower(*t & 255)) + if (_cups_tolower(*s) < _cups_tolower(*t)) return (-1); - else if (tolower(*s & 255) > tolower(*t & 255)) + else if (_cups_tolower(*s) > _cups_tolower(*t)) return (1); s ++; @@ -498,23 +638,21 @@ _cups_strcasecmp(const char *s, /* I - First string */ else return (-1); } -#endif /* !HAVE_STRCASECMP */ /* * '_cups_strncasecmp()' - Do a case-insensitive comparison on up to N chars. */ -#ifndef HAVE_STRNCASECMP int /* O - Result of comparison (-1, 0, or 1) */ _cups_strncasecmp(const char *s, /* I - First string */ - vconst char *t, /* I - Second string */ + const char *t, /* I - Second string */ size_t n) /* I - Maximum number of characters to compare */ { while (*s != '\0' && *t != '\0' && n > 0) { - if (tolower(*s & 255) < tolower(*t & 255)) + if (_cups_tolower(*s) < _cups_tolower(*t)) return (-1); - else if (tolower(*s & 255) > tolower(*t & 255)) + else if (_cups_tolower(*s) > _cups_tolower(*t)) return (1); s ++; @@ -531,7 +669,6 @@ _cups_strncasecmp(const char *s, /* I - First string */ else return (-1); } -#endif /* !HAVE_STRNCASECMP */ #ifndef HAVE_STRLCAT @@ -553,10 +690,11 @@ _cups_strlcat(char *dst, /* O - Destination string */ */ dstlen = strlen(dst); - size -= dstlen + 1; - if (!size) - return (dstlen); /* No room, return immediately... */ + if (size < (dstlen + 1)) + return (dstlen); /* No room, return immediately... */ + + size -= dstlen + 1; /* * Figure out how much room is needed... @@ -571,7 +709,7 @@ _cups_strlcat(char *dst, /* O - Destination string */ if (srclen > size) srclen = size; - memcpy(dst + dstlen, src, srclen); + memmove(dst + dstlen, src, srclen); dst[dstlen + srclen] = '\0'; return (dstlen + srclen); @@ -607,7 +745,7 @@ _cups_strlcpy(char *dst, /* O - Destination string */ if (srclen > size) srclen = size; - memcpy(dst, src, srclen); + memmove(dst, src, srclen); dst[srclen] = '\0'; return (srclen); @@ -625,8 +763,3 @@ compare_sp_items(_cups_sp_item_t *a, /* I - First item */ { return (strcmp(a->str, b->str)); } - - -/* - * End of "$Id: string.c 5238 2006-03-07 04:41:42Z mike $". - */