corn/src/lib.c

374 lines
12 KiB
C
Raw Normal View History

#include "memory.h"
2024-01-27 07:14:19 +00:00
#include <lib.h>
2024-01-27 08:01:34 +00:00
#include <stddef.h>
2024-02-04 01:59:50 +00:00
//
// memory operations
//
int memcmp(const void *restrict vl, const void *restrict vr, size_t n) {
2024-01-31 18:11:47 +00:00
const unsigned char *l = vl, *r = vr;
for (; n && *l == *r; n--, l++, r++);
return n ? *l-*r : 0;
2024-01-27 08:01:34 +00:00
}
2024-02-04 01:59:50 +00:00
void *memcpy(void *restrict dest, const void *restrict src, size_t n) {
2024-01-27 08:01:34 +00:00
char *d = dest;
2024-01-31 18:11:47 +00:00
const char *s = src;
for (; n; n--) *d++ = *s++;
return dest;
2024-01-27 08:01:34 +00:00
}
2024-02-04 01:59:50 +00:00
volatile void *memcpyv(volatile void *restrict dest, const volatile void *restrict src, size_t n) {
volatile char *d = dest;
const volatile char *s = src;
for (; n; n--) *d++ = *s++;
return dest;
}
2024-02-04 01:59:50 +00:00
void *memmove(void *dest, const void *src, size_t n) {
2024-01-31 18:11:47 +00:00
char *d = dest;
const char *s = src;
2024-01-27 08:01:34 +00:00
2024-01-31 18:11:47 +00:00
if (d==s) return d;
2024-01-27 08:01:34 +00:00
2024-01-31 18:11:47 +00:00
if (d<s) {
for (; n; n--) *d++ = *s++;
} else {
while (n) n--, d[n] = s[n];
}
2024-01-27 08:01:34 +00:00
2024-01-31 18:11:47 +00:00
return dest;
2024-01-27 08:01:34 +00:00
}
2024-02-04 01:59:50 +00:00
void *memset(void *dest, int c, size_t n) {
2024-01-31 18:11:47 +00:00
unsigned char *d = dest;
for (; n; n--) {
*d++ = c;
};
2024-01-31 18:11:47 +00:00
return dest;
2024-01-27 08:01:34 +00:00
}
2024-02-04 01:59:50 +00:00
volatile void *memsetv(volatile void *dest, int c, size_t n) {
volatile unsigned char *d = dest;
for (; n; n--) {
*d++ = c;
};
return dest;
}
2024-02-04 01:59:50 +00:00
//
// string operations
//
int strncmp(const char *restrict lhs, const char *restrict rhs, size_t n) {
2024-01-27 07:14:19 +00:00
const unsigned char *l=(void *)lhs, *r=(void *)rhs;
if (!n--) return 0;
for (; *l && *r && n && *l == *r ; l++, r++, n--);
return *l - *r;
}
2024-02-04 01:59:50 +00:00
size_t strlen(const char *str) {
const char *p;
for (p = str; *p != 0; p++) {}
return p - str;
}
//
// string copying and concatenation
//
char *stpcpy(char *restrict dest, const char *restrict src) {
char *d = dest;
for (; (*d = *src); d++, src++);
return d;
}
char *stpncpy(char *restrict dest, const char *restrict src, size_t n) {
char *d = dest;
for (; (*d = *src) && n; d++, src++, n--);
memset(d, 0, n);
return d;
}
2024-01-27 08:38:27 +00:00
char *strcpy(char *restrict dest, const char *restrict src) {
2024-02-01 03:30:35 +00:00
char *d = dest;
for (; (*d = *src); d++, src++);
2024-01-27 08:38:27 +00:00
return dest;
}
2024-02-04 01:59:50 +00:00
char *strncpy(char *restrict dest, const char *restrict src, size_t n) {
2024-02-01 03:30:35 +00:00
char *d = dest;
for (; (*d = *src) && n; d++, src++, n--);
memset(d, 0, n);
2024-01-27 08:38:27 +00:00
return dest;
}
2024-02-04 01:59:50 +00:00
char *strcat(char *restrict dest, const char *restrict src) {
strcpy(dest + strlen(dest), src);
return dest;
2024-01-30 02:10:29 +00:00
}
2024-02-04 01:59:50 +00:00
//
// character operations
//
2024-01-30 02:10:29 +00:00
2024-01-27 08:01:34 +00:00
int isspace(int c) {
2024-01-31 18:11:47 +00:00
switch (c) {
case ' ':
case '\t':
case '\v':
case '\f':
case '\r':
case '\n':
return 1;
default:
return 0;
}
2024-01-27 07:14:19 +00:00
}
2024-01-27 08:01:34 +00:00
int isdigit(int c) {
2024-02-04 01:59:50 +00:00
return c >= '0' && c <= '9';
2024-01-27 08:01:34 +00:00
}
2024-02-04 01:59:50 +00:00
//
// string/numeric conversions
//
2024-01-27 08:01:34 +00:00
#define ATOX(name, type) \
2024-02-01 03:30:35 +00:00
type name(const char *s) { \
for (; isspace(*s); s++); \
2024-01-31 18:11:47 +00:00
int neg = 0; \
switch (*s) { \
case '-': \
neg = 1; \
2024-02-04 01:59:50 +00:00
/* fallthrough */ \
2024-01-31 18:11:47 +00:00
case '+': \
s++; \
break; \
} \
type num = 0; \
for (; *s == '0'; s++); \
for (; isdigit(*s); s++) { \
num *= 10; \
num += *s - '0'; \
} \
return num * (neg ? -1 : 1); \
}
2024-01-27 08:01:34 +00:00
ATOX(atoi, int)
ATOX(atol, long int)
ATOX(atoll, long long int)
char itoc(int i) {
2024-02-01 03:30:35 +00:00
if (i < 10) {
2024-01-27 08:01:34 +00:00
return '0' + i;
} else {
return 'a' + (i - 10);
}
}
int ctoi(char c) {
2024-02-04 01:59:50 +00:00
if (c >= '0' && c <= '9') {
2024-01-27 08:01:34 +00:00
return c - '0';
2024-02-04 01:59:50 +00:00
} else if (c >= 'A' && c <= 'Z') {
2024-01-27 08:01:34 +00:00
return c - 'A' + 10;
2024-02-04 01:59:50 +00:00
} else if (c >= 'a' && c <= 'z') {
2024-01-27 08:01:34 +00:00
return c - 'a' + 10;
2024-02-04 01:59:50 +00:00
} else {
return -1;
2024-01-27 08:01:34 +00:00
}
}
2024-02-01 20:53:11 +00:00
2024-02-04 01:59:50 +00:00
#define UXTOA(type, name) \
char *name(unsigned type n, char *buffer, int radix) { \
if (n == 0) { \
buffer[0] = '0'; \
buffer[1] = '\0'; \
return buffer + 1; \
} \
char *start = buffer; \
for (; n; n /= radix) { \
*buffer++ = itoc(n % radix); \
} \
char *buf_end = buffer; \
*buffer-- = '\0'; \
while (buffer > start) { \
char tmp = *start; \
*start++ = *buffer; \
*buffer-- = tmp; \
} \
return buf_end; \
2024-02-01 20:53:11 +00:00
}
2024-02-04 01:59:50 +00:00
UXTOA(int, utoa)
UXTOA(long int, ultoa)
UXTOA(long long int, ulltoa)
2024-02-01 20:53:11 +00:00
2024-02-04 01:59:50 +00:00
#define XTOA(type, name) \
char *name(type n, char *buffer, int radix) { \
if (n == 0) { \
buffer[0] = '0'; \
buffer[1] = '\0'; \
return buffer + 1; \
} \
if (n < 0) { \
*buffer++ = '-'; \
n = -n; \
} \
char *start = buffer; \
for (; n; n /= radix) { \
*buffer++ = itoc(n % radix); \
} \
char *buf_end = buffer; \
*buffer-- = '\0'; \
while (buffer > start) { \
char tmp = *start; \
*start++ = *buffer; \
*buffer-- = tmp; \
} \
return buf_end; \
2024-02-01 20:53:11 +00:00
}
2024-02-04 01:59:50 +00:00
XTOA(int, itoa)
XTOA(long int, ltoa)
XTOA(long long int, lltoa)
2024-02-01 20:53:11 +00:00
2024-02-04 01:59:50 +00:00
#define STRTOX(name, type) \
type name( \
const char *restrict s, \
char **restrict endptr, \
int radix \
) { \
const char *s_start = s; \
for (; isspace(*s); s++); \
\
int sign = 0; \
switch (*s) { \
case '-': sign = 1; /* fallthrough */ \
case '+': s++; break; \
} \
\
if ( \
(radix == 0 || radix == 16) \
&& (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) \
) { \
radix = 16; \
s += 2; \
} else if (radix == 0) { \
if (*s == '0') { \
radix = 8; \
s++; \
} else { \
radix = 10; \
} \
} \
\
type num = 0; \
int has_digit = 0; \
\
while (1) { \
int n = ctoi(*s++); \
if (n < 0 || n >= radix) break; \
has_digit = 1; \
num = num * radix + n; \
} \
\
if (endptr != NULL) { \
*endptr = has_digit ? (char *)(s - 1) : (char *)s_start; \
} \
\
return sign ? -num : num; \
2024-02-01 20:53:11 +00:00
}
2024-02-04 01:59:50 +00:00
STRTOX(strtoi, int)
STRTOX(strtol, long int)
STRTOX(strtoll, long long int)
2024-02-01 20:53:11 +00:00
2024-02-04 01:59:50 +00:00
#define STRTOUX(name, type) \
type name( \
const char *restrict s, \
char **restrict endptr, \
int radix \
) { \
const char *s_start = s; \
for (; isspace(*s); s++); \
\
if ( \
(radix == 0 || radix == 16) \
&& (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) \
) { \
radix = 16; \
s += 2; \
} else if (radix == 0) { \
if (*s == '0') { \
radix = 8; \
s++; \
} else { \
radix = 10; \
} \
} \
\
type num = 0; \
int has_digit = 0; \
\
while (1) { \
int n = ctoi(*s++); \
if (n < 0 || n >= radix) break; \
has_digit = 1; \
num = num * radix + n; \
} \
\
if (endptr != NULL) { \
*endptr = has_digit ? (char *)(s - 1) : (char *)s_start; \
} \
\
return num; \
2024-02-01 20:53:11 +00:00
}
2024-02-04 01:59:50 +00:00
STRTOUX(strtoui, unsigned int)
STRTOUX(strtoul, unsigned long int)
STRTOUX(strtoull, unsigned long long int)
2024-02-01 20:53:11 +00:00
2024-02-04 01:59:50 +00:00
static char suffixes[] = {'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 'R', 'Q'};
2024-02-01 20:53:11 +00:00
2024-02-04 01:59:50 +00:00
char *btoa(size_t bytes, char *buf) {
// no suffix if under 1K, print up to four digits
if (bytes < 1024) {
ultoa(bytes, buf, 10);
return buf;
2024-02-01 20:53:11 +00:00
}
2024-02-04 01:59:50 +00:00
// store one digit of remainder for decimal
unsigned int remainder;
// power of 1024
int power = 0;
2024-02-01 20:53:11 +00:00
2024-02-04 01:59:50 +00:00
// iterate until remaining bytes fits in three digits
while (bytes >= 1000) {
remainder = (bytes % 1024) * 10 / 1024;
bytes /= 1024;
power += 1;
2024-01-31 18:11:47 +00:00
}
2024-01-27 08:01:34 +00:00
2024-02-04 01:59:50 +00:00
// end of number
char *end;
2024-01-27 08:01:34 +00:00
2024-02-04 01:59:50 +00:00
if (bytes >= 10) {
// no decimal
end = ultoa(bytes, buf, 10);
} else {
// decimal
end = ultoa(bytes, buf, 10);
end[0] = '.';
end = ultoa(remainder, end + 1, 10);
2024-01-31 18:11:47 +00:00
}
2024-01-27 08:01:34 +00:00
2024-02-04 01:59:50 +00:00
// add suffix
end[0] = suffixes[power - 1];
end[1] = '\0';
2024-01-27 08:01:34 +00:00
2024-02-04 01:59:50 +00:00
return buf;
}