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

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
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
解决cocos2d-x文显示问题 /* Copyright (C) 1999-2003, 2005-2006, 2008-2011 Free Software Foundation, Inc. This file is part of the GNU LIBICONV Library. The GNU LIBICONV Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU LIBICONV Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU LIBICONV Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* When installed, this file is called "iconv.h". */ #ifndef _LIBICONV_H #define _LIBICONV_H #define _LIBICONV_VERSION 0x010E /* version number: (major<<8) + minor */ extern @DLL_VARIABLE@ int _libiconv_version; /* Likewise */ /* We would like to #include any system header file which could define iconv_t, 1. in order to eliminate the risk that the user gets compilation errors because some other system header file includes /usr/include/iconv.h which defines iconv_t or declares iconv after this file, 2. when compiling for LIBICONV_PLUG, we need the proper iconv_t type in order to produce binary compatible code. But gcc's #include_next is not portable. Thus, once libiconv's iconv.h has been installed in /usr/local/include, there is no way any more to include the original /usr/include/iconv.h. We simply have to get away without it. Ad 1. The risk that a system header file does #include "iconv.h" or #include_next "iconv.h" is small. They all do #include <iconv.h>. Ad 2. The iconv_t type is a pointer type in all cases I have seen. (It has to be a scalar type because (iconv_t)(-1) is a possible return value from iconv_open().) */ /* Define iconv_t ourselves. */ #undef iconv_t #define iconv_t libiconv_t typedef void* iconv_t; /* Get size_t declaration. Get wchar_t declaration if it exists. */ #include <stddef.h> /* Get errno declaration and values. */ #include <errno.h> /* Some systems, like SunOS 4, don't have EILSEQ. Some systems, like BSD/OS, have EILSEQ in a different header. On these systems, define EILSEQ ourselves. */ #ifndef EILSEQ #define EILSEQ @EILSEQ@ #endif #ifdef __cplusplus extern "C" { #endif /* Allocates descriptor for code conversion from encoding ‘fromcode’ to encoding ‘tocode’. */ #ifndef LIBICONV_PLUG #define iconv_open libiconv_open #endif extern iconv_t iconv_open (const char* tocode, const char* fromcode); /* Converts, using conversion descriptor ‘cd’, at most ‘*inbytesleft’ bytes starting at ‘*inbuf’, writing at most ‘*outbytesleft’ bytes starting at ‘*outbuf’. Decrements ‘*inbytesleft’ and increments ‘*inbuf’ by the same amount. Decrements ‘*outbytesleft’ and increments ‘*outbuf’ by the same amount. */ #ifndef LIBICONV_PLUG #define iconv libiconv #endif extern size_t iconv (iconv_t cd, @ICONV_CONST@ char* * inbuf, size_t *inbytesleft, char* * outbuf, size_t *outbytesleft); /* Frees resources allocated for conversion descriptor ‘cd’. */ #ifndef LIBICONV_PLUG #define iconv_close libiconv_close #endif extern int iconv_close (iconv_t cd); #ifdef __cplusplus } #endif #ifndef LIBICONV_PLUG /* Nonstandard extensions. */ #if @USE_MBSTATE_T@ #if @BROKEN_WCHAR_H@ /* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before <wchar.h>. BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be included before <wchar.h>. */ #include <stddef.h> #include <stdio.h> #include <time.h> #endif #include <wchar.h> #endif #ifdef __cplusplus extern "C" { #endif /* A type that holds all memory needed by a conversion descriptor. A pointer to such an object can be used as an iconv_t. */ typedef struct { void* dummy1[28]; #if @USE_MBSTATE_T@ mbstate_t dummy2; #endif } iconv_allocation_t; /* Allocates descriptor for code conversion from encoding ‘fromcode’ to encoding ‘tocode’ into preallocated memory. Returns an error indicator (0 or -1 with errno set). */ #define iconv_open_into libiconv_open_into extern int iconv_open_into (const char* tocode, const char* fromcode, iconv_allocation_t* resultp); /* Control of attributes. */ #define iconvctl libiconvctl extern int iconvctl (iconv_t cd, int request, void* argument); /* Hook performed after every successful conversion of a Unicode character. */ typedef void (*iconv_unicode_char_hook) (unsigned int uc, void* data); /* Hook performed after every successful conversion of a wide character. */ typedef void (*iconv_wide_char_hook) (wchar_t wc, void* data); /* Set of hooks. */ struct iconv_hooks { iconv_unicode_char_hook uc_hook; iconv_wide_char_hook wc_hook; void* data; }; /* Fallback function. Invoked when a small number of bytes could not be converted to a Unicode character. This function should process all bytes from inbuf and may produce replacement Unicode characters by calling the write_replacement callback repeatedly. */ typedef void (*iconv_unicode_mb_to_uc_fallback) (const char* inbuf, size_t inbufsize, void (*write_replacement) (const unsigned int *buf, size_t buflen, void* callback_arg), void* callback_arg, void* data); /* Fallback function. Invoked when a Unicode character could not be converted to the target encoding. This function should process the character and may produce replacement bytes (in the target encoding) by calling the write_replacement callback repeatedly. */ typedef void (*iconv_unicode_uc_to_mb_fallback) (unsigned int code, void (*write_replacement) (const char *buf, size_t buflen, void* callback_arg), void* callback_arg, void* data); #if @HAVE_WCHAR_T@ /* Fallback function. Invoked when a number of bytes could not be converted to a wide character. This function should process all bytes from inbuf and may produce replacement wide characters by calling the write_replacement callback repeatedly. */ typedef void (*iconv_wchar_mb_to_wc_fallback) (const char* inbuf, size_t inbufsize, void (*write_replacement) (const wchar_t *buf, size_t buflen, void* callback_arg), void* callback_arg, void* data); /* Fallback function. Invoked when a wide character could not be converted to the target encoding. This function should process the character and may produce replacement bytes (in the target encoding) by calling the write_replacement callback repeatedly. */ typedef void (*iconv_wchar_wc_to_mb_fallback) (wchar_t code, void (*write_replacement) (const char *buf, size_t buflen, void* callback_arg), void* callback_arg, void* data); #else /* If the wchar_t type does not exist, these two fallback functions are never invoked. Their argument list therefore does not matter. */ typedef void (*iconv_wchar_mb_to_wc_fallback) (); typedef void (*iconv_wchar_wc_to_mb_fallback) (); #endif /* Set of fallbacks. */ struct iconv_fallbacks { iconv_unicode_mb_to_uc_fallback mb_to_uc_fallback; iconv_unicode_uc_to_mb_fallback uc_to_mb_fallback; iconv_wchar_mb_to_wc_fallback mb_to_wc_fallback; iconv_wchar_wc_to_mb_fallback wc_to_mb_fallback; void* data; }; /* Requests for iconvctl. */ #define ICONV_TRIVIALP 0 /* int *argument */ #define ICONV_GET_TRANSLITERATE 1 /* int *argument */ #define ICONV_SET_TRANSLITERATE 2 /* const int *argument */ #define ICONV_GET_DISCARD_ILSEQ 3 /* int *argument */ #define ICONV_SET_DISCARD_ILSEQ 4 /* const int *argument */ #define ICONV_SET_HOOKS 5 /* const struct iconv_hooks *argument */ #define ICONV_SET_FALLBACKS 6 /* const struct iconv_fallbacks *argument */ /* Listing of locale independent encodings. */ #define iconvlist libiconvlist extern void iconvlist (int (*do_one) (unsigned int namescount, const char * const * names, void* data), void* data); /* Canonicalize an encoding name. The result is either a canonical encoding name, or name itself. */ extern const char * iconv_canonicalize (const char * name); /* Support for relocatable packages. */ /* Sets the original and the current installation prefix of the package. Relocation simply replaces a pathname starting with the original prefix by the corresponding pathname with the current prefix instead. Both prefixes should be directory names without trailing slash (i.e. use "" instead of "/"). */ extern void libiconv_set_relocation_prefix (const char *orig_prefix, const char *curr_prefix); #ifdef __cplusplus } #endif #endif #endif /* _LIBICONV_H */

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EnjoyCodingAndGame

愿我的知识,成为您的财富!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值