/**********************************************************************
 
	Copyright (C) 2003 Hirohisa MORI <joshua@nichibun.ac.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	This program is distributed in the hope that it will be 
	useful, but WITHOUT ANY WARRANTY; without even the 
	implied warranty of MERCHANTABILITY or FITNESS FOR A 
	PARTICULAR PURPOSE.

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


#include	"machine/include.h"
#include	"memory_debug.h"
#include	"utils.h"
#include	"long_char.h"

/*
#define L_STR_CHECK
*/

typedef struct lstr_node {
	struct lstr_node *	next;
	CODE_METHOD *		cm;
	char *			str;
	L_CHAR *		ret;
} LSTR_NODE;

#define LSTR_NODE_HASH_SIZE		1011

LSTR_NODE * lstr_hash_table[LSTR_NODE_HASH_SIZE];

L_CHAR *
_l_string_1(CODE_METHOD * cm,char * str)
{
L_CHAR * ret,*dest;
int len;
void * work;
unsigned char * src;


	if ( str == 0 )
		return 0; 

	len = strlen(str)+1;
	ret = d_alloc(sizeof(L_CHAR)*(len+1));
	work = (*cm->open)();
	dest = ret;
	src = (unsigned char*)str;


	len = 0;
	for ( ; *src ; src ++ ) {
		if ( (*cm->to_internal)(dest,work,*src) ) {
			dest ++;
			len ++;
		}
	}
	(*cm->close)(0,work);
	*dest = 0;
	ret = d_re_alloc(ret,(len+1)*sizeof(L_CHAR));
	set_buffer(ret);


	return ret;
}

L_CHAR *
_l_string_2(CODE_METHOD * cm,char * str)
{
unsigned int key;
LSTR_NODE * n, ** np, ** st;

#ifdef L_STR_CHECK
int cnt;
static int amount;
static int max_cnt;
static unsigned int last_time;
unsigned int gt;
#endif

	key = (((unsigned int)str)+((unsigned int)cm))
			% LSTR_NODE_HASH_SIZE;

#ifdef L_STR_CHECK
	cnt = 0;
#endif

	for ( np = st = &lstr_hash_table[key] ; *np ; ) {
		n = *np;
		if ( n->str == str && n->cm == cm ) {

#ifdef L_STR_CHECK
if ( max_cnt < cnt )
max_cnt = cnt;
gt = get_xltime();
if ( gt != last_time ) {
printf("LSTR %i %i\n",max_cnt,amount);
last_time = gt;
}
#endif
			return n->ret;
		}

#ifdef L_STR_CHECK
		cnt ++;
#endif

		np = &n->next;
	}
	n = d_alloc(sizeof(*n));
	n->cm = cm;
	n->str = str;
	n->ret = ll_copy_str(_l_string_1(cm,str));
	st = &lstr_hash_table[key];
	n->next = *st;
	*st = n;

#ifdef L_STR_CHECK
	amount ++;
#endif

	return n->ret;
}


