view src/ploki/kork.c @ 8427:1fc808cd5b1f

<b_jonas> learn can\'t is the most frequent word whose pronunciation varies between /\xc9\x91\xcb\x90/ and /\xc3\xa6/ depending on dialect. The list is: advance after answer ask aunt brass can\'t cast castle chance class command dance demand draft enhance example fast father glass graph grass half last laugh mask master nasty pass past path plant rather sample shan\'t staff task vast
author HackBot
date Thu, 09 Jun 2016 21:28: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;
}