Edit

kc3-lang/libxml2/strio.c

Branch :

  • Show log

    Commit

  • Author : Bjorn Reese
    Date : 2001-06-05 12:46:33
    Hash : 906ec8a0
    Message : Upgraded to trio baseline 1.4

  • strio.c
  • /*************************************************************************
     *
     * $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.
     *
     ************************************************************************/
    
    /*
     * TODO
     * - StrToLongDouble
     */
     
    static const char rcsid[] = "@(#)$Id$";
    
    #if defined(unix) || defined(__xlC__) || defined(__QNX__)
    # 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 <locale.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
    # if defined(__QNX__)
    #  define strcasecmp(x,y) stricmp(x,y)
    #  define strncasecmp(x,y,n) strnicmp(x,y,n)
    # endif
    #elif defined(PLATFORM_WIN32)
    # define USE_STRCASECMP
    # define strcasecmp(x,y) strcmpi(x,y)
    #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 = StrAlloc(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 = StrAlloc(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));
    #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;
    }
    
    /*************************************************************************
     * StrEqualLocale
     */
    int StrEqualLocale(const char *first, const char *second)
    {
      assert(VALID(first));
      assert(VALID(second));
    
    #if defined(LC_COLLATE)
      return (strcoll(first, second) == 0);
    #else
      return StrEqual(first, second);
    #endif
    }
    
    /*************************************************************************
     * 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((int)*string) != toupper((int)*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')
    		      : 10 + (toupper((int)*source) - 'A'));
    	  source++;
    	}
          if (*source == '.')
    	{
    	  source++;
    	  while (isxdigit((int)*source))
    	    {
    	      fraction *= 16;
    	      fraction += (isdigit((int)*source)
    			   ? (*source - '0')
    			   : 10 + (toupper((int)*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((int)*target);
          target++;
          i++;
        }
      return i;
    }