Juan Lang : inetmib1: Sort the tables keyed by IP address, and use bsearch to find entries in them.

Alexandre Julliard julliard at winehq.org
Wed Jun 25 16:44:45 CDT 2008


Module: wine
Branch: master
Commit: 9e919b8ae9d739a0a36e54ad2ad5b17b83bc01f9
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=9e919b8ae9d739a0a36e54ad2ad5b17b83bc01f9

Author: Juan Lang <juan.lang at gmail.com>
Date:   Wed Jun 25 09:42:16 2008 -0700

inetmib1: Sort the tables keyed by IP address, and use bsearch to find entries in them.

---

 dlls/inetmib1/main.c |   95 +++++++++++++++++++++++++++++++++++---------------
 1 files changed, 67 insertions(+), 28 deletions(-)

diff --git a/dlls/inetmib1/main.c b/dlls/inetmib1/main.c
index d514653..20fc0b9 100644
--- a/dlls/inetmib1/main.c
+++ b/dlls/inetmib1/main.c
@@ -19,6 +19,7 @@
 #include "config.h"
 #include <assert.h>
 #include <stdarg.h>
+#include <stdlib.h>
 #include <limits.h>
 #include "windef.h"
 #include "winbase.h"
@@ -317,26 +318,35 @@ struct GenericTable
     BYTE  entries[1];
 };
 
