diff options
Diffstat (limited to 'src/lib.c')
-rw-r--r-- | src/lib.c | 390 |
1 files changed, 223 insertions, 167 deletions
@@ -2,27 +2,31 @@ #include <lib.h> #include <stddef.h> -int memcmp(const void *restrict vl, const void *restrict vr, unsigned long n) { +// +// 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, unsigned long n) { +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 *dest, const volatile void *src, unsigned long n) { +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, unsigned long n) { +void *memmove(void *dest, const void *src, size_t n) { char *d = dest; const char *s = src; @@ -37,7 +41,7 @@ void *memmove(void *dest, const void *src, unsigned long n) { return dest; } -void *memset(void *restrict dest, int c, unsigned long n) { +void *memset(void *dest, int c, size_t n) { unsigned char *d = dest; for (; n; n--) { *d++ = c; @@ -45,7 +49,7 @@ void *memset(void *restrict dest, int c, unsigned long n) { return dest; } -volatile void *memsetv(volatile void *dest, int c, unsigned long n) { +volatile void *memsetv(volatile void *dest, int c, size_t n) { volatile unsigned char *d = dest; for (; n; n--) { *d++ = c; @@ -53,36 +57,61 @@ volatile void *memsetv(volatile void *dest, int c, unsigned long n) { return dest; } -int strncmp(const char *restrict lhs, const char *restrict rhs, unsigned long n) { +// +// 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, unsigned long n) { +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; } -size_t strlen(const char *str) { - const char *p; - for (p = str; *p != 0; p++) {} - return p - str; +char *strcat(char *restrict dest, const char *restrict src) { + strcpy(dest + strlen(dest), src); + return dest; } -char *strcat(char *restrict dst, const char *restrict src) { - strcpy(dst + strlen(dst), src); - return dst; -} +// +// character operations +// int isspace(int c) { switch (c) { @@ -99,9 +128,12 @@ int isspace(int c) { } int isdigit(int c) { - return c - '0' > -1 && c - '0' < 10; + return c >= '0' && c <= '9'; } +// +// string/numeric conversions +// #define ATOX(name, type) \ type name(const char *s) { \ @@ -110,7 +142,7 @@ int isdigit(int c) { switch (*s) { \ case '-': \ neg = 1; \ - /* FALLTHRU */ \ + /* fallthrough */ \ case '+': \ s++; \ break; \ @@ -137,181 +169,205 @@ char itoc(int i) { } int ctoi(char c) { - if (c < 'A') { + if (c >= '0' && c <= '9') { return c - '0'; - } else if (c < 'a') { + } else if (c >= 'A' && c <= 'Z') { return c - 'A' + 10; - } else { + } else if (c >= 'a' && c <= 'z') { return c - 'a' + 10; + } else { + return -1; } } -static char fs_endings[] = {'K', 'M', 'G', 'T', 'P'}; -static size_t nth_pow(size_t i, size_t e) { - size_t a = i; - while(--e) - a *= i; - return a; -} - -static char nth_digit(size_t bytes, size_t place) { - while (1) { - if (bytes < nth_pow(10, place)) - break; - bytes /= 10; +#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; \ } - return bytes %= 10; -} - -char *btoa(const size_t bytes, char *buf) { - - char *start = buf; - int idx = -1; - - size_t b = bytes; - size_t s = b; - while (1) { - if (b < 1000) - break; - s = b; - b /= 1024; - idx++; - } +UXTOA(int, utoa) +UXTOA(long int, ultoa) +UXTOA(long long int, ulltoa) - if (idx == -1) { - ultoa(bytes, buf, 10); - return start; +#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; \ } - s = s * 1000 / 1024; +XTOA(int, itoa) +XTOA(long int, ltoa) +XTOA(long long int, lltoa) - if (s < 1024) { - b = 1024; - idx--; +#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; \ } - char fd = nth_digit(s, 1); - char sd = nth_digit(s, 2); - char td = nth_digit(s, 3); - - *buf = fd + '0'; - buf++; +STRTOX(strtoi, int) +STRTOX(strtol, long int) +STRTOX(strtoll, long long int) - if (b < 10) { - *buf = '.'; - buf++; +#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; \ } - *buf = sd + '0'; - buf++; +STRTOUX(strtoui, unsigned int) +STRTOUX(strtoul, unsigned long int) +STRTOUX(strtoull, unsigned long long int) - if (b < 10) - goto end; +static char suffixes[] = {'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 'R', 'Q'}; - if (b > 99) { - *buf = td + '0'; - buf++; +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; } -end: - - *buf = fs_endings[idx]; - buf++; - *buf = '\0'; - return start; -} + // store one digit of remainder for decimal + unsigned int remainder; + // power of 1024 + int power = 0; -#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; \ + // iterate until remaining bytes fits in three digits + while (bytes >= 1000) { + remainder = (bytes % 1024) * 10 / 1024; + bytes /= 1024; + power += 1; } -UXTOA(int, utoa) -UXTOA(long int, ultoa) -UXTOA(long long int, ulltoa) + // end of number + char *end; -#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; \ + 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); } -XTOA(int, itoa) -XTOA(long int, ltoa) -XTOA(long long int, lltoa) - -#define STRTOX(name, type) \ - type name(const char *s, char **endptr, int radix) { \ - *endptr = NULL; \ - for (; isspace(*s); s++); \ - int neg = 0; \ - switch (*s) { \ - case '-': \ - neg = 1; \ - /* FALLTHRU */ \ - case '+': \ - s++; \ - break; \ - } \ - if (!radix) { \ - if (*s == '0') { \ - s++; \ - if (*s == 'x' || *s == 'X') { \ - s++; \ - radix = 16; \ - } else { \ - radix = 8; \ - } \ - } else { \ - radix = 10; \ - } \ - } \ - for (; *s == '0'; s++, *endptr = (void *) s); \ - type num = 0; \ - for (; isdigit(*s); s++, *endptr = (void *) s) { \ - num *= radix; \ - num += *s - '0'; \ - } \ - return num * (neg ? -1 : 1); \ - } + // add suffix + end[0] = suffixes[power - 1]; + end[1] = '\0'; -STRTOX(strtoi, int) -STRTOX(strtol, long int) -STRTOX(strtoll, long long int) + return buf; +} |