From 94a537e6ab3069f8d34e12e5ea722250be2b89c8 Mon Sep 17 00:00:00 2001 From: Michael Graff Date: Tue, 25 Apr 2000 19:09:07 +0000 Subject: [PATCH] optimize dns_rdatatype_fromtext() --- lib/dns/gen.c | 108 ++++++++++++++++++++++++++++++++++++------------ lib/dns/rdata.c | 70 +++++++++++++++---------------- 2 files changed, 115 insertions(+), 63 deletions(-) diff --git a/lib/dns/gen.c b/lib/dns/gen.c index 8548c17043..7c735dee37 100644 --- a/lib/dns/gen.c +++ b/lib/dns/gen.c @@ -15,7 +15,7 @@ * SOFTWARE. */ -/* $Id: gen.c,v 1.38 2000/04/19 18:33:09 explorer Exp $ */ +/* $Id: gen.c,v 1.39 2000/04/25 19:09:06 explorer Exp $ */ #include @@ -136,6 +136,7 @@ struct ttnam { char typename[11]; char macroname[11]; char attr[256]; + unsigned int sorted; } typenames[256]; char * upper(char *); @@ -318,6 +319,7 @@ insert_into_typenames(int type, char *typename, char *attr) exit(1); } strcpy(ttn->attr, attr); + ttn->sorted = 0; } void @@ -420,6 +422,19 @@ sd(int rdclass, char *classname, char *dirname, char filetype) { end_directory(&dir); } +static unsigned int +HASH(char *string) +{ + unsigned int n; + unsigned char a, b; + + n = strlen(string); + a = tolower(string[0]); + b = tolower(string[n - 1]); + + return ((a + n) * b) % 256; +} + int main(int argc, char **argv) { char buf[256]; /* XXX Should be max path length */ @@ -428,7 +443,8 @@ main(int argc, char **argv) { char classname[11]; struct tt *tt; struct cc *cc; - struct ttnam *ttn; + struct ttnam *ttn, *ttn2; + unsigned int hash; struct tm *tm; time_t now; char year[11]; @@ -437,7 +453,7 @@ main(int argc, char **argv) { int class_enum = 0; int type_enum = 0; int structs = 0; - int c, i; + int c, i, j; char buf1[11]; char filetype = 'c'; FILE *fd; @@ -517,19 +533,6 @@ main(int argc, char **argv) { fprintf(stdout, copyright, year); if (code) { -#if 0 - dodecl("isc_result_t", "fromtext", FROMTEXTDECL); - dodecl("isc_result_t", "totext", TOTEXTDECL); - dodecl("isc_result_t", "fromwire", FROMWIREDECL); - dodecl("isc_result_t", "towire", TOWIREDECL); - dodecl("int", "compare", COMPAREDECL); - dodecl("isc_result_t", "fromstruct", FROMSTRUCTDECL); - dodecl("isc_result_t", "tostruct", TOSTRUCTDECL); - dodecl("void", "freestruct", FREESTRUCTDECL); - dodecl("isc_result_t", "additionaldata", ADDITIONALDATADECL); - dodecl("isc_result_t", "digest", DIGESTDECL); -#endif - fputs("\n\n", stdout); for (tt = types; tt != NULL ; tt = tt->next) fprintf(stdout, "#include \"%s/%s_%d.c\"\n", @@ -559,16 +562,10 @@ main(int argc, char **argv) { DIGESTARGS, DIGESTTYPE, DIGESTCLASS, DIGESTDEF); - fprintf(stdout, "\n#define TYPENAMES%s\n", - types != NULL ? " \\" : ""); - - lasttype = 0; - for (tt = types; tt != NULL ; tt = tt->next) - if (tt->type != lasttype) - fprintf(stdout, "\t{ %d, \"%s\", 0 },%s\n", - lasttype = tt->type, - upper(tt->typename), - tt->next != NULL ? " \\" : ""); + /* + * From here down, we are processing the rdata names and + * attributes. + */ #define PRINT_COMMA(x) (x == 255 ? "" : ",") @@ -613,6 +610,65 @@ main(int argc, char **argv) { } printf("};\n"); + /* + * Run through the list of types and pre-mark the unused + * ones as "sorted" so we simply ignore them below. + */ + for (i = 0 ; i <= 255 ; i++) { + ttn = &typenames[i]; + if (ttn->typename[0] == 0) + ttn->sorted = 1; + } + + /* + * Spit out a quick and dirty hash function. Here, + * we walk through the list of type names, and calculate + * a hash. This isn't perfect, but it will generate "pretty + * good" estimates. Lowercase the characters before + * computing in all cases. + * + * Here, walk the list from top to bottom, calculating + * the hash (mod 256) for each name. + */ + printf("#define RDATATYPE_FROMTEXT_SW(_hash,_typename,_typep) \\\n"); + printf("\tswitch (_hash) { \\\n"); + for (i = 0 ; i <= 255 ; i++) { + ttn = &typenames[i]; + + /* + * Skip entries we already processed. + */ + if (ttn->sorted != 0) + continue; + + hash = HASH(ttn->typename); + printf("\t\tcase %u: \\\n", hash); + + /* + * Find all other entries that happen to match + * this hash. + */ + for (j = i ; j <= 255 ; j++) { + ttn2 = &typenames[j]; + if (hash == HASH(ttn2->typename)) { + printf("\t\t\tif (strcasecmp(\"%s\", (_typename)) == 0) { \\\n" + "\t\t\t\tif ((typeattr[%u].flags & DNS_RDATATYPEATTR_RESERVED) != 0) \\\n" + "\t\t\t\t\treturn (ISC_R_NOTIMPLEMENTED); \\\n" + "\t\t\t\t*(_typep) = %u; \\\n" + "\t\t\t\treturn (ISC_R_SUCCESS); \\\n" + "\t\t\t} \\\n", + ttn2->typename, j, j); + ttn2->sorted = 1; + } + } + printf("\t\t\tbreak; \\\n"); + } + printf("\t}\n"); + + + /* + * Dump the class names. + */ fputs("\n", stdout); fprintf(stdout, "\n#define CLASSNAMES%s\n", diff --git a/lib/dns/rdata.c b/lib/dns/rdata.c index ddc3cd4995..fe785f563e 100644 --- a/lib/dns/rdata.c +++ b/lib/dns/rdata.c @@ -15,10 +15,11 @@ * SOFTWARE. */ -/* $Id: rdata.c,v 1.77 2000/04/14 20:13:45 explorer Exp $ */ +/* $Id: rdata.c,v 1.78 2000/04/25 19:09:07 explorer Exp $ */ #include +#include #include #include @@ -119,22 +120,6 @@ static const char octdigits[] = "01234567"; #define META 0x0001 #define RESERVED 0x0002 -#define METATYPES \ - { 0, "RESERVED0", META }, \ - { 31, "EID", RESERVED }, \ - { 32, "NIMLOC", RESERVED }, \ - { 34, "ATMA", RESERVED }, \ - { 100, "UINFO", RESERVED }, \ - { 101, "UID", RESERVED }, \ - { 102, "GID", RESERVED }, \ - { 249, "TKEY", META }, \ - { 250, "TSIG", META }, \ - { 251, "IXFR", META }, \ - { 252, "AXFR", META }, \ - { 253, "MAILB", META }, \ - { 254, "MAILA", META }, \ - { 255, "ANY", META }, - /* * Empty classes are those without any types of their own. */ @@ -194,16 +179,19 @@ static const char octdigits[] = "01234567"; { 255, "ALL", 0 }, \ { 0, NULL, 0} -static struct tbl { +struct tbl { unsigned int value; char *name; int flags; -} types[] = { TYPENAMES METATYPES {0, NULL, 0} }, -classes[] = { METACLASSES CLASSNAMES EMPTYCLASSES { 0, NULL, 0} }, -rcodes[] = { RCODENAMES }, -certs[] = { CERTNAMES }, -secalgs[] = { SECALGNAMES }, -secprotos[] = { SECPROTONAMES }; +}; + +static struct tbl classes[] = { + METACLASSES CLASSNAMES EMPTYCLASSES { 0, NULL, 0} +}; +static struct tbl rcodes[] = { RCODENAMES }; +static struct tbl certs[] = { CERTNAMES }; +static struct tbl secalgs[] = { SECALGNAMES }; +static struct tbl secprotos[] = { SECPROTONAMES }; static struct keyflag { char *name; @@ -738,21 +726,29 @@ dns_rdataclass_totext(dns_rdataclass_t rdclass, isc_buffer_t *target) { /* XXXRTH Should we use a hash table here? */ isc_result_t -dns_rdatatype_fromtext(dns_rdatatype_t *typep, isc_textregion_t *source) { - int i = 0; +dns_rdatatype_fromtext(dns_rdatatype_t *typep, isc_textregion_t *source) +{ + unsigned int hash; unsigned int n; + unsigned char a, b; + + n = source->length; + + if (n == 0) + return (DNS_R_UNKNOWN); + + a = tolower(source->base[0]); + b = tolower(source->base[n - 1]); + + hash = ((a + n) * b) % 256; + + /* + * This switch block is inlined via #define, and will use "return" + * to return a result to the caller if it is a valid (known) + * rdatatype name. + */ + RDATATYPE_FROMTEXT_SW(hash, source->base, typep); - while (types[i].name != NULL) { - n = strlen(types[i].name); - if (n == source->length && - strncasecmp(source->base, types[i].name, n) == 0) { - *typep = types[i].value; - if ((types[i].flags & RESERVED) != 0) - return (ISC_R_NOTIMPLEMENTED); - return (ISC_R_SUCCESS); - } - i++; - } return (DNS_R_UNKNOWN); }