view src/ploki/val.c @ 10131:bbbdb09e6365

<boily> le/rn mate//Mat\xc3\xa9 is a southern hemisphere shamanist beverage that opens your inner self to the Sacred World. Its enlightened users become friendly, wishing \xe2\x80\x9cG\'day, mat\xc3\xa9!\xe2\x80\x9d to one another.
author HackBot
date Sat, 14 Jan 2017 14:02:22 +0000
parents ac0403686959
children
line wrap: on
line source

#include "config.h"
#include "IO.h"
#include "Str.h"
#include "val.h"
#include "xmalloc.h"

#include <stdlib.h>
#include <assert.h>

void v_init(struct val *v) {
	v->ko = ko_new();
	v->type = V_UNDEF;
}

void v_end(struct val *v) {
	assert(v != NULL);
	V_xxx_OFF(v);
	ko_delete(v->ko);
	v->type = V_UNDEF;
}

int v_cmp_ls(struct val *v, struct val *b) {
	if (V_LIST_P(v) && V_LIST_P(b)) {
		return li_cmp(v->magic.list, b->magic.list);
	}
	V_STR(v);
	V_STR(b);
	return ko_cmp(v->ko, b->ko);
}

void v_ok_str(struct val *v) {
	if (V_STR_P(v)) {
		return;
	}

	if (V_EXT_P(v)) {
		ko_cpy_s(v->ko, io_name(v->magic.ext, NULL));
	} else if (V_LIST_P(v)) {
		size_t i;
		struct list *li = v->magic.list;
		struct val *cur;

		ko_zero(v->ko);
		for (i = 0; i < li_length(li); ++i) {
			cur = li_at(li, i);
			V_STR(cur);
			ko_cat(v->ko, cur->ko);
		}
	} else if (V_NUM_P(v)) {
		ko_num(v->ko, v->num);
	} else if (V_SUB_P(v)) {
		v_ok_num(v);
		ko_num(v->ko, v->num);
	} else {
		ko_zero(v->ko);
	}
	v->type |= V_STR_K;
}

void v_ok_num(struct val *v) {
	if (V_NUM_P(v)) {
		return;
	}

	if (V_EXT_P(v)) {
		v->num = __LINE__;
	} else if (V_SUB_P(v)) {
		v->num = sub_id(v->magic.sub);
	} else if (V_LIST_P(v)) {
		size_t i;

		v->num = 0.0;
		for (i = 0; i < li_length(v->magic.list); ++i) {
			V_NUM(li_at(v->magic.list, i));
			v->num += li_at(v->magic.list, i)->num;
		}
	} else if (V_STR_P(v)) {
		v->num = strtod(ko_szp(v->ko), NULL);
	} else {
		v->num = 0.0;
	}
	v->type |= V_NUM_K;
}

int v_true(const struct val *v) {
	if (V_EXT_P(v) || V_SUB_P(v)) {
		return 1;
	}
	if (V_LIST_P(v)) {
		return li_length(v->magic.list) != 0;
	}
	if (V_STR_P(v)) {
		return ko_length(v->ko) != 0 && (ko_length(v->ko) > 1u || ko_at(v->ko, 0) != '0');
	}
	if (V_NUM_P(v)) {
		return v->num != 0.0;
	}
	return 0;
}

void v_iniset(struct val *dst, const struct val *src) {
	v_init(dst);
	v_set(dst, src);
}

void v_set(struct val *dst, const struct val *src) {
	assert(src != NULL);

	V_xxx_OFF(dst);
	dst->type = V_UNDEF;

	if (V_SUB_P(src)) {
		dst->magic.sub = sub_incr(src->magic.sub);
		dst->type |= V_SUB_K;
	} else if (V_EXT_P(src)) {
		dst->magic.ext = io_incr(src->magic.ext);
		dst->type |= V_EXT_K;
	} else if (V_LIST_P(src)) {
		dst->magic.list = li_dup(src->magic.list);
		dst->type |= V_LIST_K;
	}

	if (V_STR_P(src)) {
		ko_cpy(dst->ko, src->ko);
		dst->type |= V_STR_K;
	}
	if (V_NUM_P(src)) {
		dst->num = src->num;
		dst->type |= V_NUM_K;
	}
}

void v_set_n(struct val *v, double d) {
	V_xxx_OFF(v);
	v->num = d;
	v->type = V_NUM_K;
}

void v_set_s(struct val *v, const String *s) {
	V_xxx_OFF(v);
	ko_cpy_m(v->ko, St_ptr(s), St_len(s));
	v->type = V_STR_K;
}

void v_set_m(struct val *v, const void *p, size_t n) {
	V_xxx_OFF(v);
	ko_cpy_m(v->ko, p, n);
	v->type = V_STR_K;
}

void v_set_io(struct val *v, IO *io) {
	V_xxx_OFF(v);
	v->magic.ext = io_incr(io);
	v->type = V_EXT_K;
}

void v_set_sub(struct val *v, struct sub *s) {
	V_xxx_OFF(v);
	v->magic.sub = sub_incr(s);
	v->type = V_SUB_K;
}

void v_set_undef(struct val *v) {
	V_xxx_OFF(v);
	v->type = V_UNDEF;
}

void v_cat(struct val *dst, struct val *src) {
	if (V_LIST_P(dst) && V_LIST_P(src)) {
		li_append(dst->magic.list, src->magic.list);
		return;
	}

	V_STR(src);
	V_STR(dst);
	V_xxx_OFF(dst);
	ko_cat(dst->ko, src->ko);
	dst->type = V_STR_K;
}

void v_cat_m(struct val *v, const void *p, size_t n) {
	V_STR(v);
	V_xxx_OFF(v);
	ko_cat_m(v->ko, p, n);
	v->type = V_STR_K;
}

void v_cat_s(struct val *v, const String *s) {
	v_cat_m(v, St_ptr(s), St_len(s));
}

void v_cat_c(struct val *v, char c) {
	v_cat_m(v, &c, 1);
}

struct val *v_undef(void) {
	struct val *v;
	v = xmalloc(1, sizeof *v);
	v_init(v);
	return v;
}

void v_delete(struct val *v) {
	v_end(v);
	xfree(v);
}

const char *v_sptr(struct val *v, size_t *l) {
	V_STR(v);
	if (l) {
		*l = ko_length(v->ko);
	}
	return ko_ptr(v->ko);
}

struct kork *v_kork(struct val *v) {
	V_STR(v);
	return v->ko;
}