ray 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (167) hide show
  1. data/README.md +9 -6
  2. data/Rakefile +1 -5
  3. data/ext/audio.c +25 -19
  4. data/ext/audio_source.c +67 -39
  5. data/ext/color.c +19 -19
  6. data/ext/drawable.c +190 -31
  7. data/ext/extconf.rb +16 -14
  8. data/ext/gl.c +310 -30
  9. data/ext/gl_buffer.c +223 -2
  10. data/ext/gl_index_buffer.c +11 -0
  11. data/ext/gl_int_array.c +24 -22
  12. data/ext/gl_vertex.c +84 -49
  13. data/ext/image.c +115 -51
  14. data/ext/image_target.c +58 -10
  15. data/ext/input.c +73 -6
  16. data/ext/mo.c +583 -0
  17. data/ext/mo.h +189 -0
  18. data/ext/music.c +9 -8
  19. data/ext/pixel_bus.c +349 -0
  20. data/ext/polygon.c +68 -45
  21. data/ext/ray.c +1 -0
  22. data/ext/ray.h +19 -1
  23. data/ext/rect.c +9 -47
  24. data/ext/say.h +1 -2
  25. data/ext/say_all.h +6 -0
  26. data/ext/say_audio.h +3 -0
  27. data/ext/say_audio_context.c +1 -4
  28. data/ext/say_basic_type.c +24 -0
  29. data/ext/say_basic_type.h +4 -0
  30. data/ext/say_buffer.c +217 -88
  31. data/ext/say_buffer.h +20 -5
  32. data/ext/say_buffer_renderer.c +10 -7
  33. data/ext/say_buffer_renderer.h +1 -1
  34. data/ext/say_buffer_slice.c +70 -76
  35. data/ext/say_context.c +109 -22
  36. data/ext/say_context.h +14 -0
  37. data/ext/say_drawable.c +113 -25
  38. data/ext/say_drawable.h +23 -2
  39. data/ext/say_error.c +7 -2
  40. data/ext/say_font.c +30 -27
  41. data/ext/say_font.h +3 -6
  42. data/ext/say_get_proc.c +35 -0
  43. data/ext/say_image.c +102 -27
  44. data/ext/say_image.h +11 -4
  45. data/ext/say_image_target.c +88 -34
  46. data/ext/say_image_target.h +3 -2
  47. data/ext/say_index_buffer.c +31 -19
  48. data/ext/say_index_buffer.h +4 -2
  49. data/ext/say_index_buffer_slice.c +78 -70
  50. data/ext/say_music.c +4 -2
  51. data/ext/say_osx.h +3 -2
  52. data/ext/say_osx_context.h +37 -4
  53. data/ext/say_osx_window.h +32 -37
  54. data/ext/say_pixel_bus.c +163 -0
  55. data/ext/say_pixel_bus.h +44 -0
  56. data/ext/say_polygon.c +2 -2
  57. data/ext/say_shader.c +66 -62
  58. data/ext/say_shader.h +2 -0
  59. data/ext/say_sprite.c +1 -2
  60. data/ext/say_target.c +14 -23
  61. data/ext/say_target.h +3 -1
  62. data/ext/say_text.c +45 -7
  63. data/ext/say_text.h +12 -3
  64. data/ext/say_thread.c +13 -6
  65. data/ext/say_thread.h +1 -1
  66. data/ext/say_thread_variable.c +5 -5
  67. data/ext/say_vertex_type.c +79 -41
  68. data/ext/say_vertex_type.h +6 -2
  69. data/ext/say_view.c +10 -31
  70. data/ext/say_view.h +1 -5
  71. data/ext/say_win.h +2 -2
  72. data/ext/say_win_context.h +49 -11
  73. data/ext/say_win_window.h +30 -27
  74. data/ext/say_window.c +3 -3
  75. data/ext/say_x11.h +3 -1
  76. data/ext/say_x11_context.h +64 -10
  77. data/ext/say_x11_window.h +22 -17
  78. data/ext/shader.c +9 -0
  79. data/ext/sprite.c +7 -1
  80. data/ext/target.c +80 -28
  81. data/ext/text.c +43 -1
  82. data/ext/view.c +53 -1
  83. data/ext/window.c +4 -0
  84. data/lib/ray/animation_list.rb +17 -2
  85. data/lib/ray/audio_source.rb +11 -0
  86. data/lib/ray/color.rb +14 -0
  87. data/lib/ray/drawable.rb +23 -0
  88. data/lib/ray/dsl/event.rb +1 -9
  89. data/lib/ray/dsl/event_runner.rb +3 -4
  90. data/lib/ray/dsl/matcher.rb +20 -1
  91. data/lib/ray/effect.rb +116 -0
  92. data/lib/ray/effect/black_and_white.rb +38 -0
  93. data/lib/ray/effect/color_inversion.rb +16 -0
  94. data/lib/ray/effect/generator.rb +145 -0
  95. data/lib/ray/effect/grayscale.rb +32 -0
  96. data/lib/ray/game.rb +25 -5
  97. data/lib/ray/gl/vertex.rb +105 -26
  98. data/lib/ray/helper.rb +5 -0
  99. data/lib/ray/image.rb +54 -13
  100. data/lib/ray/image_target.rb +7 -0
  101. data/lib/ray/matrix.rb +26 -0
  102. data/lib/ray/music.rb +4 -0
  103. data/lib/ray/pixel_bus.rb +22 -0
  104. data/lib/ray/polygon.rb +17 -0
  105. data/lib/ray/pp.rb +28 -0
  106. data/lib/ray/ray.rb +7 -1
  107. data/lib/ray/rect.rb +7 -13
  108. data/lib/ray/scene.rb +24 -5
  109. data/lib/ray/scene_list.rb +9 -0
  110. data/lib/ray/shader.rb +11 -2
  111. data/lib/ray/sound.rb +4 -0
  112. data/lib/ray/sprite.rb +23 -62
  113. data/lib/ray/target.rb +25 -0
  114. data/lib/ray/text.rb +10 -0
  115. data/lib/ray/turtle.rb +9 -3
  116. data/lib/ray/vector.rb +18 -0
  117. data/lib/ray/vertex.rb +6 -0
  118. data/lib/ray/view.rb +22 -0
  119. data/samples/animation/sprite_motion.rb +0 -60
  120. data/samples/audio/{spacial.rb → spatial.rb} +1 -1
  121. data/samples/buffer/buffer.rb +1 -0
  122. data/samples/buffer/index_buffer.rb +2 -0
  123. data/samples/cptn_ruby/cptn_ruby.rb +6 -7
  124. data/samples/effects/effect.rb +39 -0
  125. data/samples/effects/grayscale.rb +27 -0
  126. data/samples/opengl/image.rb +7 -5
  127. data/samples/opengl/instancing.rb +159 -0
  128. data/samples/opengl/instancing.rbc +3231 -0
  129. data/samples/opengl/obj_loader.rb +9 -8
  130. data/samples/opengl/shader.rb +1 -3
  131. data/samples/shaders/geometry.rb +108 -38
  132. data/samples/shaders/geometry.rbc +2074 -0
  133. data/samples/shaders/shape.rb +2 -2
  134. data/samples/starfighter/starfighter.rb +5 -5
  135. data/samples/window/get_pixel.rb +1 -1
  136. data/test/animation_list_test.rb +18 -4
  137. data/test/drawable_test.rb +70 -1
  138. data/test/effect_generator_test.rb +63 -0
  139. data/test/effect_test.rb +61 -0
  140. data/test/game_test.rb +18 -0
  141. data/test/gl_buffer_test.rb +43 -1
  142. data/test/gl_index_buffer_test.rb +5 -0
  143. data/test/gl_vertex_test.rb +28 -1
  144. data/test/image_test.rb +5 -5
  145. data/test/input_test.rb +49 -0
  146. data/test/pixel_bus_test.rb +28 -0
  147. data/test/rect_test.rb +4 -0
  148. data/{samples/_media → test/res}/Beep.wav +0 -0
  149. data/samples/_media/CptnRuby Gem.png b/data/test/res/CptnRuby → Gem.png +0 -0
  150. data/samples/_media/CptnRuby Map.txt b/data/test/res/CptnRuby → Map.txt +0 -0
  151. data/samples/_media/CptnRuby Tileset.png b/data/test/res/CptnRuby → Tileset.png +0 -0
  152. data/{samples/_media → test/res}/CptnRuby.png +0 -0
  153. data/{samples/_media → test/res}/Space.png +0 -0
  154. data/{samples/_media → test/res}/Star.png +0 -0
  155. data/{samples/_media → test/res}/Starfighter.png +0 -0
  156. data/test/res/cube.obj +28 -0
  157. data/test/res/light3d.c +2 -2
  158. data/test/res/stone.png +0 -0
  159. data/test/scene_test.rb +3 -0
  160. data/test/sprite_test.rb +10 -0
  161. data/test/text_test.rb +31 -2
  162. data/test/view_test.rb +13 -1
  163. metadata +38 -17
  164. data/ext/say_array.c +0 -124
  165. data/ext/say_array.h +0 -34
  166. data/ext/say_table.c +0 -86
  167. data/ext/say_table.h +0 -24
