#include <stddef.h>
#include <stdint.h>

// https://git.musl-libc.org/cgit/musl/tree/src/string/memcpy.c

void *memcpy(void *restrict dest, const void *restrict src, size_t n) {
  unsigned char *d = dest;
  const unsigned char *s = src;

  for (; n; n--)
    *d++ = *s++;
  return dest;
}

// https://git.musl-libc.org/cgit/musl/tree/src/string/memmove.c

void *memmove(void *dest, const void *src, size_t n) {
  char *d = dest;
  const char *s = src;

  if (d == s)
    return d;
  if ((uintptr_t)s - (uintptr_t)d - n <= -2 * n)
    return memcpy(d, s, n);

  if (d < s) {
    for (; n; n--)
      *d++ = *s++;
  } else {
    while (n)
      n--, d[n] = s[n];
  }

  return dest;
}

// https://git.musl-libc.org/cgit/musl/tree/src/string/memset.c

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;

  for (; n; n--, s++)
    *s = c;

  return dest;
}
