mruby/c VM Source Code release 3.4
Loading...
Searching...
No Matches
c_hash.c
Go to the documentation of this file.
1
48
49/***** Feature test switches ************************************************/
50/***** System headers *******************************************************/
51//@cond
52#include "vm_config.h"
53#include <string.h>
54#include <assert.h>
55//@endcond
56
57/***** Local headers ********************************************************/
58#include "mrubyc.h"
59
60/***** Constat values *******************************************************/
61/***** Macros ***************************************************************/
62/***** Typedefs *************************************************************/
63/***** Function prototypes **************************************************/
64/***** Local variables ******************************************************/
65/***** Global variables *****************************************************/
66/***** Signal catching functions ********************************************/
67/***** Local functions ******************************************************/
68/***** Global functions *****************************************************/
69
70//================================================================
77mrbc_value mrbc_hash_new(struct VM *vm, int size)
78{
79 mrbc_value value = {.tt = MRBC_TT_HASH};
80
81 /*
82 Allocate handle and data buffer.
83 */
84 mrbc_hash *h = mrbc_alloc(vm, sizeof(mrbc_hash));
85 if( !h ) return value; // ENOMEM
86
87 mrbc_value *data = mrbc_alloc(vm, sizeof(mrbc_value) * size * 2);
88 if( !data ) { // ENOMEM
89 mrbc_raw_free( h );
90 return value;
91 }
92
93 MRBC_INIT_OBJECT_HEADER( h, "HA" );
94 h->data_size = size * 2;
95 h->n_stored = 0;
96 h->data = data;
97
98 value.hash = h;
99 return value;
100}
101
102
103//================================================================
109{
110 // TODO: delete other members (for search).
111
112 mrbc_array_delete(hash);
113}
114
115
116//================================================================
124{
125 mrbc_value *p1 = hash->hash->data;
126 const mrbc_value *p2 = p1 + hash->hash->n_stored;
127
128 while( p1 < p2 ) {
129 if( mrbc_compare(p1, key) == 0 ) return p1;
130 p1 += 2;
131 }
132
133 return NULL;
134}
135
136
137//================================================================
146{
147 mrbc_value *p1 = hash->hash->data;
148 const mrbc_value *p2 = p1 + hash->hash->n_stored;
149
150 while( p1 < p2 ) {
151 if( mrbc_type(*p1) == MRBC_TT_SYMBOL &&
152 mrbc_symbol(*p1) == sym_id ) return p1;
153 p1 += 2;
154 }
155
156 return NULL;
157}
158
159
160//================================================================
169{
170 mrbc_value *v = mrbc_hash_search(hash, key);
171 int ret = 0;
172 if( v == NULL ) {
173 // set a new value
174 if( (ret = mrbc_array_push(hash, key)) != 0 ) goto RETURN;
175 ret = mrbc_array_push(hash, val);
176
177 } else {
178 // replace a value
179 mrbc_decref(v);
180 *v = *key;
181 mrbc_decref(++v);
182 *v = *val;
183 }
184
185 RETURN:
186 return ret;
187}
188
189
190//================================================================
198{
199 mrbc_value *v = mrbc_hash_search(hash, key);
200 return v ? *++v : mrbc_nil_value();
201}
202
203
204//================================================================
212{
213 mrbc_value *v = mrbc_hash_search(hash, key);
214 return v ? ++v : v;
215}
216
217
218//================================================================
226{
227 mrbc_value *v = mrbc_hash_search(hash, key);
228 if( v == NULL ) return mrbc_nil_value();
229
230 mrbc_decref(v); // key
231 mrbc_value val = v[1]; // value
232
233 mrbc_hash *h = hash->hash;
234 h->n_stored -= 2;
235
236 memmove(v, v+2, (char*)(h->data + h->n_stored) - (char*)v);
237
238 // TODO: re-index hash table if need.
239
240 return val;
241}
242
243
244//================================================================
254{
255 mrbc_value *v = mrbc_hash_search_by_id(hash, sym_id);
256 if( !v ) return (mrbc_value){.tt = MRBC_TT_EMPTY};
257
258 mrbc_value val = v[1]; // value
259
260 mrbc_hash *h = hash->hash;
261 h->n_stored -= 2;
262
263 memmove(v, v+2, (char*)(h->data + h->n_stored) - (char*)v);
264
265 // TODO: re-index hash table if need.
266
267 return val;
268}
269
270
271//================================================================
277{
278 mrbc_array_clear(hash);
279
280 // TODO: re-index hash table if need.
281}
282
283
284//================================================================
292int mrbc_hash_compare(const mrbc_value *v1, const mrbc_value *v2)
293{
294 if( v1->hash->n_stored != v2->hash->n_stored ) return 1;
295
296 mrbc_value *d1 = v1->hash->data;
297 for( int i = 0; i < mrbc_hash_size(v1); i++, d1++ ) {
298 mrbc_value *d2 = mrbc_hash_search(v2, d1); // check key
299 if( d2 == NULL ) return 1;
300 if( mrbc_compare( ++d1, ++d2 ) ) return 1; // check data
301 }
302
303 return 0;
304}
305
306
307//================================================================
314{
316 if( ret.hash == NULL ) return ret; // ENOMEM
317
318 mrbc_hash *h = src->hash;
319 memcpy( ret.hash->data, h->data, sizeof(mrbc_value) * h->n_stored );
320 ret.hash->n_stored = h->n_stored;
321
322 mrbc_value *p1 = h->data;
323 const mrbc_value *p2 = p1 + h->n_stored;
324 while( p1 < p2 ) {
325 mrbc_incref(p1++);
326 }
327
328 // TODO: dup other members.
329
330 return ret;
331}
332
333
334
335
336//================================================================
339static void c_hash_new(struct VM *vm, mrbc_value v[], int argc)
340{
341 mrbc_value ret = mrbc_hash_new(vm, 0);
342 SET_RETURN(ret);
343}
344
345
346//================================================================
349static void c_hash_get(struct VM *vm, mrbc_value v[], int argc)
350{
351 if( argc != 1 ) {
352 mrbc_raise(vm, MRBC_CLASS(ArgumentError), "wrong number of arguments");
353 return;
354 }
355
356 mrbc_value val = mrbc_hash_get(&v[0], &v[1]);
357 mrbc_incref(&val);
358 SET_RETURN(val);
359}
360
361
362//================================================================
365static void c_hash_set(struct VM *vm, mrbc_value v[], int argc)
366{
367 if( argc != 2 ) {
368 mrbc_raise(vm, MRBC_CLASS(ArgumentError), "wrong number of arguments");
369 return;
370 }
371
372 mrbc_value *v1 = &v[1];
373 mrbc_value *v2 = &v[2];
374 mrbc_hash_set(v, v1, v2);
375 v1->tt = MRBC_TT_EMPTY;
376 v2->tt = MRBC_TT_EMPTY;
377}
378
379
380//================================================================
383static void c_hash_clear(struct VM *vm, mrbc_value v[], int argc)
384{
386}
387
388
389//================================================================
392static void c_hash_dup(struct VM *vm, mrbc_value v[], int argc)
393{
394 mrbc_value ret = mrbc_hash_dup( vm, &v[0] );
395
396 SET_RETURN(ret);
397}
398
399
400//================================================================
403static void c_hash_delete(struct VM *vm, mrbc_value v[], int argc)
404{
405 // TODO : now, support only delete(key) -> object
406
407 mrbc_value ret = mrbc_hash_remove(v, v+1);
408
409 // TODO: re-index hash table if need.
410
411 SET_RETURN(ret);
412}
413
414
415//================================================================
418static void c_hash_empty(struct VM *vm, mrbc_value v[], int argc)
419{
420 int n = mrbc_hash_size(v);
421
422 if( n ) {
424 } else {
426 }
427}
428
429
430//================================================================
433static void c_hash_has_key(struct VM *vm, mrbc_value v[], int argc)
434{
435 mrbc_value *res = mrbc_hash_search(v, v+1);
436
437 if( res ) {
439 } else {
441 }
442}
443
444
445//================================================================
448static void c_hash_has_value(struct VM *vm, mrbc_value v[], int argc)
449{
450 int ret = 0;
452
453 while( mrbc_hash_i_has_next(&ite) ) {
454 mrbc_value *val = mrbc_hash_i_next(&ite) + 1; // skip key, get value
455 if( mrbc_compare(val, &v[1]) == 0 ) {
456 ret = 1;
457 break;
458 }
459 }
460
461 if( ret ) {
463 } else {
465 }
466}
467
468
469//================================================================
472static void c_hash_key(struct VM *vm, mrbc_value v[], int argc)
473{
474 mrbc_value *ret = NULL;
476
477 while( mrbc_hash_i_has_next(&ite) ) {
478 mrbc_value *kv = mrbc_hash_i_next(&ite);
479 if( mrbc_compare( &kv[1], &v[1]) == 0 ) {
480 mrbc_incref( &kv[0] );
481 ret = &kv[0];
482 break;
483 }
484 }
485
486 if( ret ) {
487 SET_RETURN(*ret);
488 } else {
490 }
491}
492
493
494//================================================================
497static void c_hash_keys(struct VM *vm, mrbc_value v[], int argc)
498{
501
502 while( mrbc_hash_i_has_next(&ite) ) {
503 mrbc_value *key = mrbc_hash_i_next(&ite);
504 mrbc_array_push(&ret, key);
505 mrbc_incref(key);
506 }
507
508 SET_RETURN(ret);
509}
510
511
512//================================================================
515static void c_hash_size(struct VM *vm, mrbc_value v[], int argc)
516{
517 int n = mrbc_hash_size(v);
518
520}
521
522
523//================================================================
526static void c_hash_merge(struct VM *vm, mrbc_value v[], int argc)
527{
528 mrbc_value ret = mrbc_hash_dup( vm, &v[0] );
530
531 while( mrbc_hash_i_has_next(&ite) ) {
532 mrbc_value *kv = mrbc_hash_i_next(&ite);
533 mrbc_hash_set( &ret, &kv[0], &kv[1] );
534 mrbc_incref( &kv[0] );
535 mrbc_incref( &kv[1] );
536 }
537
538 SET_RETURN(ret);
539}
540
541
542//================================================================
545static void c_hash_merge_self(struct VM *vm, mrbc_value v[], int argc)
546{
548
549 while( mrbc_hash_i_has_next(&ite) ) {
550 mrbc_value *kv = mrbc_hash_i_next(&ite);
551 mrbc_hash_set( v, &kv[0], &kv[1] );
552 mrbc_incref( &kv[0] );
553 mrbc_incref( &kv[1] );
554 }
555}
556
557
558//================================================================
561static void c_hash_values(struct VM *vm, mrbc_value v[], int argc)
562{
565
566 while( mrbc_hash_i_has_next(&ite) ) {
567 mrbc_value *val = mrbc_hash_i_next(&ite) + 1;
568 mrbc_array_push(&ret, val);
569 mrbc_incref(val);
570 }
571
572 SET_RETURN(ret);
573}
574
575
576#if MRBC_USE_STRING
577//================================================================
580static void c_hash_inspect(struct VM *vm, mrbc_value v[], int argc)
581{
582 if( v[0].tt == MRBC_TT_CLASS ) {
583 v[0] = mrbc_string_new_cstr(vm, mrbc_symid_to_str( v[0].cls->sym_id ));
584 return;
585 }
586
587 mrbc_value ret = mrbc_string_new_cstr(vm, "{");
588 if( !ret.string ) goto RETURN_NIL; // ENOMEM
589
591 int flag_first = 1;
592
593 while( mrbc_hash_i_has_next(&ite) ) {
594 if( !flag_first ) mrbc_string_append_cstr( &ret, ", " );
595 flag_first = 0;
596 mrbc_value *kv = mrbc_hash_i_next(&ite);
597
598 mrbc_value s1 = mrbc_send( vm, v, argc, &kv[0], "inspect", 0 );
599 mrbc_string_append( &ret, &s1 );
600 mrbc_string_delete( &s1 );
601
602 mrbc_string_append_cstr( &ret, "=>" );
603
604 s1 = mrbc_send( vm, v, argc, &kv[1], "inspect", 0 );
605 mrbc_string_append( &ret, &s1 );
606 mrbc_string_delete( &s1 );
607 }
608
609 mrbc_string_append_cstr( &ret, "}" );
610
611 SET_RETURN(ret);
612 return;
613
614 RETURN_NIL:
616}
617#endif
618
619
620/* MRBC_AUTOGEN_METHOD_TABLE
621
622 CLASS("Hash")
623 FILE("_autogen_class_hash.h")
624
625 METHOD( "new", c_hash_new )
626 METHOD( "[]", c_hash_get )
627 METHOD( "[]=", c_hash_set )
628 METHOD( "clear", c_hash_clear )
629 METHOD( "dup", c_hash_dup )
630 METHOD( "delete", c_hash_delete )
631 METHOD( "empty?", c_hash_empty )
632 METHOD( "has_key?", c_hash_has_key )
633 METHOD( "has_value?", c_hash_has_value )
634 METHOD( "key", c_hash_key )
635 METHOD( "keys", c_hash_keys )
636 METHOD( "size", c_hash_size )
637 METHOD( "length", c_hash_size )
638 METHOD( "count", c_hash_size )
639 METHOD( "merge", c_hash_merge )
640 METHOD( "merge!", c_hash_merge_self )
641 METHOD( "to_h", c_ineffect )
642 METHOD( "values", c_hash_values )
643#if MRBC_USE_STRING
644 METHOD( "inspect", c_hash_inspect )
645 METHOD( "to_s", c_hash_inspect )
646#endif
647*/
648#include "_autogen_class_hash.h"
void mrbc_raw_free(void *ptr)
Definition alloc.c:695
int mrbc_array_push(mrbc_value *ary, mrbc_value *set_val)
Definition c_array.c:252
mrbc_value mrbc_array_new(struct VM *vm, int size)
Definition c_array.c:82
void mrbc_array_clear(mrbc_value *ary)
Definition c_array.c:420
void mrbc_array_delete(mrbc_value *ary)
Definition c_array.c:113
mrbc_value mrbc_hash_get(const mrbc_value *hash, const mrbc_value *key)
Definition c_hash.c:197
mrbc_value * mrbc_hash_search(const mrbc_value *hash, const mrbc_value *key)
Definition c_hash.c:123
mrbc_value mrbc_hash_remove(mrbc_value *hash, const mrbc_value *key)
Definition c_hash.c:225
void mrbc_hash_clear(mrbc_value *hash)
Definition c_hash.c:276
int mrbc_hash_compare(const mrbc_value *v1, const mrbc_value *v2)
Definition c_hash.c:292
mrbc_value * mrbc_hash_get_p(const mrbc_value *hash, const mrbc_value *key)
Definition c_hash.c:211
mrbc_value mrbc_hash_remove_by_id(mrbc_value *hash, mrbc_sym sym_id)
Definition c_hash.c:253
void mrbc_hash_delete(mrbc_value *hash)
Definition c_hash.c:108
mrbc_value * mrbc_hash_search_by_id(const mrbc_value *hash, mrbc_sym sym_id)
Definition c_hash.c:145
mrbc_value mrbc_hash_dup(struct VM *vm, mrbc_value *src)
Definition c_hash.c:313
int mrbc_hash_set(mrbc_value *hash, mrbc_value *key, mrbc_value *val)
Definition c_hash.c:168
mrbc_value mrbc_hash_new(struct VM *vm, int size)
Definition c_hash.c:77
struct RHash mrbc_hash
Hash object.
static mrbc_value * mrbc_hash_i_next(mrbc_hash_iterator *ite)
Definition c_hash.h:141
static int mrbc_hash_size(const mrbc_value *hash)
Definition c_hash.h:86
static int mrbc_hash_i_has_next(mrbc_hash_iterator *ite)
Definition c_hash.h:133
struct RHashIterator mrbc_hash_iterator
Define Hash iterator.
static mrbc_hash_iterator mrbc_hash_iterator_new(const mrbc_value *v)
Definition c_hash.h:120
void mrbc_string_delete(mrbc_value *str)
Definition c_string.c:129
int mrbc_string_append(mrbc_value *s1, const mrbc_value *s2)
Definition c_string.c:210
static mrbc_value mrbc_string_new_cstr(struct VM *vm, const char *src)
Definition c_string.h:85
static int mrbc_string_append_cstr(mrbc_value *s1, const char *s2)
Definition c_string.h:128
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:538
#define MRBC_CLASS(cls)
Definition class.h:51
void mrbc_raise(struct VM *vm, struct RClass *exc_cls, const char *msg)
Definition error.c:150
Include at once the necessary header files.
uint16_t data_size
data buffer size.
Definition c_hash.h:45
uint16_t n_stored
num of stored.
Definition c_hash.h:46
mrbc_value * data
pointer to allocated memory.
Definition c_hash.h:47
struct RString * string
Definition value.h:164
struct RHash * hash
Definition value.h:166
mrbc_vtype tt
Definition value.h:152
Virtual Machine.
Definition vm.h:140
const char * mrbc_symid_to_str(mrbc_sym sym_id)
Definition symbol.c:238
int mrbc_compare(const mrbc_value *v1, const mrbc_value *v2)
Definition value.c:66
static void mrbc_decref(mrbc_value *v)
Definition value.h:604
#define mrbc_symbol(o)
Definition value.h:196
#define MRBC_INIT_OBJECT_HEADER(p, t)
Definition value.h:307
#define SET_INT_RETURN(n)
Definition value.h:283
#define mrbc_nil_value()
Definition value.h:210
#define SET_NIL_RETURN()
Definition value.h:266
static void mrbc_incref(mrbc_value *v)
Definition value.h:589
#define SET_TRUE_RETURN()
Definition value.h:274
#define mrbc_type(o)
Definition value.h:193
int16_t mrbc_sym
mruby/c symbol ID
Definition value.h:59
@ MRBC_TT_SYMBOL
Symbol.
Definition value.h:86
@ MRBC_TT_EMPTY
Definition value.h:77
@ MRBC_TT_HASH
Hash.
Definition value.h:97
@ MRBC_TT_CLASS
Class.
Definition value.h:87
struct RObject mrbc_value
Definition value.h:174
#define SET_RETURN(n)
Definition value.h:261
#define SET_FALSE_RETURN()
Definition value.h:270
Global configuration of mruby/c VM's.