view src/ploki/kork.c @ 8916:0234daffd946

<oerjan> addquote <int-e> I couldn\'t help thinking that maybe if one considers the ramifications in full detail it will turn out that overthinking is often not helpful and therefore, not something to be proud of.
author HackBot
date Sun, 14 Aug 2016 02:31:47 +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;
}