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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
- }