📄 strto_ll.c
字号:
/* * Copyright (C) 2000 Manuel Novoa III * * Notes: * * The primary objective of this implementation was minimal size. * * Note: Assumes char layout 0-9.*A-Z.*a-z for ordinals values. * * There are a couple of compile-time options below. * *//*****************************************************************************//* OPTIONS *//*****************************************************************************//* Set if we want errno set appropriately. *//* NOTE: Implies _STRTO_ENDPTR below */#define _STRTO_ERRNO 0/* Set if we want support for the endptr arg. *//* Implied by _STRTO_ERRNO. */#define _STRTO_ENDPTR 1/*****************************************************************************//* Don't change anything that follows. *//*****************************************************************************/#if _STRTO_ERRNO#undef _STRTO_ENDPTR#define _STRTO_ENDPTR 1#endif/*****************************************************************************//* Are there actually any machines where this might fail? */#if 'A' > 'a'#error ordering assumption violated : 'A' > 'a'#endif#include <stdlib.h>#define __USE_GNU#include <limits.h>#include <ctype.h>#if _STRTO_ERRNO#include <errno.h>#endifunsigned long long _strto_ll(const char *str, char **endptr, int base, int uflag);#if L_strto_ll/* * This is the main work fuction which handles both strtol (uflag = 0) and * strtoul (uflag = 1). */unsigned long long _strto_ll(const char *str, char **endptr, int base, int uflag){ unsigned long long number = 0; unsigned long long cutoff; char *pos = (char *) str;#if _STRTO_ENDPTR char *fail_char = (char *) str;#endif int digit, cutoff_digit; int negative; while (isspace(*pos)) { /* skip leading whitespace */ ++pos; } /* handle optional sign */ negative = 0; switch(*pos) { case '-': negative = 1; /* fall through to increment pos */ case '+': ++pos; } if ((base == 16) && (*pos == '0')) { /* handle option prefix */ ++pos;#if _STRTO_ENDPTR fail_char = pos;#endif if ((*pos == 'x') || (*pos == 'X')) { ++pos; } } if (base == 0) { /* dynamic base */ base = 10; /* default is 10 */ if (*pos == '0') { ++pos; base -= 2; /* now base is 8 (or 16) */#if _STRTO_ENDPTR fail_char = pos;#endif if ((*pos == 'x') || (*pos == 'X')) { base += 8; /* base is 16 */ ++pos; } } } if ((base < 2) || (base > 36)) { /* illegal base */ goto DONE; } cutoff_digit = ULONG_LONG_MAX % base; cutoff = ULONG_LONG_MAX / base; while (1) { digit = 40; if ((*pos >= '0') && (*pos <= '9')) { digit = (*pos - '0'); } else if (*pos >= 'a') { digit = (*pos - 'a' + 10); } else if (*pos >= 'A') { digit = (*pos - 'A' + 10); } else break; if (digit >= base) { break; } ++pos;#if _STRTO_ENDPTR fail_char = pos;#endif /* adjust number, with overflow check */ if ((number > cutoff) || ((number == cutoff) && (digit > cutoff_digit))) { number = ULONG_LONG_MAX; if (uflag) { negative = 0; /* since unsigned returns ULONG_LONG_MAX */ }#if _STRTO_ERRNO __set_errno(ERANGE);#endif } else { number = number * base + digit; } } DONE:#if _STRTO_ENDPTR if (endptr) { *endptr = fail_char; }#endif if (negative) { if (!uflag && (number > ((unsigned long long)(-(1+LONG_LONG_MIN)))+1)) {#if _STRTO_ERRNO __set_errno(ERANGE);#endif return (unsigned long long) LONG_LONG_MIN; } return (unsigned long long)(-((long long)number)); } else { if (!uflag && (number > (unsigned long long) LONG_LONG_MAX)) {#if _STRTO_ERRNO __set_errno(ERANGE);#endif return LONG_LONG_MAX; } return number; }}#endif#if L_strtoullunsigned long long strtoull(const char *str, char **endptr, int base){ return _strto_ll(str, endptr, base, 1);}#endif#if L_strtolllong long strtoll(const char *str, char **endptr, int base){ return _strto_ll(str, endptr, base, 0);}#endif#ifdef L_atolllong long atoll(const char *str){ return(_strto_ll((str),(char**)0,10,0));}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -