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"
32 template<class T
, class Allocator
>
36 int32 mNumItems
, mMaxItems
, mTableSize
, mHashMask
;
42 HashTable(Allocator
*inPool
, int32 inMaxItems
, bool inCanResize
= true)
46 mMaxItems
= inMaxItems
;
47 mTableSize
= mMaxItems
<< 1;
48 mItems
= AllocTable(mTableSize
);
49 mHashMask
= mTableSize
- 1;
50 mCanResize
= inCanResize
;
57 int32
TableSize() const { return mTableSize
; }
58 int32
MaxItems() const { return mMaxItems
; }
59 int32
NumItems() const { return mNumItems
; }
61 T
** AllocTable(int inTableSize
)
63 size_t size
= inTableSize
* sizeof(T
*);
64 T
** items
= static_cast<T
**>(mPool
->Alloc(size
));
65 for (int i
=0; i
<inTableSize
; ++i
) {
73 for (int i
=0; i
<mTableSize
; ++i
) {
81 int32 newSize
= sc_max(mTableSize
<< 1, 32);
82 int32 oldSize
= mTableSize
;
83 T
** oldItems
= mItems
;
84 mItems
= AllocTable(newSize
);
86 mMaxItems
= mTableSize
>> 1;
87 mHashMask
= mTableSize
- 1;
89 for (int i
=0; i
<oldSize
; ++i
) {
90 T
* item
= oldItems
[i
];
93 mPool
->Free(oldItems
);
94 //printf("mMaxItems %d mTableSize %d newSize %d\n", mMaxItems, mTableSize, newSize);
99 //printf("mNumItems %d\n", mNumItems);
100 //printf("mMaxItems %d\n", mMaxItems);
101 //printf("mCanResize %d\n", mCanResize);
102 if (mNumItems
>= mMaxItems
) {
103 if (!mCanResize
) return false;
107 //printf("GetHash(inItem) %d\n", GetHash(inItem));
108 //printf("GetKey(inItem) %s\n", GetKey(inItem));
109 int32 index
= IndexFor(GetHash(inItem
), (int32
*)GetKey(inItem
));
110 //printf("index %d\n", index);
112 T
*item
= mItems
[index
];
113 if (item
) return item
== inItem
;
115 mItems
[index
] = inItem
;
120 bool Remove(T
* inItem
)
122 int32 index
= IndexFor(GetHash(inItem
), (int32
*)GetKey(inItem
));
123 if (mItems
[index
] != inItem
) return false;
126 FixCollisionsFrom(index
);
131 bool RemoveKey(int32
* inKey
)
133 T
* item
= Get(inKey
);
134 if (!item
) return false;
138 int32
IndexFor(int32 inHashID
, int32
* inKey
) const
140 int index
= inHashID
& mHashMask
;
142 T
*item
= mItems
[index
];
143 if (!item
) return index
;
144 if (GetHash(item
) == inHashID
&& str4eq(inKey
, GetKey(item
))) return index
;
145 index
= (index
+ 1) & mHashMask
;
149 T
* Get(int32
* inKey
) const
151 return Get(Hash(inKey
), inKey
);
154 T
* Get(int32 inHashID
, int32
* inKey
) const
156 //printf("Get hash %d %s\n", inHashID, inKey);
157 int32 index
= IndexFor(inHashID
, inKey
);
158 //printf("index %d\n", index);
159 return mItems
[index
];
162 bool Includes(T
* inItem
) const
164 return Get(GetHash(inItem
), GetKey(inItem
)) == inItem
;
167 T
* AtIndex(int32 inIndex
) const
169 return mItems
[inIndex
];
173 void FixCollisionsFrom(int32 inIndex
)
175 int oldIndex
= inIndex
;
177 oldIndex
= (oldIndex
+ 1) & mHashMask
;
178 T
*oldItem
= mItems
[oldIndex
];
180 int newIndex
= IndexFor(GetHash(oldItem
), (int32
*)GetKey(oldItem
));
181 if (oldIndex
!= newIndex
) {
182 mItems
[oldIndex
] = mItems
[newIndex
];
183 mItems
[newIndex
] = oldItem
;
190 template<class T
, class Allocator
>
194 int32 mNumItems
, mMaxItems
, mTableSize
, mHashMask
;
200 IntHashTable(Allocator
*inPool
, int32 inMaxItems
, bool inCanResize
= true)
204 mMaxItems
= inMaxItems
;
205 mTableSize
= mMaxItems
<< 1;
206 mItems
= AllocTable(mTableSize
);
207 mHashMask
= mTableSize
- 1;
208 mCanResize
= inCanResize
;
215 int32
TableSize() const { return mTableSize
; }
216 int32
MaxItems() const { return mMaxItems
; }
217 int32
NumItems() const { return mNumItems
; }
219 T
** AllocTable(int inTableSize
)
221 size_t size
= inTableSize
* sizeof(T
*);
222 T
** items
= static_cast<T
**>(mPool
->Alloc(size
));
223 for (int i
=0; i
<inTableSize
; ++i
) {
231 int32 newSize
= sc_max(mTableSize
<< 1, 32);
232 T
** oldItems
= mItems
;
233 mItems
= AllocTable(newSize
);
234 for (int i
=0; i
<mTableSize
; ++i
) {
235 T
* item
= oldItems
[i
];
238 mTableSize
= newSize
;
239 mMaxItems
= mTableSize
>> 1;
240 mHashMask
= mTableSize
- 1;
241 mPool
->Free(oldItems
);
242 //printf("mMaxItems %d mTableSize %d newSize %d\n", mMaxItems, mTableSize, newSize);
247 //printf("mNumItems %d\n", mNumItems);
248 //printf("mMaxItems %d\n", mMaxItems);
249 //printf("mCanResize %d\n", mCanResize);
250 if (mNumItems
>= mMaxItems
) {
251 if (!mCanResize
) return false;
255 //printf("GetHash(inItem) %d\n", GetHash(inItem));
256 //printf("GetKey(inItem) %d\n", GetKey(inItem));
257 int32 index
= IndexFor(GetHash(inItem
), GetKey(inItem
));
258 //printf("index %d\n", index);
260 T
*item
= mItems
[index
];
261 if (item
) return item
== inItem
;
263 mItems
[index
] = inItem
;
268 bool Remove(T
* inItem
)
270 int32 index
= IndexFor(GetHash(inItem
), GetKey(inItem
));
271 //printf("rmv index %d hash %d key %d\n", index, GetHash(inItem), GetKey(inItem));
272 if (mItems
[index
] != inItem
) return false;
275 FixCollisionsFrom(index
);
280 bool RemoveKey(int32 inKey
)
282 T
* item
= Get(inKey
);
283 if (!item
) return false;
287 int32
IndexFor(int32 inHashID
, int32 inKey
) const
289 int index
= inHashID
& mHashMask
;
291 T
*item
= mItems
[index
];
292 if (!item
) return index
;
293 if (GetHash(item
) == inHashID
&& inKey
== GetKey(item
)) return index
;
294 index
= (index
+ 1) & mHashMask
;
298 T
* Get(int32 inKey
) const
300 //printf("Get key %d\n", inKey);
301 return Get(Hash(inKey
), inKey
);
304 T
* Get(int32 inHashID
, int32 inKey
) const
306 int32 index
= IndexFor(inHashID
, inKey
);
307 //printf("Get index %d hash %d key %d\n", index, inHashID, inKey);
308 return mItems
[index
];
311 bool Includes(T
* inItem
) const
313 return Get(GetHash(inItem
), GetKey(inItem
)) == inItem
;
316 T
* AtIndex(int32 inIndex
) const
318 return mItems
[inIndex
];
323 for (int i
=0; i
<mTableSize
; ++i
) {
326 printf("%4d %4d %08X %08X\n", i
, GetKey(item
), GetHash(item
), item
);
332 void FixCollisionsFrom(int32 inIndex
)
334 //printf("FixCollisionsFrom %d\n", inIndex);
335 int oldIndex
= inIndex
;
337 oldIndex
= (oldIndex
+ 1) & mHashMask
;
338 T
*oldItem
= mItems
[oldIndex
];
340 int newIndex
= IndexFor(GetHash(oldItem
), GetKey(oldItem
));
341 if (oldIndex
!= newIndex
) {
342 //printf("swap %d %d\n", oldIndex, newIndex);
343 mItems
[oldIndex
] = mItems
[newIndex
];
344 mItems
[newIndex
] = oldItem
;
352 void Free(void* ptr
) { free(ptr
); }
353 void* Alloc(size_t size
) { return malloc(size
); }