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

libMawk is distributed without warranty under the terms of
the GNU General Public License, version 2, 1991.
*/
#include <stdlib.h>
#include <string.h>
#include "mawk.h"
#include "array.h"
#include "memory.h"
#include "zmalloc.h"
#include "cell.h"

/* -- generic array implementation -- */

/* - creating a new array does not depend on the implementation - */
mawk_array_t mawk_array_new(mawk_state_t *MAWK, const array_imp_t *imp)
{
	mawk_array_t a;
	a = MAWK_ZMALLOC(MAWK, struct array);
	memset(a, 0, sizeof(struct array));
	if (imp == NULL)
		a->imp = mawk_array_orig_imp;
	else
		a->imp = *imp;
	return a;
}

void mawk_array_destroy(mawk_state_t *MAWK, mawk_array_t ARR)
{
	mawk_array_clear(MAWK, ARR);
	mawk_zfree(MAWK, ARR, sizeof(struct array));
}

/* catting the indices together doesn't depend on implementation */
mawk_cell_t *mawk_array_cat(mawk_state_t *MAWK, mawk_cell_t *sp, int cnt)
{
	mawk_cell_t *p;											/* walks the eval stack */
	mawk_cell_t subsep;									/* local copy of SUBSEP */
	unsigned subsep_len;					/* string length of subsep_str */
	char *subsep_str;

	unsigned total_len;						/* length of cat'ed expression */
	mawk_cell_t *top;										/* value of sp at entry */
	char *target;									/* build cat'ed char* here */
	mawk_string_t *sval;									/* build cat'ed mawk_string_t here */
	mawk_cellcpy(MAWK, &subsep, SUBSEP);
	if (subsep.type < C_STRING)
		mawk_cast1_to_str(MAWK, &subsep);
	subsep_len = string(&subsep)->len;
	subsep_str = string(&subsep)->str;

	top = sp;
	sp -= (cnt - 1);

	total_len = (cnt - 1) * subsep_len;
	for (p = sp; p <= top; p++) {
		if (p->type < C_STRING)
			mawk_cast1_to_str(MAWK, p);
		total_len += string(p)->len;
	}

	sval = mawk_new_STRING0(MAWK, total_len);
	target = sval->str;
	for (p = sp; p < top; p++) {
		memcpy(target, string(p)->str, string(p)->len);
		target += string(p)->len;
		memcpy(target, subsep_str, subsep_len);
		target += subsep_len;
	}
	/* now p == top */
	memcpy(target, string(p)->str, string(p)->len);

	for (p = sp; p <= top; p++)
		free_STRING(string(p));
	free_STRING(string(&subsep));
	/* set contents of sp , sp->type > C_STRING is possible so reset */
	sp->type = C_STRING;
	sp->ptr = (PTR) sval;
	return sp;
}

void mawk_array_clear_common(mawk_state_t *MAWK, mawk_array_t A)
{
	A->ptr = NULL;
	A->size = 0;
	A->limit = 0;
	A->hmask = 0;
	A->type = 0;

}

/* - naive implementation for the complex queries -
   these assume the most basic operations (set/get/find/delet) to be implemented
   and provide a slow, but generic implementation for the higher level
   calls */

/* TODO */
