redefined hash functions
This commit is contained in:
		| @ -81,7 +81,7 @@ static hcl_oop_oop_t expand_bucket (hcl_t* hcl, hcl_oop_oop_t oldbuc) | ||||
| 			HCL_ASSERT (hcl, HCL_IS_CONS(hcl,ass)); | ||||
| 			key = (hcl_oop_char_t)ass->car; | ||||
| 			HCL_ASSERT (hcl, HCL_IS_SYMBOL(hcl,key)); | ||||
| 			index = hcl_hashoochars(key->slot, HCL_OBJ_GET_SIZE(key)) % newsz; | ||||
| 			index = hcl_hash_oochars(key->slot, HCL_OBJ_GET_SIZE(key)) % newsz; | ||||
| 		#else | ||||
| 			int n; | ||||
| 			HCL_ASSERT (hcl, HCL_IS_CONS(hcl,ass)); | ||||
| @ -113,7 +113,7 @@ static hcl_oop_cons_t find_or_upsert (hcl_t* hcl, hcl_oop_dic_t dic, hcl_oop_t k | ||||
| 	HCL_ASSERT (hcl, HCL_IS_ARRAY(hcl,dic->bucket)); | ||||
|  | ||||
| #if defined(SYMBOL_ONLY_KEY) | ||||
| 	index = hcl_hashoochars(HCL_OBJ_GET_CHAR_SLOT(key), HCL_OBJ_GET_SIZE(key)) % HCL_OBJ_GET_SIZE(dic->bucket); | ||||
| 	index = hcl_hash_oochars(HCL_OBJ_GET_CHAR_SLOT(key), HCL_OBJ_GET_SIZE(key)) % HCL_OBJ_GET_SIZE(dic->bucket); | ||||
| #else | ||||
| 	if (hcl_hashobj(hcl, key, &index) <= -1) return HCL_NULL; | ||||
| 	index %= HCL_OBJ_GET_SIZE(dic->bucket); | ||||
| @ -199,7 +199,7 @@ static hcl_oop_cons_t find_or_upsert (hcl_t* hcl, hcl_oop_dic_t dic, hcl_oop_t k | ||||
|  | ||||
| 	#if defined(SYMBOL_ONLY_KEY) | ||||
| 		/* recalculate the index for the expanded bucket */ | ||||
| 		index = hcl_hashoochars(HCL_OBJ_GET_CHAR_SLOT(key), HCL_OBJ_GET_SIZE(key)) % HCL_OBJ_GET_SIZE(dic->bucket); | ||||
| 		index = hcl_hash_oochars(HCL_OBJ_GET_CHAR_SLOT(key), HCL_OBJ_GET_SIZE(key)) % HCL_OBJ_GET_SIZE(dic->bucket); | ||||
| 	#else | ||||
| 		hcl_hashobj(hcl, key, &index); /* this must succeed as i know 'key' is hashable */ | ||||
| 		index %= HCL_OBJ_GET_SIZE(dic->bucket); | ||||
| @ -286,7 +286,7 @@ int hcl_zapatdic (hcl_t* hcl, hcl_oop_dic_t dic, hcl_oop_t key) | ||||
| 	HCL_ASSERT (hcl, HCL_IS_ARRAY(hcl,dic->bucket)); | ||||
|  | ||||
| #if defined(SYMBOL_ONLY_KEY) | ||||
| 	index = hcl_hashoochars(HCL_OBJ_GET_CHAR_SLOT(key), HCL_OBJ_GET_SIZE(key)) % bs; | ||||
| 	index = hcl_hash_oochars(HCL_OBJ_GET_CHAR_SLOT(key), HCL_OBJ_GET_SIZE(key)) % bs; | ||||
| #else | ||||
| 	if (hcl_hashobj(hcl, key, &index) <= -1) return -1; | ||||
| 	index %= bs; | ||||
| @ -336,7 +336,7 @@ found: | ||||
| 	#if defined(SYMBOL_ONLY_KEY) | ||||
| 		/* get the natural hash index for the data in the slot at | ||||
| 		 * the current hash index */ | ||||
| 		z = hcl_hashoochars(HCL_OBJ_GET_CHAR_SLOT(ass->car), HCL_OBJ_GET_SIZE(ass->car)) % bs; | ||||
| 		z = hcl_hash_oochars(HCL_OBJ_GET_CHAR_SLOT(ass->car), HCL_OBJ_GET_SIZE(ass->car)) % bs; | ||||
| 	#else | ||||
| 		if (hcl_hashobj(hcl, ass->car, &z) <= -1) return -1; | ||||
| 		z %= bs; | ||||
|  | ||||
| @ -96,7 +96,7 @@ static void compact_symbol_table (hcl_t* hcl, hcl_oop_t _nil) | ||||
|  | ||||
| 			HCL_ASSERT (hcl, HCL_IS_SYMBOL(hcl, symbol)); | ||||
|  | ||||
| 			z = hcl_hashoochars(symbol->slot, HCL_OBJ_GET_SIZE(symbol)) % bucket_size; | ||||
| 			z = hcl_hash_oochars(symbol->slot, HCL_OBJ_GET_SIZE(symbol)) % bucket_size; | ||||
|  | ||||
| 			/* move an element if necessary */ | ||||
| 			if ((y > x && (z <= x || z > y)) || | ||||
|  | ||||
| @ -272,7 +272,7 @@ | ||||
|  | ||||
| /* ========================================================================= | ||||
|  * BASIC HCL TYPES | ||||
|  * =========================================================================*/ | ||||
|  * ========================================================================= */ | ||||
|  | ||||
| typedef char                    hcl_bch_t; | ||||
| typedef int                     hcl_bci_t; | ||||
| @ -348,6 +348,105 @@ typedef struct hcl_bcs_t hcl_bcs_t; | ||||
| /* the maximum number of bch charaters to represent a single uch character */ | ||||
| #define HCL_BCSIZE_MAX 6 | ||||
|  | ||||
| /* ========================================================================= | ||||
|  * BASIC OOP ENCODING | ||||
|  * ========================================================================= */ | ||||
|  | ||||
| /* actual structure defined in hcl.h */ | ||||
| typedef struct hcl_obj_t           hcl_obj_t; | ||||
| typedef struct hcl_obj_t*          hcl_oop_t; | ||||
|  | ||||
| /*  | ||||
|  * An object pointer(OOP) is an ordinary pointer value to an object. | ||||
|  * but some simple numeric values are also encoded into OOP using a simple | ||||
|  * bit-shifting and masking. | ||||
|  * | ||||
|  * A real OOP is stored without any bit-shifting while a non-pointer value encoded | ||||
|  * in an OOP is bit-shifted to the left by 2 and the 2 least-significant bits | ||||
|  * are set to 1 or 2. | ||||
|  *  | ||||
|  * This scheme works because the object allocators aligns the object size to | ||||
|  * a multiple of sizeof(hcl_oop_t). This way, the 2 least-significant bits | ||||
|  * of a real OOP are always 0s. | ||||
|  * | ||||
|  * With 2 bits, i can encode only 3 special types except object pointers.  | ||||
|  * Since I need more than 3 special types, I extend the tag bits up to 4 bits | ||||
|  * to represent a special data type that doesn't require a range as wide | ||||
|  * as a small integer. A unicode character, for instance, only requires 21  | ||||
|  * bits at most. An error doesn't need to be as diverse as a small integer. | ||||
|  */ | ||||
|  | ||||
| #define HCL_OOP_TAG_BITS_LO     2 | ||||
| #define HCL_OOP_TAG_BITS_HI     2 | ||||
|  | ||||
| #define HCL_OOP_TAG_SMOOI       1    /* 01 */ | ||||
| #define HCL_OOP_TAG_SMPTR       2    /* 10 */ | ||||
| #define HCL_OOP_TAG_EXTENDED    3    /* 11 - internal use only */ | ||||
| #define HCL_OOP_TAG_CHAR        3    /* 0011 */ | ||||
| #define HCL_OOP_TAG_ERROR       7    /* 0111 */ | ||||
| #define HCL_OOP_TAG_RESERVED0   11   /* 1011 */ | ||||
| #define HCL_OOP_TAG_RESERVED1   15   /* 1111 */ | ||||
|  | ||||
| #define HCL_OOP_GET_TAG_LO(oop) (((hcl_oow_t)oop) & HCL_LBMASK(hcl_oow_t, HCL_OOP_TAG_BITS_LO)) | ||||
| #define HCL_OOP_GET_TAG_LOHI(oop) (((hcl_oow_t)oop) & HCL_LBMASK(hcl_oow_t, HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_HI)) | ||||
| #define HCL_OOP_GET_TAG(oop) (HCL_OOP_GET_TAG_LO(oop) == HCL_OOP_TAG_EXTENDED? HCL_OOP_GET_TAG_LOHI(oop): HCL_OOP_GET_TAG_LO(oop)) | ||||
|  | ||||
| #define HCL_OOP_IS_NUMERIC(oop) (HCL_OOP_GET_TAG_LO(oop) != 0) | ||||
| #define HCL_OOP_IS_POINTER(oop) (HCL_OOP_GET_TAG_LO(oop) == 0) | ||||
|  | ||||
| #define HCL_OOP_IS_SMOOI(oop) (HCL_OOP_GET_TAG_LO(oop) == HCL_OOP_TAG_SMOOI) | ||||
| #define HCL_OOP_IS_SMPTR(oop) (HCL_OOP_GET_TAG_LO(oop) == HCL_OOP_TAG_SMPTR) | ||||
|  | ||||
| #define HCL_SMOOI_TO_OOP(num) ((hcl_oop_t)((((hcl_oow_t)(hcl_ooi_t)(num)) << HCL_OOP_TAG_BITS_LO) | HCL_OOP_TAG_SMOOI)) | ||||
| #define HCL_OOP_TO_SMOOI(oop) (((hcl_ooi_t)oop) >> HCL_OOP_TAG_BITS_LO) | ||||
| /* | ||||
| #define HCL_SMPTR_TO_OOP(ptr) ((hcl_oop_t)((((hcl_oow_t)(ptr)) << HCL_OOP_TAG_BITS_LO) | HCL_OOP_TAG_SMPTR)) | ||||
| #define HCL_OOP_TO_SMPTR(oop) (((hcl_ooi_t)oop) >> HCL_OOP_TAG_BITS_LO) | ||||
| */ | ||||
| #define HCL_SMPTR_TO_OOP(ptr) ((hcl_oop_t)(((hcl_oow_t)ptr) | HCL_OOP_TAG_SMPTR)) | ||||
| #define HCL_OOP_TO_SMPTR(oop) ((void*)(((hcl_oow_t)oop) & ~HCL_LBMASK(hcl_oow_t, HCL_OOP_TAG_BITS_LO))) | ||||
|  | ||||
| #define HCL_OOP_IS_CHAR(oop) (HCL_OOP_GET_TAG(oop) == HCL_OOP_TAG_CHAR) | ||||
| #define HCL_OOP_IS_ERROR(oop) (HCL_OOP_GET_TAG(oop) == HCL_OOP_TAG_ERROR) | ||||
|  | ||||
| #define HCL_OOP_TO_CHAR(oop) (((hcl_oow_t)oop) >> (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_LO)) | ||||
| #define HCL_CHAR_TO_OOP(num) ((hcl_oop_t)((((hcl_oow_t)(num)) << (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_LO)) | HCL_OOP_TAG_CHAR)) | ||||
| #define HCL_OOP_TO_ERROR(oop) (((hcl_oow_t)oop) >> (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_LO)) | ||||
| #define HCL_ERROR_TO_OOP(num) ((hcl_oop_t)((((hcl_oow_t)(num)) << (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_LO)) | HCL_OOP_TAG_ERROR)) | ||||
|  | ||||
| /* SMOOI takes up 62 bit on a 64-bit architecture and 30 bits  | ||||
|  * on a 32-bit architecture. The absolute value takes up 61 bits and 29 bits | ||||
|  * respectively for the 1 sign bit. */ | ||||
| #define HCL_SMOOI_BITS (HCL_OOI_BITS - HCL_OOP_TAG_BITS_LO) | ||||
| #define HCL_SMOOI_ABS_BITS (HCL_SMOOI_BITS - 1) | ||||
| #define HCL_SMOOI_MAX ((hcl_ooi_t)(~((hcl_oow_t)0) >> (HCL_OOP_TAG_BITS_LO + 1))) | ||||
| /* Sacrificing 1 bit pattern for a negative SMOOI makes  | ||||
|  * implementation a lot eaisier in many respect. */ | ||||
| /*#define HCL_SMOOI_MIN (-HCL_SMOOI_MAX - 1)*/ | ||||
| #define HCL_SMOOI_MIN (-HCL_SMOOI_MAX) | ||||
| #define HCL_IN_SMOOI_RANGE(ooi)  ((ooi) >= HCL_SMOOI_MIN && (ooi) <= HCL_SMOOI_MAX) | ||||
|  | ||||
|  | ||||
| /* SMPTR is a special value which has been devised to encode an address value | ||||
|  * whose low HCL_OOP_TAG_BITS_LO bits are 0. its class is SmallPointer. A pointer | ||||
|  * returned by most of system functions would be aligned to the pointer size.  | ||||
|  * you can use the followings macros when converting such a pointer without loss. */ | ||||
| #define HCL_IN_SMPTR_RANGE(ptr) ((((hcl_oow_t)ptr) & HCL_LBMASK(hcl_oow_t, HCL_OOP_TAG_BITS_LO)) == 0) | ||||
|  | ||||
| #define HCL_CHAR_BITS (HCL_OOI_BITS - HCL_OOP_TAG_BITS_LO - HCL_OOP_TAG_BITS_HI) | ||||
| #define HCL_CHAR_MIN 0 | ||||
| #define HCL_CHAR_MAX (~((hcl_oow_t)0) >> (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_HI)) | ||||
|  | ||||
| #define HCL_ERROR_BITS (HCL_OOI_BITS - HCL_OOP_TAG_BITS_LO - HCL_OOP_TAG_BITS_HI) | ||||
| #define HCL_ERROR_MIN 0 | ||||
| #define HCL_ERROR_MAX (~((hcl_oow_t)0) >> (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_HI)) | ||||
|  | ||||
| /* TODO: There are untested code where smint is converted to hcl_oow_t. | ||||
|  *       for example, the spec making macro treats the number as hcl_oow_t instead of hcl_ooi_t. | ||||
|  *       as of this writing, i skip testing that part with the spec value exceeding HCL_SMOOI_MAX. | ||||
|  *       later, please verify it works, probably by limiting the value ranges in such macros | ||||
|  */ | ||||
|  | ||||
| /* ========================================================================= | ||||
|  * TIME-RELATED TYPES | ||||
|  * =========================================================================*/ | ||||
|  | ||||
| @ -116,46 +116,126 @@ | ||||
| #endif | ||||
|  | ||||
|  | ||||
| #if (HCL_SIZEOF_SIZE_T == 4) | ||||
| #	define HCL_HASH_FNV_MAGIC_INIT (0x811c9dc5) | ||||
| #	define HCL_HASH_FNV_MAGIC_PRIME (0x01000193) | ||||
| #elif (HCL_SIZEOF_SIZE_T == 8) | ||||
|  | ||||
| #	define HCL_HASH_FNV_MAGIC_INIT (0xCBF29CE484222325) | ||||
| #	define HCL_HASH_FNV_MAGIC_PRIME (0x100000001B3l) | ||||
|  | ||||
| #elif (HCL_SIZEOF_SIZE_T == 16) | ||||
| #	define HCL_HASH_FNV_MAGIC_INIT (0x6C62272E07BB014262B821756295C58D) | ||||
| #	define HCL_HASH_FNV_MAGIC_PRIME (0x1000000000000000000013B) | ||||
| #endif | ||||
|  | ||||
| #if defined(HCL_HASH_FNV_MAGIC_INIT) | ||||
| 	/* FNV-1 hash */ | ||||
| #	define HCL_HASH_INIT HCL_HASH_FNV_MAGIC_INIT | ||||
| #	define HCL_HASH_VALUE(hv,v) (((hv) ^ (v)) * HCL_HASH_FNV_MAGIC_PRIME) | ||||
|  | ||||
| #else | ||||
| 	/* SDBM hash */ | ||||
| #	define HCL_HASH_INIT 0 | ||||
| #	define HCL_HASH_VALUE(hv,v) (((hv) << 6) + ((hv) << 16) - (hv) + (v)) | ||||
| #endif | ||||
|  | ||||
| #define HCL_HASH_VPTL(hv, ptr, len, type) do { \ | ||||
| 	hv = HCL_HASH_INIT; \ | ||||
| 	HCL_HASH_MORE_VPTL (hv, ptr, len, type); \ | ||||
| } while(0) | ||||
|  | ||||
| #define HCL_HASH_MORE_VPTL(hv, ptr, len, type) do { \ | ||||
| 	type* __hcl_hash_more_vptl_p = (type*)(ptr); \ | ||||
| 	type* __hcl_hash_more_vptl_q = (type*)__hcl_hash_more_vptl_p + (len); \ | ||||
| 	while (__hcl_hash_more_vptl_p < __hcl_hash_more_vptl_q) \ | ||||
| 	{ \ | ||||
| 		hv = HCL_HASH_VALUE(hv, *__hcl_hash_more_vptl_p); \ | ||||
| 		__hcl_hash_more_vptl_p++; \ | ||||
| 	} \ | ||||
| } while(0) | ||||
|  | ||||
| #define HCL_HASH_VPTR(hv, ptr, type) do { \ | ||||
| 	hv = HCL_HASH_INIT; \ | ||||
| 	HCL_HASH_MORE_VPTR (hv, ptr, type); \ | ||||
| } while(0) | ||||
|  | ||||
| #define HCL_HASH_MORE_VPTR(hv, ptr, type) do { \ | ||||
| 	type* __hcl_hash_more_vptr_p = (type*)(ptr); \ | ||||
| 	while (*__hcl_hash_more_vptr_p) \ | ||||
| 	{ \ | ||||
| 		hv = HCL_HASH_VALUE(hv, *__hcl_hash_more_vptr_p); \ | ||||
| 		__hcl_hash_more_vptr_p++; \ | ||||
| 	} \ | ||||
| } while(0) | ||||
|  | ||||
| #define HCL_HASH_BYTES(hv, ptr, len) HCL_HASH_VPTL(hv, ptr, len, const hcl_uint8_t) | ||||
| #define HCL_HASH_MORE_BYTES(hv, ptr, len) HCL_HASH_MORE_VPTL(hv, ptr, len, const hcl_uint8_t) | ||||
|  | ||||
| #define HCL_HASH_BCHARS(hv, ptr, len) HCL_HASH_VPTL(hv, ptr, len, const hcl_bch_t) | ||||
| #define HCL_HASH_MORE_BCHARS(hv, ptr, len) HCL_HASH_MORE_VPTL(hv, ptr, len, const hcl_bch_t) | ||||
|  | ||||
| #define HCL_HASH_UCHARS(hv, ptr, len) HCL_HASH_VPTL(hv, ptr, len, const hcl_uch_t) | ||||
| #define HCL_HASH_MORE_UCHARS(hv, ptr, len) HCL_HASH_MORE_VPTL(hv, ptr, len, const hcl_uch_t) | ||||
|  | ||||
| #define HCL_HASH_BCSTR(hv, ptr) HCL_HASH_VPTR(hv, ptr, const hcl_bch_t) | ||||
| #define HCL_HASH_MORE_BCSTR(hv, ptr) HCL_HASH_MORE_VPTR(hv, ptr, const hcl_bch_t) | ||||
|  | ||||
| #define HCL_HASH_UCSTR(hv, ptr) HCL_HASH_VPTR(hv, ptr, const hcl_uch_t) | ||||
| #define HCL_HASH_MORE_UCSTR(hv, ptr) HCL_HASH_MORE_VPTR(hv, ptr, const hcl_uch_t) | ||||
|  | ||||
|  | ||||
|  | ||||
| #if defined(__cplusplus) | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| HCL_EXPORT hcl_oow_t hcl_hash_bytes ( | ||||
| HCL_EXPORT hcl_oow_t hcl_hash_bytes_ ( | ||||
| 	const hcl_oob_t* ptr, | ||||
| 	hcl_oow_t        len | ||||
| ); | ||||
|  | ||||
| #if defined(HCL_HAVE_INLINE) | ||||
| 	static HCL_INLINE hcl_oow_t hcl_hashbchars (const hcl_bch_t* ptr, hcl_oow_t len) | ||||
| 	static HCL_INLINE hcl_oow_t hcl_hash_bytes (const hcl_oob_t* ptr, hcl_oow_t len) | ||||
| 	{ | ||||
| 		hcl_oow_t hv; | ||||
| 		HCL_HASH_BYTES (hv, ptr, len); | ||||
| 		/* constrain the hash value to be representable in a small integer | ||||
| 		 * for convenience sake */ | ||||
| 		return hv % ((hcl_oow_t)HCL_SMOOI_MAX + 1); | ||||
| 	} | ||||
|  | ||||
| 	static HCL_INLINE hcl_oow_t hcl_hash_bchars (const hcl_bch_t* ptr, hcl_oow_t len) | ||||
| 	{ | ||||
| 		return hcl_hash_bytes((const hcl_oob_t*)ptr, len * HCL_SIZEOF(hcl_bch_t)); | ||||
| 	} | ||||
|  | ||||
| 	static HCL_INLINE hcl_oow_t hcl_hashuchars (const hcl_uch_t* ptr, hcl_oow_t len) | ||||
| 	static HCL_INLINE hcl_oow_t hcl_hash_uchars (const hcl_uch_t* ptr, hcl_oow_t len) | ||||
| 	{ | ||||
| 		return hcl_hash_bytes((const hcl_oob_t*)ptr, len * HCL_SIZEOF(hcl_uch_t)); | ||||
| 	} | ||||
|  | ||||
| 	static HCL_INLINE hcl_oow_t hcl_hashwords (const hcl_oow_t* ptr, hcl_oow_t len) | ||||
| 	static HCL_INLINE hcl_oow_t hcl_hash_words (const hcl_oow_t* ptr, hcl_oow_t len) | ||||
| 	{ | ||||
| 		return hcl_hash_bytes((const hcl_oob_t*)ptr, len * HCL_SIZEOF(hcl_oow_t)); | ||||
| 	} | ||||
|  | ||||
| 	static HCL_INLINE hcl_oow_t hcl_hashhalfwords (const hcl_oohw_t* ptr, hcl_oow_t len) | ||||
| 	static HCL_INLINE hcl_oow_t hcl_hash_halfwords (const hcl_oohw_t* ptr, hcl_oow_t len) | ||||
| 	{ | ||||
| 		return hcl_hash_bytes((const hcl_oob_t*)ptr, len * HCL_SIZEOF(hcl_oohw_t)); | ||||
| 	} | ||||
| #else | ||||
| #	define hcl_hashbchars(ptr,len)    hcl_hash_bytes((const hcl_oob_t*)ptr, len * HCL_SIZEOF(hcl_bch_t)) | ||||
| #	define hcl_hashuchars(ptr,len)    hcl_hash_bytes((const hcl_oob_t*)ptr, len * HCL_SIZEOF(hcl_uch_t)) | ||||
| #	define hcl_hashwords(ptr,len)     hcl_hash_bytes((const hcl_oob_t*)ptr, len * HCL_SIZEOF(hcl_oow_t)) | ||||
| #	define hcl_hashhalfwords(ptr,len) hcl_hash_bytes((const hcl_oob_t*)ptr, len * HCL_SIZEOF(hcl_oohw_t)) | ||||
| #	define hcl_hash_bytes(ptr,len)     hcl_hash_bytes_(ptr, len) | ||||
| #	define hcl_hash_bchars(ptr,len)    hcl_hash_bytes((const hcl_oob_t*)ptr, len * HCL_SIZEOF(hcl_bch_t)) | ||||
| #	define hcl_hash_uchars(ptr,len)    hcl_hash_bytes((const hcl_oob_t*)ptr, len * HCL_SIZEOF(hcl_uch_t)) | ||||
| #	define hcl_hash_words(ptr,len)     hcl_hash_bytes((const hcl_oob_t*)ptr, len * HCL_SIZEOF(hcl_oow_t)) | ||||
| #	define hcl_hash_halfwords(ptr,len) hcl_hash_bytes((const hcl_oob_t*)ptr, len * HCL_SIZEOF(hcl_oohw_t)) | ||||
| #endif | ||||
|  | ||||
| #if defined(HCL_OOCH_IS_UCH) | ||||
| #	define hcl_hashoochars(ptr,len) hcl_hashuchars(ptr,len) | ||||
| #	define hcl_hash_oochars(ptr,len) hcl_hash_uchars(ptr,len) | ||||
| #else | ||||
| #	define hcl_hashoochars(ptr,len) hcl_hashbchars(ptr,len) | ||||
| #	define hcl_hash_oochars(ptr,len) hcl_hash_bchars(ptr,len) | ||||
| #endif | ||||
|  | ||||
| /** | ||||
|  | ||||
							
								
								
									
										119
									
								
								hcl/lib/hcl.h
									
									
									
									
									
								
							
							
						
						
									
										119
									
								
								hcl/lib/hcl.h
									
									
									
									
									
								
							| @ -196,8 +196,12 @@ enum hcl_trait_t | ||||
| }; | ||||
| typedef enum hcl_trait_t hcl_trait_t; | ||||
|  | ||||
| typedef struct hcl_obj_t           hcl_obj_t; | ||||
| typedef struct hcl_obj_t*          hcl_oop_t; | ||||
| /* ========================================================================= | ||||
|  * SPECIALIZED OOP TYPES | ||||
|  * ========================================================================= */ | ||||
|  | ||||
| /* hcl_oop_t defined in hcl-cmn.h | ||||
|  * hcl_obj_t defined further down */ | ||||
|  | ||||
| /* these are more specialized types for hcl_obj_t */ | ||||
| typedef struct hcl_obj_oop_t       hcl_obj_oop_t; | ||||
| @ -219,9 +223,9 @@ typedef struct hcl_obj_word_t*     hcl_oop_word_t; | ||||
| #define HCL_OOHW_BITS (HCL_SIZEOF_OOHW_T * 8) | ||||
|  | ||||
|  | ||||
| /* ========================================================================= */ | ||||
| /* BIGINT TYPES AND MACROS                                                   */ | ||||
| /* ========================================================================= */ | ||||
| /* ========================================================================= | ||||
|  * BIGINT TYPES AND MACROS | ||||
|  * ========================================================================= */ | ||||
| #if (HCL_SIZEOF_UINTMAX_T > HCL_SIZEOF_OOW_T) | ||||
| #	define HCL_USE_FULL_WORD | ||||
| #endif | ||||
| @ -254,102 +258,9 @@ typedef struct hcl_obj_word_t*     hcl_oop_word_t; | ||||
|  | ||||
| #endif | ||||
|  | ||||
|  | ||||
| /*  | ||||
|  * OOP encoding | ||||
|  * An object pointer(OOP) is an ordinary pointer value to an object. | ||||
|  * but some simple numeric values are also encoded into OOP using a simple | ||||
|  * bit-shifting and masking. | ||||
|  * | ||||
|  * A real OOP is stored without any bit-shifting while a non-pointer value encoded | ||||
|  * in an OOP is bit-shifted to the left by 2 and the 2 least-significant bits | ||||
|  * are set to 1 or 2. | ||||
|  *  | ||||
|  * This scheme works because the object allocators aligns the object size to | ||||
|  * a multiple of sizeof(hcl_oop_t). This way, the 2 least-significant bits | ||||
|  * of a real OOP are always 0s. | ||||
|  * | ||||
|  * With 2 bits, i can encode only 3 special types except object pointers.  | ||||
|  * Since I need more than 3 special types, I extend the tag bits up to 4 bits | ||||
|  * to represent a special data type that doesn't require a range as wide | ||||
|  * as a small integer. A unicode character, for instance, only requires 21  | ||||
|  * bits at most. An error doesn't need to be as diverse as a small integer. | ||||
|  */ | ||||
|  | ||||
| #define HCL_OOP_TAG_BITS_LO     2 | ||||
| #define HCL_OOP_TAG_BITS_HI     2 | ||||
|  | ||||
| #define HCL_OOP_TAG_SMOOI       1    /* 01 */ | ||||
| #define HCL_OOP_TAG_SMPTR       2    /* 10 */ | ||||
| #define HCL_OOP_TAG_EXTENDED    3    /* 11 - internal use only */ | ||||
| #define HCL_OOP_TAG_CHAR        3    /* 0011 */ | ||||
| #define HCL_OOP_TAG_ERROR       7    /* 0111 */ | ||||
| #define HCL_OOP_TAG_RESERVED0   11   /* 1011 */ | ||||
| #define HCL_OOP_TAG_RESERVED1   15   /* 1111 */ | ||||
|  | ||||
| #define HCL_OOP_GET_TAG_LO(oop) (((hcl_oow_t)oop) & HCL_LBMASK(hcl_oow_t, HCL_OOP_TAG_BITS_LO)) | ||||
| #define HCL_OOP_GET_TAG_LOHI(oop) (((hcl_oow_t)oop) & HCL_LBMASK(hcl_oow_t, HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_HI)) | ||||
| #define HCL_OOP_GET_TAG(oop) (HCL_OOP_GET_TAG_LO(oop) == HCL_OOP_TAG_EXTENDED? HCL_OOP_GET_TAG_LOHI(oop): HCL_OOP_GET_TAG_LO(oop)) | ||||
|  | ||||
| #define HCL_OOP_IS_NUMERIC(oop) (HCL_OOP_GET_TAG_LO(oop) != 0) | ||||
| #define HCL_OOP_IS_POINTER(oop) (HCL_OOP_GET_TAG_LO(oop) == 0) | ||||
|  | ||||
| #define HCL_OOP_IS_SMOOI(oop) (HCL_OOP_GET_TAG_LO(oop) == HCL_OOP_TAG_SMOOI) | ||||
| #define HCL_OOP_IS_SMPTR(oop) (HCL_OOP_GET_TAG_LO(oop) == HCL_OOP_TAG_SMPTR) | ||||
|  | ||||
| #define HCL_SMOOI_TO_OOP(num) ((hcl_oop_t)((((hcl_oow_t)(hcl_ooi_t)(num)) << HCL_OOP_TAG_BITS_LO) | HCL_OOP_TAG_SMOOI)) | ||||
| #define HCL_OOP_TO_SMOOI(oop) (((hcl_ooi_t)oop) >> HCL_OOP_TAG_BITS_LO) | ||||
| /* | ||||
| #define HCL_SMPTR_TO_OOP(ptr) ((hcl_oop_t)((((hcl_oow_t)(ptr)) << HCL_OOP_TAG_BITS_LO) | HCL_OOP_TAG_SMPTR)) | ||||
| #define HCL_OOP_TO_SMPTR(oop) (((hcl_ooi_t)oop) >> HCL_OOP_TAG_BITS_LO) | ||||
| */ | ||||
| #define HCL_SMPTR_TO_OOP(ptr) ((hcl_oop_t)(((hcl_oow_t)ptr) | HCL_OOP_TAG_SMPTR)) | ||||
| #define HCL_OOP_TO_SMPTR(oop) ((void*)(((hcl_oow_t)oop) & ~HCL_LBMASK(hcl_oow_t, HCL_OOP_TAG_BITS_LO))) | ||||
|  | ||||
| #define HCL_OOP_IS_CHAR(oop) (HCL_OOP_GET_TAG(oop) == HCL_OOP_TAG_CHAR) | ||||
| #define HCL_OOP_IS_ERROR(oop) (HCL_OOP_GET_TAG(oop) == HCL_OOP_TAG_ERROR) | ||||
|  | ||||
| #define HCL_OOP_TO_CHAR(oop) (((hcl_oow_t)oop) >> (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_LO)) | ||||
| #define HCL_CHAR_TO_OOP(num) ((hcl_oop_t)((((hcl_oow_t)(num)) << (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_LO)) | HCL_OOP_TAG_CHAR)) | ||||
| #define HCL_OOP_TO_ERROR(oop) (((hcl_oow_t)oop) >> (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_LO)) | ||||
| #define HCL_ERROR_TO_OOP(num) ((hcl_oop_t)((((hcl_oow_t)(num)) << (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_LO)) | HCL_OOP_TAG_ERROR)) | ||||
|  | ||||
| /* SMOOI takes up 62 bit on a 64-bit architecture and 30 bits  | ||||
|  * on a 32-bit architecture. The absolute value takes up 61 bits and 29 bits | ||||
|  * respectively for the 1 sign bit. */ | ||||
| #define HCL_SMOOI_BITS (HCL_OOI_BITS - HCL_OOP_TAG_BITS_LO) | ||||
| #define HCL_SMOOI_ABS_BITS (HCL_SMOOI_BITS - 1) | ||||
| #define HCL_SMOOI_MAX ((hcl_ooi_t)(~((hcl_oow_t)0) >> (HCL_OOP_TAG_BITS_LO + 1))) | ||||
| /* Sacrificing 1 bit pattern for a negative SMOOI makes  | ||||
|  * implementation a lot eaisier in many respect. */ | ||||
| /*#define HCL_SMOOI_MIN (-HCL_SMOOI_MAX - 1)*/ | ||||
| #define HCL_SMOOI_MIN (-HCL_SMOOI_MAX) | ||||
| #define HCL_IN_SMOOI_RANGE(ooi)  ((ooi) >= HCL_SMOOI_MIN && (ooi) <= HCL_SMOOI_MAX) | ||||
|  | ||||
|  | ||||
| /* SMPTR is a special value which has been devised to encode an address value | ||||
|  * whose low HCL_OOP_TAG_BITS_LO bits are 0. its class is SmallPointer. A pointer | ||||
|  * returned by most of system functions would be aligned to the pointer size.  | ||||
|  * you can use the followings macros when converting such a pointer without loss. */ | ||||
| #define HCL_IN_SMPTR_RANGE(ptr) ((((hcl_oow_t)ptr) & HCL_LBMASK(hcl_oow_t, HCL_OOP_TAG_BITS_LO)) == 0) | ||||
|  | ||||
| #define HCL_CHAR_BITS (HCL_OOI_BITS - HCL_OOP_TAG_BITS_LO - HCL_OOP_TAG_BITS_HI) | ||||
| #define HCL_CHAR_MIN 0 | ||||
| #define HCL_CHAR_MAX (~((hcl_oow_t)0) >> (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_HI)) | ||||
|  | ||||
| #define HCL_ERROR_BITS (HCL_OOI_BITS - HCL_OOP_TAG_BITS_LO - HCL_OOP_TAG_BITS_HI) | ||||
| #define HCL_ERROR_MIN 0 | ||||
| #define HCL_ERROR_MAX (~((hcl_oow_t)0) >> (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_HI)) | ||||
|  | ||||
| /* TODO: There are untested code where smint is converted to hcl_oow_t. | ||||
|  *       for example, the spec making macro treats the number as hcl_oow_t instead of hcl_ooi_t. | ||||
|  *       as of this writing, i skip testing that part with the spec value exceeding HCL_SMOOI_MAX. | ||||
|  *       later, please verify it works, probably by limiting the value ranges in such macros | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * Object structure | ||||
|  */ | ||||
| /* ========================================================================= | ||||
|  * OBJECT STRUCTURE | ||||
|  * ========================================================================= */ | ||||
| enum hcl_obj_type_t | ||||
| { | ||||
| 	HCL_OBJ_TYPE_OOP, | ||||
| @ -706,6 +617,10 @@ struct hcl_process_scheduler_t | ||||
| #define HCL_ISTYPEOF(hcl,oop,type) \ | ||||
| 	(!HCL_OOP_IS_NUMERIC(oop) && HCL_OBJ_GET_FLAGS_TYPE(oop) == (type)) | ||||
|  | ||||
| /* ========================================================================= | ||||
|  * HEAP | ||||
|  * ========================================================================= */ | ||||
|  | ||||
| typedef struct hcl_heap_t hcl_heap_t; | ||||
|  | ||||
| struct hcl_heap_t | ||||
| @ -716,7 +631,7 @@ struct hcl_heap_t | ||||
| }; | ||||
|  | ||||
| /* ========================================================================= | ||||
|  * HCL VM LOGGING | ||||
|  * VM LOGGING | ||||
|  * ========================================================================= */ | ||||
|  | ||||
| enum hcl_log_mask_t | ||||
|  | ||||
| @ -477,15 +477,15 @@ int hcl_hashobj (hcl_t* hcl, hcl_oop_t obj, hcl_oow_t* xhv) | ||||
| 					break; | ||||
|  | ||||
| 				case HCL_OBJ_TYPE_CHAR: | ||||
| 					hv = hcl_hashoochars (((hcl_oop_char_t)obj)->slot, HCL_OBJ_GET_SIZE(obj)); | ||||
| 					hv = hcl_hash_oochars (((hcl_oop_char_t)obj)->slot, HCL_OBJ_GET_SIZE(obj)); | ||||
| 					break; | ||||
|  | ||||
| 				case HCL_OBJ_TYPE_HALFWORD: | ||||
| 					hv = hcl_hashhalfwords(((hcl_oop_halfword_t)obj)->slot, HCL_OBJ_GET_SIZE(obj)); | ||||
| 					hv = hcl_hash_halfwords(((hcl_oop_halfword_t)obj)->slot, HCL_OBJ_GET_SIZE(obj)); | ||||
| 					break; | ||||
|  | ||||
| 				case HCL_OBJ_TYPE_WORD: | ||||
| 					hv = hcl_hashwords(((hcl_oop_word_t)obj)->slot, HCL_OBJ_GET_SIZE(obj)); | ||||
| 					hv = hcl_hash_words(((hcl_oop_word_t)obj)->slot, HCL_OBJ_GET_SIZE(obj)); | ||||
| 					break; | ||||
|  | ||||
| 				default: | ||||
|  | ||||
| @ -73,7 +73,7 @@ static hcl_oop_oop_t expand_bucket (hcl_t* hcl, hcl_oop_oop_t oldbuc) | ||||
| 			HCL_ASSERT (hcl, HCL_IS_SYMBOL(hcl, symbol)); | ||||
| 			/*HCL_ASSERT (hcl, sym->size > 0);*/ | ||||
|  | ||||
| 			index = hcl_hashoochars(symbol->slot, HCL_OBJ_GET_SIZE(symbol)) % newsz; | ||||
| 			index = hcl_hash_oochars(symbol->slot, HCL_OBJ_GET_SIZE(symbol)) % newsz; | ||||
| 			while (newbuc->slot[index] != hcl->_nil) index = (index + 1) % newsz; | ||||
| 			newbuc->slot[index] = (hcl_oop_t)symbol; | ||||
| 		} | ||||
| @ -97,7 +97,7 @@ static hcl_oop_t find_or_make_symbol (hcl_t* hcl, const hcl_ooch_t* ptr, hcl_oow | ||||
| 	} | ||||
|  | ||||
| 	HCL_ASSERT (hcl, HCL_IS_ARRAY(hcl, hcl->symtab->bucket)); | ||||
| 	index = hcl_hashoochars(ptr, len) % HCL_OBJ_GET_SIZE(hcl->symtab->bucket); | ||||
| 	index = hcl_hash_oochars(ptr, len) % HCL_OBJ_GET_SIZE(hcl->symtab->bucket); | ||||
|  | ||||
| 	/* find a matching symbol in the open-addressed symbol table */ | ||||
| 	while (hcl->symtab->bucket->slot[index] != hcl->_nil)  | ||||
| @ -153,7 +153,7 @@ static hcl_oop_t find_or_make_symbol (hcl_t* hcl, const hcl_ooch_t* ptr, hcl_oow | ||||
| 		hcl->symtab->bucket = bucket; | ||||
|  | ||||
| 		/* recalculate the index for the expanded bucket */ | ||||
| 		index = hcl_hashoochars(ptr, len) % HCL_OBJ_GET_SIZE(hcl->symtab->bucket); | ||||
| 		index = hcl_hash_oochars(ptr, len) % HCL_OBJ_GET_SIZE(hcl->symtab->bucket); | ||||
|  | ||||
| 		while (hcl->symtab->bucket->slot[index] != hcl->_nil)  | ||||
| 			index = (index + 1) % HCL_OBJ_GET_SIZE(hcl->symtab->bucket); | ||||
|  | ||||
| @ -35,48 +35,13 @@ | ||||
|  *  utobcstr -> ucstr to bcstr | ||||
|  */ | ||||
|  | ||||
| #if HCL_SIZEOF_OOW_T == 4 | ||||
| #	define FNV_MAGIC_INIT (0x811c9dc5) | ||||
| #	define FNV_MAGIC_PRIME (0x01000193) | ||||
| #elif HCL_SIZEOF_OOW_T == 8 | ||||
| #	define FNV_MAGIC_INIT (0xCBF29CE484222325) | ||||
| #	define FNV_MAGIC_PRIME (0x100000001B3) | ||||
| #elif HCL_SIZEOF_OOW_T == 16 | ||||
| #	define FNV_MAGIC_INIT (0x6C62272E07BB014262B821756295C58D) | ||||
| #	define FNV_MAGIC_PRIME (0x1000000000000000000013B) | ||||
| #endif | ||||
|  | ||||
| hcl_oow_t hcl_hash_bytes (const hcl_oob_t* ptr, hcl_oow_t len) | ||||
| hcl_oow_t hcl_hash_bytes_ (const hcl_oob_t* ptr, hcl_oow_t len) | ||||
| { | ||||
| 	hcl_oow_t h; | ||||
| 	const hcl_uint8_t* bp, * be; | ||||
|  | ||||
| 	bp = ptr; be = bp + len; | ||||
|  | ||||
| 	/* this hash doesn't produce good distribution */ | ||||
| 	/*  | ||||
| 	h = 0 | ||||
| 	while (bp < be) h = h * 31 + *bp++; | ||||
| 	*/ | ||||
|  | ||||
| #if defined(FNV_MAGIC_INIT) | ||||
| 	/* FNV-1 hash */ | ||||
| 	h = FNV_MAGIC_INIT; | ||||
| 	while (bp < be) | ||||
| 	{ | ||||
| 		h ^= (hcl_oow_t)(*bp++); | ||||
| 		h *= FNV_MAGIC_PRIME; | ||||
| 	} | ||||
| #else | ||||
| 	/* SDBM hash is known to produce good overall distribution | ||||
| 	 * for many different data sets */ | ||||
| 	h = 0; | ||||
| 	while (bp < be) h = (h << 6) + (h << 16) - h + *bp++; | ||||
| #endif | ||||
|  | ||||
| 	hcl_oow_t hv; | ||||
| 	HCL_HASH_BYTES (hv, ptr, len); | ||||
| 	/* constrain the hash value to be representable in a small integer | ||||
| 	 * for convenience sake */ | ||||
| 	return h % ((hcl_oow_t)HCL_SMOOI_MAX + 1); | ||||
| 	return hv % ((hcl_oow_t)HCL_SMOOI_MAX + 1); | ||||
| } | ||||
|  | ||||
| int hcl_equal_uchars (const hcl_uch_t* str1, const hcl_uch_t* str2, hcl_oow_t len) | ||||
|  | ||||
		Reference in New Issue
	
	Block a user