2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #include "SC_BoundsMacros.h"
29 template<class T
, class Allocator
, class KeyType
>
33 int32 mNumItems
, mMaxItems
, mTableSize
, mHashMask
;
39 HashTable(Allocator
*inPool
, int32 inMaxItems
, bool inCanResize
= true)
43 mMaxItems
= inMaxItems
;
44 mTableSize
= mMaxItems
<< 1;
45 mItems
= AllocTable(mTableSize
);
46 mHashMask
= mTableSize
- 1;
47 mCanResize
= inCanResize
;
54 int32
TableSize() const { return mTableSize
; }
55 int32
MaxItems() const { return mMaxItems
; }
56 int32
NumItems() const { return mNumItems
; }
58 T
** AllocTable(int inTableSize
)
60 size_t size
= inTableSize
* sizeof(T
*);
61 T
** items
= static_cast<T
**>(mPool
->Alloc(size
));
62 for (int i
=0; i
<inTableSize
; ++i
) {
70 int32 newSize
= sc_max(mTableSize
<< 1, 32);
71 T
** oldItems
= mItems
;
72 mItems
= AllocTable(newSize
);
73 for (int i
=0; i
<mTableSize
; ++i
) {
74 T
* item
= oldItems
[i
];
78 mMaxItems
= mTableSize
>> 1;
79 mHashMask
= mTableSize
- 1;
80 mPool
->Free(oldItems
);
81 //printf("mMaxItems %d mTableSize %d newSize %d\n", mMaxItems, mTableSize, newSize);
86 //printf("mNumItems %d\n", mNumItems);
87 //printf("mMaxItems %d\n", mMaxItems);
88 //printf("mCanResize %d\n", mCanResize);
89 if (mNumItems
>= mMaxItems
) {
90 if (!mCanResize
) return false;
94 //printf("GetHash(inItem) %d\n", GetHash(inItem));
95 //printf("GetKey(inItem) %s\n", GetKey(inItem));
96 int32 index
= IndexFor(GetHash(inItem
), GetKey(inItem
));
97 //printf("index %d\n", index);
99 T
*item
= mItems
[index
];
100 if (item
) return item
== inItem
;
102 mItems
[index
] = inItem
;
107 bool Remove(T
* inItem
)
109 int32 index
= IndexFor(GetHash(inItem
), GetKey(inItem
));
110 if (mItems
[index
] != inItem
) return false;
113 FixCollisionsFrom(index
);
118 int32
IndexFor(int32 inHashID
, KeyType inKey
) const
120 int index
= inHashID
& mHashMask
;
122 T
*item
= mItems
[index
];
123 if (!item
) return index
;
124 if (GetHash(item
) == inHashID
125 && strcmp(inKey
, GetKey(item
)) == 0) return index
;
126 index
= (index
+ 1) & mHashMask
;
130 T
* Get(KeyType inKey
) const
132 return Get(Hash(inKey
), inKey
);
135 T
* Get(int32 inHashID
, KeyType inKey
) const
137 int32 index
= IndexFor(inHashID
, inKey
);
138 return mItems
[index
];
141 bool Includes(T
* inItem
) const
143 return Get(GetHash(inItem
), GetKey(inItem
)) == inItem
;
146 T
* AtIndex(int32 inIndex
) const
148 return mItems
[inIndex
];
152 void FixCollisionsFrom(int32 inIndex
)
154 int oldIndex
= inIndex
;
156 oldIndex
= (oldIndex
+ 1) & mHashMask
;
157 T
*oldItem
= mItems
[oldIndex
];
159 int newIndex
= IndexFor(GetHash(oldItem
), GetKey(oldItem
));
160 if (oldIndex
!= newIndex
) {
161 mItems
[oldIndex
] = mItems
[newIndex
];
162 mItems
[newIndex
] = oldItem
;
168 template<class T
, int kMaxItems
, class KeyType
>
169 class StaticHashTable
171 int32 mNumItems
, mTableSize
, mHashMask
;
172 T
* mItems
[kMaxItems
*2];
179 mTableSize
= kMaxItems
<< 1;
181 mHashMask
= mTableSize
- 1;
187 int32
TableSize() const { return mTableSize
; }
188 int32
MaxItems() const { return kMaxItems
; }
189 int32
NumItems() const { return mNumItems
; }
193 for (int i
=0; i
<mTableSize
; ++i
) {
200 if (mNumItems
>= kMaxItems
) return false;
202 int32 index
= IndexFor(GetHash(inItem
), GetKey(inItem
));
204 T
*item
= mItems
[index
];
205 if (item
) return item
== inItem
;
207 mItems
[index
] = inItem
;
212 bool Remove(T
* inItem
)
214 int32 index
= IndexFor(GetHash(inItem
), GetKey(inItem
));
215 if (mItems
[index
] != inItem
) return false;
218 FixCollisionsFrom(index
);
223 int32
IndexFor(int32 inHashID
, KeyType inKey
) const
225 int index
= inHashID
& mHashMask
;
227 T
*item
= mItems
[index
];
228 if (!item
) return index
;
229 if (GetHash(item
) == inHashID
230 && strcmp(inKey
, GetKey(item
)) == 0) return index
;
231 index
= (index
+ 1) & mHashMask
;
235 T
* Get(KeyType inKey
) const
237 return Get(Hash(inKey
), inKey
);
240 T
* Get(int32 inHashID
, KeyType inKey
) const
242 int32 index
= IndexFor(inHashID
, inKey
);
243 return mItems
[index
];
246 bool Includes(T
* inItem
) const
248 return Get(GetHash(inItem
), GetKey(inItem
)) == inItem
;
251 T
* AtIndex(int32 inIndex
) const
253 return mItems
[inIndex
];
257 void FixCollisionsFrom(int32 inIndex
)
259 int oldIndex
= inIndex
;
261 oldIndex
= (oldIndex
+ 1) & mHashMask
;
262 T
*oldItem
= mItems
[oldIndex
];
264 int newIndex
= IndexFor(GetHash(oldItem
), GetKey(oldItem
));
265 if (oldIndex
!= newIndex
) {
266 mItems
[oldIndex
] = mItems
[newIndex
];
267 mItems
[newIndex
] = oldItem
;