view src/ploki/mars.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 "Str.h"
#include "mars.h"
#include "op.h"
#include "xmalloc.h"

enum {MAGIC = 128};

static void null(struct mars **p, size_t n) {
	for (; n; --n) {
		p[n - 1] = NULL;
	}
}

void ma_init(struct mars *m) {
	m->data = NULL;
	m->table = xmalloc(m->size = MAGIC, sizeof *m->table);
	null(m->table, m->size);
}

void ma_end(struct mars *m) {
	for (; m->size; --m->size) {
		if (m->table[m->size - 1]) {
			ma_end(m->table[m->size - 1]);
			xfree(m->table[m->size - 1]);
		}
	}
	xfree(m->table);
}

int ma_enter(struct mars *m, const String *key, struct op *value) {
	size_t p;

	for (p = 0; p < St_len(key); ++p) {
		size_t tmp = ST_INDEX(key, p);
		if (m->size <= tmp) {
			m->table = xrealloc(m->table, m->size * 2);
			null(m->table + m->size, m->size);
			m->size *= 2;
		}
		if (!m->table[tmp]) {
			m->table[tmp] = xmalloc(1, sizeof *m->table[tmp]);
			ma_init(m->table[tmp]);
		}
		m = m->table[tmp];
	}

	if (m->data) {
		return -1;
	}
	m->data = value;
	return 0;
}

int ma_exists(const struct mars *m, const String *key) {
	size_t p;
	const struct op *ret = NULL;

	for (p = 0; p < St_len(key); ++p) {
		size_t tmp = ST_INDEX(key, p);
		ret = m->data;
		if (tmp >= m->size || !m->table[tmp]) {
			return 0;
		}
		m = m->table[tmp];
	}
	return ret != NULL;
}

struct op *ma_find(const struct mars *m, String *key) {
	size_t p;
	struct op *ret = NULL;

	for (p = 0; p < St_len(key); ++p) {
		size_t tmp = ST_INDEX(key, p);
		ret = m->data;
		if (tmp >= m->size || !m->table[tmp]) {
			break;
		}
		m = m->table[tmp];
	}
	if (ret) {
		St_del(key, 0, p);
	}
	return ret;
}