Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /****************************************************************************
  2. *
  3. *                            Open Watcom Project
  4. *
  5. *    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
  6. *
  7. *  ========================================================================
  8. *
  9. *    This file contains Original Code and/or Modifications of Original
  10. *    Code as defined in and that are subject to the Sybase Open Watcom
  11. *    Public License version 1.0 (the 'License'). You may not use this file
  12. *    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
  13. *    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
  14. *    provided with the Original Code and Modifications, and is also
  15. *    available at www.sybase.com/developer/opensource.
  16. *
  17. *    The Original Code and all software distributed under the License are
  18. *    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  19. *    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
  20. *    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
  21. *    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
  22. *    NON-INFRINGEMENT. Please see the License for the specific language
  23. *    governing rights and limitations under the License.
  24. *
  25. *  ========================================================================
  26. *
  27. * Description:  String to long long conversion routines.
  28. *
  29. ****************************************************************************/
  30.  
  31.  
  32. #include "variety.h"
  33. #include "widechar.h"
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <inttypes.h>
  37. #ifdef __WIDECHAR__
  38.     #include <wctype.h>
  39. #else
  40.     #include <ctype.h>
  41. #endif
  42. #include <errno.h>
  43. #include <limits.h>
  44. #include "seterrno.h"
  45.  
  46. /* This is heavily based on strtol() implementation; however this code needs
  47.  * to use 64-bit arithmetic and there is little need to drag in all the
  48.  * supporting code for people who just need 16- or 32-bit string to integer
  49.  * conversion.
  50.  */
  51.  
  52. /*
  53.  * this table is the largest value that can safely be multiplied
  54.  * by the associated base without overflowing
  55.  */
  56. static unsigned long long nearly_overflowing[] = {
  57.     ULLONG_MAX / 2,  ULLONG_MAX / 3,  ULLONG_MAX / 4,  ULLONG_MAX / 5,
  58.     ULLONG_MAX / 6,  ULLONG_MAX / 7,  ULLONG_MAX / 8,  ULLONG_MAX / 9,
  59.     ULLONG_MAX / 10, ULLONG_MAX / 11, ULLONG_MAX / 12, ULLONG_MAX / 13,
  60.     ULLONG_MAX / 14, ULLONG_MAX / 15, ULLONG_MAX / 16, ULLONG_MAX / 17,
  61.     ULLONG_MAX / 18, ULLONG_MAX / 19, ULLONG_MAX / 20, ULLONG_MAX / 21,
  62.     ULLONG_MAX / 22, ULLONG_MAX / 23, ULLONG_MAX / 24, ULLONG_MAX / 25,
  63.     ULLONG_MAX / 26, ULLONG_MAX / 27, ULLONG_MAX / 28, ULLONG_MAX / 29,
  64.     ULLONG_MAX / 30, ULLONG_MAX / 31, ULLONG_MAX / 32, ULLONG_MAX / 33,
  65.     ULLONG_MAX / 34, ULLONG_MAX / 35, ULLONG_MAX / 36
  66. };
  67.  
  68. static int radix_value( CHAR_TYPE c )
  69. {
  70.     if( c >= '0'  &&  c <= '9' ) return( c - '0' );
  71.     c = __F_NAME(tolower,towlower)(c);
  72.     if( c >= 'a'  &&  c <= 'i' ) return( c - 'a' + 10 );
  73.     if( c >= 'j'  &&  c <= 'r' ) return( c - 'j' + 19 );
  74.     if( c >= 's'  &&  c <= 'z' ) return( c - 's' + 28 );
  75.     return( 37 );
  76. }
  77.  
  78. #define hexstr(p) (p[0] == '0' && (p[1] == 'x' || p[1] == 'X'))
  79.  
  80. static unsigned long long int _stoll( const CHAR_TYPE *nptr, CHAR_TYPE **endptr, int base, int who )
  81. {
  82.     const CHAR_TYPE         *p;
  83.     const CHAR_TYPE         *startp;
  84.     int                     digit;
  85.     unsigned long long int  value;
  86.     unsigned long long int  prev_value;
  87.     CHAR_TYPE               sign;
  88.     char                    overflow;   /*overflow is used as a flag so it does not
  89.                                          *need to be of type CHAR_TYPE */
  90.  
  91.     if( endptr != NULL )
  92.         *endptr = (CHAR_TYPE *)nptr;
  93.     p = nptr;
  94.     while( __F_NAME(isspace,iswspace)(*p) )
  95.         ++p;
  96.     sign = *p;
  97.     if( sign == '+'  ||  sign == '-' )
  98.         ++p;
  99.     if( base == 0 ) {
  100.         if( hexstr(p) )
  101.             base = 16;
  102.         else if( *p == '0' )
  103.             base = 8;
  104.         else
  105.             base = 10;
  106.     }
  107.     if( base < 2  ||  base > 36 ) {
  108.         __set_errno( EDOM );
  109.         return( 0 );
  110.     }
  111.     if( base == 16 ) {
  112.         if( hexstr(p) )
  113.             p += 2;    /* skip over '0x' */
  114.     }
  115.     startp = p;
  116.     overflow = 0;
  117.     value = 0;
  118.     for(;;) {
  119.         digit = radix_value( *p );
  120.         if( digit >= base )
  121.             break;
  122.         if( value > nearly_overflowing[base-2] )
  123.             overflow = 1;
  124.         prev_value = value;
  125.         value = value * base + digit;
  126.         if( value < prev_value )
  127.             overflow = 1;
  128.         ++p;
  129.     }
  130.     if( p == startp )
  131.         p = nptr;
  132.     if( endptr != NULL )
  133.         *endptr = (CHAR_TYPE *)p;
  134.     if( who == 1 ) {
  135.         if( value >= 0x8000000000000000 ) {
  136.             if( value == 0x8000000000000000  &&  sign == '-' ) {
  137.                 ;  /* OK */
  138.             } else {
  139.                 overflow = 1;
  140.             }
  141.         }
  142.     }
  143.     if( overflow ) {
  144.         __set_errno( ERANGE );
  145.         if( who == 0 )
  146.             return( ULLONG_MAX );
  147.         if( sign == '-' )
  148.             return( LLONG_MIN );
  149.         return( LLONG_MAX );
  150.     }
  151.     if( sign == '-' )
  152.         value = - value;
  153.     return( value );
  154. }
  155.  
  156.  
  157. _WCRTLINK unsigned long long int __F_NAME(strtoull,wcstoull)( const CHAR_TYPE *nptr, CHAR_TYPE **endptr, int base )
  158. {
  159.     return( _stoll( nptr, endptr, base, 0 ) );
  160. }
  161.  
  162.  
  163. _WCRTLINK long long int __F_NAME(strtoll,wcstoll)( const CHAR_TYPE *nptr, CHAR_TYPE **endptr, int base )
  164. {
  165.     return( _stoll( nptr, endptr, base, 1 ) );
  166. }
  167.  
  168. /* Assuming that intmax_t is equal to long long and uintmax_t to unsigned long long */
  169. _WCRTLINK uintmax_t __F_NAME(strtoumax,wcstoumax)( const CHAR_TYPE *nptr, CHAR_TYPE **endptr, int base )
  170. {
  171.     return( _stoll( nptr, endptr, base, 0 ) );
  172. }
  173.  
  174. _WCRTLINK intmax_t __F_NAME(strtoimax,wcstoimax)( const CHAR_TYPE *nptr, CHAR_TYPE **endptr, int base )
  175. {
  176.     return( _stoll( nptr, endptr, base, 1 ) );
  177. }
  178.