chipmunk 4.1.0-x86-mswin32 → 5.3.4.0-x86-mswin32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/{ext/chipmunk/cpCollision.h → LICENSE} +4 -5
  2. data/README +67 -0
  3. data/Rakefile +76 -29
  4. data/ext/chipmunk/extconf.rb +38 -0
  5. data/ext/chipmunk/rb_chipmunk.c +162 -21
  6. data/ext/chipmunk/rb_chipmunk.h +39 -11
  7. data/ext/chipmunk/rb_cpArbiter.c +253 -0
  8. data/ext/chipmunk/rb_cpBB.c +60 -4
  9. data/ext/chipmunk/rb_cpBody.c +282 -17
  10. data/ext/chipmunk/rb_cpConstraint.c +336 -0
  11. data/ext/chipmunk/rb_cpShape.c +145 -4
  12. data/ext/chipmunk/rb_cpSpace.c +438 -57
  13. data/ext/chipmunk/rb_cpVect.c +98 -2
  14. data/lib/1.8/chipmunk.so +0 -0
  15. data/lib/1.9/chipmunk.so +0 -0
  16. data/lib/chipmunk.rb +168 -0
  17. metadata +29 -41
  18. data/ext/chipmunk/chipmunk.c +0 -69
  19. data/ext/chipmunk/chipmunk.h +0 -91
  20. data/ext/chipmunk/cpArbiter.c +0 -263
  21. data/ext/chipmunk/cpArbiter.h +0 -85
  22. data/ext/chipmunk/cpArray.c +0 -114
  23. data/ext/chipmunk/cpArray.h +0 -45
  24. data/ext/chipmunk/cpBB.c +0 -46
  25. data/ext/chipmunk/cpBB.h +0 -53
  26. data/ext/chipmunk/cpBody.c +0 -180
  27. data/ext/chipmunk/cpBody.h +0 -132
  28. data/ext/chipmunk/cpCollision.c +0 -390
  29. data/ext/chipmunk/cpHashSet.c +0 -219
  30. data/ext/chipmunk/cpHashSet.h +0 -79
  31. data/ext/chipmunk/cpJoint.c +0 -553
  32. data/ext/chipmunk/cpJoint.h +0 -122
  33. data/ext/chipmunk/cpPolyShape.c +0 -139
  34. data/ext/chipmunk/cpPolyShape.h +0 -92
  35. data/ext/chipmunk/cpShape.c +0 -244
  36. data/ext/chipmunk/cpShape.h +0 -141
  37. data/ext/chipmunk/cpSpace.c +0 -530
  38. data/ext/chipmunk/cpSpace.h +0 -120
  39. data/ext/chipmunk/cpSpaceHash.c +0 -455
  40. data/ext/chipmunk/cpSpaceHash.h +0 -100
  41. data/ext/chipmunk/cpVect.c +0 -63
  42. data/ext/chipmunk/cpVect.h +0 -106
  43. data/ext/chipmunk/prime.h +0 -68
  44. data/ext/chipmunk/rb_cpJoint.c +0 -136
