view src/ploki/val.c @ 8065:591b1467ccdf

<int-e> le/rn paste/"Paste" is a short story by Henry James. Its contents has been cut into pieces and distributed over numerous tin boxes on the World Wide Web, little pearls of wisdom buried among ordinary pastes.
author HackBot
date Sun, 15 May 2016 13:14:57 +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;
}