#include void *memcpy(void *s1, const void *s2, size_t n) { const char *f = s2; char *t = s1; while (n-- > 0) *t++ = *f++; return s1; } void *memmove(void *s1, const void *s2, size_t n) { const char *f = s2; char *t = s1; if (f < t) { f += n; t += n; while (n-- > 0) *--t = *--f; } else while (n-- > 0) *t++ = *f++; return s1; } void *memset(void *dest, int c, size_t n) { unsigned char *s = dest; size_t k; /* Fill head and tail with minimal branching. Each * conditional ensures that all the subsequently used * offsets are well-defined and in the dest region. */ if (!n) return dest; s[0] = c; s[n - 1] = c; if (n <= 2) return dest; s[1] = c; s[2] = c; s[n - 2] = c; s[n - 3] = c; if (n <= 6) return dest; s[3] = c; s[n - 4] = c; if (n <= 8) return dest; /* Advance pointer to align it at a 4-byte boundary, * and truncate n to a multiple of 4. The previous code * already took care of any head/tail that get cut off * by the alignment. */ k = -(uintptr_t)s & 3; s += k; n -= k; n &= -4; #ifdef __GNUC__ typedef uint32_t __attribute__((__may_alias__)) u32; typedef uint64_t __attribute__((__may_alias__)) u64; u32 c32 = ((u32)-1) / 255 * (unsigned char)c; /* In preparation to copy 32 bytes at a time, aligned on * an 8-byte bounary, fill head/tail up to 28 bytes each. * As in the initial byte-based head/tail fill, each * conditional below ensures that the subsequent offsets * are valid (e.g. !(n<=24) implies n>=28). */ *(u32 *)(s + 0) = c32; *(u32 *)(s + n - 4) = c32; if (n <= 8) return dest; *(u32 *)(s + 4) = c32; *(u32 *)(s + 8) = c32; *(u32 *)(s + n - 12) = c32; *(u32 *)(s + n - 8) = c32; if (n <= 24) return dest; *(u32 *)(s + 12) = c32; *(u32 *)(s + 16) = c32; *(u32 *)(s + 20) = c32; *(u32 *)(s + 24) = c32; *(u32 *)(s + n - 28) = c32; *(u32 *)(s + n - 24) = c32; *(u32 *)(s + n - 20) = c32; *(u32 *)(s + n - 16) = c32; /* Align to a multiple of 8 so we can fill 64 bits at a time, * and avoid writing the same bytes twice as much as is * practical without introducing additional branching. */ k = 24 + ((uintptr_t)s & 4); s += k; n -= k; /* If this loop is reached, 28 tail bytes have already been * filled, so any remainder when n drops below 32 can be * safely ignored. */ u64 c64 = c32 | ((u64)c32 << 32); for (; n >= 32; n -= 32, s += 32) { *(u64 *)(s + 0) = c64; *(u64 *)(s + 8) = c64; *(u64 *)(s + 16) = c64; *(u64 *)(s + 24) = c64; } #else /* Pure C fallback with no aliasing violations. */ for (; n; n--, s++) *s = c; #endif return dest; } // int memcmp(const void *s1, const void *s2, size_t n) { // if (n != 0) { // const unsigned char *p1 = s1, *p2 = s2; // // do { // if (*p1++ != *p2++) // return (*--p1 - *--p2); // } while (--n != 0); // } // return (0); // } char *itoa(int value, char *str, int base) { char *p = str; char *p1, *p2; unsigned int uvalue = value; int negative = 0; if (base < 2 || base > 36) { *str = '\0'; return str; } if (value < 0 && base == 10) { negative = 1; uvalue = -value; } // Convert to string do { int digit = uvalue % base; *p++ = (digit < 10) ? '0' + digit : 'a' + (digit - 10); uvalue /= base; } while (uvalue); if (negative) *p++ = '-'; *p = '\0'; // Reverse string p1 = str; p2 = p - 1; while (p1 < p2) { char tmp = *p1; *p1++ = *p2; *p2-- = tmp; } return str; } // void *memset(void *dst, int c, size_t length) { // u8 *ptr = (u8 *)dst; // const u8 value = (u8)c; // // while (length--) *(ptr++) = value; // // return dst; // } // void *memcpy(void *dst, const void *src, size_t len) { // u8 *d = (u8 *)dst; // const u8 *s = (const u8 *)src; // for (size_t i = 0; i < len; i++) { // d[i] = s[i]; // } // return dst; // } // void *memmove(void *dst, const void *src, size_t len) { // u8 *d = (u8 *)dst; // const u8 *s = (const u8 *)src; // if (d < s) { // for (size_t i = 0; i < len; i++) { // d[i] = s[i]; // } // } else if (d > s) { // for (size_t i = len; i > 0; i--) { // d[i - 1] = s[i - 1]; // } // } // return dst; // } int memcmp(const void *s1, const void *s2, size_t len) { const u8 *a = (const u8 *)s1; const u8 *b = (const u8 *)s2; for (size_t i = 0; i < len; i++) { if (a[i] != b[i]) { return (int)a[i] - (int)b[i]; } } return 0; } size_t strlen(const char *s) { const char *p = s; while (*p) ++p; return (size_t)(p - s); } size_t strnlen(const char *s, size_t maxlen) { size_t len = 0; while (len < maxlen && s[len] != '\0') { len++; } return len; }