ray 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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) {