ray 0.2.0 → 0.2.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c843cd687fe51478f64ee9e801e9ee9132f6ee4b
4
+ data.tar.gz: dc17809793037e626252a10c884847236cd0834b
5
+ SHA512:
6
+ metadata.gz: b94b4d5571a75a68ddd840ddae8987c0ac4e71a7823f5019021ac9ea127f03658c7c582c9c6bba81ecc44732d4e4510a8c557964c242373d194d8d9bcca3377e
7
+ data.tar.gz: 8c4e58c2d0d9df0817349e4e1cc662b7e1645876435b44dd4f2dd62ab364e3510b0468f8ec5ab87ea9e1ef2631c9cececdd6ae0d18dfca38693eb5fd439e68fb
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Ray - Copyright (c) 2011 - Mon ouïe
2
+
3
+ This software is provided 'as-is', without any express or
4
+ implied warranty. In no event will the authors be held
5
+ liable for any damages arising from the use of this software.
6
+
7
+ Permission is granted to anyone to use this software for any purpose,
8
+ including commercial applications, and to alter it and redistribute
9
+ it freely, subject to the following restrictions:
10
+
11
+ 1. The origin of this software must not be misrepresented;
12
+ you must not claim that you wrote the original software.
13
+ If you use this software in a product, an acknowledgment
14
+ in the product documentation would be appreciated but
15
+ is not required.
16
+
17
+ 2. Altered source versions must be plainly marked as such,
18
+ and must not be misrepresented as being the original software.
19
+
20
+ 3. This notice may not be removed or altered from any
21
+ source distribution.
data/README.md CHANGED
@@ -261,4 +261,3 @@ using Ray's animation objects:
261
261
 
262
262
  (They can really be used to animate any change, not just those that are visible,
263
263
  and not just those applied to a drawable.)
264
-
@@ -123,6 +123,8 @@ VALUE ray_drawable_alloc(VALUE self) {
123
123
 
124
124
  VALUE rb = Data_Wrap_Struct(self, NULL, ray_drawable_free, obj);
125
125
 
126
+ rb_iv_set(rb, "@shader_attributes", Qnil);
127
+
126
128
  obj->drawable = NULL;
127
129
  obj->obj = rb;
128
130
 
@@ -389,6 +391,23 @@ VALUE ray_drawable_set_matrix(VALUE self, VALUE val) {
389
391
  return val;
390
392
  }
391
393
 
394
+ /*
395
+ * @overload default_matrix
396
+ * Default transformation matrix
397
+ *
398
+ * This is useful when matrix is set to a custom matrix or matrix_proc is
399
+ * non-nil. It allows to retrieve the matrix that would be used otherwise, for
400
+ * instance to multiply it by another matrix to apply more transformations.
401
+ *
402
+ * @return [Ray::Matrix]
403
+ */
404
+ static
405
+ VALUE ray_drawable_default_matrix(VALUE self) {
406
+ say_matrix *mat = say_drawable_get_default_matrix(ray_rb2drawable(self));
407
+ return Data_Wrap_Struct(rb_path2class("Ray::Matrix"), NULL, say_matrix_free,
408
+ mat);
409
+ }
410
+
392
411
  /*
393
412
  * @overload transform(point)
394
413
  * Applies the transformations to a point
@@ -577,6 +596,8 @@ void Init_ray_drawable() {
577
596
 
578
597
  rb_define_method(ray_cDrawable, "matrix", ray_drawable_matrix, 0);
579
598
  rb_define_method(ray_cDrawable, "matrix=", ray_drawable_set_matrix, 1);
599
+ rb_define_method(ray_cDrawable, "default_matrix",
600
+ ray_drawable_default_matrix, 0);
580
601
  rb_define_method(ray_cDrawable, "transform", ray_drawable_transform, 1);
581
602
  /* @endgroup */
582
603
 
@@ -1,6 +1,6 @@
1
1
  require 'mkmf'
2
2
 
3
- $CFLAGS << " -Wextra -Wall -Wno-unused-parameter -std=gnu99"
3
+ $CFLAGS << " -Wextra -Wall -Wno-unused-parameter -std=gnu99 "
4
4
 
5
5
  unless RUBY_PLATFORM =~ /mingw/
6
6
  $CFLAGS << " " << `freetype-config --cflags`.chomp
@@ -230,12 +230,29 @@ VALUE ray_image_tex_rect(VALUE self, VALUE rect) {
230
230
  /*
231
231
  * Binds the texture, which will be used as GL_TEXTURE_2D when drawing with
232
232
  * OpenGL
233
+ *
234
+ * This is equivalent to calling #bind_to with unit set to 0.
233
235
  */
234
236
  VALUE ray_image_bind(VALUE self) {
235
237
  say_image_bind(ray_rb2image(self));
236
238
  return self;
237
239
  }
238
240
 
241
+ /*
242
+ * @overload bind_to(unit)
243
+ * Binds the texture to a given unit (0 <= unit < 32)
244
+ * @param [Integer] unit Texture unit
245
+ */
246
+ VALUE ray_image_bind_to(VALUE self, VALUE unit) {
247
+ int c_unit = NUM2INT(unit);
248
+ if (c_unit >= 32 || c_unit < 0)
249
+ rb_raise(rb_eRangeError, "texture unit %d out of bounds", c_unit);
250
+
251
+ say_image_bind_to(ray_rb2image(self), c_unit);
252
+
253
+ return self;
254
+ }
255
+
239
256
  /*
240
257
  * @return [Integer] Identifer of the image's texture
241
258
  */
@@ -322,6 +339,7 @@ void Init_ray_image() {
322
339
 
323
340
  /* @group OpenGL access */
324
341
  rb_define_method(ray_cImage, "bind", ray_image_bind, 0);
342
+ rb_define_method(ray_cImage, "bind_to", ray_image_bind_to, 1);
325
343
  rb_define_method(ray_cImage, "texture", ray_image_texture, 0);
326
344
  /* @endgroup */
327
345
  }
@@ -336,6 +336,33 @@ VALUE ray_matrix_perspective(VALUE self,
336
336
  return self;
337
337
  }
338
338
 
339
+ /*
340
+ * @overload set_transformation(origin, pos, z, scale, angle)
341
+ * Resets the matrix content to a 2D transformation matrix
342
+ *
343
+ * @param [Vector2] origin Origin of all the transformations
344
+ * @param [Vector2] pos Position of the object
345
+ * @param [Float] z Z ordering
346
+ * @param [Vector2] scale Scaling factor
347
+ * @param [Float] angle Rotation
348
+ */
349
+ static
350
+ VALUE ray_matrix_set_transformation(VALUE self,
351
+ VALUE origin,
352
+ VALUE pos, VALUE z,
353
+ VALUE scale,
354
+ VALUE angle) {
355
+ rb_check_frozen(self);
356
+
357
+ say_matrix_set_transformation(ray_rb2matrix(self),
358
+ ray_convert_to_vector2(origin),
359
+ ray_convert_to_vector2(pos),
360
+ NUM2DBL(z),
361
+ ray_convert_to_vector2(scale),
362
+ NUM2DBL(angle));
363
+
364
+ return self;
365
+ }
339
366
 
340
367
  /*
341
368
  Document-class: Ray::Matrix
@@ -371,4 +398,6 @@ void Init_ray_matrix() {
371
398
  rb_define_method(ray_cMatrix, "look_at", ray_matrix_look_at, 3);
372
399
  rb_define_method(ray_cMatrix, "orthogonal", ray_matrix_orthogonal, 6);
373
400
  rb_define_method(ray_cMatrix, "perspective", ray_matrix_perspective, 4);
401
+ rb_define_method(ray_cMatrix, "set_transformation",
402
+ ray_matrix_set_transformation, 5);
374
403
  }
data/ext/mo.c CHANGED
@@ -28,7 +28,7 @@ void mo_array_init(mo_array *ary, size_t el_size) {
28
28
  }
29
29
 
30
30
  void mo_array_release(mo_array *ary) {
31
- if (ary->release && ary->size > 0) {
31
+ if (ary->release) {
32
32
  void *end = mo_array_end(ary);
33
33
  for (void *i = mo_array_begin(ary); i < end; mo_array_next(ary, &i))
34
34
  ary->release(i);
@@ -168,114 +168,174 @@ void mo_array_reserve(mo_array *ary, size_t size) {
168
168
  if (ary->capa > size)
169
169
  return;
170
170
 
171
- ary->buffer = realloc(ary->buffer, size * ary->el_size);
171
+ ary->buffer = realloc(ary->buffer, size * ary->capa);
172
172
  ary->capa = size;
173
173
  }
174
174
 
175
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);
176
+ ary->buffer = realloc(ary->buffer, ary->size * ary->capa);
178
177
  ary->capa = ary->size;
179
178
  }
180
179
 
181
180
  /**
182
- * Doubly linked list.
181
+ * String.
183
182
  */
184
183
 
185
- mo_list *mo_list_create(size_t el_size) {
186
- mo_list *list = malloc(sizeof(mo_list) + el_size);
184
+ void mo_string_init(mo_string *str) {
185
+ mo_array_init(str, sizeof(char));
186
+ mo_array_resize(str, 1);
187
+ mo_string_at(str, 0) = '\0';
188
+ }
189
+
190
+ void mo_string_init_from_cstr(mo_string *str, const char *cstr) {
191
+ mo_string_init(str);
192
+ mo_string_replace(str, cstr);
193
+ }
194
+
195
+ void mo_string_init_from_buf(mo_string *str, const char *cstr, size_t size) {
196
+ mo_string_init(str);
197
+ mo_array_resize(str, size + 1);
198
+ memcpy(mo_string_cstr(str), cstr, size);
199
+ mo_string_at(str, size) = '\0';
200
+ }
201
+
202
+ void mo_string_replace(mo_string *str, const char *cstr) {
203
+ mo_array_resize(str, strlen(cstr) + 1);
204
+ strcpy(mo_string_cstr(str), cstr);
205
+ }
206
+
207
+ size_t mo_string_len(mo_string *str) {
208
+ return str->size - 1;
209
+ }
210
+
211
+ void mo_string_append(mo_string *str, const char *cstr) {
212
+ size_t old_size = str->size;
213
+
214
+ mo_array_resize(str, old_size + strlen(cstr));
215
+ strcpy(mo_array_get_ptr(str, old_size - 1, char), cstr);
216
+ }
217
+
218
+ char *mo_string_cstr(mo_string *str) {
219
+ return (char*)str->buffer;
220
+ }
221
+
222
+ int mo_string_cmp(mo_string *a, mo_string *b) {
223
+ return strcmp(mo_string_cstr(a), mo_string_cstr(b));
224
+ }
225
+
226
+ /**
227
+ * Doubly linked list.
228
+ */
187
229
 
188
- list->prev = list->next = NULL;
230
+ void mo_list_init(mo_list *list, size_t el_size) {
231
+ list->head = list->last = NULL;
189
232
 
190
233
  list->release = NULL;
191
234
  list->copy = NULL;
192
235
 
193
236
  list->el_size = el_size;
194
-
195
- return list;
196
237
  }
197
238
 
198
- void mo_list_free(mo_list *list) {
199
- do {
200
- mo_list *next = list->next;
239
+ void mo_list_release(mo_list *list) {
240
+ mo_list_it *it = list->head;
241
+
242
+ while (it) {
243
+ mo_list_it *next = it->next;
201
244
 
202
245
  if (list->release)
203
- list->release(list->data);
204
- free(list);
246
+ list->release(it->data);
247
+ free(it);
205
248
 
206
- list = next;
207
- } while (list);
249
+ it = next;
250
+ }
208
251
  }
209
252
 
210
- mo_list *mo_list_prepend(mo_list *list, void *data) {
211
- mo_list *prev = malloc(sizeof(mo_list) + list->el_size);
253
+ mo_list *mo_list_create(size_t el_size) {
254
+ mo_list *list = malloc(sizeof(mo_list));
255
+ mo_list_init(list, el_size);
256
+ return list;
257
+ }
212
258
 
213
- prev->prev = list->prev;
214
- prev->next = list;
259
+ void mo_list_free(mo_list *list) {
260
+ mo_list_release(list);
261
+ free(list);
262
+ }
215
263
 
216
- if (list->prev)
217
- list->prev->next = list;
264
+ void mo_list_prepend(mo_list *list, mo_list_it *it, void *data) {
265
+ mo_list_it *new_it = malloc(offsetof(mo_list_it, data) + list->el_size);
218
266
 
219
- list->prev = prev;
267
+ new_it->next = it;
220
268
 
221
- prev->release = list->release;
222
- prev->copy = list->copy;
269
+ if (it && it->prev) {
270
+ new_it->prev = it->prev;
271
+ it->prev->next = new_it;
272
+ }
273
+ else
274
+ new_it->prev = NULL;
223
275
 
224
- prev->el_size = list->el_size;
276
+ if (it)
277
+ it->prev = new_it;
225
278
 
226
- if (prev->copy)
227
- prev->copy(prev->data, data);
228
- else if (data)
229
- memcpy(prev->data, data, prev->el_size);
279
+ if (!list->last)
280
+ list->last = new_it;
230
281
 
231
- return prev;
232
- }
282
+ if (it == list->head)
283
+ list->head = new_it;
233
284
 
234
- mo_list *mo_list_insert(mo_list *list, void *data) {
235
- mo_list *next = malloc(sizeof(mo_list) + list->el_size);
285
+ if (list->copy)
286
+ list->copy(new_it->data, data);
287
+ else
288
+ memcpy(new_it->data, data, list->el_size);
289
+ }
236
290
 
237
- next->prev = list;
238
- next->next = list->next;
291
+ void mo_list_insert(mo_list *list, mo_list_it *it, void *data) {
292
+ mo_list_it *new_it = malloc(offsetof(mo_list_it, data) + list->el_size);
239
293
 
240
- if (list->next)
241
- list->next->prev = next;
294
+ new_it->prev = it;
242
295
 
243
- list->next = next;
296
+ if (it && it->next) {
297
+ new_it->next = it->next;
298
+ it->next->prev = new_it;
299
+ }
300
+ else
301
+ new_it->next = NULL;
244
302
 
245
- next->release = list->release;
246
- next->copy = list->copy;
303
+ if (it)
304
+ it->next = new_it;
247
305
 
248
- next->el_size = list->el_size;
306
+ if (!list->head)
307
+ list->head = new_it;
249
308
 
250
- if (next->copy)
251
- next->copy(next->data, data);
252
- else if (data)
253
- memcpy(next->data, data, next->el_size);
309
+ if (it == list->last)
310
+ list->last = new_it;
254
311
 
255
- return next;
312
+ if (list->copy)
313
+ list->copy(new_it->data, data);
314
+ else
315
+ memcpy(new_it->data, data, list->el_size);
256
316
  }
257
317
 
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;
318
+ void mo_list_delete(mo_list *list, mo_list_it *it) {
319
+ if (it->prev)
320
+ it->prev->next = it->next;
321
+ else /* is head */
322
+ list->head = it->next;
264
323
 
265
- mo_list *next = list->next;
324
+ if (it->next)
325
+ it->next->prev = it->prev;
326
+ else /* is tail */
327
+ list->last = it->prev;
266
328
 
267
329
  if (list->release)
268
- list->release(list->data);
269
- free(list);
270
-
271
- return next;
330
+ list->release(it->data);
331
+ free(it);
272
332
  }
273
333
 
274
- void mo_list_set(mo_list *list, void *data) {
334
+ void mo_list_set(mo_list *list, mo_list_it *it, void *data) {
275
335
  if (list->copy)
276
- list->copy(list->data, data);
336
+ list->copy(it->data, data);
277
337
  else
278
- memcpy(list->data, data, list->el_size);
338
+ memcpy(it->data, data, list->el_size);
279
339
  }
280
340
 
281
341
  /**
@@ -287,34 +347,11 @@ void mo_hash_zero_ptr(void *ptr) {
287
347
  *(void**)ptr = NULL;
288
348
  }
289
349
 
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
350
  void mo_hash_init(mo_hash *hash, size_t key_size, size_t el_size) {
313
- mo_array_init(&hash->buffer, sizeof(mo_list*));
351
+ mo_array_init(&hash->buffer, sizeof(mo_hash_list*));
314
352
 
315
- hash->buffer.init = mo_hash_zero_ptr;
353
+ hash->buffer.init = mo_hash_zero_ptr;
316
354
  mo_array_resize(&hash->buffer, 16);
317
- hash->buffer.release = mo_hash_list_free;
318
355
 
319
356
  hash->release = NULL;
320
357
  hash->copy = NULL;
@@ -331,8 +368,23 @@ void mo_hash_init(mo_hash *hash, size_t key_size, size_t el_size) {
331
368
  hash->hash_of = NULL;
332
369
  }
333
370
 
334
- static
335
371
  void mo_hash_release(mo_hash *hash) {
372
+ for (size_t i = 0; i < hash->buffer.size; i++) {
373
+ mo_hash_list *it = mo_array_get_as(&hash->buffer, i, mo_hash_list*);
374
+
375
+ while (it) {
376
+ mo_hash_list *next = it->next;
377
+
378
+ if (hash->key_release)
379
+ hash->key_release(it->data);
380
+ if (hash->release)
381
+ hash->release(it->data + hash->key_size);
382
+ free(it);
383
+
384
+ it = next;
385
+ }
386
+ }
387
+
336
388
  mo_array_release(&hash->buffer);
337
389
  }
338
390
 
@@ -349,12 +401,11 @@ void mo_hash_free(mo_hash *hash) {
349
401
 
350
402
  bool mo_hash_has_key(mo_hash *hash, void *key) {
351
403
  int id = hash->hash_of(key) % hash->buffer.size;
352
- mo_list *bucket = mo_array_get_as(&hash->buffer, id, mo_list*);
404
+ mo_hash_list *it = mo_array_get_as(&hash->buffer, id, mo_hash_list*);
353
405
 
354
- while (bucket) {
355
- if (hash->key_cmp(bucket->data + sizeof(mo_hash*), key) == 0)
406
+ for (; it; it = it->next) {
407
+ if (hash->key_cmp(it->data, key) == 0)
356
408
  return true;
357
- bucket = bucket->next;
358
409
  }
359
410
 
360
411
  return false;
@@ -362,12 +413,11 @@ bool mo_hash_has_key(mo_hash *hash, void *key) {
362
413
 
363
414
  void *mo_hash_get(mo_hash *hash, void *key) {
364
415
  int id = hash->hash_of(key) % hash->buffer.size;
365
- mo_list *bucket = mo_array_get_as(&hash->buffer, id, mo_list*);
416
+ mo_hash_list *it = mo_array_get_as(&hash->buffer, id, mo_hash_list*);
366
417
 
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;
418
+ for (; it; it = it->next) {
419
+ if (hash->key_cmp(it->data, key) == 0)
420
+ return it->data + hash->key_size;
371
421
  }
372
422
 
373
423
  return NULL;
@@ -402,34 +452,22 @@ void mo_hash_grow(mo_hash *hash) {
402
452
  /*
403
453
  * Release the current hash, and use the copy instead.
404
454
  */
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
- */
455
+ mo_array_release(&hash->buffer);
412
456
 
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
- }
457
+ *hash = copy;
418
458
  }
419
459
 
420
460
  static
421
461
  void mo_hash_fill_bucket(mo_hash *hash, void *store, void *key, void *data) {
422
- *(mo_hash**)store = hash;
423
-
424
462
  if (hash->key_copy)
425
- hash->key_copy((uint8_t*)store + sizeof(mo_hash*), key);
463
+ hash->key_copy((uint8_t*)store, key);
426
464
  else
427
- memcpy((uint8_t*)store + sizeof(mo_hash*), key, hash->key_size);
465
+ memcpy((uint8_t*)store, key, hash->key_size);
428
466
 
429
467
  if (hash->copy)
430
- hash->copy((uint8_t*)store + sizeof(mo_hash*) + hash->key_size, data);
468
+ hash->copy((uint8_t*)store + hash->key_size, data);
431
469
  else
432
- memcpy((uint8_t*)store + sizeof(mo_hash*) + hash->key_size, data,
470
+ memcpy((uint8_t*)store + hash->key_size, data,
433
471
  hash->el_size);
434
472
  }
435
473
 
@@ -438,30 +476,31 @@ void mo_hash_set(mo_hash *hash, void *key, void *data) {
438
476
  mo_hash_grow(hash);
439
477
 
440
478
  int id = hash->hash_of(key) % hash->buffer.size;
441
- mo_list *bucket = mo_array_get_as(&hash->buffer, id, mo_list*);
479
+ mo_hash_list *bucket = mo_array_get_as(&hash->buffer, id, mo_hash_list*);
442
480
 
443
481
  hash->size += 1;
444
482
 
445
483
  if (!bucket) {
446
- bucket = mo_list_create(sizeof(mo_hash*) + hash->key_size + hash->el_size);
447
- bucket->release = mo_hash_bucket_free;
484
+ bucket = malloc(offsetof(mo_hash_list, data) +
485
+ hash->key_size + hash->el_size);
448
486
 
487
+ bucket->next = NULL;
449
488
  mo_hash_fill_bucket(hash, bucket->data, key, data);
450
489
 
451
- mo_array_get_as(&hash->buffer, id, mo_list*) = bucket;
490
+ mo_array_get_as(&hash->buffer, id, mo_hash_list*) = bucket;
452
491
  }
453
492
  else {
454
- mo_list *it = bucket, *last = bucket;
493
+ mo_hash_list *it = bucket, *last = bucket;
494
+
455
495
  while (it) {
456
- if (hash->key_cmp(it->data + sizeof(mo_hash*), key) == 0) {
496
+ if (hash->key_cmp(it->data, key) == 0) {
457
497
  hash->size -= 1;
458
498
 
459
499
  if (hash->copy) {
460
- hash->copy(it->data + sizeof(mo_hash*) + hash->key_size, data);
500
+ hash->copy(it->data + hash->key_size, data);
461
501
  }
462
502
  else {
463
- memcpy(it->data + sizeof(mo_hash*) + hash->key_size, data,
464
- hash->el_size);
503
+ memcpy(it->data + hash->key_size, data, hash->el_size);
465
504
  }
466
505
 
467
506
  return;
@@ -471,28 +510,41 @@ void mo_hash_set(mo_hash *hash, void *key, void *data) {
471
510
  it = it->next;
472
511
  }
473
512
 
474
- last = mo_list_insert(last, NULL);
513
+ last = malloc(offsetof(mo_hash_list, data) +
514
+ hash->key_size + hash->el_size);
515
+ last->next = NULL;
475
516
  mo_hash_fill_bucket(hash, last->data, key, data);
517
+
518
+ bucket->next = last;
476
519
  }
477
520
  }
478
521
 
479
522
  void mo_hash_del(mo_hash *hash, void *key) {
480
523
  int id = hash->hash_of(key) % hash->buffer.size;
481
- mo_list *bucket = mo_array_get_as(&hash->buffer, id, mo_list*);
524
+ mo_hash_list *bucket = mo_array_get_as(&hash->buffer, id, mo_hash_list*);
482
525
 
483
- mo_list *it = bucket, *next = bucket->next;
526
+ mo_hash_list *it = bucket, *next = bucket->next, *prev = NULL;
484
527
  while (it) {
485
- if (hash->key_cmp(it->data + sizeof(mo_hash*), key) == 0) {
528
+ if (hash->key_cmp(it->data, key) == 0) {
486
529
  hash->size -= 1;
487
- mo_list_delete(it);
530
+
531
+ if (prev)
532
+ prev->next = it->next;
533
+ else /* is head */
534
+ mo_array_get_as(&hash->buffer, id, mo_hash_list*) = next;
535
+
536
+ if (hash->key_release)
537
+ hash->key_release(it->data);
538
+ if (hash->release)
539
+ hash->release(it->data + hash->key_size);
540
+ free(it);
541
+
488
542
  break;
489
543
  }
490
544
 
491
- it = it->next;
545
+ prev = it;
546
+ it = it->next;
492
547
  }
493
-
494
- if (it == bucket) /* Head changed */
495
- mo_array_get_as(&hash->buffer, id, mo_list*) = next;
496
548
  }
497
549
 
498
550
  mo_hash_it mo_hash_begin(mo_hash *hash) {
@@ -503,7 +555,9 @@ mo_hash_it mo_hash_begin(mo_hash *hash) {
503
555
  };
504
556
 
505
557
  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*);
558
+ mo_hash_list *bucket = mo_array_get_as(&hash->buffer, ret.id,
559
+ mo_hash_list*);
560
+
507
561
  if (bucket) {
508
562
  ret.list = bucket;
509
563
  break;
@@ -518,11 +572,11 @@ bool mo_hash_it_is_end(mo_hash_it *it) {
518
572
  }
519
573
 
520
574
  void *mo_hash_it_key(mo_hash_it *it) {
521
- return it->list->data + sizeof(mo_hash*);
575
+ return it->list->data;
522
576
  }
523
577
 
524
578
  void *mo_hash_it_val(mo_hash_it *it) {
525
- return it->list->data + sizeof(mo_hash*) + it->hash->key_size;
579
+ return it->list->data + it->hash->key_size;
526
580
  }
527
581
 
528
582
  void mo_hash_it_next(mo_hash_it *it) {
@@ -532,7 +586,8 @@ void mo_hash_it_next(mo_hash_it *it) {
532
586
  it->list = NULL;
533
587
 
534
588
  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*);
589
+ mo_hash_list *bucket = mo_array_get_as(&it->hash->buffer, it->id,
590
+ mo_hash_list*);
536
591
  if (bucket) {
537
592
  it->list = bucket;
538
593
  return;
@@ -559,7 +614,7 @@ int mo_hash_pointer_cmp(const void *a, const void *b) {
559
614
  }
560
615
 
561
616
  int mo_hash_of_u32(void *ptr) {
562
- return (*(uint32_t*)ptr) * MAGIC_NUMBER;
617
+ return *(uint32_t*)ptr * MAGIC_NUMBER;
563
618
  }
564
619
 
565
620
  int mo_hash_u32_cmp(const void *a, const void *b) {
@@ -571,7 +626,7 @@ int mo_hash_u32_cmp(const void *a, const void *b) {
571
626
  }
572
627
 
573
628
  int mo_hash_of_size(void *ptr) {
574
- return (*(size_t*)ptr) * MAGIC_NUMBER;
629
+ return *(size_t*)ptr * MAGIC_NUMBER;
575
630
  }
576
631
 
577
632
  int mo_hash_size_cmp(const void *a, const void *b) {