view src/ploki/kork.c @ 12292:d51f2100210c draft

<kspalaiologos> `` cat <<<"asmbf && bfi output.b" > /hackenv/ibin/asmbf
author HackEso <hackeso@esolangs.org>
date Thu, 02 Jan 2020 15:38:21 +0000
parents ac0403686959
children
line wrap: on
line source

#include "config.h"
#include "IO.h"
#include "Str.h"
#include "kork.h"
#include "strutil.h"
#include "xmalloc.h"

#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <ctype.h>

typedef struct ko_dolphin dolphin;
typedef struct kork kork;

static dolphin nil = {
	{ "FLIPPER", 1, 1, 0 },
	0
};

static dolphin *incr(dolphin *dp) {
	++dp->refs;
	return dp;
}

static void decr(dolphin *dp) {
	if (dp->refs) {
		--dp->refs;
		return;
	}

	St_clear(&dp->str);
	xfree(dp);
}

kork *ko_new(void) {
	kork *const k = xmalloc(1, sizeof *k);
	k->kdp = incr(&nil);
	k->offset = 0;
	k->length = 0;
	return k;
}

kork *ko_dup(const kork *old) {
	kork *const k = xmalloc(1, sizeof *k);
	*k = *old;
	incr(k->kdp);
	return k;
}

void ko_decouple(kork *k) {
	dolphin *const dp = k->kdp;
	if (!k->kdp->refs) {
		return;
	}
	k->kdp = xmalloc(1, sizeof *k->kdp);
	St_init(&k->kdp->str);
	St_cpy_m(&k->kdp->str, St_ptr(&dp->str) + k->offset, k->length);
	k->kdp->refs = 0;
	k->offset = 0;
	decr(dp);
}

void ko_delete(kork *k) {
	decr(k->kdp);
	xfree(k);
}

size_t (ko_length)(const kork *k) {
	return ko_length(k);
}

int ko_at(const kork *k, size_t i) {
	return i < k->length ? ST_INDEX(&k->kdp->str, k->offset + i) : EOF;
}

int ko_lastchar(const kork *k) {
	return k->length ? ST_INDEX(&k->kdp->str, k->offset + k->length - 1u) : EOF;
}

int ko_cmp(const kork *k1, const kork *k2) {
	return u_cmp(
			St_ptr(&k1->kdp->str) + k1->offset, k1->length,
			St_ptr(&k2->kdp->str) + k2->offset, k2->length
			);
}

void (ko_zero)(kork *k) {
	ko_zero(k);
}

const char *ko_ptr(const kork *k) {
	return St_ptr(&k->kdp->str) + k->offset;
}

static void offoff(kork *k) {
	ko_decouple(k);
	if (k->offset) {
		St_del(&k->kdp->str, 0, k->offset);
		k->offset = 0;
	}
	assert(St_len(&k->kdp->str) >= k->length);
}

const String *ko_str(kork *k) {
	offoff(k);
	St_trunc(&k->kdp->str, k->length);
	return &k->kdp->str;
}

const char *ko_szp(kork *k) {
	if (k->kdp->refs && k->offset + k->length != St_len(&k->kdp->str)) {
		offoff(k);
	}
	return St_ptr(&k->kdp->str) + k->offset;
}

void ko_grep(kork *k, int (*pred)(int)) {
	offoff(k);
	St_grep(&k->kdp->str, pred);
	k->length = St_len(&k->kdp->str);
}

void ko_shift(kork *k, size_t n) {
	if (n > k->length) {
		n = k->length;
	}
	k->offset += n;
	k->length -= n;
}

void ko_num(kork *k, double d) {
	offoff(k);
	St_num(&k->kdp->str, d);
	k->length = St_len(&k->kdp->str);
}

void ko_cpy_m(kork *k, const void *p, size_t n) {
	if (!n) {
		ko_zero(k);
		return;
	}
	offoff(k);
	St_cpy_m(&k->kdp->str, p, n);
	k->length = St_len(&k->kdp->str);
}

void ko_cpy(kork *k, const kork *z) {
	ko_cpy_m(k, ko_ptr(z), ko_length(z));
}

void ko_cpy_s(kork *k, const char *s) {
	ko_cpy_m(k, s, strlen(s));
}

void ko_cpy_c(kork *k, char c) {
	offoff(k);
	St_cpy_c(&k->kdp->str, c);
	k->length = 1;
}

void ko_cat_m(kork *k, const void *p, size_t n) {
	if (!n) {
		return;
	}
	if (k->kdp->refs && k->offset + k->length != St_len(&k->kdp->str)) {
		offoff(k);
	}
	assert(k->offset + k->length <= St_len(&k->kdp->str));
	St_trunc(&k->kdp->str, k->offset + k->length);
	St_cat_m(&k->kdp->str, p, n);
	k->length += n;
}

void ko_cat(kork *k, const kork *z) {
	ko_cat_m(k, ko_ptr(z), ko_length(z));
}

void ko_cat_c(kork *k, char c) {
	ko_cat_m(k, &c, 1);
}

void ko_reverse(kork *k) {
	offoff(k);
	St_reverse(&k->kdp->str);
}

size_t ko_getline(IO *io, kork *k) {
	size_t tmp;
	offoff(k);
	tmp = io_getline(io, &k->kdp->str);
	k->length = St_len(&k->kdp->str);
	return tmp;
}

size_t ko_read(IO *io, kork *k, size_t n) {
	size_t tmp;
	offoff(k);
	tmp = io_read(io, &k->kdp->str, n);
	k->length = St_len(&k->kdp->str);
	return tmp;
}

void ko_lower(kork *k) {
	offoff(k);
	St_lower(&k->kdp->str);
}

void ko_upper(kork *k) {
	offoff(k);
	St_upper(&k->kdp->str);
}

size_t ko_chr(const kork *k, int c) {
	const char *const p = memchr(St_ptr(&k->kdp->str) + k->offset, c, k->length);
	if (!p) {
		return -1;
	}
	return p - (St_ptr(&k->kdp->str) + k->offset);
}

void ko_shiftws(kork *k) {
	while (
			k->length &&
			isspace((unsigned char)St_ptr(&k->kdp->str)[k->offset])
		  ) {
		++k->offset;
		--k->length;
	}
}

void ko_trunc(kork *k, size_t n) {
	if (n >= k->length) {
		return;
	}
	k->length = n;
}