/****************************************************************************
 * 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

/* ======================================================================== */
/* [macro] */

static 
int knh_StringUnit_fcmp__default(StringUnit *b, knh_bytes_t v1, knh_bytes_t v2);

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

void
knh_StringUnit_struct_init(Ctx *ctx, knh_StringUnit *b, int init, Object *cs)
{
	b->spec.flag = 0;
	b->spec.cid  = CLASS_String;
	KNH_INITv(b->spec.urn, TS_EMPTY);
	KNH_INITv(b->spec.tag,  TS_EMPTY);
	KNH_INITv(b->spec.defvalue, TS_EMPTY);
	//
	b->fnew = new_StringX__fast;
	b->fcmp = knh_StringUnit_fcmp__default;
	b->fbconv = NULL;
	KNH_INITv(b->bconv, KNH_NULL);
	b->charlen = 0;
	b->bytelen = 0;
	KNH_INITv(b->pattern, KNH_NULL);
	KNH_INITv(b->vocabDictIdx, KNH_NULL);
}

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

#define _knh_StringUnit_struct_copy   NULL

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

#define _knh_StringUnit_struct_compare  NULL

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

void
knh_StringUnit_struct_traverse(Ctx *ctx, knh_StringUnit *b, f_traverse gc)
{
	gc(ctx, b->spec.urn);
	gc(ctx, b->spec.tag);
	gc(ctx, b->spec.defvalue);

	gc(ctx, b->bconv);
	gc(ctx, b->pattern);
	gc(ctx, b->vocabDictIdx);
}

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

StringUnit *new_StringUnit(Ctx *ctx, knh_flag_t flag, knh_class_t cid, String *urn, String *tag)
{
	StringUnit* o = (StringUnit*)new_Object__RAW(ctx, FLAG_StringUnit, CLASS_StringUnit, sizeof(knh_StringUnit));
	knh_StringUnit_struct_init(ctx, DP(o), 0, NULL);

	DP(o)->spec.flag = flag;
	DP(o)->spec.cid  = cid;
	KNH_SETv(ctx, DP(o)->spec.urn, urn);
	KNH_SETv(ctx, DP(o)->spec.tag, tag);
	return o;
}

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

Object *knh_String_cspec(Ctx *ctx)
{
	return (Object*)new_StringUnit(ctx, 0, CLASS_String, TS_EMPTY, TS_EMPTY);
}

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

Object *knh_StringX_finitvalue(Ctx *ctx, knh_class_t cid)
{
	DEBUG_ASSERT_cid(cid);
	{
		StringUnit *u = (StringUnit*)knh_tClass[cid].cspec;
		KNH_ASSERT(IS_StringUnit(u));
		return DP(u)->spec.defvalue;
	}
}

/* ======================================================================== */
/* [methods] */
//
//size_t knh_StringUnit_fbconv__toupper(Ctx *ctx, BytesConv *o, knh_bytes_t t, Bytes *ba)
//{
//	size_t i;
//	for(i = 0; i < t.len; i++) {
//		knh_Bytes_putc(ctx, ba, toupper(t.buf[i]));
//	}
//	return i;
//}
//
///* ------------------------------------------------------------------------ */
//
//size_t knh_StringUnit_fbconv__tolower(Ctx *ctx, BytesConv *o, knh_bytes_t t, Bytes *ba)
//{
//	size_t i;
//	for(i = 0; i < t.len; i++) {
//		knh_Bytes_putc(ctx, ba, tolower(t.buf[i]));
//	}
//	return i;
//}

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

static
int knh_StringUnit_fcmp__default(StringUnit *o, knh_bytes_t v1, knh_bytes_t v2)
{
	size_t i, max = knh_uint_min(v1.len, v2.len);
	for(i = 0; i < max; i++) {
		int res = v1.buf[i] - v2.buf[i];
		if(res != 0) return res;
	}
	return v1.len - v2.len;
}

///* ======================================================================== */
///* [Dict] */
//
//knh_class_t KNH_TVOCAB(Ctx *ctx, char *urn, char *tag, ...)
//{
//	knh_class_t cid = knh_tClass_newId(ctx);
//	StringUnit* o = new_StringUnit(ctx, 0, cid, new_String__T(ctx, urn), new_String__T(ctx, tag));
//	char *vocab = NULL;
//	va_list args; 
//
//	va_start(args , tag);
//	if((vocab = va_arg(args, char*)) != NULL) {
//		knh_StringUnit_initDict(ctx, o, NULL, NULL, NULL, NULL);
//		knh_StringUnit_addDict__STEXT(ctx, o, vocab);
//		while((vocab = va_arg(args, char*)) != NULL) {
//			knh_StringUnit_addDict__STEXT(ctx, o, vocab);
//		}
//	}
//	va_end(args);
//	KNH_TCLASS_SPEC(ctx, CLASS_String, o);
//	return cid;
//}
//
///* ------------------------------------------------------------------------ */
//
//void knh_StringUnit_initDict(Ctx *ctx, StringUnit *o, ObjectNULL *dict, f_bconv fbconv, f_sunit_new fnew, f_sunit_cmp fcmp)
//{
//
//	DP(o)->fbconv = fbconv;
//	DP(o)->fnew = (fnew == NULL) ? knh_StringUnit_fnew__dict : fnew;
//	DP(o)->fcmp = (fcmp == NULL) ? knh_StringUnit_fcmp__dict : fcmp;
//	
//	if(dict == NULL || IS_NULL(dict)) {
//		KNH_SETv(ctx, DP(o)->vocabDictIdx, new_DictIdx(ctx, 12, 0));
//	}
//	else if(IS_DictIdx(dict)) {
//		KNH_SETv(ctx, DP(o)->vocabDictIdx, dict);
//	}
//	else {
//		TODO();
//		KNH_SETv(ctx, DP(o)->vocabDictIdx, new_DictIdx(ctx, 12, 0));
//	}
//}
//
///* ------------------------------------------------------------------------ */
//
//String* knh_StringUnit_fnew__dict(Ctx *ctx, StringUnit *o, knh_bytes_t t, void *orig, size_t off, size_t len)
//{
//	knh_index_t n = knh_DictIdx_index(ctx, DP(o)->vocabDictIdx, t);
//	if(n != -1) return  new_Nue__asIllegalString(ctx, o, t);
//	return knh_DictIdx_get__fast(DP(o)->vocabDictIdx, n);
//}
//
///* ------------------------------------------------------------------------ */
//
//knh_int_t knh_StringUnit_fcmp__dict(StringUnit *o, knh_bytes_t v1, knh_bytes_t v2)
//{
//	return knh_DictIdx_index(NULL, DP(o)->vocabDictIdx, v1) - knh_DictIdx_index(NULL, DP(o)->vocabDictIdx, v2);
//}
//
///* ------------------------------------------------------------------------ */
//
//void knh_StringUnit_addDict__STEXT(Ctx *ctx, StringUnit *o, char *vocab)
//{
//	KNH_ASSERT(vocab != NULL);
//	knh_DictIdx_add__fast(ctx, DP(o)->vocabDictIdx, new_String__STEXT(ctx, DP(o)->spec.cid, vocab));
//}

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

#ifdef __cplusplus
}
#endif
