-
Notifications
You must be signed in to change notification settings - Fork 1
/
faker-hash.h
135 lines (120 loc) · 3.27 KB
/
faker-hash.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/* Copyright (C)2004 Landmark Graphics
* Copyright (C)2005 Sun Microsystems, Inc.
*
* This library is free software and may be redistributed and/or modified under
* the terms of the wxWindows Library License, Version 3 or (at your option)
* any later version. The full license is in the LICENSE.txt file included
* with this distribution.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* wxWindows Library License for more details.
*/
// Generic hash table
#include "rrmutex.h"
typedef struct __hashclassstruct
{
_hashkeytype1 key1;
_hashkeytype2 key2;
_hashvaluetype value;
int refcount;
struct __hashclassstruct *prev, *next;
} _hashclassstruct;
class _hashclass
{
public:
void killhash(void)
{
rrcs::safelock l(mutex);
while(start!=NULL) killentry(start);
}
int add(_hashkeytype1 key1, _hashkeytype2 key2, _hashvaluetype value, bool useref=false)
{
_hashclassstruct *ptr=NULL;
if(!key1) _throw("Invalid argument");
rrcs::safelock l(mutex);
if((ptr=findentry(key1, key2))!=NULL)
{
if(value) ptr->value=value;
if(useref) ptr->refcount++; return 0;
}
errifnot(ptr=new _hashclassstruct);
memset(ptr, 0, sizeof(_hashclassstruct));
ptr->prev=end; if(end) end->next=ptr;
if(!start) start=ptr;
end=ptr;
end->key1=key1; end->key2=key2; end->value=value;
if(useref) end->refcount=1;
entries++;
return 1;
}
_hashvaluetype find(_hashkeytype1 key1, _hashkeytype2 key2, bool useref=false)
{
_hashclassstruct *ptr=NULL;
// if(!key1) _throw("Invalid argument");
rrcs::safelock l(mutex);
if((ptr=findentry(key1, key2))!=NULL)
{
if(!ptr->value) ptr->value=attach(key1, key2);
return ptr->value;
}
return (_hashvaluetype)0;
}
void remove(_hashkeytype1 key1, _hashkeytype2 key2, bool useref=false)
{
_hashclassstruct *ptr=NULL;
// if(!key1) _throw("Invalid argument");
rrcs::safelock l(mutex);
if((ptr=findentry(key1, key2))!=NULL)
{
if(useref && ptr->refcount>0) ptr->refcount--;
if(!useref || ptr->refcount<=0) killentry(ptr);
}
}
int numEntries(void) {return entries;}
protected:
_hashclass(void)
{
start=end=NULL;
entries=0;
}
virtual ~_hashclass(void)
{
killhash();
}
_hashclassstruct *findentry(_hashkeytype1 key1, _hashkeytype2 key2)
{
_hashclassstruct *ptr=NULL;
// if(!key1) _throw("Invalid argument");
rrcs::safelock l(mutex);
ptr=start;
while(ptr!=NULL)
{
if((ptr->key1==key1 && ptr->key2==key2) || compare(key1, key2, ptr))
{
return ptr;
}
ptr=ptr->next;
}
return NULL;
}
void killentry(_hashclassstruct *ptr)
{
rrcs::safelock l(mutex);
if(ptr->prev) ptr->prev->next=ptr->next;
if(ptr->next) ptr->next->prev=ptr->prev;
if(ptr==start) start=ptr->next;
if(ptr==end) end=ptr->prev;
if(ptr->value) detach(ptr);
memset(ptr, 0, sizeof(_hashclassstruct));
delete ptr;
entries--;
}
int entries;
virtual _hashvaluetype attach(_hashkeytype1, _hashkeytype2)=0;
virtual void detach(_hashclassstruct *h)=0;
virtual bool compare(_hashkeytype1, _hashkeytype2, _hashclassstruct *h)=0;
_hashclassstruct *start, *end;
rrcs mutex;
};