@@ -0,0 +1,583 @@
1
+ #include "mo.h"
2
+
3
+ /**
4
+ * Dynamic array.
5
+ */
6
+
7
+ mo_array *mo_array_create(size_t el_size) {
8
+ mo_array *ret = malloc(sizeof(mo_array));
9
+ mo_array_init(ret, el_size);
10
+
11
+ return ret;
12
+ }
13
+
14
+ void mo_array_free(mo_array *ary) {
15
+ mo_array_release(ary);
16
+ free(ary);
17
+ }
18
+
19
+ void mo_array_init(mo_array *ary, size_t el_size) {
20
+ ary->buffer = malloc(el_size * 16);
21
+ ary->size = 0;
22
+ ary->capa = 16;
23
+ ary->el_size = el_size;
24
+
25
+ ary->init = NULL;
26
+ ary->release = NULL;
27
+ ary->copy = NULL;
28
+ }
29
+
30
+ void mo_array_release(mo_array *ary) {
31
+ if (ary->release && ary->size > 0) {
32
+ void *end = mo_array_end(ary);
33
+ for (void *i = mo_array_begin(ary); i < end; mo_array_next(ary, &i))
34
+ ary->release(i);
35
+ }
36
+
37
+ if (ary->buffer)
38
+ free(ary->buffer);
39
+ }
40
+
41
+ void *mo_array_quick_at(mo_array *ary, size_t i) {
42
+ return &((uint8_t*)ary->buffer)[i * ary->el_size];
43
+ }
44
+
45
+ void *mo_array_at(mo_array *ary, size_t i) {
46
+ return i >= ary->size ? NULL : mo_array_quick_at(ary, i);
47
+ }
48
+
49
+ void *mo_array_begin(mo_array *ary) {
50
+ return ary->buffer;
51
+ }
52
+
53
+ void *mo_array_end(mo_array *ary) {
54
+ return mo_array_quick_at(ary, ary->size);
55
+ }
56
+
57
+ void mo_array_next(mo_array *ary, void **ptr) {
58
+ *(uint8_t**)ptr += ary->el_size;
59
+ }
60
+
61
+ void mo_array_set(mo_array *ary, size_t i, void *obj) {
62
+ assert(i < ary->size);
63
+
64
+ void *cur = mo_array_quick_at(ary, i);
65
+ if (ary->release) ary->release(cur);
66
+
67
+ if (ary->copy)
68
+ ary->copy(cur, obj);
69
+ else
70
+ memcpy(cur, obj, ary->el_size);
71
+ }
72
+
73
+ void mo_array_insert(mo_array *ary, size_t i, void *obj) {
74
+ assert(i <= ary->size);
75
+
76
+ if (++ary->size > ary->capa) {
77
+ ary->buffer = realloc(ary->buffer, ary->capa * 2 * ary->el_size);
78
+ ary->capa *= 2;
79
+ }
80
+
81
+ void *ptr = mo_array_quick_at(ary, i);
82
+
83
+ if (ary->size - 1 != i) {
84
+ void *next = (void*)((uint8_t*)ptr + ary->el_size);
85
+ memmove(next, ptr, (ary->size - i) * ary->el_size);
86
+ }
87
+
88
+ if (ary->copy)
89
+ ary->copy(ptr, obj);
90
+ else
91
+ memcpy(ptr, obj, ary->el_size);
92
+ }
93
+
94
+ void mo_array_push(mo_array *ary, void *obj) {
95
+ mo_array_insert(ary, ary->size, obj);
96
+ }
97
+
98
+ void mo_array_delete(mo_array *ary, size_t i) {
99
+ assert(i < ary->size);
100
+
101
+ void *ptr = mo_array_quick_at(ary, i);
102
+ if (ary->release) ary->release(ptr);
103
+
104
+ if (i != ary->size - 1) {
105
+ void *next = (void*)((uint8_t*)ptr + ary->el_size);
106
+ memmove(ptr, next, (ary->size - i) * ary->el_size);
107
+ }
108
+
109
+ ary->size--;
110
+ }
111
+
112
+ mo_array mo_array_dup(mo_array *ary) {
113
+ mo_array ret;
114
+ mo_array_copy(&ret, ary);
115
+
116
+ return ret;
117
+ }
118
+
119
+ void mo_array_copy(mo_array *dst, mo_array *src) {
120
+ dst->buffer = malloc(src->el_size * src->size);
121
+ dst->size = src->size;
122
+ dst->capa = src->size;
123
+ dst->el_size = src->el_size;
124
+
125
+ dst->init = src->init;
126
+ dst->release = src->release;
127
+ dst->copy = src->copy;
128
+
129
+ if (dst->copy) {
130
+ void *src_end = mo_array_end(src);
131
+ for (void *src_ptr = mo_array_begin(src), *dst_ptr = mo_array_begin(dst);
132
+ src_ptr < src_end;
133
+ mo_array_next(src, &src_ptr), mo_array_next(dst, &dst_ptr)) {
134
+ dst->copy(dst_ptr, src_ptr);
135
+ }
136
+ }
137
+ else
138
+ memcpy(dst->buffer, src->buffer, dst->size * dst->el_size);
139
+ }
140
+
141
+ mo_array *mo_array_qsort(mo_array *ary, mo_cmp cmp) {
142
+ qsort(ary->buffer, ary->size, ary->el_size, cmp);
143
+ return ary;
144
+ }
145
+
146
+ void mo_array_resize(mo_array *ary, size_t size) {
147
+ mo_array_reserve(ary, size);
148
+
149
+ if (size > ary->size && ary->init) {
150
+ void *end = mo_array_quick_at(ary, size);
151
+ for (void *i = mo_array_quick_at(ary, ary->size); i < end;
152
+ mo_array_next(ary, &i)) {
153
+ ary->init(i);
154
+ }
155
+ }
156
+ else if (size < ary->size && ary->release) {
157
+ void *end = mo_array_quick_at(ary, ary->size);
158
+ for (void *i = mo_array_quick_at(ary, size); i < end;
159
+ mo_array_next(ary, &i)) {
160
+ ary->release(i);
161
+ }
162
+ }
163
+
164
+ ary->size = size;
165
+ }
166
+
167
+ void mo_array_reserve(mo_array *ary, size_t size) {
168
+ if (ary->capa > size)
169
+ return;
170
+
171
+ ary->buffer = realloc(ary->buffer, size * ary->el_size);
172
+ ary->capa = size;
173
+ }
174
+
175
+ void mo_array_shrink(mo_array *ary) {
176
+ if (ary->capa == ary->size) return;
177
+ ary->buffer = realloc(ary->buffer, ary->size * ary->el_size);
178
+ ary->capa = ary->size;
179
+ }
180
+
181
+ /**
182
+ * Doubly linked list.
183
+ */
184
+
185
+ mo_list *mo_list_create(size_t el_size) {
186
+ mo_list *list = malloc(sizeof(mo_list) + el_size);
187
+
188
+ list->prev = list->next = NULL;
189
+
190
+ list->release = NULL;
191
+ list->copy = NULL;
192
+
193
+ list->el_size = el_size;
194
+
195
+ return list;
196
+ }
197
+
198
+ void mo_list_free(mo_list *list) {
199
+ do {
200
+ mo_list *next = list->next;
201
+
202
+ if (list->release)
203
+ list->release(list->data);
204
+ free(list);
205
+
206
+ list = next;
207
+ } while (list);
208
+ }
209
+
210
+ mo_list *mo_list_prepend(mo_list *list, void *data) {
211
+ mo_list *prev = malloc(sizeof(mo_list) + list->el_size);
212
+
213
+ prev->prev = list->prev;
214
+ prev->next = list;
215
+
216
+ if (list->prev)
217
+ list->prev->next = list;
218
+
219
+ list->prev = prev;
220
+
221
+ prev->release = list->release;
222
+ prev->copy = list->copy;
223
+
224
+ prev->el_size = list->el_size;
225
+
226
+ if (prev->copy)
227
+ prev->copy(prev->data, data);
228
+ else if (data)
229
+ memcpy(prev->data, data, prev->el_size);
230
+
231
+ return prev;
232
+ }
233
+
234
+ mo_list *mo_list_insert(mo_list *list, void *data) {
235
+ mo_list *next = malloc(sizeof(mo_list) + list->el_size);
236
+
237
+ next->prev = list;
238
+ next->next = list->next;
239
+
240
+ if (list->next)
241
+ list->next->prev = next;
242
+
243
+ list->next = next;
244
+
245
+ next->release = list->release;
246
+ next->copy = list->copy;
247
+
248
+ next->el_size = list->el_size;
249
+
250
+ if (next->copy)
251
+ next->copy(next->data, data);
252
+ else if (data)
253
+ memcpy(next->data, data, next->el_size);
254
+
255
+ return next;
256
+ }
257
+
258
+ mo_list *mo_list_delete(mo_list *list) {
259
+ if (list->prev)
260
+ list->prev->next = list->next;
261
+
262
+ if (list->next)
263
+ list->next->prev = list->prev;
264
+
265
+ mo_list *next = list->next;
266
+
267
+ if (list->release)
268
+ list->release(list->data);
269
+ free(list);
270
+
271
+ return next;
272
+ }
273
+
274
+ void mo_list_set(mo_list *list, void *data) {
275
+ if (list->copy)
276
+ list->copy(list->data, data);
277
+ else
278
+ memcpy(list->data, data, list->el_size);
279
+ }
280
+
281
+ /**
282
+ * Hash table.
283
+ */
284
+
285
+ static
286
+ void mo_hash_zero_ptr(void *ptr) {
287
+ *(void**)ptr = NULL;
288
+ }
289
+
290
+ static
291
+ void mo_hash_list_free(void *ptr) {
292
+ mo_list *list = *(mo_list**)ptr;
293
+ if (list) mo_list_free(list);
294
+ }
295
+
296
+ static
297
+ void mo_hash_bucket_free(void *ptr) {
298
+ uint8_t *start = ptr;
299
+
300
+ mo_hash *hash = *(mo_hash**)start;
301
+ if (!hash)
302
+ return;
303
+
304
+ if (hash->key_release)
305
+ hash->key_release(start + sizeof(mo_hash*));
306
+
307
+ if (hash->release)
308
+ hash->release(start + sizeof(mo_hash*) + hash->key_size);
309
+ }
310
+
311
+ static
312
+ void mo_hash_init(mo_hash *hash, size_t key_size, size_t el_size) {
313
+ mo_array_init(&hash->buffer, sizeof(mo_list*));
314
+
315
+ hash->buffer.init = mo_hash_zero_ptr;
316
+ mo_array_resize(&hash->buffer, 16);
317
+ hash->buffer.release = mo_hash_list_free;
318
+
319
+ hash->release = NULL;
320
+ hash->copy = NULL;
321
+
322
+ hash->key_release = NULL;
323
+ hash->key_copy = NULL;
324
+ hash->key_cmp = NULL;
325
+
326
+ hash->size = 0;
327
+
328
+ hash->el_size = el_size;
329
+ hash->key_size = key_size;
330
+
331
+ hash->hash_of = NULL;
332
+ }
333
+
334
+ static
335
+ void mo_hash_release(mo_hash *hash) {
336
+ mo_array_release(&hash->buffer);
337
+ }
338
+
339
+ mo_hash *mo_hash_create(size_t key_size, size_t el_size) {
340
+ mo_hash *ret = malloc(sizeof(mo_hash));
341
+ mo_hash_init(ret, key_size, el_size);
342
+ return ret;
343
+ }
344
+
345
+ void mo_hash_free(mo_hash *hash) {
346
+ mo_hash_release(hash);
347
+ free(hash);
348
+ }
349
+
350
+ bool mo_hash_has_key(mo_hash *hash, void *key) {
351
+ int id = hash->hash_of(key) % hash->buffer.size;
352
+ mo_list *bucket = mo_array_get_as(&hash->buffer, id, mo_list*);
353
+
354
+ while (bucket) {
355
+ if (hash->key_cmp(bucket->data + sizeof(mo_hash*), key) == 0)
356
+ return true;
357
+ bucket = bucket->next;
358
+ }
359
+
360
+ return false;
361
+ }
362
+
363
+ void *mo_hash_get(mo_hash *hash, void *key) {
364
+ int id = hash->hash_of(key) % hash->buffer.size;
365
+ mo_list *bucket = mo_array_get_as(&hash->buffer, id, mo_list*);
366
+
367
+ while (bucket) {
368
+ if (hash->key_cmp(bucket->data + sizeof(mo_hash*), key) == 0)
369
+ return bucket->data + sizeof(mo_hash*) + hash->key_size;
370
+ bucket = bucket->next;
371
+ }
372
+
373
+ return NULL;
374
+ }
375
+
376
+ static
377
+ void mo_hash_grow(mo_hash *hash) {
378
+ /*
379
+ * Create a bigger hash, and push the current values there.
380
+ */
381
+ mo_hash copy;
382
+ mo_hash_init(&copy, hash->key_size, hash->el_size);
383
+ mo_array_resize(&copy.buffer, hash->buffer.size * 2);
384
+
385
+ copy.release = hash->release;
386
+ copy.copy = hash->copy;
387
+
388
+ copy.key_release = hash->key_release;
389
+ copy.key_copy = hash->key_copy;
390
+ copy.key_cmp = hash->key_cmp;
391
+
392
+ copy.hash_of = hash->hash_of;
393
+
394
+ mo_hash_it it = mo_hash_begin(hash);
395
+ for (; !mo_hash_it_is_end(&it); mo_hash_it_next(&it)) {
396
+ void *key = mo_hash_it_key(&it);
397
+ void *val = mo_hash_it_val(&it);
398
+
399
+ mo_hash_set(&copy, key, val);
400
+ }
401
+
402
+ /*
403
+ * Release the current hash, and use the copy instead.
404
+ */
405
+ mo_hash_release(hash);
406
+ *hash = copy;
407
+
408
+ /*
409
+ * Because each element actually contains a pointer to the hash, we need to
410
+ * update it.
411
+ */
412
+
413
+ it = mo_hash_begin(hash);
414
+ for (; !mo_hash_it_is_end(&it); mo_hash_it_next(&it)) {
415
+ mo_hash **data = (mo_hash**)(it.list->data);
416
+ *data = hash;
417
+ }
418
+ }
419
+
420
+ static
421
+ void mo_hash_fill_bucket(mo_hash *hash, void *store, void *key, void *data) {
422
+ *(mo_hash**)store = hash;
423
+
424
+ if (hash->key_copy)
425
+ hash->key_copy((uint8_t*)store + sizeof(mo_hash*), key);
426
+ else
427
+ memcpy((uint8_t*)store + sizeof(mo_hash*), key, hash->key_size);
428
+
429
+ if (hash->copy)
430
+ hash->copy((uint8_t*)store + sizeof(mo_hash*) + hash->key_size, data);
431
+ else
432
+ memcpy((uint8_t*)store + sizeof(mo_hash*) + hash->key_size, data,
433
+ hash->el_size);
434
+ }
435
+
436
+ void mo_hash_set(mo_hash *hash, void *key, void *data) {
437
+ if (hash->size + 1 > hash->buffer.size)
438
+ mo_hash_grow(hash);
439
+
440
+ int id = hash->hash_of(key) % hash->buffer.size;
441
+ mo_list *bucket = mo_array_get_as(&hash->buffer, id, mo_list*);
442
+
443
+ hash->size += 1;
444
+
445
+ if (!bucket) {
446
+ bucket = mo_list_create(sizeof(mo_hash*) + hash->key_size + hash->el_size);
447
+ bucket->release = mo_hash_bucket_free;
448
+
449
+ mo_hash_fill_bucket(hash, bucket->data, key, data);
450
+
451
+ mo_array_get_as(&hash->buffer, id, mo_list*) = bucket;
452
+ }
453
+ else {
454
+ mo_list *it = bucket, *last = bucket;
455
+ while (it) {
456
+ if (hash->key_cmp(it->data + sizeof(mo_hash*), key) == 0) {
457
+ hash->size -= 1;
458
+
459
+ if (hash->copy) {
460
+ hash->copy(it->data + sizeof(mo_hash*) + hash->key_size, data);
461
+ }
462
+ else {
463
+ memcpy(it->data + sizeof(mo_hash*) + hash->key_size, data,
464
+ hash->el_size);
465
+ }
466
+
467
+ return;
468
+ }
469
+
470
+ last = it;
471
+ it = it->next;
472
+ }
473
+
474
+ last = mo_list_insert(last, NULL);
475
+ mo_hash_fill_bucket(hash, last->data, key, data);
476
+ }
477
+ }
478
+
479
+ void mo_hash_del(mo_hash *hash, void *key) {
480
+ int id = hash->hash_of(key) % hash->buffer.size;
481
+ mo_list *bucket = mo_array_get_as(&hash->buffer, id, mo_list*);
482
+
483
+ mo_list *it = bucket, *next = bucket->next;
484
+ while (it) {
485
+ if (hash->key_cmp(it->data + sizeof(mo_hash*), key) == 0) {
486
+ hash->size -= 1;
487
+ mo_list_delete(it);
488
+ break;
489
+ }
490
+
491
+ it = it->next;
492
+ }
493
+
494
+ if (it == bucket) /* Head changed */
495
+ mo_array_get_as(&hash->buffer, id, mo_list*) = next;
496
+ }
497
+
498
+ mo_hash_it mo_hash_begin(mo_hash *hash) {
499
+ mo_hash_it ret = {
500
+ hash,
501
+ NULL,
502
+ 0
503
+ };
504
+
505
+ for (ret.id = 0; ret.id < hash->buffer.size; ret.id++) {
506
+ mo_list *bucket = mo_array_get_as(&hash->buffer, ret.id, mo_list*);
507
+ if (bucket) {
508
+ ret.list = bucket;
509
+ break;
510
+ }
511
+ }
512
+
513
+ return ret;
514
+ }
515
+
516
+ bool mo_hash_it_is_end(mo_hash_it *it) {
517
+ return it->list == NULL;
518
+ }
519
+
520
+ void *mo_hash_it_key(mo_hash_it *it) {
521
+ return it->list->data + sizeof(mo_hash*);
522
+ }
523
+
524
+ void *mo_hash_it_val(mo_hash_it *it) {
525
+ return it->list->data + sizeof(mo_hash*) + it->hash->key_size;
526
+ }
527
+
528
+ void mo_hash_it_next(mo_hash_it *it) {
529
+ if (it->list->next)
530
+ it->list = it->list->next;
531
+ else {
532
+ it->list = NULL;
533
+
534
+ for (it->id++; it->id < it->hash->buffer.size; it->id++) {
535
+ mo_list *bucket = mo_array_get_as(&it->hash->buffer, it->id, mo_list*);
536
+ if (bucket) {
537
+ it->list = bucket;
538
+ return;
539
+ }
540
+ }
541
+ }
542
+ }
543
+
544
+ /*
545
+ * Used in magical computations.
546
+ */
547
+ #define MAGIC_NUMBER 2654435761
548
+
549
+ int mo_hash_of_pointer(void *ptr) {
550
+ return (long)(*(void**)ptr) * MAGIC_NUMBER;
551
+ }
552
+
553
+ int mo_hash_pointer_cmp(const void *a, const void *b) {
554
+ void *first = *(void**)a, *sec = *(void**)b;
555
+
556
+ if (first > sec) return +1;
557
+ else if (sec > first) return -1;
558
+ else return +0;
559
+ }
560
+
561
+ int mo_hash_of_u32(void *ptr) {
562
+ return (*(uint32_t*)ptr) * MAGIC_NUMBER;
563
+ }
564
+
565
+ int mo_hash_u32_cmp(const void *a, const void *b) {
566
+ uint32_t first = *(uint32_t*)a, sec = *(uint32_t*)b;
567
+
568
+ if (first > sec) return +1;
569
+ else if (sec > first) return -1;
570
+ else return +0;
571
+ }
572
+
573
+ int mo_hash_of_size(void *ptr) {
574
+ return (*(size_t*)ptr) * MAGIC_NUMBER;
575
+ }
576
+
577
+ int mo_hash_size_cmp(const void *a, const void *b) {
578
+ size_t first = *(size_t*)a, sec = *(size_t*)b;
579
+
580
+ if (first > sec) return +1;
581
+ else if (sec > first) return -1;
582
+ else return +0;
583
+ }