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