| /************************************************************************* |
| * |
| * $Id$ |
| * |
| * Copyright (C) 1998 Bjorn Reese and Daniel Stenberg. |
| * |
| * Permission to use, copy, modify, and distribute this software for any |
| * purpose with or without fee is hereby granted, provided that the above |
| * copyright notice and this permission notice appear in all copies. |
| * |
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED |
| * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF |
| * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND |
| * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. |
| * |
| ************************************************************************/ |
| |
| /* DV for libxml */ |
| #include <libxml/xmlversion.h> |
| #ifdef WITH_TRIO |
| |
| /* FIXME |
| * StrToLongDouble |
| */ |
| |
| static const char rcsid[] = "@(#)$Id$"; |
| |
| #if defined(unix) || defined(__xlC__) |
| # define PLATFORM_UNIX |
| #elif defined(WIN32) || defined(_WIN32) |
| # define PLATFORM_WIN32 |
| #elif defined(AMIGA) && defined(__GNUC__) |
| # define PLATFORM_UNIX |
| #endif |
| |
| #if defined(__STDC__) && (__STDC_VERSION__ >= 199901L) |
| # define TRIO_C99 |
| #endif |
| |
| #include "strio.h" |
| #include <string.h> |
| #include <ctype.h> |
| #include <stdarg.h> |
| #include <time.h> |
| #include <math.h> |
| #ifndef DEBUG |
| # define NDEBUG |
| #endif |
| #include <assert.h> |
| |
| #ifndef NULL |
| # define NULL 0 |
| #endif |
| #define NIL ((char)0) |
| #ifndef FALSE |
| # define FALSE (1 == 0) |
| # define TRUE (! FALSE) |
| #endif |
| |
| #define VALID(x) (NULL != (x)) |
| #define INVALID(x) (NULL == (x)) |
| |
| #if defined(PLATFORM_UNIX) |
| # define USE_STRCASECMP |
| # define USE_STRNCASECMP |
| # define USE_STRERROR |
| #elif defined(PLATFORM_WIN32) |
| # define USE_STRCMPI |
| #endif |
| |
| /************************************************************************* |
| * StrAppendMax |
| */ |
| char *StrAppendMax(char *target, size_t max, const char *source) |
| { |
| assert(VALID(target)); |
| assert(VALID(source)); |
| assert(max > 0); |
| |
| max -= StrLength(target) + 1; |
| return (max > 0) ? strncat(target, source, max) : target; |
| } |
| |
| /************************************************************************* |
| * StrCopyMax |
| */ |
| char *StrCopyMax(char *target, size_t max, const char *source) |
| { |
| assert(VALID(target)); |
| assert(VALID(source)); |
| assert(max > 0); /* Includes != 0 */ |
| |
| target = strncpy(target, source, max - 1); |
| target[max - 1] = (char)0; |
| return target; |
| } |
| |
| /************************************************************************* |
| * StrDuplicate |
| */ |
| char *StrDuplicate(const char *source) |
| { |
| char *target; |
| |
| assert(VALID(source)); |
| |
| target = (char *)malloc(StrLength(source) + 1); |
| if (target) |
| { |
| StrCopy(target, source); |
| } |
| return target; |
| } |
| |
| /************************************************************************* |
| * StrDuplicateMax |
| */ |
| char *StrDuplicateMax(const char *source, size_t max) |
| { |
| char *target; |
| size_t len; |
| |
| assert(VALID(source)); |
| assert(max > 0); |
| |
| /* Make room for string plus a terminating zero */ |
| len = StrLength(source) + 1; |
| if (len > max) |
| { |
| len = max; |
| } |
| target = (char *)malloc(len); |
| if (target) |
| { |
| StrCopyMax(target, len, source); |
| } |
| return target; |
| } |
| |
| /************************************************************************* |
| * StrEqual |
| */ |
| int StrEqual(const char *first, const char *second) |
| { |
| assert(VALID(first)); |
| assert(VALID(second)); |
| |
| if (VALID(first) && VALID(second)) |
| { |
| #if defined(USE_STRCASECMP) |
| return (0 == strcasecmp(first, second)); |
| #elif defined(USE_STRCMPI) |
| return (0 == strcmpi(first, second)); |
| #else |
| while ((*first != NIL) && (*second != NIL)) |
| { |
| if (toupper(*first) != toupper(*second)) |
| { |
| break; |
| } |
| first++; |
| second++; |
| } |
| return ((*first == NIL) && (*second == NIL)); |
| #endif |
| } |
| return FALSE; |
| } |
| |
| /************************************************************************* |
| * StrEqualCase |
| */ |
| int StrEqualCase(const char *first, const char *second) |
| { |
| assert(VALID(first)); |
| assert(VALID(second)); |
| |
| if (VALID(first) && VALID(second)) |
| { |
| return (0 == strcmp(first, second)); |
| } |
| return FALSE; |
| } |
| |
| /************************************************************************* |
| * StrEqualCaseMax |
| */ |
| int StrEqualCaseMax(const char *first, size_t max, const char *second) |
| { |
| assert(VALID(first)); |
| assert(VALID(second)); |
| |
| if (VALID(first) && VALID(second)) |
| { |
| return (0 == strncmp(first, second, max)); |
| } |
| return FALSE; |
| } |
| |
| /************************************************************************* |
| * StrEqualMax |
| */ |
| int StrEqualMax(const char *first, size_t max, const char *second) |
| { |
| assert(VALID(first)); |
| assert(VALID(second)); |
| |
| if (VALID(first) && VALID(second)) |
| { |
| #if defined(USE_STRNCASECMP) |
| return (0 == strncasecmp(first, second, max)); |
| #else |
| /* Not adequately tested yet */ |
| size_t cnt = 0; |
| while ((*first != NIL) && (*second != NIL) && (cnt <= max)) |
| { |
| if (toupper(*first) != toupper(*second)) |
| { |
| break; |
| } |
| first++; |
| second++; |
| cnt++; |
| } |
| return ((cnt == max) || ((*first == NIL) && (*second == NIL))); |
| #endif |
| } |
| return FALSE; |
| } |
| |
| /************************************************************************* |
| * StrError |
| */ |
| const char *StrError(int errorNumber) |
| { |
| #if defined(USE_STRERROR) |
| return strerror(errorNumber); |
| #else |
| return "unknown"; |
| #endif |
| } |
| |
| /************************************************************************* |
| * StrFormatDate |
| */ |
| size_t StrFormatDateMax(char *target, |
| size_t max, |
| const char *format, |
| const struct tm *datetime) |
| { |
| assert(VALID(target)); |
| assert(VALID(format)); |
| assert(VALID(datetime)); |
| assert(max > 0); |
| |
| return strftime(target, max, format, datetime); |
| } |
| |
| /************************************************************************* |
| * StrHash |
| */ |
| unsigned long StrHash(const char *string, int type) |
| { |
| unsigned long value = 0L; |
| char ch; |
| |
| assert(VALID(string)); |
| |
| switch (type) |
| { |
| case STRIO_HASH_PLAIN: |
| while ( (ch = *string++) != NIL ) |
| { |
| value *= 31; |
| value += (unsigned long)ch; |
| } |
| break; |
| default: |
| assert(FALSE); |
| break; |
| } |
| return value; |
| } |
| |
| /************************************************************************* |
| * StrMatch |
| */ |
| int StrMatch(char *string, char *pattern) |
| { |
| assert(VALID(string)); |
| assert(VALID(pattern)); |
| |
| for (; ('*' != *pattern); ++pattern, ++string) |
| { |
| if (NIL == *string) |
| { |
| return (NIL == *pattern); |
| } |
| if ((toupper(*string) != toupper(*pattern)) |
| && ('?' != *pattern)) |
| { |
| return FALSE; |
| } |
| } |
| /* two-line patch to prevent *too* much recursiveness: */ |
| while ('*' == pattern[1]) |
| pattern++; |
| |
| do |
| { |
| if ( StrMatch(string, &pattern[1]) ) |
| { |
| return TRUE; |
| } |
| } |
| while (*string++); |
| |
| return FALSE; |
| } |
| |
| /************************************************************************* |
| * StrMatchCase |
| */ |
| int StrMatchCase(char *string, char *pattern) |
| { |
| assert(VALID(string)); |
| assert(VALID(pattern)); |
| |
| for (; ('*' != *pattern); ++pattern, ++string) |
| { |
| if (NIL == *string) |
| { |
| return (NIL == *pattern); |
| } |
| if ((*string != *pattern) |
| && ('?' != *pattern)) |
| { |
| return FALSE; |
| } |
| } |
| /* two-line patch to prevent *too* much recursiveness: */ |
| while ('*' == pattern[1]) |
| pattern++; |
| |
| do |
| { |
| if ( StrMatchCase(string, &pattern[1]) ) |
| { |
| return TRUE; |
| } |
| } |
| while (*string++); |
| |
| return FALSE; |
| } |
| |
| /************************************************************************* |
| * StrSpanFunction |
| * |
| * Untested |
| */ |
| size_t StrSpanFunction(char *source, int (*Function)(int)) |
| { |
| size_t count = 0; |
| |
| assert(VALID(source)); |
| assert(VALID(Function)); |
| |
| while (*source != NIL) |
| { |
| if (Function(*source)) |
| break; /* while */ |
| source++; |
| count++; |
| } |
| return count; |
| } |
| |
| /************************************************************************* |
| * StrSubstringMax |
| */ |
| char *StrSubstringMax(const char *string, size_t max, const char *find) |
| { |
| size_t count; |
| size_t size; |
| char *result = NULL; |
| |
| assert(VALID(string)); |
| assert(VALID(find)); |
| |
| size = StrLength(find); |
| if (size >= max) |
| { |
| for (count = 0; count > max - size; count++) |
| { |
| if (StrEqualMax(find, size, &string[count])) |
| { |
| result = (char *)&string[count]; |
| break; |
| } |
| } |
| } |
| return result; |
| } |
| |
| /************************************************************************* |
| * StrToDouble |
| * |
| * double ::= [ <sign> ] |
| * ( <number> | |
| * <number> <decimal_point> <number> | |
| * <decimal_point> <number> ) |
| * [ <exponential> [ <sign> ] <number> ] |
| * number ::= 1*( <digit> ) |
| * digit ::= ( '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' ) |
| * exponential ::= ( 'e' | 'E' ) |
| * sign ::= ( '-' | '+' ) |
| * decimal_point ::= '.' |
| */ |
| double StrToDouble(const char *source, const char **endp) |
| { |
| #if defined(TRIO_C99) |
| return strtod(source, endp); |
| #else |
| /* Preliminary code */ |
| int isNegative = FALSE; |
| int isExponentNegative = FALSE; |
| unsigned long integer = 0; |
| unsigned long fraction = 0; |
| unsigned long fracdiv = 1; |
| unsigned long exponent = 0; |
| double value = 0.0; |
| |
| /* First try hex-floats */ |
| if ((source[0] == '0') && ((source[1] == 'x') || (source[1] == 'X'))) |
| { |
| source += 2; |
| while (isxdigit((int)*source)) |
| { |
| integer *= 16; |
| integer += (isdigit((int)*source) ? (*source - '0') : |
| (isupper((int)*source) ? (*source - 'A') : |
| (*source - 'a'))); |
| source++; |
| } |
| if (*source == '.') |
| { |
| source++; |
| while (isxdigit((int)*source)) |
| { |
| fraction *= 16; |
| fraction += (isdigit((int)*source) ? (*source - '0') : |
| (isupper((int)*source) ? (*source - 'A') : |
| (*source - 'a'))); |
| fracdiv *= 16; |
| source++; |
| } |
| if ((*source == 'p') || (*source == 'P')) |
| { |
| source++; |
| if ((*source == '+') || (*source == '-')) |
| { |
| isExponentNegative = (*source == '-'); |
| source++; |
| } |
| while (isdigit((int)*source)) |
| { |
| exponent *= 10; |
| exponent += (*source - '0'); |
| source++; |
| } |
| } |
| } |
| } |
| else /* Then try normal decimal floats */ |
| { |
| isNegative = (*source == '-'); |
| /* Skip sign */ |
| if ((*source == '+') || (*source == '-')) |
| source++; |
| |
| /* Integer part */ |
| while (isdigit((int)*source)) |
| { |
| integer *= 10; |
| integer += (*source - '0'); |
| source++; |
| } |
| |
| if (*source == '.') |
| { |
| source++; /* skip decimal point */ |
| while (isdigit((int)*source)) |
| { |
| fraction *= 10; |
| fraction += (*source - '0'); |
| fracdiv *= 10; |
| source++; |
| } |
| } |
| if ((*source == 'e') || (*source == 'E')) |
| { |
| source++; /* Skip exponential indicator */ |
| isExponentNegative = (*source == '-'); |
| if ((*source == '+') || (*source == '-')) |
| source++; |
| while (isdigit((int)*source)) |
| { |
| exponent *= 10; |
| exponent += (*source - '0'); |
| source++; |
| } |
| } |
| } |
| |
| value = (double)integer; |
| if (fraction != 0) |
| { |
| value += (double)fraction / (double)fracdiv; |
| } |
| if (exponent != 0) |
| { |
| if (isExponentNegative) |
| value /= pow((double)10, (double)exponent); |
| else |
| value *= pow((double)10, (double)exponent); |
| } |
| if (isNegative) |
| value = -value; |
| |
| if (endp) |
| *endp = source; |
| return value; |
| #endif |
| } |
| |
| /************************************************************************* |
| * StrToFloat |
| */ |
| float StrToFloat(const char *source, const char **endp) |
| { |
| #if defined(TRIO_C99) |
| return strtof(source, endp); |
| #else |
| return (float)StrToDouble(source, endp); |
| #endif |
| } |
| |
| /************************************************************************* |
| * StrToUpper |
| */ |
| int StrToUpper(char *target) |
| { |
| int i = 0; |
| |
| assert(VALID(target)); |
| |
| while (NIL != *target) |
| { |
| *target = toupper(*target); |
| target++; |
| i++; |
| } |
| return i; |
| } |
| |
| /* DV for libxml */ |
| #endif /* WITH_TRIO */ |