/****************************************************************************
 * KONOHA COPYRIGHT, LICENSE NOTICE, AND DISCRIMER  
 * 
 * Copyright (c) 2005-2008, Kimio Kuramitsu <kimio at ynu.ac.jp>
 *           (c) 2008-      Konoha Software Foundation  
 * All rights reserved.
 * 
 * You may choose one of the following two licenses when you use konoha. 
 * See www.konohaware.org/license.html for further information.
 * 
 * (1) GNU General Public License 2.0      (with    KONOHA_UNDER_GPL2)
 * (2) Konoha Software Foundation License 1.0
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *  
 ****************************************************************************/

/* ************************************************************************ */

#include"commons.h"

/* ************************************************************************ */

#ifdef __cplusplus 
extern "C" {
#endif

/* ======================================================================== */
/* [structs] */

void
knh_ClassMap_struct_init(Ctx *ctx, knh_ClassMap *b, int init, Object *cs)
{
	b->size   = 0;
	b->capacity = knh_uint_min(4, init);
	b->maplist   = (Mapper**)KNH_MALLOC(ctx, b->capacity * sizeof(Mapper*));
	knh_bzero(b->maplist, b->capacity * sizeof(Mapper*));
}

/* ------------------------------------------------------------------------ */

#define _knh_ClassMap_struct_copy    NULL

/* ------------------------------------------------------------------------ */

#define _knh_ClassMap_struct_compare  NULL

/* ------------------------------------------------------------------------ */

void
knh_ClassMap_struct_traverse(Ctx *ctx, knh_ClassMap *b, f_traverse gc)
{
	int i;
	for(i = 0; i < b->size; i++) {
		gc(ctx, b->maplist[i]);
	}
	if(IS_SWEEP(gc)) {
		KNH_FREE(b->maplist, b->capacity * sizeof(Mapper*));
	}
}

/* ======================================================================== */
/* [constructors] */

ClassMap* new_ClassMap0(Ctx *ctx, knh_ushort_t capacity)
{
	knh_ClassMap_t *o = 
		(knh_ClassMap_t*)new_Object__RAW(ctx, FLAG_ClassMap, CLASS_ClassMap, sizeof(knh_ClassMap));
	knh_ClassMap_struct_init(ctx, DP(o), capacity, NULL);
	knh_ClassMap_setSorted(o, 1);
	return o;
}

/* ------------------------------------------------------------------------ */

void knh_ClassMap_resize(Ctx *ctx, ClassMap *o, size_t newsize)
{
	Mapper **newlist = (Mapper**)KNH_MALLOC(ctx, newsize * sizeof(Mapper*));
	knh_bzero(newlist, newsize);
	knh_int_t i;
	for(i = 0; i < DP(o)->size; i++) {
		newlist[i] = DP(o)->maplist[i];
	}
	KNH_FREE(DP(o)->maplist, DP(o)->capacity * sizeof(Mapper*));
	DP(o)->maplist = newlist;
	DP(o)->capacity = newsize;
}

/* ------------------------------------------------------------------------ */

int 
knh_ClassMap_util_cmp(const Mapper *m1, const Mapper *m2)
{
	int res = DP(m1)->flag - DP(m2)->flag;
	return (res == 0) ? DP(m2)->tcid - DP(m1)->tcid : res;
}

/* ------------------------------------------------------------------------ */

void knh_ClassMap_sort(Ctx *ctx, ClassMap *o)
{
	if(!knh_ClassMap_isSorted(o)) {
		knh_qsort(DP(o)->maplist, DP(o)->size, sizeof(Mapper*), 
					(int (*)(const void*, const void*))knh_ClassMap_util_cmp);		
		knh_ClassMap_setSorted(o, 1);
	}
}

/* ------------------------------------------------------------------------ */

void knh_ClassMap_add(Ctx *ctx, ClassMap *o, Mapper *map)
{
	if(DP(o)->size == DP(o)->capacity) {
		knh_ClassMap_resize(ctx, o, DP(o)->capacity + 8);
	}
	KNH_ASSERT(DP(o)->maplist[DP(o)->size] == NULL);
	KNH_INITv(DP(o)->maplist[DP(o)->size], map);
	DP(o)->size++;
}

/* ======================================================================== */
/* [movabletext] */

/* @method void ClassMap.%dump(OutputStream w, Any m) */

void knh_ClassMap__dump(Ctx *ctx, ClassMap *o, OutputStream *w, Any *m)
{
	int i;
	for(i = 0; i < DP(o)->size; i++) {
		knh_printf(ctx, w, "[%d]\t", i);
		knh_Mapper__repr(ctx, DP(o)->maplist[i], w, m);
		knh_write_EOL(ctx, w);
	}
}

/* ------------------------------------------------------------------------ */

#ifdef __cplusplus
}
#endif
