Jelajahi Sumber

Added Hash.h which uses djb2a hash and implemented it in a few places where Map.h is used

Caleb James DeLisle 8 tahun lalu
induk
melakukan
8173faac81
6 mengubah file dengan 59 tambahan dan 8 penghapusan
  1. 2 5
      admin/Admin.c
  2. 2 2
      net/InterfaceController.c
  3. 30 0
      util/Hash.h
  4. 4 1
      util/Map.h
  5. 11 0
      util/platform/Sockaddr.c
  6. 10 0
      util/platform/Sockaddr.h

+ 2 - 5
admin/Admin.c

@@ -63,16 +63,13 @@ struct MapValue
 #define Map_KEY_TYPE struct Sockaddr*
 #define Map_VALUE_TYPE struct MapValue*
 #include "util/Map.h"
-
 static inline uint32_t Map_LastMessageTimeByAddr_hash(struct Sockaddr** key)
 {
-    uint32_t* k = (uint32_t*) *key;
-    return k[ ((*key)->addrLen / 4)-1 ];
+    return Sockaddr_hash(*key);
 }
-
 static inline int Map_LastMessageTimeByAddr_compare(struct Sockaddr** keyA, struct Sockaddr** keyB)
 {
-    return Bits_memcmp(*keyA, *keyB, (*keyA)->addrLen);
+    return Sockaddr_compare(*keyA, *keyB);
 }
 
 /////// end map

+ 2 - 2
net/InterfaceController.c

@@ -70,11 +70,11 @@
 #include "util/Map.h"
 static inline uint32_t Map_EndpointsBySockaddr_hash(struct Sockaddr** key)
 {
-    return Checksum_engine((uint8_t*) &(key[0][1]), key[0]->addrLen - Sockaddr_OVERHEAD);
+    return Sockaddr_hash(*key);
 }
 static inline int Map_EndpointsBySockaddr_compare(struct Sockaddr** keyA, struct Sockaddr** keyB)
 {
-    return Bits_memcmp((uint8_t*) *keyA, (uint8_t*) *keyB, keyA[0]->addrLen);
+    return Sockaddr_compare(*keyA, *keyB);
 }
 // ---------------- EndMap ----------------
 

+ 30 - 0
util/Hash.h

@@ -0,0 +1,30 @@
+/* vim: set expandtab ts=4 sw=4: */
+/*
+ * You may redistribute this program and/or modify it under the terms of
+ * the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * This program 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 <http://www.gnu.org/licenses/>.
+ */
+#ifndef Hash_H
+#define Hash_H
+
+#include <stdint.h>
+
+/** The DJB2a hash (equivilant to DJB2 but using XOR instead of +) */
+static uint32_t Hash_compute(uint8_t* str, int length)
+{
+    uint32_t hash = 5381;
+    for (int i = 0; i < length; i++) {
+        hash = ((hash << 5) + hash) ^ str[i];
+    }
+    return hash;
+}
+
+#endif

+ 4 - 1
util/Map.h

@@ -18,6 +18,7 @@
 
 #include "util/Bits.h"
 
+
 #if defined(Map_KEY_TYPE)
     Assert_compileTime(!(sizeof(Map_KEY_TYPE) % 4));
     #define Map_ENABLE_KEYS
@@ -40,10 +41,11 @@
     // Hashcode calculator.
     static inline uint32_t Map_FUNCTION(hash)(Map_KEY_TYPE* key);
     #ifndef Map_USE_HASH
+        #include "util/Hash.h"
         // Get the last 4 bytes of the key by default.
         static inline uint32_t Map_FUNCTION(hash)(Map_KEY_TYPE* key)
         {
-            return ((uint32_t*)key)[(sizeof(Map_KEY_TYPE) / 4) - 1];
+            return Hash_compute((uint8_t*)key, sizeof(Map_KEY_TYPE));
         }
     #endif
 
@@ -229,3 +231,4 @@ static inline int Map_FUNCTION(put)(Map_VALUE_TYPE* value,
 #undef Map_ENABLE_HANDLES
 #undef Map_KEY_TYPE
 #undef Map_ENABLE_KEYS
+#undef Map_USE_COMPARATOR

+ 11 - 0
util/platform/Sockaddr.c

@@ -19,6 +19,7 @@
 #include "util/CString.h"
 #include "util/Bits.h"
 #include "util/Hex.h"
+#include "util/Hash.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -309,3 +310,13 @@ struct Sockaddr* Sockaddr_fromName(char* name, struct Allocator* alloc)
     }
     return NULL;
 }
+
+uint32_t Sockaddr_hash(const struct Sockaddr* addr)
+{
+    return Hash_compute((uint8_t*)addr, addr->addrLen);
+}
+
+int Sockaddr_compare(const struct Sockaddr* a, const struct Sockaddr* b)
+{
+    return Bits_memcmp(a, b, a->addrLen);
+}

+ 10 - 0
util/platform/Sockaddr.h

@@ -136,4 +136,14 @@ struct Sockaddr* Sockaddr_clone(const struct Sockaddr* addr, struct Allocator* a
  */
 void Sockaddr_normalizeNative(void* nativeSockaddr);
 
+/**
+ * Get a hash for hashtable lookup.
+ */
+uint32_t Sockaddr_hash(const struct Sockaddr* addr);
+
+/**
+ * Compare two sockaddrs for sorting, comparison does not put them in any specific order.
+ */
+int Sockaddr_compare(const struct Sockaddr* a, const struct Sockaddr* b);
+
 #endif