mirror of
https://git.stationery.faith/corn/corn.git
synced 2024-09-20 02:21:42 +00:00
374 lines
12 KiB
C
374 lines
12 KiB
C
#include "memory.h"
|
|
#include <lib.h>
|
|
#include <stddef.h>
|
|
|
|
//
|
|
// memory operations
|
|
//
|
|
|
|
int memcmp(const void *restrict vl, const void *restrict vr, size_t n) {
|
|
const unsigned char *l = vl, *r = vr;
|
|
for (; n && *l == *r; n--, l++, r++);
|
|
return n ? *l-*r : 0;
|
|
}
|
|
|
|
void *memcpy(void *restrict dest, const void *restrict src, size_t n) {
|
|
char *d = dest;
|
|
const char *s = src;
|
|
for (; n; n--) *d++ = *s++;
|
|
return dest;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
void *memmove(void *dest, const void *src, size_t n) {
|
|
char *d = dest;
|
|
const char *s = src;
|
|
|
|
if (d==s) return d;
|
|
|
|
if (d<s) {
|
|
for (; n; n--) *d++ = *s++;
|
|
} else {
|
|
while (n) n--, d[n] = s[n];
|
|
}
|
|
|
|
return dest;
|
|
}
|
|
|
|
void *memset(void *dest, int c, size_t n) {
|
|
unsigned char *d = dest;
|
|
for (; n; n--) {
|
|
*d++ = c;
|
|
};
|
|
return dest;
|
|
}
|
|
|
|
volatile void *memsetv(volatile void *dest, int c, size_t n) {
|
|
volatile unsigned char *d = dest;
|
|
for (; n; n--) {
|
|
*d++ = c;
|
|
};
|
|
return dest;
|
|
}
|
|
|
|
//
|
|
// string operations
|
|
//
|
|
|
|
int strncmp(const char *restrict lhs, const char *restrict rhs, size_t n) {
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
char *strcpy(char *restrict dest, const char *restrict src) {
|
|
char *d = dest;
|
|
for (; (*d = *src); d++, src++);
|
|
return dest;
|
|
}
|
|
|
|
char *strncpy(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 dest;
|
|
}
|
|
|
|
char *strcat(char *restrict dest, const char *restrict src) {
|
|
strcpy(dest + strlen(dest), src);
|
|
return dest;
|
|
}
|
|
|
|
//
|
|
// character operations
|
|
//
|
|
|
|
int isspace(int c) {
|
|
switch (c) {
|
|
case ' ':
|
|
case '\t':
|
|
case '\v':
|
|
case '\f':
|
|
case '\r':
|
|
case '\n':
|
|
return 1;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int isdigit(int c) {
|
|
return c >= '0' && c <= '9';
|
|
}
|
|
|
|
//
|
|
// string/numeric conversions
|
|
//
|
|
|
|
#define ATOX(name, type) \
|
|
type name(const char *s) { \
|
|
for (; isspace(*s); s++); \
|
|
int neg = 0; \
|
|
switch (*s) { \
|
|
case '-': \
|
|
neg = 1; \
|
|
/* fallthrough */ \
|
|
case '+': \
|
|
s++; \
|
|
break; \
|
|
} \
|
|
type num = 0; \
|
|
for (; *s == '0'; s++); \
|
|
for (; isdigit(*s); s++) { \
|
|
num *= 10; \
|
|
num += *s - '0'; \
|
|
} \
|
|
return num * (neg ? -1 : 1); \
|
|
}
|
|
|
|
ATOX(atoi, int)
|
|
ATOX(atol, long int)
|
|
ATOX(atoll, long long int)
|
|
|
|
char itoc(int i) {
|
|
if (i < 10) {
|
|
return '0' + i;
|
|
} else {
|
|
return 'a' + (i - 10);
|
|
}
|
|
}
|
|
|
|
int ctoi(char c) {
|
|
if (c >= '0' && c <= '9') {
|
|
return c - '0';
|
|
} else if (c >= 'A' && c <= 'Z') {
|
|
return c - 'A' + 10;
|
|
} else if (c >= 'a' && c <= 'z') {
|
|
return c - 'a' + 10;
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
#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; \
|
|
}
|
|
|
|
UXTOA(int, utoa)
|
|
UXTOA(long int, ultoa)
|
|
UXTOA(long long int, ulltoa)
|
|
|
|
#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; \
|
|
}
|
|
|
|
XTOA(int, itoa)
|
|
XTOA(long int, ltoa)
|
|
XTOA(long long int, lltoa)
|
|
|
|
#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; \
|
|
}
|
|
|
|
STRTOX(strtoi, int)
|
|
STRTOX(strtol, long int)
|
|
STRTOX(strtoll, long long int)
|
|
|
|
#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; \
|
|
}
|
|
|
|
STRTOUX(strtoui, unsigned int)
|
|
STRTOUX(strtoul, unsigned long int)
|
|
STRTOUX(strtoull, unsigned long long int)
|
|
|
|
static char suffixes[] = {'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 'R', 'Q'};
|
|
|
|
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;
|
|
}
|
|
|
|
// store one digit of remainder for decimal
|
|
unsigned int remainder;
|
|
// power of 1024
|
|
int power = 0;
|
|
|
|
// iterate until remaining bytes fits in three digits
|
|
while (bytes >= 1000) {
|
|
remainder = (bytes % 1024) * 10 / 1024;
|
|
bytes /= 1024;
|
|
power += 1;
|
|
}
|
|
|
|
// end of number
|
|
char *end;
|
|
|
|
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);
|
|
}
|
|
|
|
// add suffix
|
|
end[0] = suffixes[power - 1];
|
|
end[1] = '\0';
|
|
|
|
return buf;
|
|
}
|