Files
Custom-Operating-System/libs/libc/stdlib/tools.c

145 lines
3.2 KiB
C

#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
int atoi(const char* s)
{
// FIXME: Add overflow checks
int res = 0;
int len = strlen(s);
int mul = 1;
for (int i = 0; i < len; i++) {
mul *= 10;
}
for (int i = 0; i < len; i++) {
mul /= 10;
res += (s[i] - '0') * mul;
}
return res;
}
long strtol(const char* nptr, char** endptr, int base)
{
const char* p = nptr;
const char* endp = nptr;
bool negative = false;
bool overflow = false;
unsigned long n = 0;
if (base < 0 || base == 1 || base > 36) {
set_errno(EINVAL);
return 0;
}
while (isspace(*p)) {
p++;
}
if (*p == '+') {
p++;
} else if (*p == '-') {
negative = 1;
p++;
}
if (*p == '0') {
p++;
endp = p;
if (base == 16 && (*p == 'X' || *p == 'x')) {
p++;
} else if (base == 0) {
if (*p == 'X' || *p == 'x') {
base = 16, p++;
} else {
base = 8;
}
}
} else if (base == 0) {
base = 10;
}
unsigned long cutoff = (negative) ? -(LONG_MIN / base) : LONG_MAX / base;
int cutlim = (negative) ? -(LONG_MIN % base) : LONG_MAX % base;
for (;;) {
int digit;
if (*p >= 'a') {
digit = (*p - 'a') + 10;
} else if (*p >= 'A') {
digit = *p - 'A' + 10;
} else if (*p <= '9') {
digit = *p - '0';
} else {
break;
}
if (digit < 0 || digit >= base) {
break;
}
p++;
endp = p;
if (overflow) {
if (endptr) {
continue;
}
break;
}
if (n > cutoff || (n == cutoff && digit > cutlim)) {
overflow = 1;
continue;
}
n = n * base + digit;
}
if (endptr) {
*endptr = (char*)endp;
}
if (overflow) {
set_errno(ERANGE);
return ((negative) ? LONG_MIN : LONG_MAX);
}
return (long)((negative) ? -n : n);
}
#define SWAPARR(a, b, size) \
do { \
size_t __size = (size); \
char *__a = (a), *__b = (b); \
do { \
char __tmp = *__a; \
*__a++ = *__b; \
*__b++ = __tmp; \
} while (--__size > 0); \
} while (0)
void __qsortimpl(void* vbase, size_t n, size_t size, int (*compar)(const void*, const void*), int l, int r)
{
char* base = (char*)vbase;
if (l >= r) {
return;
}
int lm = l - 1;
for (int rm = l; rm < r; rm++) {
if (compar(&base[rm * size], &base[r * size]) < 0) {
lm++;
SWAPARR(&base[lm * size], &base[rm * size], size);
}
}
SWAPARR(&base[(lm + 1) * size], &base[r * size], size);
__qsortimpl(vbase, n, size, compar, l, lm);
__qsortimpl(vbase, n, size, compar, lm + 2, r);
}
void qsort(void* vbase, size_t n, size_t size, int (*compar)(const void*, const void*))
{
__qsortimpl(vbase, n, size, compar, 0, n - 1);
}