[Groonga-commit] groonga/groonga [master] Reimplement match_key().

Back to archive index

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)




Groonga-commit メーリングリストの案内
Back to archive index