mirror of
https://git.stationery.faith/corn/corn.git
synced 2024-11-22 06:32:18 +00:00
fix lib
This commit is contained in:
parent
f785bce3cc
commit
6b49a206c2
2 changed files with 417 additions and 229 deletions
234
include/lib.h
234
include/lib.h
|
@ -3,60 +3,77 @@
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
/**
|
|
||||||
* The memcmp() function compares the first n bytes (each interpreted as unsigned char) of the memory
|
//
|
||||||
* areas s1 and s2.
|
// memory operations
|
||||||
*/
|
//
|
||||||
int memcmp(const void *restrict s1, const void *restrict s2, unsigned long n);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the memcpy() function copies n bytes from memory area src to memory area dest.
|
* Compare the first n bytes (interpreted as unsigned char) of the memory areas s1 and s2
|
||||||
* the memory areas must not overlap.
|
* @param s1 - the first memory area
|
||||||
|
* @param s2 - the second memory area
|
||||||
|
* @param n - the byte count
|
||||||
|
* @returns an interger less than, equal to, or greater than 0 if the first n bytes
|
||||||
|
* of s1 are less than, equal to, or greater than s2.
|
||||||
*/
|
*/
|
||||||
void *memcpy(void *restrict dest, const void *restrict src, unsigned long n);
|
int memcmp(const void *restrict s1, const void *restrict s2, size_t n);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the memcpy() function copies n bytes from memory area src to memory area dest.
|
* Copy the first n bytes from memory area src to memory area dest. The memory
|
||||||
* the memory areas must not overlap.
|
* areas must not overlap.
|
||||||
|
* @param dest - the destination
|
||||||
|
* @param src - the source
|
||||||
|
* @param n - the byte count
|
||||||
|
* @returns a pointer to dest
|
||||||
*/
|
*/
|
||||||
volatile void *memcpyv(volatile void *dest, const volatile void *src, unsigned long n);
|
void *memcpy(void *restrict dest, const void *restrict src, size_t n);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The memmove() function copies n bytes from memory area src to memory area dest. The memory areas
|
* Volatile version of memcpy.
|
||||||
* may overlap: copying takes place as though the bytes in src are first copied into a temporary array
|
* Copy the first n bytes from memory area src to memory area dest. The memory
|
||||||
* that does not overlap src or dest, and the bytes are then copied from the temporary array to dest.
|
* areas must not overlap.
|
||||||
|
* @param dest - the destination
|
||||||
|
* @param src - the source
|
||||||
|
* @param n - the byte count
|
||||||
|
* @returns a pointer to dest
|
||||||
*/
|
*/
|
||||||
void *memmove(void *dest, const void *src, unsigned long n);
|
volatile void *memcpyv(volatile void *restrict dest, const volatile void *restrict src, size_t n);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The memset() function fills the first n bytes of the memory area pointed to by s with the constant
|
* Copy the first n bytes from memory area src to memory area dest. The memory
|
||||||
* byte c.
|
* areas may overlap; memmove behaves as though the bytes are first copied to a
|
||||||
|
* temporary array.
|
||||||
|
* @param dest - the destination
|
||||||
|
* @param src - the source
|
||||||
|
* @param n - the byte count
|
||||||
|
* @returns a pointer to dest
|
||||||
*/
|
*/
|
||||||
void *memset(void *restrict dest, int c, unsigned long n);
|
void *memmove(void *dest, const void *src, size_t n);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The memset() function fills the first n bytes of the memory area pointed to by s with the constant
|
* Fill the first n bytes of the memory region dest with the constant byte c.
|
||||||
* byte c.
|
* @param dest - the destination
|
||||||
|
* @param c - the byte to write
|
||||||
|
* @param n - the byte count
|
||||||
|
* @returns a pointer to dest
|
||||||
*/
|
*/
|
||||||
volatile void *memsetv(volatile void *dest, int c, unsigned long n);
|
void *memset(void *dest, int c, size_t n);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The strcmp() function compares the two strings s1 and s2. The locale is not taken into account
|
* Volatile version of memset.
|
||||||
* (for a locale-aware comparison, see strcoll(3)). The comparison is done using unsigned characters.
|
* Fill the first n bytes of the memory region dest with the constant byte c.
|
||||||
|
* @param c - the byte to write
|
||||||
|
* @param n - the byte count
|
||||||
|
* @returns a pointer to dest
|
||||||
*/
|
*/
|
||||||
int strncmp(const char *restrict s1, const char *restrict s2, unsigned long n);
|
volatile void *memsetv(volatile void *dest, int c, size_t n);
|
||||||
|
|
||||||
/**
|
|
||||||
* Copys the string pointed to by src , into a string at the buffer pointer to by dest.
|
|
||||||
* The dest buffer must be long enough to hold src.
|
|
||||||
*/
|
|
||||||
char *strcpy(char *restrict dest, const char *restrict src);
|
|
||||||
|
|
||||||
/**
|
//
|
||||||
* Copys the string pointed to by src , into a string at the buffer pointer to by dest.
|
// string operations
|
||||||
* The dest buffer must be long enough to hold src or size n.
|
//
|
||||||
*/
|
|
||||||
char *strncpy(char *restrict dest, const char *restrict src, unsigned long n);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the length of the string pointed to by str, excluding
|
* Calculates the length of the string pointed to by str, excluding
|
||||||
|
@ -67,13 +84,75 @@ char *strncpy(char *restrict dest, const char *restrict src, unsigned long n);
|
||||||
size_t strlen(const char *str);
|
size_t strlen(const char *str);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Concatenate the string pointed to by src after the string pointed
|
* Compare at most the first n bytes of the strings s1 and s2. The comparison is
|
||||||
* to by dst.
|
* done using unsigned characters.
|
||||||
* @param dst - the pointer to the destination string
|
* @param s1 - a pointer to the first string
|
||||||
* @param src - the pointer to the source string
|
* @param s2 - a pointer to the second string
|
||||||
* @returns dst
|
* @param n - the maximum number of bytes
|
||||||
|
* @returns an interger less than, equal to, or greater than 0 if s1 compares less
|
||||||
|
* than, equal to, or greater than s2
|
||||||
*/
|
*/
|
||||||
char *strcat(char *restrict dst, const char *restrict src);
|
int strncmp(const char *restrict s1, const char *restrict s2, size_t n);
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// string copying and concatenation
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies the string pointed to by src into the buffer pointer to by dest.
|
||||||
|
* The dest buffer must be long enough to hold src.
|
||||||
|
* @param dest - the destination
|
||||||
|
* @param src - the source
|
||||||
|
* @returns a pointer to dest
|
||||||
|
*/
|
||||||
|
char *strcpy(char *restrict dest, const char *restrict src);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies the string pointed to by src into the buffer pointer to by dest.
|
||||||
|
* The dest buffer must be long enough to hold src or size n.
|
||||||
|
* @param dest - the destination
|
||||||
|
* @param src - the source
|
||||||
|
* @param n - the maximum number of bytes
|
||||||
|
* @returns a pointer to dest
|
||||||
|
*/
|
||||||
|
char *strncpy(char *restrict dest, const char *restrict src, size_t n);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies the string pointed to by src into the buffer pointed to by dest.
|
||||||
|
* The dest buffer must be long enough to hold src.
|
||||||
|
* @param dest - the destination
|
||||||
|
* @param src - the source
|
||||||
|
* @param n - the maximum number of bytes
|
||||||
|
* @returns a pointer to the terminating null byte
|
||||||
|
*/
|
||||||
|
char *stpcpy(char *restrict dest, const char *restrict src);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies the string pointed to by src into the buffer pointed to by dest.
|
||||||
|
* The dest buffer must be long enough to hold src or size n.
|
||||||
|
* @param dest - the destination
|
||||||
|
* @param src - the source
|
||||||
|
* @param n - the maximum number of bytes
|
||||||
|
* @returns a pointer to the byte after the last character copied
|
||||||
|
*/
|
||||||
|
char *stpncpy(char *restrict dest, const char *restrict src, size_t n);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concatenate the string pointed to by src after the string pointed
|
||||||
|
* to by dest.
|
||||||
|
* @param dest - the destination
|
||||||
|
* @param src - the source
|
||||||
|
* @returns a pointer to dest
|
||||||
|
*/
|
||||||
|
char *strcat(char *restrict dest, const char *restrict src);
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// character operations
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns 1 if c is a space
|
* @returns 1 if c is a space
|
||||||
|
@ -95,10 +174,16 @@ char itoc(int i);
|
||||||
/**
|
/**
|
||||||
* converts single base 36 chat into int
|
* converts single base 36 chat into int
|
||||||
* @param c - base 36 char
|
* @param c - base 36 char
|
||||||
* @returns i - int
|
* @returns i - int, or -1 if the char was invalid
|
||||||
*/
|
*/
|
||||||
int ctoi(char c);
|
int ctoi(char c);
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// string/numeric conversions
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the initial portiion of the string pointed to by s to int.
|
* Converts the initial portiion of the string pointed to by s to int.
|
||||||
* @param s - the string to convert
|
* @param s - the string to convert
|
||||||
|
@ -168,14 +253,6 @@ char *ultoa(unsigned long int n, char *buffer, int radix);
|
||||||
*/
|
*/
|
||||||
char *ulltoa(unsigned long long int n, char *buffer, int radix);
|
char *ulltoa(unsigned long long int n, char *buffer, int radix);
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a byte count to a human readable file size
|
|
||||||
* @param bytes - the bytes to convert
|
|
||||||
* @param buf - the buffer to store it in
|
|
||||||
* @preturns - bus
|
|
||||||
*/
|
|
||||||
char *btoa(size_t bytes, char *buf);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the string in str to an int value based on the given base.
|
* Converts the string in str to an int value based on the given base.
|
||||||
* The endptr is updated to where the string was no longer valid.
|
* The endptr is updated to where the string was no longer valid.
|
||||||
|
@ -187,7 +264,7 @@ char *btoa(size_t bytes, char *buf);
|
||||||
int strtoi(const char *str, char **endptr, int base);
|
int strtoi(const char *str, char **endptr, int base);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the string in str to an long value based on the given base.
|
* Converts the string in str to a long value based on the given base.
|
||||||
* The endptr is updated to where the string was no longer valid.
|
* The endptr is updated to where the string was no longer valid.
|
||||||
* @param str - the string buffer
|
* @param str - the string buffer
|
||||||
* @param endptr - the endptr
|
* @param endptr - the endptr
|
||||||
|
@ -197,7 +274,7 @@ int strtoi(const char *str, char **endptr, int base);
|
||||||
long int strtol(const char *str, char **endptr, int base);
|
long int strtol(const char *str, char **endptr, int base);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the string in str to an long long value based on the given base.
|
* Converts the string in str to a long long value based on the given base.
|
||||||
* The endptr is updated to where the string was no longer valid.
|
* The endptr is updated to where the string was no longer valid.
|
||||||
* @param str - the string buffer
|
* @param str - the string buffer
|
||||||
* @param endptr - the endptr
|
* @param endptr - the endptr
|
||||||
|
@ -206,6 +283,61 @@ long int strtol(const char *str, char **endptr, int base);
|
||||||
*/
|
*/
|
||||||
long long int strtoll(const char *str, char **endptr, int base);
|
long long int strtoll(const char *str, char **endptr, int base);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the string in str to an unsigned int value based on the given base.
|
||||||
|
* The endptr is updated to where the string was no longer valid.
|
||||||
|
* @param str - the string buffer
|
||||||
|
* @param endptr - the endptr
|
||||||
|
* @param base - the base to convert to
|
||||||
|
* @returns 0 on error or success, error if endptr is still equal to str
|
||||||
|
*/
|
||||||
|
unsigned int strtoui(const char *str, char **endptr, int base);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the string in str to an unsigned long value based on the given base.
|
||||||
|
* The endptr is updated to where the string was no longer valid.
|
||||||
|
* @param str - the string buffer
|
||||||
|
* @param endptr - the endptr
|
||||||
|
* @param base - the base to convert to
|
||||||
|
* @returns 0 on error or success, error if endptr is still equal to str
|
||||||
|
*/
|
||||||
|
unsigned long int strtoul(const char *str, char **endptr, int base);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the string in str to an unsigned long long value based on the given base.
|
||||||
|
* The endptr is updated to where the string was no longer valid.
|
||||||
|
* @param str - the string buffer
|
||||||
|
* @param endptr - the endptr
|
||||||
|
* @param base - the base to convert to
|
||||||
|
* @returns 0 on error or success, error if endptr is still equal to str
|
||||||
|
*/
|
||||||
|
unsigned long long int strtoull(const char *str, char **endptr, int base);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a byte count to a human readable file size of at most four characters
|
||||||
|
* using binary suffixes.
|
||||||
|
*
|
||||||
|
* The following rules are applied:
|
||||||
|
* - If the byte count is less than 1024, the count is written in decimal
|
||||||
|
* and no suffix is applied
|
||||||
|
* - Otherwise, repeatedly divide by 1024 until the value is under 1000.
|
||||||
|
* - If the value has two or three decimal digits, print it followed by the
|
||||||
|
* approprate suffix.
|
||||||
|
* - If the value has one decimal digit, print it along with a single fractional
|
||||||
|
* digit. This also applies if the value is zero.
|
||||||
|
*
|
||||||
|
* @param bytes - the bytes to convert
|
||||||
|
* @param buf - a pointer to the buffer to store it in (which must be at least five
|
||||||
|
* bytes long)
|
||||||
|
* @returns - buf
|
||||||
|
*/
|
||||||
|
char *btoa(size_t bytes, char *buf);
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// printing and formatting
|
||||||
|
//
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prints out a char
|
* Prints out a char
|
||||||
* @param c - the char
|
* @param c - the char
|
||||||
|
|
306
src/lib.c
306
src/lib.c
|
@ -2,27 +2,31 @@
|
||||||
#include <lib.h>
|
#include <lib.h>
|
||||||
#include <stddef.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;
|
const unsigned char *l = vl, *r = vr;
|
||||||
for (; n && *l == *r; n--, l++, r++);
|
for (; n && *l == *r; n--, l++, r++);
|
||||||
return n ? *l-*r : 0;
|
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;
|
char *d = dest;
|
||||||
const char *s = src;
|
const char *s = src;
|
||||||
for (; n; n--) *d++ = *s++;
|
for (; n; n--) *d++ = *s++;
|
||||||
return dest;
|
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;
|
volatile char *d = dest;
|
||||||
const volatile char *s = src;
|
const volatile char *s = src;
|
||||||
for (; n; n--) *d++ = *s++;
|
for (; n; n--) *d++ = *s++;
|
||||||
return dest;
|
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;
|
char *d = dest;
|
||||||
const char *s = src;
|
const char *s = src;
|
||||||
|
|
||||||
|
@ -37,7 +41,7 @@ void *memmove(void *dest, const void *src, unsigned long n) {
|
||||||
return dest;
|
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;
|
unsigned char *d = dest;
|
||||||
for (; n; n--) {
|
for (; n; n--) {
|
||||||
*d++ = c;
|
*d++ = c;
|
||||||
|
@ -45,7 +49,7 @@ void *memset(void *restrict dest, int c, unsigned long n) {
|
||||||
return dest;
|
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;
|
volatile unsigned char *d = dest;
|
||||||
for (; n; n--) {
|
for (; n; n--) {
|
||||||
*d++ = c;
|
*d++ = c;
|
||||||
|
@ -53,37 +57,62 @@ volatile void *memsetv(volatile void *dest, int c, unsigned long n) {
|
||||||
return dest;
|
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;
|
const unsigned char *l=(void *)lhs, *r=(void *)rhs;
|
||||||
if (!n--) return 0;
|
if (!n--) return 0;
|
||||||
for (; *l && *r && n && *l == *r ; l++, r++, n--);
|
for (; *l && *r && n && *l == *r ; l++, r++, n--);
|
||||||
return *l - *r;
|
return *l - *r;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 *d = dest;
|
|
||||||
for (; (*d = *src) && n; d++, src++, n--);
|
|
||||||
memset(d, 0, n);
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t strlen(const char *str) {
|
size_t strlen(const char *str) {
|
||||||
const char *p;
|
const char *p;
|
||||||
for (p = str; *p != 0; p++) {}
|
for (p = str; *p != 0; p++) {}
|
||||||
return p - str;
|
return p - str;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *strcat(char *restrict dst, const char *restrict src) {
|
//
|
||||||
strcpy(dst + strlen(dst), src);
|
// string copying and concatenation
|
||||||
return dst;
|
//
|
||||||
|
|
||||||
|
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) {
|
int isspace(int c) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case ' ':
|
case ' ':
|
||||||
|
@ -99,9 +128,12 @@ int isspace(int c) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int isdigit(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) \
|
#define ATOX(name, type) \
|
||||||
type name(const char *s) { \
|
type name(const char *s) { \
|
||||||
|
@ -110,7 +142,7 @@ int isdigit(int c) {
|
||||||
switch (*s) { \
|
switch (*s) { \
|
||||||
case '-': \
|
case '-': \
|
||||||
neg = 1; \
|
neg = 1; \
|
||||||
/* FALLTHRU */ \
|
/* fallthrough */ \
|
||||||
case '+': \
|
case '+': \
|
||||||
s++; \
|
s++; \
|
||||||
break; \
|
break; \
|
||||||
|
@ -137,91 +169,17 @@ char itoc(int i) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int ctoi(char c) {
|
int ctoi(char c) {
|
||||||
if (c < 'A') {
|
if (c >= '0' && c <= '9') {
|
||||||
return c - '0';
|
return c - '0';
|
||||||
} else if (c < 'a') {
|
} else if (c >= 'A' && c <= 'Z') {
|
||||||
return c - 'A' + 10;
|
return c - 'A' + 10;
|
||||||
} else {
|
} else if (c >= 'a' && c <= 'z') {
|
||||||
return c - 'a' + 10;
|
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;
|
|
||||||
}
|
|
||||||
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++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (idx == -1) {
|
|
||||||
ultoa(bytes, buf, 10);
|
|
||||||
return start;
|
|
||||||
}
|
|
||||||
|
|
||||||
s = s * 1000 / 1024;
|
|
||||||
|
|
||||||
if (s < 1024) {
|
|
||||||
b = 1024;
|
|
||||||
idx--;
|
|
||||||
}
|
|
||||||
|
|
||||||
char fd = nth_digit(s, 1);
|
|
||||||
char sd = nth_digit(s, 2);
|
|
||||||
char td = nth_digit(s, 3);
|
|
||||||
|
|
||||||
*buf = fd + '0';
|
|
||||||
buf++;
|
|
||||||
|
|
||||||
if (b < 10) {
|
|
||||||
*buf = '.';
|
|
||||||
buf++;
|
|
||||||
}
|
|
||||||
|
|
||||||
*buf = sd + '0';
|
|
||||||
buf++;
|
|
||||||
|
|
||||||
if (b < 10)
|
|
||||||
goto end;
|
|
||||||
|
|
||||||
if (b > 99) {
|
|
||||||
*buf = td + '0';
|
|
||||||
buf++;
|
|
||||||
}
|
|
||||||
|
|
||||||
end:
|
|
||||||
|
|
||||||
*buf = fs_endings[idx];
|
|
||||||
buf++;
|
|
||||||
*buf = '\0';
|
|
||||||
return start;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define UXTOA(type, name) \
|
#define UXTOA(type, name) \
|
||||||
char *name(unsigned type n, char *buffer, int radix) { \
|
char *name(unsigned type n, char *buffer, int radix) { \
|
||||||
|
@ -278,40 +236,138 @@ XTOA(long int, ltoa)
|
||||||
XTOA(long long int, lltoa)
|
XTOA(long long int, lltoa)
|
||||||
|
|
||||||
#define STRTOX(name, type) \
|
#define STRTOX(name, type) \
|
||||||
type name(const char *s, char **endptr, int radix) { \
|
type name( \
|
||||||
*endptr = NULL; \
|
const char *restrict s, \
|
||||||
|
char **restrict endptr, \
|
||||||
|
int radix \
|
||||||
|
) { \
|
||||||
|
const char *s_start = s; \
|
||||||
for (; isspace(*s); s++); \
|
for (; isspace(*s); s++); \
|
||||||
int neg = 0; \
|
\
|
||||||
|
int sign = 0; \
|
||||||
switch (*s) { \
|
switch (*s) { \
|
||||||
case '-': \
|
case '-': sign = 1; /* fallthrough */ \
|
||||||
neg = 1; \
|
case '+': s++; break; \
|
||||||
/* FALLTHRU */ \
|
|
||||||
case '+': \
|
|
||||||
s++; \
|
|
||||||
break; \
|
|
||||||
} \
|
} \
|
||||||
if (!radix) { \
|
\
|
||||||
if (*s == '0') { \
|
if ( \
|
||||||
s++; \
|
(radix == 0 || radix == 16) \
|
||||||
if (*s == 'x' || *s == 'X') { \
|
&& (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) \
|
||||||
s++; \
|
) { \
|
||||||
radix = 16; \
|
radix = 16; \
|
||||||
} else { \
|
s += 2; \
|
||||||
|
} else if (radix == 0) { \
|
||||||
|
if (*s == '0') { \
|
||||||
radix = 8; \
|
radix = 8; \
|
||||||
} \
|
s++; \
|
||||||
} else { \
|
} else { \
|
||||||
radix = 10; \
|
radix = 10; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
for (; *s == '0'; s++, *endptr = (void *) s); \
|
\
|
||||||
type num = 0; \
|
type num = 0; \
|
||||||
for (; isdigit(*s); s++, *endptr = (void *) s) { \
|
int has_digit = 0; \
|
||||||
num *= radix; \
|
\
|
||||||
num += *s - '0'; \
|
while (1) { \
|
||||||
|
int n = ctoi(*s++); \
|
||||||
|
if (n < 0 || n >= radix) break; \
|
||||||
|
has_digit = 1; \
|
||||||
|
num = num * radix + n; \
|
||||||
} \
|
} \
|
||||||
return num * (neg ? -1 : 1); \
|
\
|
||||||
|
if (endptr != NULL) { \
|
||||||
|
*endptr = has_digit ? (char *)(s - 1) : (char *)s_start; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
return sign ? -num : num; \
|
||||||
}
|
}
|
||||||
|
|
||||||
STRTOX(strtoi, int)
|
STRTOX(strtoi, int)
|
||||||
STRTOX(strtol, long int)
|
STRTOX(strtol, long int)
|
||||||
STRTOX(strtoll, long 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;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue