Skip to content

libc: minimal: Add strtoll() and strtoull() #39612

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions doc/guides/portability/posix.rst
Original file line number Diff line number Diff line change
Expand Up @@ -308,9 +308,9 @@ This is implemented as part of the minimal C library available in Zephyr.
strtok_r(),+
strtol(),+
strtold(),
strtoll(),
strtoll(),+
strtoul(),+
strtoull(),
strtoull(),+
strtoumax(),
strxfrm(),
time(),+
Expand Down
2 changes: 2 additions & 0 deletions lib/libc/minimal/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ zephyr_library_sources(
source/stdlib/atoi.c
source/stdlib/strtol.c
source/stdlib/strtoul.c
source/stdlib/strtoll.c
source/stdlib/strtoull.c
source/stdlib/malloc.c
source/stdlib/bsearch.c
source/stdlib/exit.c
Expand Down
2 changes: 2 additions & 0 deletions lib/libc/minimal/include/stdlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ extern "C" {

unsigned long strtoul(const char *nptr, char **endptr, int base);
long strtol(const char *nptr, char **endptr, int base);
unsigned long long strtoull(const char *nptr, char **endptr, int base);
long long strtoll(const char *nptr, char **endptr, int base);
int atoi(const char *s);

void *malloc(size_t size);
Expand Down
110 changes: 110 additions & 0 deletions lib/libc/minimal/source/stdlib/strtoll.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/* SPDX-License-Identifier: BSD-4-Clause-UC */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgment:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <limits.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>

/*
* Convert a string to a long long integer.
*
* Ignores `locale' stuff. Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
long long strtoll(const char *nptr, char **endptr, register int base)
{
register const char *s = nptr;
register unsigned long long acc;
register int c;
register unsigned long long cutoff;
register int neg = 0, any, cutlim;

/*
* See strtol for comments as to the logic used.
*/
do {
c = *s++;
} while (isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
} else if (c == '+') {
c = *s++;
}

if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
}

if (base == 0) {
base = c == '0' ? 8 : 10;
}

cutoff = neg ? -(unsigned long long)LLONG_MIN : LLONG_MAX;
cutlim = cutoff % (unsigned long long)base;
cutoff /= (unsigned long long)base;
for (acc = 0, any = 0;; c = *s++) {
if (isdigit(c)) {
c -= '0';
} else if (isalpha(c)) {
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
} else {
break;
}
if (c >= base) {
break;
}
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) {
any = -1;
} else {
any = 1;
acc *= base;
acc += c;
}
}

if (any < 0) {
acc = neg ? LLONG_MIN : LLONG_MAX;
errno = ERANGE;
} else if (neg) {
acc = -acc;
}

if (endptr != NULL) {
*endptr = (char *)(any ? s - 1 : nptr);
}
return acc;
}
108 changes: 108 additions & 0 deletions lib/libc/minimal/source/stdlib/strtoull.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/* SPDX-License-Identifier: BSD-4-Clause-UC */

/*
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgment:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <limits.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>

/*
* Convert a string to an unsigned long long integer.
*
* Ignores `locale' stuff. Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
unsigned long long strtoull(const char *nptr, char **endptr, register int base)
{
register const char *s = nptr;
register unsigned long long acc;
register int c;
register unsigned long long cutoff;
register int neg = 0, any, cutlim;

/*
* See strtol for comments as to the logic used.
*/
do {
c = *s++;
} while (isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
} else if (c == '+') {
c = *s++;
}

if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
}

if (base == 0) {
base = c == '0' ? 8 : 10;
}

cutoff = (unsigned long long)ULLONG_MAX / (unsigned long long)base;
cutlim = (unsigned long long)ULLONG_MAX % (unsigned long long)base;
for (acc = 0, any = 0;; c = *s++) {
if (isdigit(c)) {
c -= '0';
} else if (isalpha(c)) {
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
} else {
break;
}
if (c >= base) {
break;
}
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) {
any = -1;
} else {
any = 1;
acc *= base;
acc += c;
}
}
if (any < 0) {
acc = ULLONG_MAX;
errno = ERANGE;
} else if (neg) {
acc = -acc;
}
if (endptr != NULL) {
*endptr = (char *)(any ? s - 1 : nptr);
}
return acc;
}
2 changes: 0 additions & 2 deletions samples/net/civetweb/common/include/libc_extensions.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,8 @@ size_t strspn(const char *s1, const char *s2);
int iscntrl(int c);

double atof(const char *str);
long long strtoll(const char *str, char **endptr, int base);
int sscanf(const char *s, const char *format, ...);
char *strerror(int err);
unsigned long long strtoull(const char *str, char **endptr, int base);

time_t time(time_t *t);
struct tm *gmtime(const time_t *ptime);
Expand Down
6 changes: 0 additions & 6 deletions samples/net/civetweb/common/src/libc_extensions.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,12 +153,6 @@ double atof(const char *str)
return (double)atoi(str);
}

long long strtoll(const char *str, char **endptr, int base)
{
/* XXX good enough for civetweb uses */
return (long long)strtol(str, endptr, base);
}

/*
* Most of the wrappers below are copies of the wrappers in net/sockets.h,
* but they are available only if CONFIG_NET_SOCKETS_POSIX_NAMES is enabled
Expand Down
Loading