-/* Finds the index in table whose IP address (at offset addressOffset within the
- * entry) matches that given the OID, which is assumed to have at least 4 IDs.
- */
-static UINT findOIDIPAddressInTable(AsnObjectIdentifier *oid,
-    struct GenericTable *table, size_t tableEntrySize, size_t addressOffset)
+static DWORD oidToIpAddr(AsnObjectIdentifier *oid)
 {
-    DWORD addr;
-    UINT i, index = 0;
-
+    assert(oid && oid->idLength >= 4);
     /* Map the IDs to an IP address in little-endian order */
-    addr = (BYTE)oid->ids[3] << 24 | (BYTE)oid->ids[2] << 16 |
+    return (BYTE)oid->ids[3] << 24 | (BYTE)oid->ids[2] << 16 |
         (BYTE)oid->ids[1] << 8 | (BYTE)oid->ids[0];
-    /* Find the item whose address matches */
-    for (i = 0; !index && i < table->numEntries; i++)
-    {
-        DWORD tableAddr =
-            *(DWORD *)(table->entries + i * tableEntrySize + addressOffset);
+}
+
+typedef void (*oidToKeyFunc)(AsnObjectIdentifier *oid, void *dst);
+typedef int (*compareFunc)(const void *key, const void *value);
+
+static UINT findValueInTable(AsnObjectIdentifier *oid,
+    struct GenericTable *table, size_t tableEntrySize, oidToKeyFunc makeKey,
+    compareFunc compare)
+{
+    UINT index = 0;
+    void *key = HeapAlloc(GetProcessHeap(), 0, tableEntrySize);
 
-        if (addr == tableAddr)
-            index = i + 1;
+    if (key)
+    {
+        void *value;
+
+        makeKey(oid, key);
+        value = bsearch(key, table->entries, table->numEntries, tableEntrySize,
+            compare);
+        if (value)
+            index = ((BYTE *)value - (BYTE *)table->entries) / tableEntrySize
+                + 1;
+        HeapFree(GetProcessHeap(), 0, key);
     }
     return index;
 }
@@ -352,7 +362,8 @@ static UINT findOIDIPAddressInTable(AsnObjectIdentifier *oid,
  */
 static AsnInteger32 getItemAndIpAddressInstanceFromOid(AsnObjectIdentifier *oid,
     AsnObjectIdentifier *base, BYTE bPduType, struct GenericTable *table,
-    size_t tableEntrySize, size_t addressOffset, UINT *item, UINT *instance)
+    size_t tableEntrySize, oidToKeyFunc makeKey, compareFunc compare,
+    UINT *item, UINT *instance)
 {
     AsnInteger32 ret = SNMP_ERRORSTATUS_NOERROR;
 
@@ -398,8 +409,8 @@ static AsnInteger32 getItemAndIpAddressInstanceFromOid(AsnObjectIdentifier *oid,
                 AsnObjectIdentifier ipOid = { 4, oid->ids + base->idLength + 1
                     };
 
-                *instance = findOIDIPAddressInTable(&ipOid, table,
-                    tableEntrySize, addressOffset) + 1;
+                *instance = findValueInTable(&ipOid, table, tableEntrySize,
+                    makeKey, compare) + 1;
                 if (*instance > table->numEntries)
                     ret = SNMP_ERRORSTATUS_NOSUCHNAME;
             }
@@ -419,8 +430,8 @@ static AsnInteger32 getItemAndIpAddressInstanceFromOid(AsnObjectIdentifier *oid,
                 AsnObjectIdentifier ipOid = { 4, oid->ids + base->idLength + 1
                     };
 
-                *instance = findOIDIPAddressInTable(&ipOid, table,
-                    tableEntrySize, addressOffset);
+                *instance = findValueInTable(&ipOid, table, tableEntrySize,
+                    makeKey, compare);
                 if (!*instance)
                     ret = SNMP_ERRORSTATUS_NOSUCHNAME;
             }
@@ -632,16 +643,30 @@ static struct structToAsnValue mib2IpAddrMap[] = {
 
 static void mib2IpAddrInit(void)
 {
-    DWORD size = 0, ret = GetIpAddrTable(NULL, &size, FALSE);
+    DWORD size = 0, ret = GetIpAddrTable(NULL, &size, TRUE);
 
     if (ret == ERROR_INSUFFICIENT_BUFFER)
     {
         ipAddrTable = HeapAlloc(GetProcessHeap(), 0, size);
         if (ipAddrTable)
-            GetIpAddrTable(ipAddrTable, &size, FALSE);
+            GetIpAddrTable(ipAddrTable, &size, TRUE);
     }
 }
 
+static void oidToIpAddrRow(AsnObjectIdentifier *oid, void *dst)
+{
+    MIB_IPADDRROW *row = dst;
+
+    row->dwAddr = oidToIpAddr(oid);
+}
+
+static int compareIpAddrRow(const void *a, const void *b)
+{
+    const MIB_IPADDRROW *key = a, *value = b;
+
+    return key->dwAddr - value->dwAddr;
+}
+
 static BOOL mib2IpAddrQuery(BYTE bPduType, SnmpVarBind *pVarBind,
     AsnInteger32 *pErrorStatus)
 {
@@ -657,7 +682,7 @@ static BOOL mib2IpAddrQuery(BYTE bPduType, SnmpVarBind *pVarBind,
     case SNMP_PDU_GETNEXT:
         *pErrorStatus = getItemAndIpAddressInstanceFromOid(&pVarBind->name,
             &myOid, bPduType, (struct GenericTable *)ipAddrTable,
-            sizeof(MIB_IPADDRROW), FIELD_OFFSET(MIB_IPADDRROW, dwAddr), &item,
+            sizeof(MIB_IPADDRROW), oidToIpAddrRow, compareIpAddrRow, &item,
             &tableIndex);
         if (!*pErrorStatus)
         {
@@ -701,16 +726,30 @@ static struct structToAsnValue mib2IpRouteMap[] = {
 
 static void mib2IpRouteInit(void)
 {
-    DWORD size = 0, ret = GetIpForwardTable(NULL, &size, FALSE);
+    DWORD size = 0, ret = GetIpForwardTable(NULL, &size, TRUE);
 
     if (ret == ERROR_INSUFFICIENT_BUFFER)
     {
         ipRouteTable = HeapAlloc(GetProcessHeap(), 0, size);
         if (ipRouteTable)
-            GetIpForwardTable(ipRouteTable, &size, FALSE);
+            GetIpForwardTable(ipRouteTable, &size, TRUE);
     }
 }
 
+static void oidToIpForwardRow(AsnObjectIdentifier *oid, void *dst)
+{
+    MIB_IPFORWARDROW *row = dst;
+
+    row->dwForwardDest = oidToIpAddr(oid);
+}
+
+static int compareIpForwardRow(const void *a, const void *b)
+{
+    const MIB_IPFORWARDROW *key = a, *value = b;
+
+    return key->dwForwardDest - value->dwForwardDest;
+}
+
 static BOOL mib2IpRouteQuery(BYTE bPduType, SnmpVarBind *pVarBind,
     AsnInteger32 *pErrorStatus)
 {
@@ -726,8 +765,8 @@ static BOOL mib2IpRouteQuery(BYTE bPduType, SnmpVarBind *pVarBind,
     case SNMP_PDU_GETNEXT:
         *pErrorStatus = getItemAndIpAddressInstanceFromOid(&pVarBind->name,
             &myOid, bPduType, (struct GenericTable *)ipRouteTable,
-            sizeof(MIB_IPFORWARDROW),
-            FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardDest), &item, &tableIndex);
+            sizeof(MIB_IPFORWARDROW), oidToIpForwardRow, compareIpForwardRow,
+            &item, &tableIndex);
         if (!*pErrorStatus)
         {
             assert(tableIndex);




More information about the wine-cvs mailing list