strtoull.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:5k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* 
  2.  * strtoull.c --
  3.  *
  4.  * Source code for the "strtoull" library procedure.
  5.  *
  6.  * Copyright (c) 1988 The Regents of the University of California.
  7.  * Copyright (c) 1994 Sun Microsystems, Inc.
  8.  *
  9.  * See the file "license.terms" for information on usage and redistribution
  10.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  11.  *
  12.  * RCS: @(#) $Id: strtoull.c,v 1.5 2002/02/24 02:53:25 dgp Exp $
  13.  */
  14. #include "tcl.h"
  15. #include "tclPort.h"
  16. #include <ctype.h>
  17. /*
  18.  * The table below is used to convert from ASCII digits to a
  19.  * numerical equivalent.  It maps from '0' through 'z' to integers
  20.  * (100 for non-digit characters).
  21.  */
  22. static char cvtIn[] = {
  23.     0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* '0' - '9' */
  24.     100, 100, 100, 100, 100, 100, 100, /* punctuation */
  25.     10, 11, 12, 13, 14, 15, 16, 17, 18, 19, /* 'A' - 'Z' */
  26.     20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
  27.     30, 31, 32, 33, 34, 35,
  28.     100, 100, 100, 100, 100, 100, /* punctuation */
  29.     10, 11, 12, 13, 14, 15, 16, 17, 18, 19, /* 'a' - 'z' */
  30.     20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
  31.     30, 31, 32, 33, 34, 35};
  32. /*
  33.  *----------------------------------------------------------------------
  34.  *
  35.  * strtoull --
  36.  *
  37.  * Convert an ASCII string into an integer.
  38.  *
  39.  * Results:
  40.  * The return value is the integer equivalent of string.  If endPtr
  41.  * is non-NULL, then *endPtr is filled in with the character
  42.  * after the last one that was part of the integer.  If string
  43.  * doesn't contain a valid integer value, then zero is returned
  44.  * and *endPtr is set to string.
  45.  *
  46.  * Side effects:
  47.  * None.
  48.  *
  49.  *----------------------------------------------------------------------
  50.  */
  51. #if TCL_WIDE_INT_IS_LONG
  52. unsigned long long
  53. #else
  54. Tcl_WideUInt
  55. #endif
  56. strtoull(string, endPtr, base)
  57.     CONST char *string; /* String of ASCII digits, possibly
  58.  * preceded by white space.  For bases
  59.  * greater than 10, either lower- or
  60.  * upper-case digits may be used.
  61.  */
  62.     char **endPtr; /* Where to store address of terminating
  63.  * character, or NULL. */
  64.     int base; /* Base for conversion.  Must be less
  65.  * than 37.  If 0, then the base is chosen
  66.  * from the leading characters of string:
  67.  * "0x" means hex, "0" means octal, anything
  68.  * else means decimal.
  69.  */
  70. {
  71.     register CONST char *p;
  72.     register Tcl_WideUInt result = 0;
  73.     register unsigned digit;
  74.     register Tcl_WideUInt shifted;
  75.     int anyDigits = 0, negative = 0;
  76.     /*
  77.      * Skip any leading blanks.
  78.      */
  79.     p = string;
  80.     while (isspace(UCHAR(*p))) { /* INTL: locale-dependent */
  81. p += 1;
  82.     }
  83.     /*
  84.      * Check for a sign.
  85.      */
  86.     if (*p == '-') {
  87. p += 1;
  88. negative = 1;
  89.     } else {
  90. if (*p == '+') {
  91.     p += 1;
  92. }
  93.     }
  94.     /*
  95.      * If no base was provided, pick one from the leading characters
  96.      * of the string.
  97.      */
  98.     
  99.     if (base == 0) {
  100. if (*p == '0') {
  101.     p += 1;
  102.     if (*p == 'x' || *p == 'X') {
  103. p += 1;
  104. base = 16;
  105.     } else {
  106. /*
  107.  * Must set anyDigits here, otherwise "0" produces a
  108.  * "no digits" error.
  109.  */
  110. anyDigits = 1;
  111. base = 8;
  112.     }
  113. } else {
  114.     base = 10;
  115. }
  116.     } else if (base == 16) {
  117. /*
  118.  * Skip a leading "0x" from hex numbers.
  119.  */
  120. if ((p[0] == '0') && (p[1] == 'x' || *p == 'X')) {
  121.     p += 2;
  122. }
  123.     }
  124.     /*
  125.      * Sorry this code is so messy, but speed seems important.  Do
  126.      * different things for base 8, 10, 16, and other.
  127.      */
  128.     if (base == 8) {
  129. for ( ; ; p += 1) {
  130.     digit = *p - '0';
  131.     if (digit > 7) {
  132. break;
  133.     }
  134.     shifted = result << 3;
  135.     if ((shifted >> 3) != result) {
  136. goto overflow;
  137.     }
  138.     result = shifted + digit;
  139.     if ( result < shifted ) {
  140. goto overflow;
  141.     }
  142.     anyDigits = 1;
  143. }
  144.     } else if (base == 10) {
  145. for ( ; ; p += 1) {
  146.     digit = *p - '0';
  147.     if (digit > 9) {
  148. break;
  149.     }
  150.     shifted = 10 * result;
  151.     if ((shifted / 10) != result) {
  152. goto overflow;
  153.     }
  154.     result = shifted + digit;
  155.     if ( result < shifted ) {
  156. goto overflow;
  157.     }
  158.     anyDigits = 1;
  159. }
  160.     } else if (base == 16) {
  161. for ( ; ; p += 1) {
  162.     digit = *p - '0';
  163.     if (digit > ('z' - '0')) {
  164. break;
  165.     }
  166.     digit = cvtIn[digit];
  167.     if (digit > 15) {
  168. break;
  169.     }
  170.     shifted = result << 4;
  171.     if ((shifted >> 4) != result) {
  172. goto overflow;
  173.     }
  174.     result = shifted + digit;
  175.     if ( result < shifted ) {
  176. goto overflow;
  177.     }
  178.     anyDigits = 1;
  179. }
  180.     } else if ( base >= 2 && base <= 36 ) {
  181. for ( ; ; p += 1) {
  182.     digit = *p - '0';
  183.     if (digit > ('z' - '0')) {
  184. break;
  185.     }
  186.     digit = cvtIn[digit];
  187.     if (digit >= (unsigned) base) {
  188. break;
  189.     }
  190.     shifted = result * base;
  191.     if ((shifted/base) != result) {
  192. goto overflow;
  193.     }
  194.     result = shifted + digit;
  195.     if ( result < shifted ) {
  196. goto overflow;
  197.     }
  198.     anyDigits = 1;
  199. }
  200.     }
  201.     /*
  202.      * Negate if we found a '-' earlier.
  203.      */
  204.     if (negative) {
  205. result = (Tcl_WideUInt)(-((Tcl_WideInt)result));
  206.     }
  207.     /*
  208.      * See if there were any digits at all.
  209.      */
  210.     if (!anyDigits) {
  211. p = string;
  212.     }
  213.     if (endPtr != 0) {
  214. *endPtr = (char *) p;
  215.     }
  216.     return result;
  217.     /*
  218.      * On overflow generate the right output
  219.      */
  220.  overflow:
  221.     errno = ERANGE;
  222.     if (endPtr != 0) {
  223. for ( ; ; p += 1) {
  224.     digit = *p - '0';
  225.     if (digit > ('z' - '0')) {
  226. break;
  227.     }
  228.     digit = cvtIn[digit];
  229.     if (digit >= (unsigned) base) {
  230. break;
  231.     }
  232. }
  233. *endPtr = (char *) p;
  234.     }
  235.     return (Tcl_WideUInt)Tcl_LongAsWide(-1);
  236. }