null+****@clear*****
null+****@clear*****
2012年 4月 3日 (火) 18:07:18 JST
Susumu Yata 2012-04-03 18:07:18 +0900 (Tue, 03 Apr 2012) New Revision: 6d37ab9fd45be945e18d455b80b3847a30a974c5 Log: Reimplement match_key(). Modified files: lib/hash.c Modified: lib/hash.c (+57 -10) =================================================================== --- lib/hash.c 2012-04-03 16:46:25 +0900 (39b80b3) +++ lib/hash.c 2012-04-03 18:07:18 +0900 (d628c03) @@ -963,7 +963,20 @@ typedef struct { uint8_t value[1]; } grn_tiny_hash_entry; +/* + * hash_value is valid even if the entry is grn_plain_hash_entry. In this case, + * its hash_value equals its key. + * flag, key_size and key.buf are valid if the entry has a variable length key. + */ +typedef struct { + uint32_t hash_value; + uint16_t flag; + uint16_t key_size; +} grn_hash_entry_header; + typedef union { + uint32_t hash_value; + grn_hash_entry_header header; grn_plain_hash_entry plain_entry; grn_rich_hash_entry rich_entry; grn_io_hash_entry io_entry; @@ -1166,7 +1179,7 @@ grn_hash_entry_put_key(grn_ctx *ctx, grn_hash *hash, memcpy(entry->tiny_entry.key.ptr, key, key_size); entry->tiny_entry.flag = 0; } - entry->io_entry.hash_value = hash_value; + entry->io_entry.hash_value = hash_value; /* FIXME: typo */ entry->tiny_entry.key_size = key_size; } } else { @@ -1180,6 +1193,47 @@ grn_hash_entry_put_key(grn_ctx *ctx, grn_hash *hash, return GRN_SUCCESS; } +/* + * grn_hash_entry_compare_key() returns GRN_TRUE if the entry key equals the + * specified key, or GRN_FALSE otherwise. + */ +inline static grn_bool +grn_hash_entry_compare_key(grn_ctx *ctx, grn_hash *hash, + grn_hash_entry *entry, uint32_t hash_value, + const void *key, unsigned int key_size) +{ + if (hash->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) { + if (entry->hash_value != hash_value || + entry->header.key_size != key_size) { + return GRN_FALSE; + } + if (IO_HASHP(hash)) { + if (entry->io_entry.flag & HASH_IMMEDIATE) { + return !memcmp(key, entry->io_entry.key.buf, key_size); + } else { + const void * const entry_key_ptr = + grn_io_hash_key_at(ctx, hash, entry->io_entry.key.offset); + return !memcmp(key, entry_key_ptr, key_size); + } + } else { + if (entry->tiny_entry.flag & HASH_IMMEDIATE) { + return !memcmp(key, entry->tiny_entry.key.buf, key_size); + } else { + return !memcmp(key, entry->tiny_entry.key.ptr, key_size); + } + } + } else { + if (entry->hash_value != hash_value) { + return GRN_FALSE; + } + if (key_size == sizeof(uint32_t)) { + return GRN_TRUE; + } else { + return !memcmp(key, entry->rich_entry.key_and_value, key_size); + } + } +} + inline static char * get_key(grn_ctx *ctx, grn_hash *hash, entry_str *n) { @@ -1203,15 +1257,8 @@ inline static int match_key(grn_ctx *ctx, grn_hash *hash, entry_str *ee, uint32_t h, const char *key, unsigned int len) { - if (hash->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) { - return (ee->key == h && - ee->size == len && - !memcmp(key, get_key(ctx, hash, ee), len)); - } else { - return (ee->key == h && - ((len == sizeof(uint32_t)) || - !memcmp(key, get_key(ctx, hash, ee), len))); - } + return grn_hash_entry_compare_key(ctx, hash, (grn_hash_entry *)ee, + h, key, len); } #define GARBAGE (0xffffffff)