Quellcode durchsuchen

libdpkg: Move the FNV hash function into a new strhash module

This will allow using the hash function in other parts of the code.
The additional changes are:

 - Fix an incorrect value in a comment.
 - Uppercase preprocessor macros.
 - Add unit tests.
Guillem Jover vor 11 Jahren
Ursprung
Commit
c342c6d0bb
7 geänderte Dateien mit 84 neuen und 21 gelöschten Zeilen
  1. 1 0
      debian/changelog
  2. 1 0
      lib/dpkg/Makefile.am
  3. 1 0
      lib/dpkg/libdpkg.map
  4. 3 20
      lib/dpkg/pkg-db.c
  5. 50 0
      lib/dpkg/strhash.c
  6. 2 0
      lib/dpkg/string.h
  7. 26 1
      lib/dpkg/test/t-string.c

+ 1 - 0
debian/changelog

@@ -103,6 +103,7 @@ dpkg (1.17.14) UNRELEASED; urgency=low
   * Say arch-wildcard instead of arch-alias in dpkg-architecture --help output.
   * Test suite:
     - Do not leave temporary files behind on failure or when interrupted.
+    - Add basic unit tests for the FNV hashing function.
   * Add --build and --extract command aliases to dpkg-source.
   * Print file or package names instead of pointers in dpkg debug output,
     to make it more meaningful and reproducible.

+ 1 - 0
lib/dpkg/Makefile.am

@@ -84,6 +84,7 @@ libdpkg_la_SOURCES = \
 	progress.c \
 	report.c \
 	string.c \
+	strhash.c \
 	strwide.c \
 	subproc.c \
 	tarfn.c \

+ 1 - 0
lib/dpkg/libdpkg.map

@@ -73,6 +73,7 @@ LIBDPKG_PRIVATE {
 	cisdigit;
 
 	str_match_end;
+	str_fnv_hash;
 	str_escape_fmt;
 	str_strip_quotes;
 	str_quote_meta;

+ 3 - 20
lib/dpkg/pkg-db.c

@@ -32,35 +32,18 @@
 #include <dpkg/i18n.h>
 #include <dpkg/dpkg.h>
 #include <dpkg/dpkg-db.h>
+#include <dpkg/string.h>
 #include <dpkg/arch.h>
 
 /* This must always be a prime for optimal performance.
  * With 4093 buckets, we glean a 20% speedup, for 8191 buckets
  * we get 23%. The nominal increase in memory usage is a mere
- * sizeof(void *) * 8063 (i.e. less than 32 KiB on 32bit systems). */
+ * sizeof(void *) * 8191 (i.e. less than 32 KiB on 32bit systems). */
 #define BINS 8191
 
 static struct pkgset *bins[BINS];
 static int npkg, nset;
 
-#define FNV_offset_basis 2166136261ul
-#define FNV_mixing_prime 16777619ul
-
-/**
- * Fowler/Noll/Vo -- simple string hash.
- *
- * For more info, see <http://www.isthe.com/chongo/tech/comp/fnv/index.html>.
- */
-static unsigned int hash(const char *name) {
-  register unsigned int h = FNV_offset_basis;
-  register unsigned int p = FNV_mixing_prime;
-  while( *name ) {
-    h *= p;
-    h ^= *name++;
-  }
-  return h;
-}
-
 /**
  * Return the package set with the given name.
  *
@@ -86,7 +69,7 @@ pkg_db_find_set(const char *inname)
   p= name;
   while(*p) { *p= tolower(*p); p++; }
 
-  setp = bins + (hash(name) % (BINS));
+  setp = bins + (str_fnv_hash(name) % (BINS));
   while (*setp && strcasecmp((*setp)->name, name))
     setp = &(*setp)->next;
   if (*setp) {

+ 50 - 0
lib/dpkg/strhash.c

@@ -0,0 +1,50 @@
+/*
+ * libdpkg - Debian packaging suite library routines
+ * strhash.c - FNV string hashing support
+ *
+ * Copyright © 2003 Daniel Silverstone <dsilvers@digital-scurf.org>
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <compat.h>
+
+#include <dpkg/string.h>
+
+#define FNV_OFFSET_BASIS 2166136261UL
+#define FNV_MIXING_PRIME 16777619UL
+
+/**
+ * Fowler/Noll/Vo -- FNV-1 simple string hash.
+ *
+ * For more info, @see <http://www.isthe.com/chongo/tech/comp/fnv/index.html>.
+ *
+ * @param str The string to hash.
+ *
+ * @return The hashed value.
+ */
+unsigned int
+str_fnv_hash(const char *str)
+{
+	register unsigned int h = FNV_OFFSET_BASIS;
+	register unsigned int p = FNV_MIXING_PRIME;
+
+	while (*str) {
+		h *= p;
+		h ^= *str++;
+	}
+
+	return h;
+}

+ 2 - 0
lib/dpkg/string.h

@@ -54,6 +54,8 @@ str_is_set(const char *str)
 
 bool str_match_end(const char *str, const char *end);
 
+unsigned int str_fnv_hash(const char *str);
+
 char *str_escape_fmt(char *dest, const char *src, size_t n);
 char *str_quote_meta(const char *src);
 char *str_strip_quotes(char *str);

+ 26 - 1
lib/dpkg/test/t-string.c

@@ -27,6 +27,8 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <stdio.h>
+
 static void
 test_str_is_set(void)
 {
@@ -52,6 +54,28 @@ test_str_match_end(void)
 	test_fail(str_match_end("foo bar quux", "foo"));
 }
 
+static void
+test_str_fnv_hash(void)
+{
+	test_pass(str_fnv_hash("") == 0x811c9dc5UL);
+	test_pass(str_fnv_hash("a") == 0x050c5d7eUL);
+	test_pass(str_fnv_hash("b") == 0x050c5d7dUL);
+	test_pass(str_fnv_hash("c") == 0x050c5d7cUL);
+	test_pass(str_fnv_hash("d") == 0x050c5d7bUL);
+	test_pass(str_fnv_hash("e") == 0x050c5d7aUL);
+	test_pass(str_fnv_hash("f") == 0x050c5d79UL);
+	test_pass(str_fnv_hash("fo") == 0x6b772514UL);
+	test_pass(str_fnv_hash("foo") == 0x408f5e13UL);
+	test_pass(str_fnv_hash("foob") == 0xb4b1178bUL);
+	test_pass(str_fnv_hash("fooba") == 0xfdc80fb0UL);
+	test_pass(str_fnv_hash("foobar") == 0x31f0b262UL);
+
+	test_pass(str_fnv_hash("test-string") == 0x4a5b5149UL);
+	test_pass(str_fnv_hash("Test-string") == 0xdef8cb29UL);
+	test_pass(str_fnv_hash("rest-string") == 0x7808f697UL);
+	test_pass(str_fnv_hash("Rest-string") == 0xf15be3f7UL);
+}
+
 static void
 test_str_escape_fmt(void)
 {
@@ -160,10 +184,11 @@ test_str_strip_quotes(void)
 static void
 test(void)
 {
-	test_plan(32);
+	test_plan(48);
 
 	test_str_is_set();
 	test_str_match_end();
+	test_str_fnv_hash();
 	test_str_escape_fmt();
 	test_str_quote_meta();
 	test_str_strip_quotes();