source: branches/port5/ptpan/PT_hashing.cxx

Last change on this file was 5908, checked in by westram, 16 years ago
  • source files with identical names are really a pain when using valgrind
File size: 3.4 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <unistd.h>
5#include <math.h>
6#include <PT_server.h>
7#include <PT_server_prototypes.h>
8#include "ptpan.h"
9#include "pt_prototypes.h"
10
11/* /// "AllocHashArray()" */
12struct HashArray * AllocHashArray(ULONG size)
13{
14  struct HashArray *ha;
15  ha = (struct HashArray *) calloc(1, sizeof(struct HashArray));
16  if(ha)
17  {
18    ha->ha_Array = (struct HashEntry *) calloc(size, sizeof(struct HashEntry));
19    if(ha->ha_Array)
20    {
21      ha->ha_InitialSize = ha->ha_Size = size;
22      return(ha);
23    }
24    freeset(ha, NULL);
25  }
26  return(ha);
27}
28/* \\\ */
29
30/* /// "FreeHashArray()" */
31void FreeHashArray(struct HashArray *ha)
32{
33  if(!ha)
34  {
35    return;
36  }
37  free(ha->ha_Array);
38  free(ha);
39}
40/* \\\ */
41
42/* /// "ClearHashArray()" */
43void ClearHashArray(struct HashArray *ha)
44{
45  memset(ha->ha_Array, 0, ha->ha_Size * sizeof(struct HashEntry));
46  ha->ha_InitialSize = ha->ha_Size;
47  ha->ha_Used = 0;
48}
49/* \\\ */
50
51/* /// "GetHashEntry()" */
52struct HashEntry * GetHashEntry(struct HashArray *ha, ULONG hashkey)
53{
54  struct HashEntry *he;
55  ULONG tmpkey = hashkey;
56  ULONG size = ha->ha_Size;
57  hashkey++; /* avoid zero */
58  do
59  {
60    he = &ha->ha_Array[tmpkey++ % size];
61    if(!he->he_Key)
62    {
63      if(size > ha->ha_InitialSize)
64      {
65        size /= 2;
66        tmpkey = hashkey-1;
67      } else {
68        return(NULL);
69      }
70    }
71    if(he->he_Key == hashkey)
72    {
73      return(he);
74    }
75  } while(TRUE);
76  return(NULL);
77}
78/* \\\ */
79
80/* /// "EnlargeHashArray() */
81BOOL EnlargeHashArray(struct HashArray *ha)
82{
83  struct HashEntry *newarray;
84  newarray = (struct HashEntry *) realloc(ha->ha_Array, ((ha->ha_Size<<1)+1) * sizeof(struct HashEntry));
85  printf("doubling size!\n");
86  if(newarray)
87  {
88    memset(&newarray[ha->ha_Size], 0, (ha->ha_Size + 1) * sizeof(struct HashEntry));
89    ha->ha_Size += ha->ha_Size + 1;
90    ha->ha_Array = newarray;
91    return(TRUE);
92  }
93  return(FALSE);
94}
95/* \\\ */
96
97/* /// "InsertHashEntry()" */
98BOOL InsertHashEntry(struct HashArray *ha, ULONG hashkey, ULONG data)
99{
100  ULONG size = ha->ha_Size;
101  ULONG maxnext = (ULONG) sqrt((double) size);
102  struct HashEntry *he;
103  ULONG tmpkey = hashkey;
104
105  if(ha->ha_Used > (size >> 1)) /* if hash table > 50% full, resize */
106  {
107    EnlargeHashArray(ha);
108    size = ha->ha_Size;
109  }
110  hashkey++; /* avoid zero */
111  do
112  {
113    he = &ha->ha_Array[tmpkey++ % size];
114    if(!he->he_Key)
115    {
116      he->he_Key = hashkey;
117      he->he_Data = data;
118      ha->ha_Used++;
119      return(TRUE);
120    }
121  } while(--maxnext);
122  /* okay, this is a very bad case of collisions in a row */
123  if(ha->ha_InitialSize < ha->ha_Size)
124  {
125    /* try to clean things up first */
126    struct HashEntry *oldarray = ha->ha_Array;
127    ULONG cnt;
128   
129    ha->ha_Array  = (struct HashEntry *) calloc(ha->ha_Size, sizeof(struct HashEntry));
130    if(ha->ha_Array)
131    {
132      ha->ha_InitialSize = ha->ha_Size; /* avoid running into this part a second time */
133      /* insert stuff from scratch */
134      for(cnt = 0; cnt < ha->ha_Size; cnt++)
135      {
136        if(oldarray[cnt].he_Key)
137        {
138        InsertHashEntry(ha, oldarray[cnt].he_Key - 1, oldarray[cnt].he_Data);
139        }
140      }
141      free(oldarray);
142      return(InsertHashEntry(ha, hashkey - 1, data));
143    }
144  } else {
145    /* bad. increase size as last resort. */
146    if(EnlargeHashArray(ha))
147    {
148      return(InsertHashEntry(ha, hashkey - 1, data));
149    } else {
150      /* okay, we tried everything */
151      return(FALSE);
152    }
153  }
154  return(FALSE);
155}
156/* \\\ */
Note: See TracBrowser for help on using the repository browser.