diff options
Diffstat (limited to 'src/LYHash.c')
-rw-r--r-- | src/LYHash.c | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/src/LYHash.c b/src/LYHash.c new file mode 100644 index 0000000..f419c7e --- /dev/null +++ b/src/LYHash.c @@ -0,0 +1,144 @@ +/* + * $LynxId: LYHash.c,v 1.39 2018/03/29 00:38:59 tom Exp $ + * + * A hash table for the (fake) CSS support in Lynx-rp + * (c) 1996 Rob Partington + * rewritten 1997 by Klaus Weide. + * rewritten 2018 -TD + */ +#include <LYHash.h> +#include <LYUtils.h> +#include <LYLeaks.h> +#include <LYStrings.h> +#include <LYGlobalDefs.h> + +#ifdef USE_COLOR_STYLE + +#undef HASH_TYPE + +#define HASH_SIZE CSHASHSIZE +#define HASH_TYPE int +#define HASH_OF(h, v) ((HASH_TYPE)((h) * 3 + UCH(v)) % HASH_SIZE) + +static int count_bump; +static size_t limit; +static char *buffer; + +static char *get_buffer(size_t need) +{ + if (++need > limit) { + char *test = realloc(buffer, (limit = (1 + need) * 2)); + + if (test == 0) + outofmem(__FILE__, "LYHash"); + buffer = test; + } + return buffer; +} + +/* + * This is the same algorithm as the private anchor_hash() in HTAnchor.c, but + * with a different value for HASH_SIZE. + */ +static HASH_TYPE cs_hash(const char *string) +{ + HASH_TYPE hash = 0; + HASH_TYPE best, n; + bucket *data; + const char *p; + + for (p = string; *p; p++) + hash = HASH_OF(hash, *p); + + /* + * The computed hash-code is only a starting point. Check for collision. + */ + best = hash; + for (n = 0; n < HASH_SIZE; n++) { + int nn = (n + hash) % HASH_SIZE; + + data = &hashStyles[nn]; + if (data->name == 0 || !strcmp(string, data->name)) { + best = nn; + hash = nn; + break; + } + ++count_bump; + } + data = &hashStyles[best]; + if (data->name != 0) { + if (strcmp(string, data->name)) { + CTRACE_STYLE((tfp, "cs_hash(%s) overwriting %d\n", string, data->name)); + FREE(data->name); + StrAllocCopy(data->name, string); + } + } else { + StrAllocCopy(data->name, string); + } + + CTRACE_STYLE((tfp, "cs_hash(%s) = %d\n", string, hash)); + return hash; +} + +int color_style_1(const char *string) +{ + int hash; + + if (dump_output_immediately) { + hash = 0; + } else { + get_buffer(strlen(string)); + strcpy(buffer, string); + LYLowerCase(buffer); + hash = cs_hash(buffer); + } + return hash; +} + +int color_style_3(const char *p, const char *q, const char *r) +{ + int hash; + + if (dump_output_immediately) { + hash = 0; + } else { + get_buffer(strlen(p) + strlen(q) + strlen(r)); + strcpy(buffer, p); + strcat(buffer, q); + strcat(buffer, r); + LYLowerCase(buffer); + hash = cs_hash(buffer); + } + return hash; +} + +void report_hashStyles(void) +{ + int i; + int count_name = 0; + int count_used = 0; + + for (i = 0; i < CSHASHSIZE; i++) { + count_name += (hashStyles[i].name != 0); + count_used += (hashStyles[i].used != 0); + } + CTRACE((tfp, "Style hash:\n")); + CTRACE((tfp, "%5d names allocated\n", count_name)); + CTRACE((tfp, "%5d buckets used\n", count_used)); + CTRACE((tfp, "%5d hash collisions\n", count_bump)); +} + +void free_hashStyles(void) +{ + int i; + + for (i = 0; i < CSHASHSIZE; i++) { + FREE(hashStyles[i].name); + hashStyles[i].used = FALSE; + } + FREE(buffer); + limit = 0; + count_bump = 0; +} + +#endif /* USE_COLOR_STYLE */ |