#include "config.h"
#if HAVE_OHASH
int dummy;
#else
/* $OpenBSD: ohash.c,v 1.1 2014/06/02 18:52:03 deraadt Exp $ */
/* Copyright (c) 1999, 2004 Marc Espie <espie@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include "compat_ohash.h"
struct _ohash_record {
const char *p;
};
#define DELETED ((const char *)h)
/* Don't bother changing the hash table if the change is small enough. */
static void ohash_resize(struct ohash *);
/* This handles the common case of variable length keys, where the
* key is stored at the end of the record.
*/
void *
{
char *p;
if (!*end)
if (p) {
}
return (void *)p;
}
/* hash_delete only frees the hash structure. Use hash_first/hash_next
* to free entries as well. */
void
{
#ifndef NDEBUG
h->t = NULL;
#endif
}
static void
{
struct _ohash_record *n;
unsigned int j;
unsigned int i, incr;
else
else
#ifdef STATS_HASH
#endif
if (!n)
return;
for (j = 0; j < h->size; j++) {
while (n[i].p != NULL) {
i += incr;
if (i >= ns)
i -= ns;
}
n[i].p = h->t[j].p;
}
}
h->t = n;
h->deleted = 0;
}
void *
{
void *result = (void *)h->t[i].p;
return NULL;
#ifdef STATS_HASH
#endif
h->t[i].p = DELETED;
h->deleted++;
ohash_resize(h);
return result;
}
void *
{
if (h->t[i].p == DELETED)
return NULL;
else
return (void *)h->t[i].p;
}
void *
{
#ifdef STATS_HASH
#endif
if (h->t[i].p == DELETED) {
h->deleted--;
h->t[i].p = p;
} else {
h->t[i].p = p;
/* Arbitrary resize boundary. Tweak if not efficient enough. */
ohash_resize(h);
}
return p;
}
unsigned int
{
}
void *
{
*pos = 0;
return ohash_next(h, pos);
}
void *
{
return (void *)h->t[(*pos)++].p;
return NULL;
}
void
{
#ifdef STATS_HASH
STAT_HASH_SIZE += h->size;
#endif
/* Copy info so that caller may free it. */
}
ohash_interval(const char *s, const char **e)
{
uint32_t k;
if (!*e)
*e = s + strlen(s);
if (s == *e)
k = 0;
else
k = *s++;
while (s != *e)
k = ((k << 2) | (k >> 30)) ^ *s++;
return k;
}
unsigned int
{
unsigned int i, incr;
unsigned int empty;
#ifdef STATS_HASH
#endif
while (h->t[i].p != NULL) {
#ifdef STATS_HASH
#endif
if (h->t[i].p == DELETED) {
empty = i;
h->t[empty].p = h->t[i].p;
h->t[i].p = DELETED;
return empty;
} else {
#ifdef STATS_HASH
#endif
return i;
}
}
i += incr;
if (i >= h->size)
i -= h->size;
}
/* Found an empty position. */
i = empty;
return i;
}
unsigned int
{
unsigned int i, incr;
unsigned int empty;
#ifdef STATS_HASH
#endif
while (h->t[i].p != NULL) {
#ifdef STATS_HASH
#endif
if (h->t[i].p == DELETED) {
empty = i;
h->t[empty].p = h->t[i].p;
h->t[i].p = DELETED;
return empty;
} else {
#ifdef STATS_HASH
#endif
} return i;
}
i += incr;
if (i >= h->size)
i -= h->size;
}
/* Found an empty position. */
i = empty;
return i;
}
unsigned int
{
const char *e = NULL;
return ohash_qlookupi(h, s, &e);
}
unsigned int
{
hv = ohash_interval(s, e);
return ohash_lookup_interval(h, s, *e, hv);
}
#endif /*!HAVE_OHASH*/