Reimplement strtol/strtoul/atoi (#5400)
newlibc version is pulling in (part of) locale support Adapted from uClibc source code Addded support for 0b.... prefix for binary numbers
This commit is contained in:
parent
0a2e5a5878
commit
2abcaebd81
|
@ -15,6 +15,7 @@ COMMON_SRC = \
|
|||
common/printf.c \
|
||||
common/streambuf.c \
|
||||
common/string_light.c \
|
||||
common/strtol.c \
|
||||
common/time.c \
|
||||
common/typeconversion.c \
|
||||
config/config_eeprom.c \
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
/* Copyright (C) 2002 Manuel Novoa III
|
||||
* From my (incomplete) stdlib library for linux and (soon) elks.
|
||||
*
|
||||
* This 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.
|
||||
*
|
||||
* This 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 this library; if not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
|
||||
* Adapted for Betaflight by Petr Ledvina, 2018
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "common/utils.h"
|
||||
|
||||
#define _STRTO_ENDPTR 1
|
||||
|
||||
unsigned long _strto_l(const char * str, char ** endptr, int base, int sflag)
|
||||
{
|
||||
unsigned long number, cutoff;
|
||||
#if _STRTO_ENDPTR
|
||||
const char *fail_char;
|
||||
#define SET_FAIL(X) fail_char = (X)
|
||||
#else
|
||||
#define SET_FAIL(X) ((void)(X)) /* Keep side effects. */
|
||||
#endif
|
||||
unsigned char negative, digit, cutoff_digit;
|
||||
|
||||
SET_FAIL(str);
|
||||
|
||||
while (isspace(*str)) { /* Skip leading whitespace. */
|
||||
++str;
|
||||
}
|
||||
|
||||
/* Handle optional sign. */
|
||||
negative = 0;
|
||||
switch (*str) {
|
||||
case '-':
|
||||
negative = 1; /* Fall through to increment str. */
|
||||
FALLTHROUGH;
|
||||
case '+':
|
||||
++str;
|
||||
}
|
||||
|
||||
if (!base || base == 16 || base == 2) { /* Either dynamic (base = 0) or base with 0[xb] prefix. */
|
||||
if (*str == '0') {
|
||||
SET_FAIL(++str);
|
||||
if ((!base || base == 16) && tolower(*str) == 'x') {
|
||||
++str;
|
||||
base = 16;
|
||||
} else if ((!base || base == 2) && tolower(*str) == 'b') {
|
||||
++str;
|
||||
base = 2;
|
||||
} else if(!base) {
|
||||
base = 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
number = 0;
|
||||
|
||||
if (((unsigned)(base - 2)) < 35) { /* Legal base. */
|
||||
cutoff_digit = ULONG_MAX % base;
|
||||
cutoff = ULONG_MAX / base;
|
||||
do {
|
||||
digit = ( (*str - '0') <= 9)
|
||||
? /* 0..9 */ (*str - '0')
|
||||
: /* else */ (((0x20 | *str) >= 'a') /* WARNING: assumes ascii. */
|
||||
? /* >= A/a */ ((0x20 | *str) - ('a' - 10))
|
||||
: /* else */ 40 /* bad value */);
|
||||
|
||||
if (digit >= base) {
|
||||
break;
|
||||
}
|
||||
|
||||
SET_FAIL(++str);
|
||||
|
||||
if ((number > cutoff)
|
||||
|| ((number == cutoff) && (digit > cutoff_digit))) {
|
||||
number = ULONG_MAX;
|
||||
negative &= sflag;
|
||||
} else {
|
||||
number = number * base + digit;
|
||||
}
|
||||
} while (1);
|
||||
}
|
||||
|
||||
#if _STRTO_ENDPTR
|
||||
if (endptr) {
|
||||
*endptr = (char *) fail_char;
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
unsigned long tmp = (negative
|
||||
? ((unsigned long)(-(1+LONG_MIN)))+1
|
||||
: LONG_MAX);
|
||||
if (sflag && (number > tmp)) {
|
||||
number = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return negative ? (unsigned long)(-((long)number)) : number;
|
||||
}
|
||||
|
||||
long strtol(const char * str, char ** endptr, int base)
|
||||
{
|
||||
return _strto_l(str, endptr, base, 1);
|
||||
}
|
||||
|
||||
unsigned long strtoul(const char * str, char ** endptr, int base)
|
||||
{
|
||||
return _strto_l(str, endptr, base, 0);
|
||||
}
|
||||
|
||||
int atoi(const char *str)
|
||||
{
|
||||
return strtol(str, NULL, 10);
|
||||
}
|
Loading…
Reference in New Issue