atoi在glibc 2.24中的实现的相关源代码

来源:互联网 发布:mac 自动弹出网页 编辑:程序博客网 时间:2024/05/15 23:46
glibc 2.24


atoi.c
    1 /* Copyright (C) 1991-2016 Free Software Foundation, Inc.
    2    This file is part of the GNU C Library.
    3 
    4    The GNU C Library is free software; you can redistribute it and/or
    5    modify it under the terms of the GNU Lesser General Public
    6    License as published by the Free Software Foundation; either
    7    version 2.1 of the License, or (at your option) any later version.
    8 
    9    The GNU C Library is distributed in the hope that it will be useful,
   10    but WITHOUT ANY WARRANTY; without even the implied warranty of
   11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   12    Lesser General Public License for more details.
   13 
   14    You should have received a copy of the GNU Lesser General Public
   15    License along with the GNU C Library; if not, see
   16    <http://www.gnu.org/licenses/>.  */
   17 
   18 #include <stdlib.h>
   19 
   20 #undef  atoi
   21 
   22 
   23 /* Convert a string to an int.  */
   24 int
   25 atoi (const char *nptr)
   26 {
   27   return (int) strtol (nptr, (char **) NULL, 10);
   28 }


strtol.c
   94 INT
   95 INTERNAL (strtol) (const STRING_TYPE *nptr, STRING_TYPE **endptr,
   96            int base, int group)
   97 {
   98   return INTERNAL (__strtol_l) (nptr, endptr, base, group, _NL_CURRENT_LOCALE);
   99 }


strtol_l.c
  217  /* Convert NPTR to an `unsigned long int' or `long int' in base BASE.
  218    If BASE is 0 the base is determined by the presence of a leading
  219    zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
  220    If BASE is < 2 or > 36, it is reset to 10.
  221    If ENDPTR is not NULL, a pointer to the character after the last
  222    one converted is stored in *ENDPTR.  */
  223 
  224 INT
  225 INTERNAL (__strtol_l) (const STRING_TYPE *nptr, STRING_TYPE **endptr,
  226                int base, int group, __locale_t loc)
  227 {
  228   int negative;
  229   unsigned LONG int cutoff;
  230   unsigned int cutlim;
  231   unsigned LONG int i;
  232   const STRING_TYPE *s;
  233   UCHAR_TYPE c;
  234   const STRING_TYPE *save, *end;
  235   int overflow;
  236 #ifndef USE_WIDE_CHAR
  237   size_t cnt;
  238 #endif
  239 
  240 #ifdef USE_NUMBER_GROUPING
  241   struct __locale_data *current = loc->__locales[LC_NUMERIC];
  242   /* The thousands character of the current locale.  */
  243 # ifdef USE_WIDE_CHAR
  244   wchar_t thousands = L'\0';
  245 # else
  246   const char *thousands = NULL;
  247   size_t thousands_len = 0;
  248 # endif
  249   /* The numeric grouping specification of the current locale,
  250      in the format described in <locale.h>.  */
  251   const char *grouping;
  252 
  253   if (__glibc_unlikely (group))
  254     {
  255       grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
  256       if (*grouping <= 0 || *grouping == CHAR_MAX)
  257     grouping = NULL;
  258       else
  259     {
  260       /* Figure out the thousands separator character.  */
  261 # ifdef USE_WIDE_CHAR
  262 #  ifdef _LIBC
  263       thousands = _NL_CURRENT_WORD (LC_NUMERIC,
  264                     _NL_NUMERIC_THOUSANDS_SEP_WC);
  265 #  endif
  266       if (thousands == L'\0')
  267         grouping = NULL;
  268 # else
  269 #  ifdef _LIBC
  270       thousands = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
  271 #  endif
  272       if (*thousands == '\0')
  273         {
  274           thousands = NULL;
  275           grouping = NULL;
  276         }
  277 # endif
  278     }
  279     }
  280   else
  281     grouping = NULL;
  282 #endif
  283 
  284   if (base < 0 || base == 1 || base > 36)
  285     {
  286       __set_errno (EINVAL);
  287       return 0;
  288     }
  289 
  290   save = s = nptr;
  291 
  292   /* Skip white space.  */
  293   while (ISSPACE (*s))
  294     ++s;
  295   if (__glibc_unlikely (*s == L_('\0')))
  296     goto noconv;
  297 
  298   /* Check for a sign.  */
  299   negative = 0;
  300   if (*s == L_('-'))
  301     {
  302       negative = 1;
  303       ++s;
  304     }
  305   else if (*s == L_('+'))
  306     ++s;
  307 
  308   /* Recognize number prefix and if BASE is zero, figure it out ourselves.  */
  309   if (*s == L_('0'))
  310     {
  311       if ((base == 0 || base == 16) && TOUPPER (s[1]) == L_('X'))
  312     {
  313       s += 2;
  314       base = 16;
  315     }
  316       else if (base == 0)
  317     base = 8;
  318     }
  319   else if (base == 0)
  320     base = 10;
  321 
  322   /* Save the pointer so we can check later if anything happened.  */
  323   save = s;
  324 
  325 #ifdef USE_NUMBER_GROUPING
  326   if (base != 10)
  327     grouping = NULL;
  328 
  329   if (__glibc_unlikely (grouping != NULL))
  330     {
  331 # ifndef USE_WIDE_CHAR
  332       thousands_len = strlen (thousands);
  333 # endif
  334 
  335       /* Find the end of the digit string and check its grouping.  */
  336       end = s;
  337       if (
  338 # ifdef USE_WIDE_CHAR
  339       *s != thousands
  340 # else
  341       ({ for (cnt = 0; cnt < thousands_len; ++cnt)
  342            if (thousands[cnt] != end[cnt])
  343          break;
  344          cnt < thousands_len; })
  345 # endif
  346       )
  347     {
  348       for (c = *end; c != L_('\0'); c = *++end)
  349         if (((STRING_TYPE) c < L_('0') || (STRING_TYPE) c > L_('9'))
  350 # ifdef USE_WIDE_CHAR
  351         && (wchar_t) c != thousands
  352 # else
  353         && ({ for (cnt = 0; cnt < thousands_len; ++cnt)
  354             if (thousands[cnt] != end[cnt])
  355               break;
  356               cnt < thousands_len; })
  357 # endif
  358         && (!ISALPHA (c)
  359             || (int) (TOUPPER (c) - L_('A') + 10) >= base))
  360           break;
  361 
  362 # ifdef USE_WIDE_CHAR
  363       end = __correctly_grouped_prefixwc (s, end, thousands, grouping);
  364 # else
  365       end = __correctly_grouped_prefixmb (s, end, thousands, grouping);
  366 # endif
  367     }
  368     }
  369   else
  370 #endif
  371     end = NULL;
  372 
  373   /* Avoid runtime division; lookup cutoff and limit.  */
  374   cutoff = cutoff_tab[base - 2];
  375   cutlim = cutlim_tab[base - 2];
  376 
  377   overflow = 0;
  378   i = 0;
  379   c = *s;
  380   if (sizeof (long int) != sizeof (LONG int))
  381     {
  382       unsigned long int j = 0;
  383       unsigned long int jmax = jmax_tab[base - 2];
  384 
  385       for (;c != L_('\0'); c = *++s)
  386     {
  387       if (s == end)
  388         break;
  389       if (c >= L_('0') && c <= L_('9'))
  390         c -= L_('0');
  391 #ifdef USE_NUMBER_GROUPING
  392 # ifdef USE_WIDE_CHAR
  393       else if (grouping && (wchar_t) c == thousands)
  394         continue;
  395 # else
  396       else if (thousands_len)
  397         {
  398           for (cnt = 0; cnt < thousands_len; ++cnt)
  399         if (thousands[cnt] != s[cnt])
  400           break;
  401           if (cnt == thousands_len)
  402         {
  403           s += thousands_len - 1;
  404           continue;
  405         }
  406           if (ISALPHA (c))
  407         c = TOUPPER (c) - L_('A') + 10;
  408           else
  409         break;
  410         }
  411 # endif
  412 #endif
  413       else if (ISALPHA (c))
  414         c = TOUPPER (c) - L_('A') + 10;
  415       else
  416         break;
  417       if ((int) c >= base)
  418         break;
  419       /* Note that we never can have an overflow.  */
  420       else if (j >= jmax)
  421         {
  422           /* We have an overflow.  Now use the long representation.  */
  423           i = (unsigned LONG int) j;
  424           goto use_long;
  425         }
  426       else
  427         j = j * (unsigned long int) base + c;
  428     }
  429 
  430       i = (unsigned LONG int) j;
  431     }
  432   else
  433     for (;c != L_('\0'); c = *++s)
  434       {
  435     if (s == end)
  436       break;
  437     if (c >= L_('0') && c <= L_('9'))
  438       c -= L_('0');
  439 #ifdef USE_NUMBER_GROUPING
  440 # ifdef USE_WIDE_CHAR
  441     else if (grouping && (wchar_t) c == thousands)
  442       continue;
  443 # else
  444     else if (thousands_len)
  445       {
  446         for (cnt = 0; cnt < thousands_len; ++cnt)
  447           if (thousands[cnt] != s[cnt])
  448         break;
  449         if (cnt == thousands_len)
  450           {
  451         s += thousands_len - 1;
  452         continue;
  453           }
  454         if (ISALPHA (c))
  455           c = TOUPPER (c) - L_('A') + 10;
  456         else
  457           break;
  458       }
  459 # endif
  460 #endif
  461     else if (ISALPHA (c))
  462       c = TOUPPER (c) - L_('A') + 10;
  463     else
  464       break;
  465     if ((int) c >= base)
  466       break;
  467     /* Check for overflow.  */
  468     if (i > cutoff || (i == cutoff && c > cutlim))
  469       overflow = 1;
  470     else
  471       {
  472       use_long:
  473         i *= (unsigned LONG int) base;
  474         i += c;
  475       }
  476       }
  477 
  478   /* Check if anything actually happened.  */
  479   if (s == save)
  480     goto noconv;
  481 
  482   /* Store in ENDPTR the address of one character
  483      past the last character we converted.  */
  484   if (endptr != NULL)
  485     *endptr = (STRING_TYPE *) s;
  486 
  487 #if !UNSIGNED
  488   /* Check for a value that is within the range of
  489      `unsigned LONG int', but outside the range of `LONG int'.  */
  490   if (overflow == 0
  491       && i > (negative
  492           ? -((unsigned LONG int) (STRTOL_LONG_MIN + 1)) + 1
  493           : (unsigned LONG int) STRTOL_LONG_MAX))
  494     overflow = 1;
  495 #endif
  496 
  497   if (__glibc_unlikely (overflow))
  498     {
  499       __set_errno (ERANGE);
  500 #if UNSIGNED
  501       return STRTOL_ULONG_MAX;
  502 #else
  503       return negative ? STRTOL_LONG_MIN : STRTOL_LONG_MAX;
  504 #endif
  505     }
  506 
  507   /* Return the result of the appropriate sign.  */
  508   return negative ? -i : i;
  509 
  510 noconv:
  511   /* We must handle a special case here: the base is 0 or 16 and the
  512      first two characters are '0' and 'x', but the rest are no
  513      hexadecimal digits.  This is no error case.  We return 0 and
  514      ENDPTR points to the `x`.  */
  515   if (endptr != NULL)
  516     {
  517       if (save - nptr >= 2 && TOUPPER (save[-1]) == L_('X')
  518       && save[-2] == L_('0'))
  519     *endptr = (STRING_TYPE *) &save[-1];
  520       else
  521     /*  There was no number to convert.  */
  522     *endptr = (STRING_TYPE *) nptr;
  523     }
  524 
  525   return 0L;
  526 }
0 0