/*
libmawk changes (C) 2014, Tibor 'Igor2' Palinkas;

This is a source file for mawk, an implementation of
the AWK programming language.

This file implements generic virtual array calls clear, loop_vector and load.
These calls rely on the low level find/set/iterator implementation of the
custom array and saves the time for the implementor writing these functions.
In return these functions are not fast at all.
*/

#include "mawk.h"
#include "zmalloc.h"
#include "memory.h"
#include "split.h"

void mawk_array_clear_generic(mawk_state_t *MAWK, mawk_array_t arr)
{
	void *it;
	const mawk_cell_t *idx;

	if (arr->imp.it_start == NULL)
		mawk_bozo(MAWK, "mawk_array_clear_generic() on an array without iterator");
	if (arr->imp.delet == NULL)
		mawk_bozo(MAWK, "mawk_array_clear_generic() on an array without delet");

	it = arr->imp.it_start(MAWK, arr);
	for(;;) {
		idx = arr->imp.it_next(MAWK, arr, it);
		if (idx == NULL)
			break;
		arr->imp.delet(MAWK, arr, idx);
	}
	arr->imp.it_stop(MAWK, arr, it);
}

mawk_string_t **mawk_array_loop_vector_generic(mawk_state_t *MAWK, mawk_array_t arr, unsigned *size)
{
	void *it;
	const mawk_cell_t *idx;
	mawk_string_t **ret = NULL;
	unsigned used = 0, alloced = 0;

	if (arr->imp.it_start == NULL)
		mawk_bozo(MAWK, "mawk_array_loop_vector_generic() on an array without iterator");

	it = arr->imp.it_start(MAWK, arr);
	for(;;) {
		idx = arr->imp.it_next(MAWK, arr, it);
		if (idx == NULL)
			break;
		if (used >= alloced) {
			alloced += 128;
			ret = mawk_realloc(MAWK, ret, sizeof(mawk_string_t *) * alloced);
		}
		ret[used] = idx->ptr;
		ret[used]->ref_cnt++;
		used++;
	}
	arr->imp.it_stop(MAWK, arr, it);
	*size = used;
	return ret;
}

void mawk_array_load_generic(mawk_state_t *MAWK, mawk_array_t arr, int cnt)
{
	mawk_cell_t cidx, cval;

	if (arr->imp.set == NULL)
		mawk_bozo(MAWK, "mawk_array_load_generic() on an array without set");

	if (arr->imp.clear != NULL)
		arr->imp.clear(MAWK, arr);
	else
		mawk_array_clear_generic(MAWK, arr);

	cidx.type = C_NUM;
	cval.type = C_STRING;

#define action(idx, sval) \
	cidx.d.dval = idx+1; \
	cval.ptr = (PTR) sval; \
	arr->imp.set(MAWK, arr, &cidx, &cval);

	mawk_split_walk(MAWK, cnt, 1, action);

#undef action

}
