135 lines
2.7 KiB
C
135 lines
2.7 KiB
C
/*
|
|
* libc.c
|
|
*
|
|
* Created on: Oct 11, 2018
|
|
* Author: rick
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <limits.h>
|
|
#include <errno.h>
|
|
|
|
/* everything of stdlib is implemented in this file except for:
|
|
* - qsort
|
|
**/
|
|
|
|
|
|
int abs(int val) {
|
|
return val >= 0 ? val : (val * -1);
|
|
}
|
|
|
|
long labs(long val) {
|
|
return val >= 0 ? val : (val * -1);
|
|
}
|
|
|
|
long long llabs(long long val) {
|
|
return val >= 0 ? val : (val * -1);
|
|
}
|
|
|
|
// next stolen form https://www.techiedelight.com/implement-itoa-function-in-c/
|
|
// inline function to swapc two numbers
|
|
void swapc(char *x, char *y) {
|
|
char t = *x;
|
|
*x = *y;
|
|
*y = t;
|
|
}
|
|
|
|
// function to reverse buffer[i..j]
|
|
char *reverse(char *buffer, int i, int j) {
|
|
while (i < j)
|
|
swapc(&buffer[i++], &buffer[j--]);
|
|
|
|
return buffer;
|
|
}
|
|
|
|
// Iterative function to implement itoa() function in C
|
|
char *itoa(int value, char *buffer, int base) {
|
|
// invalid input
|
|
if (base < 2 || base > 32)
|
|
return buffer;
|
|
|
|
// consider absolute value of number
|
|
int n = abs(value);
|
|
|
|
int i = 0;
|
|
while (n) {
|
|
int r = n % base;
|
|
|
|
if (r >= 10)
|
|
buffer[i++] = 65 + (r - 10);
|
|
else
|
|
buffer[i++] = 48 + r;
|
|
|
|
n = n / base;
|
|
}
|
|
|
|
// if number is 0
|
|
if (i == 0)
|
|
buffer[i++] = '0';
|
|
|
|
// If base is 10 and value is negative, the resulting string
|
|
// is preceded with a minus sign (-)
|
|
// With any other base, value is always considered unsigned
|
|
if (value < 0 && base == 10)
|
|
buffer[i++] = '-';
|
|
|
|
buffer[i] = '\0'; // null terminate string
|
|
|
|
// reverse the string and return it
|
|
return reverse(buffer, 0, i - 1);
|
|
}
|
|
|
|
long strtol(const char *nptr, char **endptr, int base) {
|
|
if (base > 36) {
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
char sign = '+';
|
|
long n = 0;
|
|
long i;
|
|
const char *c = nptr;
|
|
while (*c == ' ') {
|
|
c++;
|
|
}
|
|
if (*c == '+') {
|
|
c++;
|
|
} else if (*c == '-') {
|
|
sign = '-';
|
|
c++;
|
|
}
|
|
while (*c != '\0') {
|
|
n *= base;
|
|
if (*c >= '0' && *c <= '9') {
|
|
i = *c - '0';
|
|
} else if (*c >= 'a' && *c <= 'z') {
|
|
i = *c - 'a' + 10;
|
|
} else if (*c >= 'A' && *c <= 'Z') {
|
|
i = *c - 'A' + 10;
|
|
} else {
|
|
errno = EINVAL;
|
|
n = -1;
|
|
goto _set_endptr;
|
|
}
|
|
if (i >= base) {
|
|
errno = EINVAL;
|
|
n = -1;
|
|
goto _set_endptr;
|
|
}
|
|
if (i > (LONG_MAX - n)) {
|
|
errno = ERANGE;
|
|
n = sign == '-' ? LONG_MIN : LONG_MAX;
|
|
goto _set_endptr;
|
|
}
|
|
n += i;
|
|
c++;
|
|
}
|
|
if (sign == '-') {
|
|
n *= -1;
|
|
}
|
|
_set_endptr:
|
|
if (endptr != NULL) {
|
|
*endptr = c;
|
|
}
|
|
return n;
|
|
}
|