/**
 * @file src/str.c
 */

#include "str.h"
#include "chore.h"
#include <stdbit.h>
#include <stdlib.h>

[[gnu::const]] overloadable slice_t
slice(mut_slice_t ms, size_t start, size_t end) {
  return (slice_t){
    .s = ms.s + start,
    .len = end - start,
  };
}

[[gnu::const]] overloadable slice_t slice(slice_t s, size_t start, size_t end) {
  return (slice_t){
    .s = s.s + start,
    .len = end - start,
  };
}

#define DEF_SLICE_GENE(T) \
  overloadable bool eq(T x, T y) { \
    if (x.len != y.len) return false; \
    if (x.s == y.s) return true; \
    return !memcmp(x.s, y.s, x.len); \
  } \
  overloadable void printany(T x) { \
    printf("%.*s", (int)x.len, x.s); \
  } \
  overloadable void printanyf(T x) { \
    printf("\"%.*s\"", (int)x.len, x.s); \
  }
MAP(DEF_SLICE_GENE, mut_slice_t, slice_t)

slice_t referEntire(mut_slice_t ms) {
  return slice(ms, 0, ms.len);
}

slice_t fromString(char const *s) {
  return (slice_t){
    .s = s,
    .len = strlen(s),
  };
}

mut_slice_t mutFromString(char const *s) {
  size_t len = strlen(s);
  size_t cap = stdc_bit_ceil(len);
  char *dup = xalloc(char, cap);
  memcpy(dup, s, len);
  return (mut_slice_t){
    .s = dup,
    .len = len,
    .cap = cap,
    .owned = true,
  };
}

void freeMutSlice(mut_slice_t const *ms) {
  if (ms->owned) free(ms->s);
}

mut_slice_t concat(slice_t l, slice_t r) {
  size_t len = l.len + r.len;
  size_t cap = stdc_bit_ceil(len);
  char *s = xalloc(char, cap);
  memcpy(s, l.s, l.len);
  memcpy(s + l.len, r.s, r.len);
  return (mut_slice_t){
    .s = s,
    .len = len,
    .cap = cap,
    .owned = true,
  };
}