@@ -1,390 +0,0 @@
1
- /* Copyright (c) 2007 Scott Lembcke
2
- *
3
- * Permission is hereby granted, free of charge, to any person obtaining a copy
4
- * of this software and associated documentation files (the "Software"), to deal
5
- * in the Software without restriction, including without limitation the rights
6
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- * copies of the Software, and to permit persons to whom the Software is
8
- * furnished to do so, subject to the following conditions:
9
- *
10
- * The above copyright notice and this permission notice shall be included in
11
- * all copies or substantial portions of the Software.
12
- *
13
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
- * SOFTWARE.
20
- */
21
-
22
- #include <stdlib.h>
23
- #include <math.h>
24
- #include <stdio.h>
25
- #include <assert.h>
26
-
27
- #include "chipmunk.h"
28
-
29
- typedef int (*collisionFunc)(cpShape*, cpShape*, cpContact**);
30
-
31
- static collisionFunc *colfuncs = NULL;
32
-
33
- // Add contact points for circle to circle collisions.
34
- // Used by several collision tests.
35
- static int
36
- circle2circleQuery(cpVect p1, cpVect p2, cpFloat r1, cpFloat r2, cpContact **con)
37
- {
38
- cpFloat mindist = r1 + r2;
39
- cpVect delta = cpvsub(p2, p1);
40
- cpFloat distsq = cpvlengthsq(delta);
41
- if(distsq >= mindist*mindist) return 0;
42
-
43
- cpFloat dist = sqrtf(distsq);
44
- // To avoid singularities, do nothing in the case of dist = 0.
45
- cpFloat non_zero_dist = (dist ? dist : INFINITY);
46
-
47
- // Allocate and initialize the contact.
48
- (*con) = (cpContact *)malloc(sizeof(cpContact));
49
- cpContactInit(
50
- (*con),
51
- cpvadd(p1, cpvmult(delta, 0.5 + (r1 - 0.5*mindist)/non_zero_dist)),
52
- cpvmult(delta, 1.0/non_zero_dist),
53
- dist - mindist,
54
- 0
55
- );
56
-
57
- return 1;
58
- }
59
-
60
- // Collide circle shapes.
61
- static int
62
- circle2circle(cpShape *shape1, cpShape *shape2, cpContact **arr)
63
- {
64
- cpCircleShape *circ1 = (cpCircleShape *)shape1;
65
- cpCircleShape *circ2 = (cpCircleShape *)shape2;
66
-
67
- return circle2circleQuery(circ1->tc, circ2->tc, circ1->r, circ2->r, arr);
68
- }
69
-
70
- // Collide circles to segment shapes.
71
- static int
72
- circle2segment(cpShape *circleShape, cpShape *segmentShape, cpContact **con)
73
- {
74
- cpCircleShape *circ = (cpCircleShape *)circleShape;
75
- cpSegmentShape *seg = (cpSegmentShape *)segmentShape;
76
-
77
- // Radius sum
78
- cpFloat rsum = circ->r + seg->r;
79
-
80
- // Calculate normal distance from segment.
81
- cpFloat dn = cpvdot(seg->tn, circ->tc) - cpvdot(seg->ta, seg->tn);
82
- cpFloat dist = fabs(dn) - rsum;
83
- if(dist > 0.0f) return 0;
84
-
85
- // Calculate tangential distance along segment.
86
- cpFloat dt = -cpvcross(seg->tn, circ->tc);
87
- cpFloat dtMin = -cpvcross(seg->tn, seg->ta);
88
- cpFloat dtMax = -cpvcross(seg->tn, seg->tb);
89
-
90
- // Decision tree to decide which feature of the segment to collide with.
91
- if(dt < dtMin){
92
- if(dt < (dtMin - rsum)){
93
- return 0;
94
- } else {
95
- return circle2circleQuery(circ->tc, seg->ta, circ->r, seg->r, con);
96
- }
97
- } else {
98
- if(dt < dtMax){
99
- cpVect n = (dn < 0.0f) ? seg->tn : cpvneg(seg->tn);
100
- (*con) = (cpContact *)malloc(sizeof(cpContact));
101
- cpContactInit(
102
- (*con),
103
- cpvadd(circ->tc, cpvmult(n, circ->r + dist*0.5f)),
104
- n,
105
- dist,
106
- 0
107
- );
108
- return 1;
109
- } else {
110
- if(dt < (dtMax + rsum)) {
111
- return circle2circleQuery(circ->tc, seg->tb, circ->r, seg->r, con);
112
- } else {
113
- return 0;
114
- }
115
- }
116
- }
117
-
118
- return 1;
119
- }
120
-
121
- // Helper function for allocating contact point lists.
122
- static cpContact *
123
- addContactPoint(cpContact **arr, int *max, int *num)
124
- {
125
- if(*arr == NULL){
126
- // Allocate the array if it hasn't been done.
127
- (*max) = 2;
128
- (*num) = 0;
129
- (*arr) = (cpContact *)malloc((*max)*sizeof(cpContact));
130
- } else if(*num == *max){
131
- // Extend it if necessary.
132
- (*max) *= 2;
133
- (*arr) = (cpContact *)realloc(*arr, (*max)*sizeof(cpContact));
134
- }
135
-
136
- cpContact *con = &(*arr)[*num];
137
- (*num)++;
138
-
139
- return con;
140
- }
141
-
142
- // Find the minimum separating axis for the give poly and axis list.
143
- static inline int
144
- findMSA(cpPolyShape *poly, cpPolyShapeAxis *axes, int num, cpFloat *min_out)
145
- {
146
- int min_index = 0;
147
- cpFloat min = cpPolyShapeValueOnAxis(poly, axes->n, axes->d);
148
- if(min > 0.0) return -1;
149
-
150
- for(int i=1; i<num; i++){
151
- cpFloat dist = cpPolyShapeValueOnAxis(poly, axes[i].n, axes[i].d);
152
- if(dist > 0.0) {
153
- return -1;
154
- } else if(dist > min){
155
- min = dist;
156
- min_index = i;
157
- }
158
- }
159
-
160
- (*min_out) = min;
161
- return min_index;
162
- }
163
-
164
- // Add contacts for penetrating vertexes.
165
- static inline int
166
- findVerts(cpContact **arr, cpPolyShape *poly1, cpPolyShape *poly2, cpVect n, cpFloat dist)
167
- {
168
- int max = 0;
169
- int num = 0;
170
-
171
- for(int i=0; i<poly1->numVerts; i++){
172
- cpVect v = poly1->tVerts[i];
173
- if(cpPolyShapeContainsVertPartial(poly2, v, cpvneg(n)))
174
- cpContactInit(addContactPoint(arr, &max, &num), v, n, dist, CP_HASH_PAIR(poly1, i));
175
- }
176
-
177
- for(int i=0; i<poly2->numVerts; i++){
178
- cpVect v = poly2->tVerts[i];
179
- if(cpPolyShapeContainsVertPartial(poly1, v, n))
180
- cpContactInit(addContactPoint(arr, &max, &num), v, n, dist, CP_HASH_PAIR(poly2, i));
181
- }
182
-
183
- // if(!num)
184
- // addContactPoint(arr, &size, &num, cpContactNew(shape1->body->p, n, dist, 0));
185
-
186
- return num;
187
- }
188
-
189
- // Collide poly shapes together.
190
- static int
191
- poly2poly(cpShape *shape1, cpShape *shape2, cpContact **arr)
192
- {
193
- cpPolyShape *poly1 = (cpPolyShape *)shape1;
194
- cpPolyShape *poly2 = (cpPolyShape *)shape2;
195
-
196
- cpFloat min1;
197
- int mini1 = findMSA(poly2, poly1->tAxes, poly1->numVerts, &min1);
198
- if(mini1 == -1) return 0;
199
-
200
- cpFloat min2;
201
- int mini2 = findMSA(poly1, poly2->tAxes, poly2->numVerts, &min2);
202
- if(mini2 == -1) return 0;
203
-
204
- // There is overlap, find the penetrating verts
205
- if(min1 > min2)
206
- return findVerts(arr, poly1, poly2, poly1->tAxes[mini1].n, min1);
207
- else
208
- return findVerts(arr, poly1, poly2, cpvneg(poly2->tAxes[mini2].n), min2);
209
- }
210
-
211
- // Like cpPolyValueOnAxis(), but for segments.
212
- static inline float
213
- segValueOnAxis(cpSegmentShape *seg, cpVect n, cpFloat d)
214
- {
215
- cpFloat a = cpvdot(n, seg->ta) - seg->r;
216
- cpFloat b = cpvdot(n, seg->tb) - seg->r;
217
- return cpfmin(a, b) - d;
218
- }
219
-
220
- // Identify vertexes that have penetrated the segment.
221
- static inline void
222
- findPointsBehindSeg(cpContact **arr, int *max, int *num, cpSegmentShape *seg, cpPolyShape *poly, cpFloat pDist, cpFloat coef)
223
- {
224
- cpFloat dta = cpvcross(seg->tn, seg->ta);
225
- cpFloat dtb = cpvcross(seg->tn, seg->tb);
226
- cpVect n = cpvmult(seg->tn, coef);
227
-
228
- for(int i=0; i<poly->numVerts; i++){
229
- cpVect v = poly->tVerts[i];
230
- if(cpvdot(v, n) < cpvdot(seg->tn, seg->ta)*coef + seg->r){
231
- cpFloat dt = cpvcross(seg->tn, v);
232
- if(dta >= dt && dt >= dtb){
233
- cpContactInit(addContactPoint(arr, max, num), v, n, pDist, CP_HASH_PAIR(poly, i));
234
- }
235
- }
236
- }
237
- }
238
-
239
- // This one is complicated and gross. Just don't go there...
240
- // TODO: Comment me!
241
- static int
242
- seg2poly(cpShape *shape1, cpShape *shape2, cpContact **arr)
243
- {
244
- cpSegmentShape *seg = (cpSegmentShape *)shape1;
245
- cpPolyShape *poly = (cpPolyShape *)shape2;
246
- cpPolyShapeAxis *axes = poly->tAxes;
247
-
248
- cpFloat segD = cpvdot(seg->tn, seg->ta);
249
- cpFloat minNorm = cpPolyShapeValueOnAxis(poly, seg->tn, segD) - seg->r;
250
- cpFloat minNeg = cpPolyShapeValueOnAxis(poly, cpvneg(seg->tn), -segD) - seg->r;
251
- if(minNeg > 0.0f || minNorm > 0.0f) return 0;
252
-
253
- int mini = 0;
254
- cpFloat poly_min = segValueOnAxis(seg, axes->n, axes->d);
255
- if(poly_min > 0.0f) return 0;
256
- for(int i=0; i<poly->numVerts; i++){
257
- cpFloat dist = segValueOnAxis(seg, axes[i].n, axes[i].d);
258
- if(dist > 0.0f){
259
- return 0;
260
- } else if(dist > poly_min){
261
- poly_min = dist;
262
- mini = i;
263
- }
264
- }
265
-
266
- int max = 0;
267
- int num = 0;
268
-
269
- cpVect poly_n = cpvneg(axes[mini].n);
270
-
271
- cpVect va = cpvadd(seg->ta, cpvmult(poly_n, seg->r));
272
- cpVect vb = cpvadd(seg->tb, cpvmult(poly_n, seg->r));
273
- if(cpPolyShapeContainsVert(poly, va))
274
- cpContactInit(addContactPoint(arr, &max, &num), va, poly_n, poly_min, CP_HASH_PAIR(seg, 0));
275
- if(cpPolyShapeContainsVert(poly, vb))
276
- cpContactInit(addContactPoint(arr, &max, &num), vb, poly_n, poly_min, CP_HASH_PAIR(seg, 1));
277
-
278
- // Floating point precision problems here.
279
- // This will have to do for now.
280
- poly_min -= cp_collision_slop;
281
- if(minNorm >= poly_min || minNeg >= poly_min) {
282
- if(minNorm > minNeg)
283
- findPointsBehindSeg(arr, &max, &num, seg, poly, minNorm, 1.0f);
284
- else
285
- findPointsBehindSeg(arr, &max, &num, seg, poly, minNeg, -1.0f);
286
- }
287
-
288
- // If no other collision points are found, try colliding endpoints.
289
- if(num == 0){
290
- cpVect poly_a = poly->tVerts[mini];
291
- cpVect poly_b = poly->tVerts[(mini + 1)%poly->numVerts];
292
-
293
- if(circle2circleQuery(seg->ta, poly_a, seg->r, 0.0f, arr))
294
- return 1;
295
-
296
- if(circle2circleQuery(seg->tb, poly_a, seg->r, 0.0f, arr))
297
- return 1;
298
-
299
- if(circle2circleQuery(seg->ta, poly_b, seg->r, 0.0f, arr))
300
- return 1;
301
-
302
- if(circle2circleQuery(seg->tb, poly_b, seg->r, 0.0f, arr))
303
- return 1;
304
- }
305
-
306
- return num;
307
- }
308
-
309
- // This one is less gross, but still gross.
310
- // TODO: Comment me!
311
- static int
312
- circle2poly(cpShape *shape1, cpShape *shape2, cpContact **con)
313
- {
314
- cpCircleShape *circ = (cpCircleShape *)shape1;
315
- cpPolyShape *poly = (cpPolyShape *)shape2;
316
- cpPolyShapeAxis *axes = poly->tAxes;
317
-
318
- int mini = 0;
319
- cpFloat min = cpvdot(axes->n, circ->tc) - axes->d - circ->r;
320
- for(int i=0; i<poly->numVerts; i++){
321
- cpFloat dist = cpvdot(axes[i].n, circ->tc) - axes[i].d - circ->r;
322
- if(dist > 0.0){
323
- return 0;
324
- } else if(dist > min) {
325
- min = dist;
326
- mini = i;
327
- }
328
- }
329
-
330
- cpVect n = axes[mini].n;
331
- cpVect a = poly->tVerts[mini];
332
- cpVect b = poly->tVerts[(mini + 1)%poly->numVerts];
333
- cpFloat dta = cpvcross(n, a);
334
- cpFloat dtb = cpvcross(n, b);
335
- cpFloat dt = cpvcross(n, circ->tc);
336
-
337
- if(dt < dtb){
338
- return circle2circleQuery(circ->tc, b, circ->r, 0.0f, con);
339
- } else if(dt < dta) {
340
- (*con) = (cpContact *)malloc(sizeof(cpContact));
341
- cpContactInit(
342
- (*con),
343
- cpvsub(circ->tc, cpvmult(n, circ->r + min/2.0f)),
344
- cpvneg(n),
345
- min,
346
- 0
347
- );
348
-
349
- return 1;
350
- } else {
351
- return circle2circleQuery(circ->tc, a, circ->r, 0.0f, con);
352
- }
353
- }
354
-
355
- static void
356
- addColFunc(cpShapeType a, cpShapeType b, collisionFunc func)
357
- {
358
- colfuncs[a + b*CP_NUM_SHAPES] = func;
359
- }
360
-
361
- #ifdef __cplusplus
362
- extern "C" {
363
- #endif
364
- // Initializes the array of collision functions.
365
- // Called by cpInitChipmunk().
366
- void
367
- cpInitCollisionFuncs(void)
368
- {
369
- if(!colfuncs)
370
- colfuncs = (collisionFunc *)calloc(CP_NUM_SHAPES*CP_NUM_SHAPES, sizeof(collisionFunc));
371
-
372
- addColFunc(CP_CIRCLE_SHAPE, CP_CIRCLE_SHAPE, circle2circle);
373
- addColFunc(CP_CIRCLE_SHAPE, CP_SEGMENT_SHAPE, circle2segment);
374
- addColFunc(CP_SEGMENT_SHAPE, CP_POLY_SHAPE, seg2poly);
375
- addColFunc(CP_CIRCLE_SHAPE, CP_POLY_SHAPE, circle2poly);
376
- addColFunc(CP_POLY_SHAPE, CP_POLY_SHAPE, poly2poly);
377
- }
378
- #ifdef __cplusplus
379
- }
380
- #endif
381
-
382
- int
383
- cpCollideShapes(cpShape *a, cpShape *b, cpContact **arr)
384
- {
385
- // Their shape types must be in order.
386
- assert(a->klass->type <= b->klass->type);
387
-
388
- collisionFunc cfunc = colfuncs[a->klass->type + b->klass->type*CP_NUM_SHAPES];
389
- return (cfunc) ? cfunc(a, b, arr) : 0;
390
- }
@@ -1,219 +0,0 @@
1
- /* Copyright (c) 2007 Scott Lembcke
2
- *
3
- * Permission is hereby granted, free of charge, to any person obtaining a copy
4
- * of this software and associated documentation files (the "Software"), to deal
5
- * in the Software without restriction, including without limitation the rights
6
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- * copies of the Software, and to permit persons to whom the Software is
8
- * furnished to do so, subject to the following conditions:
9
- *
10
- * The above copyright notice and this permission notice shall be included in
11
- * all copies or substantial portions of the Software.
12
- *
13
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
- * SOFTWARE.
20
- */
21
-
22
- #include <stdlib.h>
23
- #include <assert.h>
24
-
25
- #include "chipmunk.h"
26
- #include "prime.h"
27
-
28
- void
29
- cpHashSetDestroy(cpHashSet *set)
30
- {
31
- // Free the chains.
32
- for(int i=0; i<set->size; i++){
33
- // Free the bins in the chain.
34
- cpHashSetBin *bin = set->table[i];
35
- while(bin){
36
- cpHashSetBin *next = bin->next;
37
- free(bin);
38
- bin = next;
39
- }
40
- }
41
-
42
- // Free the table.
43
- free(set->table);
44
- }
45
-
46
- void
47
- cpHashSetFree(cpHashSet *set)
48
- {
49
- if(set) cpHashSetDestroy(set);
50
- free(set);
51
- }
52
-
53
- cpHashSet *
54
- cpHashSetAlloc(void)
55
- {
56
- return (cpHashSet *)calloc(1, sizeof(cpHashSet));
57
- }
58
-
59
- cpHashSet *
60
- cpHashSetInit(cpHashSet *set, int size, cpHashSetEqlFunc eqlFunc, cpHashSetTransFunc trans)
61
- {
62
- set->size = next_prime(size);
63
- set->entries = 0;
64
-
65
- set->eql = eqlFunc;
66
- set->trans = trans;
67
-
68
- set->default_value = NULL;
69
-
70
- set->table = (cpHashSetBin **)calloc(set->size, sizeof(cpHashSetBin *));
71
-
72
- return set;
73
- }
74
-
75
- cpHashSet *
76
- cpHashSetNew(int size, cpHashSetEqlFunc eqlFunc, cpHashSetTransFunc trans)
77
- {
78
- return cpHashSetInit(cpHashSetAlloc(), size, eqlFunc, trans);
79
- }
80
-
81
- static int
82
- setIsFull(cpHashSet *set)
83
- {
84
- return (set->entries >= set->size);
85
- }
86
-
87
- static void
88
- cpHashSetResize(cpHashSet *set)
89
- {
90
- // Get the next approximate doubled prime.
91
- int newSize = next_prime(set->size + 1);
92
- // Allocate a new table.
93
- cpHashSetBin **newTable = (cpHashSetBin **)calloc(newSize, sizeof(cpHashSetBin *));
94
-
95
- // Iterate over the chains.
96
- for(int i=0; i<set->size; i++){
97
- // Rehash the bins into the new table.
98
- cpHashSetBin *bin = set->table[i];
99
- while(bin){
100
- cpHashSetBin *next = bin->next;
101
-
102
- int index = bin->hash%newSize;
103
- bin->next = newTable[index];
104
- newTable[index] = bin;
105
-
106
- bin = next;
107
- }
108
- }
109
-
110
- free(set->table);
111
-
112
- set->table = newTable;
113
- set->size = newSize;
114
- }
115
-
116
- void *
117
- cpHashSetInsert(cpHashSet *set, unsigned int hash, void *ptr, void *data)
118
- {
119
- int index = hash%set->size;
120
-
121
- // Find the bin with the matching element.
122
- cpHashSetBin *bin = set->table[index];
123
- while(bin && !set->eql(ptr, bin->elt))
124
- bin = bin->next;
125
-
126
- // Create it necessary.
127
- if(!bin){
128
- bin = (cpHashSetBin *)malloc(sizeof(cpHashSetBin));
129
- bin->hash = hash;
130
- bin->elt = set->trans(ptr, data); // Transform the pointer.
131
-
132
- bin->next = set->table[index];
133
- set->table[index] = bin;
134
-
135
- set->entries++;
136
-
137
- // Resize the set if it's full.
138
- if(setIsFull(set))
139
- cpHashSetResize(set);
140
- }
141
-
142
- return bin->elt;
143
- }
144
-
145
- void *
146
- cpHashSetRemove(cpHashSet *set, unsigned int hash, void *ptr)
147
- {
148
- int index = hash%set->size;
149
-
150
- // Pointer to the previous bin pointer.
151
- cpHashSetBin **prev_ptr = &set->table[index];
152
- // Pointer the the current bin.
153
- cpHashSetBin *bin = set->table[index];
154
-
155
- // Find the bin
156
- while(bin && !set->eql(ptr, bin->elt)){
157
- prev_ptr = &bin->next;
158
- bin = bin->next;
159
- }
160
-
161
- // Remove it if it exists.
162
- if(bin){
163
- // Update the previos bin pointer to point to the next bin.
164
- (*prev_ptr) = bin->next;
165
- set->entries--;
166
-
167
- void *return_value = bin->elt;
168
- free(bin);
169
- return return_value;
170
- }
171
-
172
- return NULL;
173
- }
174
-
175
- void *
176
- cpHashSetFind(cpHashSet *set, unsigned int hash, void *ptr)
177
- {
178
- int index = hash%set->size;
179
- cpHashSetBin *bin = set->table[index];
180
- while(bin && !set->eql(ptr, bin->elt))
181
- bin = bin->next;
182
-
183
- return (bin ? bin->elt : set->default_value);
184
- }
185
-
186
- void
187
- cpHashSetEach(cpHashSet *set, cpHashSetIterFunc func, void *data)
188
- {
189
- for(int i=0; i<set->size; i++){
190
- cpHashSetBin *bin;
191
- for(bin = set->table[i]; bin; bin = bin->next)
192
- func(bin->elt, data);
193
- }
194
- }
195
-
196
- void
197
- cpHashSetReject(cpHashSet *set, cpHashSetRejectFunc func, void *data)
198
- {
199
- // Iterate over all the chains.
200
- for(int i=0; i<set->size; i++){
201
- // The rest works similarly to cpHashSetRemove() above.
202
- cpHashSetBin **prev_ptr = &set->table[i];
203
- cpHashSetBin *bin = set->table[i];
204
- while(bin){
205
- cpHashSetBin *next = bin->next;
206
-
207
- if(func(bin->elt, data)){
208
- prev_ptr = &bin->next;
209
- } else {
210
- (*prev_ptr) = next;
211
-
212
- set->entries--;
213
- free(bin);
214
- }
215
-
216
- bin = next;
217
- }
218
- }
219
- }