#include "memory.h" #include #include // // 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= '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; }