mruby/c VM Source Code master (2026/08/06)
Loading...
Searching...
No Matches
c_hash.c
Go to the documentation of this file.
1
49
50/***** Feature test switches ************************************************/
51/***** System headers *******************************************************/
52//@cond
53#include "vm_config.h"
54#include <string.h>
55#include <assert.h>
56//@endcond
57
58/***** Local headers ********************************************************/
59#include "mrubyc.h"
60
61/***** Constat values *******************************************************/
62/***** Macros ***************************************************************/
63/***** Typedefs *************************************************************/
64/***** Function prototypes **************************************************/
65/***** Local variables ******************************************************/
66/***** Global variables *****************************************************/
67/***** Signal catching functions ********************************************/
68/***** Local functions ******************************************************/
69/***** Global functions *****************************************************/
70
71//================================================================
79{
80 // Allocate handle and data buffer.
81 mrbc_hash *hash = mrbc_alloc(vm, sizeof(mrbc_hash));
82 mrbc_value *data = mrbc_alloc(vm, sizeof(mrbc_value) * size * 2);
83
84 *hash = (mrbc_hash){
86 .data_size = size * 2,
87 .n_stored = 0,
88 .data = data,
89 };
90
91 return mrbc_immediate_value(MRBC_TT_HASH, .hash = hash);
92}
93
94
95//================================================================
101{
102 // TODO: delete other members (for search).
103
104 mrbc_array_delete(hash);
105}
106
107
108//================================================================
116{
117 mrbc_value *p1 = hash->hash->data;
118 const mrbc_value *p2 = p1 + hash->hash->n_stored;
119
120 while( p1 < p2 ) {
121 if( mrbc_compare(p1, key) == 0 ) return p1;
122 p1 += 2;
123 }
124
125 return NULL;
126}
127
128
129//================================================================
138{
139 mrbc_value *p1 = hash->hash->data;
140 const mrbc_value *p2 = p1 + hash->hash->n_stored;
141
142 while( p1 < p2 ) {
143 if( mrbc_type(*p1) == MRBC_TT_SYMBOL &&
144 mrbc_symbol(*p1) == sym_id ) return p1;
145 p1 += 2;
146 }
147
148 return NULL;
149}
150
151
152//================================================================
161{
162 mrbc_value *v = mrbc_hash_search(hash, key);
163 int ret = 0;
164 if( v == NULL ) {
165 // set a new value
166 if( (ret = mrbc_array_push(hash, key)) != 0 ) goto RETURN;
167 ret = mrbc_array_push(hash, val);
168
169 } else {
170 // replace a value
171 mrbc_decref(v);
172 *v = *key;
173 mrbc_decref(++v);
174 *v = *val;
175 }
176
177 RETURN:
178 return ret;
179}
180
181
182//================================================================
190{
191 mrbc_value *v = mrbc_hash_search(hash, key);
192 return v ? *++v : mrbc_nil_value();
193}
194
195
196//================================================================
204{
205 mrbc_value *v = mrbc_hash_search(hash, key);
206 return v ? ++v : v;
207}
208
209
210//================================================================
218{
219 mrbc_value *v = mrbc_hash_search(hash, key);
220 if( v == NULL ) return mrbc_nil_value();
221
222 mrbc_decref(v); // key
223 mrbc_value val = v[1]; // value
224
225 mrbc_hash *h = hash->hash;
226 h->n_stored -= 2;
227
228 memmove(v, v+2, (char*)(h->data + h->n_stored) - (char*)v);
229
230 // TODO: re-index hash table if need.
231
232 return val;
233}
234
235
236//================================================================
246{
247 mrbc_value *v = mrbc_hash_search_by_id(hash, sym_id);
248 if( !v ) return mrbc_immediate_value(MRBC_TT_EMPTY);
249
250 mrbc_value val = v[1]; // value
251
252 mrbc_hash *h = hash->hash;
253 h->n_stored -= 2;
254
255 memmove(v, v+2, (char*)(h->data + h->n_stored) - (char*)v);
256
257 // TODO: re-index hash table if need.
258
259 return val;
260}
261
262
263//================================================================
269{
270 mrbc_array_clear(hash);
271
272 // TODO: re-index hash table if need.
273}
274
275
276//================================================================
284int mrbc_hash_compare(const mrbc_value *v1, const mrbc_value *v2)
285{
286 if( v1->hash->n_stored != v2->hash->n_stored ) return 1;
287
288 mrbc_value *d1 = v1->hash->data;
289 for( int i = 0; i < mrbc_hash_size(v1); i++, d1++ ) {
290 mrbc_value *d2 = mrbc_hash_search(v2, d1); // check key
291 if( d2 == NULL ) return 1;
292 if( mrbc_compare( ++d1, ++d2 ) ) return 1; // check data
293 }
294
295 return 0;
296}
297
298
299//================================================================
306{
308 mrbc_hash *h = src->hash;
309
310 memcpy( ret.hash->data, h->data, sizeof(mrbc_value) * h->n_stored );
311 ret.hash->n_stored = h->n_stored;
312
313 mrbc_value *p1 = h->data;
314 const mrbc_value *p2 = p1 + h->n_stored;
315 while( p1 < p2 ) {
316 mrbc_incref(p1++);
317 }
318
319 // TODO: dup other members.
320
321 return ret;
322}
323
324
325
326
327//================================================================
330static void c_hash_new(mrbc_vm *vm, mrbc_value v[], int argc)
331{
332 mrbc_value ret = mrbc_hash_new(vm, 0);
333 SET_RETURN(ret);
334}
335
336
337//================================================================
340static void c_hash_get(mrbc_vm *vm, mrbc_value v[], int argc)
341{
342 if( argc != 1 ) {
343 mrbc_raise(vm, MRBC_CLASS(ArgumentError), "wrong number of arguments");
344 return;
345 }
346
347 mrbc_value val = mrbc_hash_get(&v[0], &v[1]);
348 mrbc_incref(&val);
349 SET_RETURN(val);
350}
351
352
353//================================================================
356static void c_hash_set(mrbc_vm *vm, mrbc_value v[], int argc)
357{
358 if( argc != 2 ) {
359 mrbc_raise(vm, MRBC_CLASS(ArgumentError), "wrong number of arguments");
360 return;
361 }
362
363 mrbc_value *v1 = &v[1];
364 mrbc_value *v2 = &v[2];
365 mrbc_hash_set(v, v1, v2);
368}
369
370
371//================================================================
374static void c_hash_clear(mrbc_vm *vm, mrbc_value v[], int argc)
375{
377}
378
379
380//================================================================
383static void c_hash_deconstruct_keys(mrbc_vm *vm, mrbc_value v[], int argc)
384{
385 if (argc != 1) {
386 mrbc_raise(vm, MRBC_CLASS(ArgumentError), "wrong number of arguments");
387 return;
388 }
389 // For pattern matching - return self (not a copy)
390}
391
392
393//================================================================
397static void c_hash_pat_values(mrbc_vm *vm, mrbc_value v[], int argc)
398{
399 if( argc != 1 ) {
400 mrbc_raise(vm, MRBC_CLASS(ArgumentError), "wrong number of arguments");
401 return;
402 }
403
404 mrbc_value *keys = &v[1];
405 int klen = mrbc_array_size(keys);
406
407 for( int i = 0; i < klen; i++ ) {
408 mrbc_value key = mrbc_array_get(keys, i);
409 if( mrbc_hash_search(&v[0], &key) == NULL ) {
411 return;
412 }
413 }
414
415 mrbc_value result = mrbc_array_new(vm, klen);
416 for( int i = 0; i < klen; i++ ) {
417 mrbc_value key = mrbc_array_get(keys, i);
418 mrbc_value *found = mrbc_hash_search(&v[0], &key);
419 mrbc_value val = found[1];
420 mrbc_incref(&val);
421 mrbc_array_push(&result, &val);
422 }
423
424 SET_RETURN(result);
425}
426
427
428//================================================================
432static void c_hash_except_keys(mrbc_vm *vm, mrbc_value v[], int argc)
433{
434 if( argc != 1 ) {
435 mrbc_raise(vm, MRBC_CLASS(ArgumentError), "wrong number of arguments");
436 return;
437 }
438
439 mrbc_value *excl_keys = &v[1];
440 int klen = mrbc_array_size(excl_keys);
441 mrbc_value result = mrbc_hash_new(vm, mrbc_hash_size(&v[0]));
443
444 while( mrbc_hash_i_has_next(&ite) ) {
445 mrbc_value *kv = mrbc_hash_i_next(&ite);
446 int found = 0;
447 for( int i = 0; i < klen; i++ ) {
448 mrbc_value excl_key = mrbc_array_get(excl_keys, i);
449 if( mrbc_compare(&kv[0], &excl_key) == 0 ) {
450 found = 1;
451 break;
452 }
453 }
454 if( !found ) {
455 mrbc_hash_set(&result, &kv[0], &kv[1]);
456 mrbc_incref(&kv[0]);
457 mrbc_incref(&kv[1]);
458 }
459 }
460
461 SET_RETURN(result);
462}
463
464
465//================================================================
468static void c_hash_dup(mrbc_vm *vm, mrbc_value v[], int argc)
469{
470 mrbc_value ret = mrbc_hash_dup( vm, &v[0] );
471
472 SET_RETURN(ret);
473}
474
475
476//================================================================
479static void c_hash_delete(mrbc_vm *vm, mrbc_value v[], int argc)
480{
481 // TODO : now, support only delete(key) -> object
482
483 mrbc_value ret = mrbc_hash_remove(v, v+1);
484
485 // TODO: re-index hash table if need.
486
487 SET_RETURN(ret);
488}
489
490
491//================================================================
494static void c_hash_empty(mrbc_vm *vm, mrbc_value v[], int argc)
495{
496 int n = mrbc_hash_size(v);
497
498 SET_BOOL_RETURN( !n );
499}
500
501
502//================================================================
505static void c_hash_has_key(mrbc_vm *vm, mrbc_value v[], int argc)
506{
507 mrbc_value *res = mrbc_hash_search(v, v+1);
508
509 SET_BOOL_RETURN( res != NULL );
510}
511
512
513//================================================================
516static void c_hash_has_value(mrbc_vm *vm, mrbc_value v[], int argc)
517{
518 int ret = 0;
520
521 while( mrbc_hash_i_has_next(&ite) ) {
522 mrbc_value *val = mrbc_hash_i_next(&ite) + 1; // skip key, get value
523 if( mrbc_compare(val, &v[1]) == 0 ) {
524 ret = 1;
525 break;
526 }
527 }
528
529 SET_BOOL_RETURN( ret );
530}
531
532
533//================================================================
536static void c_hash_key(mrbc_vm *vm, mrbc_value v[], int argc)
537{
538 mrbc_value *ret = NULL;
540
541 while( mrbc_hash_i_has_next(&ite) ) {
542 mrbc_value *kv = mrbc_hash_i_next(&ite);
543 if( mrbc_compare( &kv[1], &v[1]) == 0 ) {
544 mrbc_incref( &kv[0] );
545 ret = &kv[0];
546 break;
547 }
548 }
549
550 if( ret ) {
551 SET_RETURN(*ret);
552 } else {
554 }
555}
556
557
558//================================================================
561static void c_hash_keys(mrbc_vm *vm, mrbc_value v[], int argc)
562{
565
566 while( mrbc_hash_i_has_next(&ite) ) {
567 mrbc_value *key = mrbc_hash_i_next(&ite);
568 mrbc_array_push(&ret, key);
569 mrbc_incref(key);
570 }
571
572 SET_RETURN(ret);
573}
574
575
576//================================================================
579static void c_hash_size(mrbc_vm *vm, mrbc_value v[], int argc)
580{
581 int n = mrbc_hash_size(v);
582
584}
585
586
587//================================================================
590static void c_hash_merge(mrbc_vm *vm, mrbc_value v[], int argc)
591{
592 mrbc_value ret = mrbc_hash_dup( vm, &v[0] );
594
595 while( mrbc_hash_i_has_next(&ite) ) {
596 mrbc_value *kv = mrbc_hash_i_next(&ite);
597 mrbc_hash_set( &ret, &kv[0], &kv[1] );
598 mrbc_incref( &kv[0] );
599 mrbc_incref( &kv[1] );
600 }
601
602 SET_RETURN(ret);
603}
604
605
606//================================================================
609static void c_hash_merge_self(mrbc_vm *vm, mrbc_value v[], int argc)
610{
612
613 while( mrbc_hash_i_has_next(&ite) ) {
614 mrbc_value *kv = mrbc_hash_i_next(&ite);
615 mrbc_hash_set( v, &kv[0], &kv[1] );
616 mrbc_incref( &kv[0] );
617 mrbc_incref( &kv[1] );
618 }
619}
620
621
622//================================================================
625static void c_hash_values(mrbc_vm *vm, mrbc_value v[], int argc)
626{
629
630 while( mrbc_hash_i_has_next(&ite) ) {
631 mrbc_value *val = mrbc_hash_i_next(&ite) + 1;
632 mrbc_array_push(&ret, val);
633 mrbc_incref(val);
634 }
635
636 SET_RETURN(ret);
637}
638
639
640//================================================================
643static void c_hash_fetch(mrbc_vm *vm, mrbc_value v[], int argc)
644{
645 if( argc < 1 || argc > 2 ) {
646 mrbc_raise(vm, MRBC_CLASS(ArgumentError), "wrong number of arguments");
647 return;
648 }
649
650 mrbc_value *val = mrbc_hash_search(v, v+1);
651 if( val ) {
652 mrbc_incref(++val);
653 SET_RETURN(*val);
654 return;
655 }
656
657 // key not found
658 if( argc == 2 ) {
659 // return default value
660 mrbc_incref(&v[2]);
661 SET_RETURN(v[2]);
662 return;
663 }
664
665 // no default - raise
666 mrbc_raise(vm, MRBC_CLASS(RuntimeError), "key not found");
667}
668
669
670#if MRBC_USE_STRING
671//================================================================
674static void c_hash_inspect(mrbc_vm *vm, mrbc_value v[], int argc)
675{
676 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) {
677 mrbc_object_inspect(vm, v, argc);
678 return;
679 }
680
681 mrbc_value ret = mrbc_string_new_cstr(vm, "{");
683 int flag_first = 1;
684
685 while( mrbc_hash_i_has_next(&ite) ) {
686 if( !flag_first ) mrbc_string_append_cstr( &ret, ", " );
687 flag_first = 0;
688 mrbc_value *kv = mrbc_hash_i_next(&ite);
689 mrbc_value s1;
690
691 if (mrbc_type(*kv) == MRBC_TT_SYMBOL) {
692 const char *s = mrbc_symid_to_str(kv->sym_id);
693 mrbc_string_append_cstr( &ret, s );
694 mrbc_string_append_cstr( &ret, ": " );
695 } else {
696 s1 = mrbc_send( vm, v, argc, &kv[0], "inspect", 0 );
697 mrbc_string_append( &ret, &s1 );
698 mrbc_string_delete( &s1 );
699 mrbc_string_append_cstr( &ret, " => " );
700 }
701
702 s1 = mrbc_send( vm, v, argc, &kv[1], "inspect", 0 );
703 mrbc_string_append( &ret, &s1 );
704 mrbc_string_delete( &s1 );
705 }
706
707 mrbc_string_append_cstr( &ret, "}" );
708
709 SET_RETURN(ret);
710 return;
711}
712#endif
713
714
715/* MRBC_AUTOGEN_METHOD_TABLE
716
717 CLASS("Hash")
718 FILE("_autogen_class_hash.h")
719
720 METHOD( "new", c_hash_new )
721 METHOD( "[]", c_hash_get )
722 METHOD( "[]=", c_hash_set )
723 METHOD( "__except", c_hash_except_keys )
724 METHOD( "__pat_values", c_hash_pat_values )
725 METHOD( "clear", c_hash_clear )
726 METHOD( "deconstruct_keys", c_hash_deconstruct_keys )
727 METHOD( "dup", c_hash_dup )
728 METHOD( "delete", c_hash_delete )
729 METHOD( "empty?", c_hash_empty )
730 METHOD( "fetch", c_hash_fetch )
731 METHOD( "has_key?", c_hash_has_key )
732 METHOD( "has_value?", c_hash_has_value )
733 METHOD( "key", c_hash_key )
734 METHOD( "keys", c_hash_keys )
735 METHOD( "size", c_hash_size )
736 METHOD( "length", c_hash_size )
737 METHOD( "count", c_hash_size )
738 METHOD( "merge", c_hash_merge )
739 METHOD( "merge!", c_hash_merge_self )
740 METHOD( "to_h", c_ineffect )
741 METHOD( "values", c_hash_values )
742#if MRBC_USE_STRING
743 METHOD( "inspect", c_hash_inspect )
744 METHOD( "to_s", c_hash_inspect )
745#endif
746*/
747#include "_autogen_class_hash.h"
#define mrbc_immediate_value(...)
Definition boxing_no.h:75
#define mrbc_symbol(o)
Definition boxing_no.h:62
#define mrbc_nil_value()
Definition boxing_no.h:70
static void mrbc_set_tt(mrbc_value *p, mrbc_vtype type)
Definition boxing_no.h:125
#define mrbc_type(o)
Definition boxing_no.h:57
struct RObject mrbc_value
Value object. Default version.
int mrbc_array_push(mrbc_value *ary, mrbc_value *set_val)
Definition c_array.c:243
mrbc_value mrbc_array_get(const mrbc_value *ary, int idx)
Definition c_array.c:207
mrbc_value mrbc_array_new(mrbc_vm *vm, int size)
Definition c_array.c:83
void mrbc_array_clear(mrbc_value *ary)
Definition c_array.c:409
void mrbc_array_delete(mrbc_value *ary)
Definition c_array.c:105
static int mrbc_array_size(const mrbc_value *ary)
Definition c_array.h:84
mrbc_value mrbc_hash_get(const mrbc_value *hash, const mrbc_value *key)
Definition c_hash.c:189
mrbc_value * mrbc_hash_search(const mrbc_value *hash, const mrbc_value *key)
Definition c_hash.c:115
mrbc_value mrbc_hash_remove(mrbc_value *hash, const mrbc_value *key)
Definition c_hash.c:217
void mrbc_hash_clear(mrbc_value *hash)
Definition c_hash.c:268
int mrbc_hash_compare(const mrbc_value *v1, const mrbc_value *v2)
Definition c_hash.c:284
mrbc_value mrbc_hash_dup(mrbc_vm *vm, mrbc_value *src)
Definition c_hash.c:305
mrbc_value * mrbc_hash_get_p(const mrbc_value *hash, const mrbc_value *key)
Definition c_hash.c:203
mrbc_value mrbc_hash_remove_by_id(mrbc_value *hash, mrbc_sym sym_id)
Definition c_hash.c:245
mrbc_value mrbc_hash_new(mrbc_vm *vm, int size)
Definition c_hash.c:78
void mrbc_hash_delete(mrbc_value *hash)
Definition c_hash.c:100
mrbc_value * mrbc_hash_search_by_id(const mrbc_value *hash, mrbc_sym sym_id)
Definition c_hash.c:137
int mrbc_hash_set(mrbc_value *hash, mrbc_value *key, mrbc_value *val)
Definition c_hash.c:160
struct RHash mrbc_hash
Hash object.
static mrbc_value * mrbc_hash_i_next(mrbc_hash_iterator *ite)
Definition c_hash.h:143
static int mrbc_hash_size(const mrbc_value *hash)
Definition c_hash.h:88
static int mrbc_hash_i_has_next(mrbc_hash_iterator *ite)
Definition c_hash.h:135
struct RHashIterator mrbc_hash_iterator
Define Hash iterator.
static mrbc_hash_iterator mrbc_hash_iterator_new(const mrbc_value *v)
Definition c_hash.h:122
void mrbc_object_inspect(mrbc_vm *vm, mrbc_value v[], int argc)
Definition c_object.c:91
void mrbc_string_delete(mrbc_value *str)
Definition c_string.c:107
int mrbc_string_append(mrbc_value *s1, const mrbc_value *s2)
Definition c_string.c:185
static int mrbc_string_append_cstr(mrbc_value *s1, const char *s2)
Definition c_string.h:134
static mrbc_value mrbc_string_new_cstr(mrbc_vm *vm, const char *src)
Definition c_string.h:91
mrbc_value mrbc_send(struct VM *vm, mrbc_value *v, int argc, mrbc_value *recv, const char *method_name, int n_params,...)
Definition class.c:526
#define MRBC_CLASS(cls)
Definition class.h:55
void mrbc_raise(struct VM *vm, struct RClass *exc_cls, const char *msg)
Definition error.c:145
Include at once the necessary header files.
uint16_t n_stored
num of stored.
Definition c_hash.h:48
mrbc_value * data
pointer to allocated memory.
Definition c_hash.h:49
mrbc_sym sym_id
Definition boxing_no.h:26
struct RHash * hash
Definition boxing_no.h:34
const char * mrbc_symid_to_str(mrbc_sym sym_id)
Definition symbol.c:239
int mrbc_compare(const mrbc_value *v1, const mrbc_value *v2)
Definition value.c:68
static void mrbc_decref(mrbc_value *v)
Definition value.h:572
#define MRBC_INIT_OBJECT_HEADER_DI(t)
Definition value.h:147
#define SET_BOOL_RETURN(n)
Definition value.h:238
#define SET_INT_RETURN(n)
Definition value.h:243
#define SET_NIL_RETURN()
Definition value.h:226
static void mrbc_incref(mrbc_value *v)
Definition value.h:557
int16_t mrbc_sym
mruby/c symbol ID
Definition value.h:62
@ MRBC_TT_SYMBOL
Symbol.
Definition value.h:89
@ MRBC_TT_EMPTY
Definition value.h:80
@ MRBC_TT_HASH
Hash.
Definition value.h:100
@ MRBC_TT_CLASS
Class.
Definition value.h:90
#define SET_RETURN(n)
Definition value.h:221
#define SET_FALSE_RETURN()
Definition value.h:230
struct VM mrbc_vm
Virtual Machine.
Global configuration of mruby/c VM's.