mruby/c VM Source Code master (2026/08/06)
Loading...
Searching...
No Matches
c_array.c
Go to the documentation of this file.
1
54
55/***** Feature test switches ************************************************/
56/***** System headers *******************************************************/
57//@cond
58#include "vm_config.h"
59#include <string.h>
60#include <assert.h>
61//@endcond
62
63/***** Local headers ********************************************************/
64#include "mrubyc.h"
65
66/***** Constat values *******************************************************/
67/***** Macros ***************************************************************/
68/***** Typedefs *************************************************************/
69/***** Function prototypes **************************************************/
70/***** Local variables ******************************************************/
71/***** Global variables *****************************************************/
72/***** Signal catching functions ********************************************/
73/***** Local functions ******************************************************/
74/***** Global functions *****************************************************/
75
76//================================================================
84{
85 // Allocate handle and data buffer.
86 mrbc_array *ary = mrbc_alloc(vm, sizeof(mrbc_array));
87 mrbc_value *data = mrbc_alloc(vm, sizeof(mrbc_value) * size);
88
89 *ary = (mrbc_array){
91 .data_size = size,
92 .n_stored = 0,
93 .data = data,
94 };
95
96 return mrbc_immediate_value(MRBC_TT_ARRAY, .array = ary);
97}
98
99
100//================================================================
106{
107 mrbc_array *h = ary->array;
108
109 mrbc_value *p1 = h->data;
110 const mrbc_value *p2 = p1 + h->n_stored;
111 while( p1 < p2 ) {
112 mrbc_decref(p1++);
113 }
114
116}
117
118
119#if defined(MRBC_ALLOC_VMID)
120//================================================================
125void mrbc_array_clear_vm_id(mrbc_value *ary)
126{
127 mrbc_array *h = ary->array;
128
129 mrbc_set_vm_id( h, 0 );
130
131 mrbc_value *p1 = h->data;
132 const mrbc_value *p2 = p1 + h->n_stored;
133 while( p1 < p2 ) {
134 mrbc_clear_vm_id(p1++);
135 }
136}
137#endif
138
139
140//================================================================
147int mrbc_array_resize(mrbc_value *ary, int size)
148{
149 if( size <= 0 ) size = 1;
150
151 mrbc_array *h = ary->array;
152 mrbc_value *data = mrbc_raw_realloc(h->data, sizeof(mrbc_value) * size);
153
154 h->data = data;
155 h->data_size = size;
156
157 return 0;
158}
159
160
161//================================================================
169int mrbc_array_set(mrbc_value *ary, int idx, mrbc_value *set_val)
170{
171 mrbc_array *h = ary->array;
172
173 if( idx < 0 ) {
174 idx = h->n_stored + idx;
175 if( idx < 0 ) return E_INDEX_ERROR;
176 }
177
178 // need resize?
179 if( idx >= h->data_size ) {
180 mrbc_array_resize(ary, idx + 1);
181 }
182
183 if( idx < h->n_stored ) {
184 // release existing data.
185 mrbc_decref( &h->data[idx] );
186 } else {
187 // clear empty cells.
188 for( int i = h->n_stored; i < idx; i++ ) {
189 mrbc_set_nil( &h->data[i] );
190 }
191 h->n_stored = idx + 1;
192 }
193
194 h->data[idx] = *set_val;
195
196 return 0;
197}
198
199
200//================================================================
208{
209 mrbc_array *h = ary->array;
210
211 if( idx < 0 ) idx = h->n_stored + idx;
212 if( idx < 0 || idx >= h->n_stored ) return mrbc_nil_value();
213
214 return h->data[idx];
215}
216
217
218//================================================================
226{
227 mrbc_array *h = ary->array;
228
229 if( idx < 0 ) idx = h->n_stored + idx;
230 if( idx < 0 || idx >= h->n_stored ) return NULL;
231
232 return &h->data[idx];
233}
234
235
236//================================================================
244{
245 mrbc_array *h = ary->array;
246
247 if( h->n_stored >= h->data_size ) {
248 mrbc_array_resize(ary, h->data_size + 6);
249 }
250
251 h->data[h->n_stored++] = *set_val;
252
253 return 0;
254}
255
256
257//================================================================
265{
266 mrbc_array *ha_d = ary->array;
267 mrbc_array *ha_s = set_val->array;
268 int new_size = ha_d->n_stored + ha_s->n_stored;
269
270 if( new_size > ha_d->data_size ) {
271 mrbc_array_resize(ary, new_size);
272 }
273
274 memcpy( &ha_d->data[ha_d->n_stored], ha_s->data,
275 sizeof(mrbc_value) * ha_s->n_stored );
276 ha_d->n_stored += ha_s->n_stored;
277
278 return 0;
279}
280
281
282//================================================================
289{
290 mrbc_array *h = ary->array;
291
292 if( h->n_stored <= 0 ) return mrbc_nil_value();
293 return h->data[--h->n_stored];
294}
295
296
297//================================================================
305{
306 return mrbc_array_insert(ary, 0, set_val);
307}
308
309
310//================================================================
317{
318 mrbc_array *h = ary->array;
319
320 if( h->n_stored <= 0 ) return mrbc_nil_value();
321
322 mrbc_value ret = h->data[0];
323 memmove(h->data, h->data+1, sizeof(mrbc_value) * --h->n_stored);
324
325 return ret;
326}
327
328
329//================================================================
337int mrbc_array_insert(mrbc_value *ary, int idx, mrbc_value *set_val)
338{
339 mrbc_array *h = ary->array;
340
341 if( idx < 0 ) {
342 idx = h->n_stored + idx + 1;
343 if( idx < 0 ) return E_INDEX_ERROR;
344 }
345
346 // need resize?
347 int size = 0;
348 if( idx >= h->data_size ) {
349 size = idx + 1;
350 } else if( h->n_stored >= h->data_size ) {
351 size = h->data_size + 1;
352 }
353 if( size ) {
354 mrbc_array_resize(ary, size);
355 }
356
357 // move datas.
358 if( idx < h->n_stored ) {
359 memmove(h->data + idx + 1, h->data + idx,
360 sizeof(mrbc_value) * (h->n_stored - idx));
361 }
362
363 // set data
364 h->data[idx] = *set_val;
365 h->n_stored++;
366
367 // clear empty cells if need.
368 if( idx >= h->n_stored ) {
369 for( int i = h->n_stored-1; i < idx; i++ ) {
370 mrbc_set_nil( &h->data[i] );
371 }
372 h->n_stored = idx + 1;
373 }
374
375 return 0;
376}
377
378
379//================================================================
387{
388 mrbc_array *h = ary->array;
389
390 if( idx < 0 ) idx = h->n_stored + idx;
391 if( idx < 0 || idx >= h->n_stored ) return mrbc_nil_value();
392
393 mrbc_value ret = h->data[idx];
394 h->n_stored--;
395 if( idx < h->n_stored ) {
396 memmove(h->data + idx, h->data + idx + 1,
397 sizeof(mrbc_value) * (h->n_stored - idx));
398 }
399
400 return ret;
401}
402
403
404//================================================================
410{
411 mrbc_array *h = ary->array;
412
413 mrbc_value *p1 = h->data;
414 const mrbc_value *p2 = p1 + h->n_stored;
415 while( p1 < p2 ) {
416 mrbc_decref(p1++);
417 }
418
419 h->n_stored = 0;
420}
421
422
423//================================================================
432int mrbc_array_compare(const mrbc_value *v1, const mrbc_value *v2)
433{
434 for( int i = 0; ; i++ ) {
435 if( i >= mrbc_array_size(v1) || i >= mrbc_array_size(v2) ) {
436 return mrbc_array_size(v1) - mrbc_array_size(v2);
437 }
438
439 int res = mrbc_compare( &v1->array->data[i], &v2->array->data[i] );
440 if( res != 0 ) return res;
441 }
442}
443
444
445//================================================================
452void mrbc_array_minmax(mrbc_value *ary, mrbc_value **pp_min_value, mrbc_value **pp_max_value)
453{
454 mrbc_array *h = ary->array;
455
456 if( h->n_stored == 0 ) {
457 *pp_min_value = NULL;
458 *pp_max_value = NULL;
459 return;
460 }
461
462 mrbc_value *p_min_value = h->data;
463 mrbc_value *p_max_value = h->data;
464
465 for( int i = 1; i < h->n_stored; i++ ) {
466 if( mrbc_compare( &h->data[i], p_min_value ) < 0 ) {
467 p_min_value = &h->data[i];
468 }
469 if( mrbc_compare( &h->data[i], p_max_value ) > 0 ) {
470 p_max_value = &h->data[i];
471 }
472 }
473
474 *pp_min_value = p_min_value;
475 *pp_max_value = p_max_value;
476}
477
478
479//================================================================
487{
488 mrbc_array *sh = ary->array;
489 mrbc_value dv = mrbc_array_new(vm, sh->n_stored);
490
491 memcpy( dv.array->data, sh->data, sizeof(mrbc_value) * sh->n_stored );
492 dv.array->n_stored = sh->n_stored;
493
494 mrbc_value *p1 = dv.array->data;
495 const mrbc_value *p2 = p1 + dv.array->n_stored;
496 while( p1 < p2 ) {
497 mrbc_incref(p1++);
498 }
499
500 return dv;
501}
502
503
504//================================================================
517{
518 mrbc_array *ha_s = src->array;
519 if( pos < 0 ) pos = 0;
520 int new_size = ha_s->n_stored - pos;
521 if( new_size < 0 ) new_size = 0;
522 int remain_size = ha_s->n_stored - new_size;
523 mrbc_value ret = mrbc_array_new(vm, new_size);
524 mrbc_array *ha_r = ret.array;
525
526 memcpy( ha_r->data, ha_s->data + remain_size, sizeof(mrbc_value) * new_size );
527 ha_s->n_stored = remain_size;
528 mrbc_array_resize( src, remain_size );
529 ha_r->n_stored = new_size;
530
531 return ret;
532}
533
534//================================================================
541int mrbc_array_index(const mrbc_value *ary, const mrbc_value *val)
542{
543 int n = ary->array->n_stored;
544 for( int i = 0; i < n; i++ ) {
545 if( mrbc_compare(&ary->array->data[i], val) == 0 ) return i;
546 }
547 return -1;
548}
549
550
551//================================================================
559{
560 mrbc_value ret = mrbc_array_dup(vm, ary);
561
562 mrbc_array_uniq_self( &ret );
563 return ret;
564}
565
566
567//================================================================
574{
575 mrbc_array *ah = ary->array;
576 int size = ah->n_stored;
577
578 for( int i = 0; i < size-1; i++ ) {
579 for( int j = i+1; j < size; j++ ) {
580 if( mrbc_compare( &ah->data[i], &ah->data[j] ) != 0 ) continue;
581
582 mrbc_decref( &ah->data[j] );
583 int rest = --size - j;
584 if( rest == 0 ) break;
585
586 memmove( &ah->data[j], &ah->data[j+1], sizeof(mrbc_value) * rest );
587 j--;
588 }
589 }
590
591 int ret = ah->n_stored - size;
592 ah->n_stored = size;
593
594 return ret;
595}
596
597
598//================================================================
601static void c_array_new(mrbc_vm *vm, mrbc_value v[], int argc)
602{
603 /*
604 in case of new()
605 */
606 if( argc == 0 ) {
607 mrbc_value ret = mrbc_array_new(vm, 0);
608
609 SET_RETURN(ret);
610 return;
611 }
612
613 /*
614 in case of new(num)
615 */
616 if( argc == 1 && mrbc_type(v[1]) == MRBC_TT_INTEGER && mrbc_integer(v[1]) >= 0 ) {
617 int num = mrbc_integer(v[1]);
618 mrbc_value ret = mrbc_array_new(vm, num);
619
620 if( num > 0 ) {
621 mrbc_array_set(&ret, num - 1, &mrbc_nil_value());
622 }
623 SET_RETURN(ret);
624 return;
625 }
626
627 /*
628 in case of new(num, value)
629 */
630 if( argc == 2 && mrbc_type(v[1]) == MRBC_TT_INTEGER && mrbc_integer(v[1]) >= 0 ) {
631 int num = mrbc_integer(v[1]);
632 mrbc_value ret = mrbc_array_new(vm, num);
633
634 for( int i = 0; i < num; i++ ) {
635 mrbc_incref(&v[2]);
636 mrbc_array_set(&ret, i, &v[2]);
637 }
638 SET_RETURN(ret);
639 return;
640 }
641
642 /*
643 other case
644 */
645 mrbc_raise( vm, MRBC_CLASS(ArgumentError), 0 );
646}
647
648
649//================================================================
652static void c_array_add(mrbc_vm *vm, mrbc_value v[], int argc)
653{
654 if( mrbc_type(v[1]) != MRBC_TT_ARRAY ) {
655 mrbc_raise( vm, MRBC_CLASS(TypeError), 0 );
656 return;
657 }
658
659 mrbc_array *h1 = v[0].array;
660 mrbc_array *h2 = v[1].array;
661 mrbc_value value = mrbc_array_new(vm, h1->n_stored + h2->n_stored);
662
663 memcpy( value.array->data, h1->data,
664 sizeof(mrbc_value) * h1->n_stored );
665 memcpy( value.array->data + h1->n_stored, h2->data,
666 sizeof(mrbc_value) * h2->n_stored );
667 value.array->n_stored = h1->n_stored + h2->n_stored;
668
669 mrbc_value *p1 = value.array->data;
670 const mrbc_value *p2 = p1 + value.array->n_stored;
671 while( p1 < p2 ) {
672 mrbc_incref(p1++);
673 }
674
676 SET_RETURN(value);
677}
678
679
680//================================================================
683static void c_array_get(mrbc_vm *vm, mrbc_value v[], int argc)
684{
685 /*
686 in case of Array[...] -> Array
687 */
688 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) {
689 mrbc_value ret = mrbc_array_new(vm, argc);
690
691 memcpy( ret.array->data, &v[1], sizeof(mrbc_value) * argc );
692 for( int i = 1; i <= argc; i++ ) {
693 mrbc_set_tt( &v[i], MRBC_TT_EMPTY );
694 }
695 ret.array->n_stored = argc;
696
697 SET_RETURN(ret);
698 return;
699 }
700
701 /*
702 in case of self[nth] -> object | nil
703 */
704 if( argc == 1 && mrbc_type(v[1]) == MRBC_TT_INTEGER ) {
705 mrbc_value ret = mrbc_array_get(v, mrbc_integer(v[1]));
706 mrbc_incref(&ret);
707 SET_RETURN(ret);
708 return;
709 }
710
711 /*
712 in case of self[Range] -> Array | nil
713 */
714 if (argc == 1 && mrbc_type(v[1]) == MRBC_TT_RANGE) {
715 int len = mrbc_array_size(&v[0]);
716 mrbc_value *range_ptr = &v[1];
717
718 // Get range start and end from range object
719 mrbc_value start_val = mrbc_range_first(range_ptr);
720 mrbc_value end_val = mrbc_range_last(range_ptr);
721 int flag_exclude = mrbc_range_exclude_end(range_ptr);
722
723 // Handle beginless range (e.g., ..1, ...2)
724 int start;
725 if (mrbc_type(start_val) == MRBC_TT_NIL) {
726 start = 0;
727 } else if (mrbc_type(start_val) == MRBC_TT_INTEGER) {
728 start = mrbc_integer(start_val);
729 } else {
730 goto TYPE_ERROR;
731 }
732
733 // Handle endless range (e.g., 0.., 1..., 0..., 1...)
734 int end;
735 if (mrbc_type(end_val) == MRBC_TT_NIL) {
736 end = len;
737 } else if (mrbc_type(end_val) == MRBC_TT_INTEGER) {
738 end = mrbc_integer(end_val);
739 } else {
740 goto TYPE_ERROR;
741 }
742
743 // Negative indices
744 if (start < 0) start += len;
745 if (end < 0) end += len;
746
747 if (start < 0 || start > len) goto RETURN_NIL;
748 // Allow end < 0 only for empty arrays with endless ranges
749 if (end < 0 && len > 0) goto RETURN_NIL;
750
751 // Adjust end for exclusive range
752 if (!flag_exclude) end++;
753
754 // Calculate size
755 int size = end - start;
756 if (size < 0) size = 0;
757 if (start + size > len) size = len - start;
758
759 mrbc_value ret = mrbc_array_new(vm, size);
760 if (ret.array == NULL) return; // ENOMEM
761
762 for (int i = 0; i < size; i++) {
763 mrbc_value val = mrbc_array_get(v, start + i);
764 mrbc_incref(&val);
765 mrbc_array_push(&ret, &val);
766 }
767
768 SET_RETURN(ret);
769 return;
770 }
771
772 /*
773 in case of self[start, length] -> Array | nil
774 */
775 if( argc == 2 && mrbc_type(v[1]) == MRBC_TT_INTEGER && mrbc_type(v[2]) == MRBC_TT_INTEGER ) {
776 int len = mrbc_array_size(&v[0]);
777 int idx = mrbc_integer(v[1]);
778 if( idx < 0 ) idx += len;
779 if( idx < 0 ) goto RETURN_NIL;
780
781 int size = (mrbc_integer(v[2]) < (len - idx)) ? mrbc_integer(v[2]) : (len - idx);
782 // min( mrbc_integer(v[2]), (len - idx) )
783 if( size < 0 ) goto RETURN_NIL;
784
785 mrbc_value ret = mrbc_array_new(vm, size);
786
787 for( int i = 0; i < size; i++ ) {
788 mrbc_value val = mrbc_array_get(v, mrbc_integer(v[1]) + i);
789 mrbc_incref(&val);
790 mrbc_array_push(&ret, &val);
791 }
792
793 SET_RETURN(ret);
794 return;
795 }
796
797 /*
798 other case
799 */
800 mrbc_raise( vm, MRBC_CLASS(ArgumentError), 0 );
801 return;
802
803 TYPE_ERROR:
804 mrbc_raise( vm, MRBC_CLASS(TypeError), 0 );
805 return;
806
807 RETURN_NIL:
809}
810
811
812//================================================================
815static void c_array_set(mrbc_vm *vm, mrbc_value v[], int argc)
816{
817 /*
818 in case of self[nth] = val
819 */
820 if( argc == 2 && mrbc_type(v[1]) == MRBC_TT_INTEGER ) {
821 if( mrbc_array_set(v, mrbc_integer(v[1]), &v[2]) != 0 ) {
822 mrbc_raise( vm, MRBC_CLASS(IndexError), "too small for array");
823 return;
824 }
825
826 // return val
827 mrbc_incref(&v[2]);
828 mrbc_decref(&v[0]);
829 v[0] = v[2];
831 return;
832 }
833
834 /*
835 in case of self[start, length] = val
836 */
837 if( argc == 3 && mrbc_type(v[1]) == MRBC_TT_INTEGER &&
838 mrbc_type(v[2]) == MRBC_TT_INTEGER ) {
839 int pos = mrbc_integer(v[1]);
840 int len = mrbc_integer(v[2]);
841
842 if( pos < 0 ) {
843 pos = v[0].array->n_stored + pos;
844 if( pos < 0 ) {
845 mrbc_raise( vm, MRBC_CLASS(IndexError), "index too small for array");
846 return;
847 }
848 } else if( pos > v[0].array->n_stored ) {
849 mrbc_array_set( &v[0], pos-1, &mrbc_nil_value() );
850 len = 0;
851 }
852 if( len < 0 ) {
853 mrbc_raise( vm, MRBC_CLASS(IndexError), "negative length");
854 return;
855 }
856 if( pos+len > v[0].array->n_stored ) {
857 len = v[0].array->n_stored - pos;
858 }
859
860 // split 2 part
861 mrbc_value v1 = mrbc_array_divide(vm, &v[0], pos+len);
862 mrbc_array *ha0 = v[0].array;
863
864 // delete data from tail.
865 for( int i = 0; i < len; i++ ) {
866 mrbc_decref( &ha0->data[--ha0->n_stored] );
867 }
868
869 // append data
870 if( mrbc_type(v[3]) == MRBC_TT_ARRAY ) {
871 mrbc_array_push_m(&v[0], &v[3]);
872 for( int i = 0; i < v[3].array->n_stored; i++ ) {
873 mrbc_incref( &v[3].array->data[i] );
874 }
875 } else {
876 mrbc_incref(&v[3]);
877 mrbc_array_push(&v[0], &v[3]);
878 }
879
880 mrbc_array_push_m(&v[0], &v1);
882
883 // return val
884 mrbc_decref(&v[0]);
885 v[0] = v[3];
887 return;
888 }
889
890 /*
891 other case
892 */
893 mrbc_raise( vm, MRBC_CLASS(ArgumentError), 0 );
894}
895
896
897//================================================================
900static void c_array_clear(mrbc_vm *vm, mrbc_value v[], int argc)
901{
903}
904
905
906//================================================================
909static void c_array_difference(mrbc_vm *vm, mrbc_value v[], int argc)
910{
911 mrbc_value ret = mrbc_array_dup(vm, &v[0]);
912
913 for( int i = 1; i <= argc; i++ ) {
914 if( mrbc_type(v[i]) != MRBC_TT_ARRAY ) {
915 mrbc_raise( vm, MRBC_CLASS(TypeError), 0 );
916 return;
917 }
918
919 for( int j = 0; j < mrbc_array_size(&v[i]); j++ ) {
920 int idx;
921 while( (idx = mrbc_array_index( &ret, &v[i].array->data[j] )) >= 0 ) {
922 mrbc_array *ah = ret.array;
923 ah->n_stored--;
924 memmove(ah->data + idx, ah->data + idx + 1,
925 sizeof(mrbc_value) * (ah->n_stored - idx));
926 }
927 }
928 }
929
930 SET_RETURN(ret);
931}
932
933
934//================================================================
937static void c_array_delete_at(mrbc_vm *vm, mrbc_value v[], int argc)
938{
939 if( argc == 1 && mrbc_type(v[1]) == MRBC_TT_INTEGER ) {
941 SET_RETURN(val);
942 } else {
943 mrbc_raise( vm, MRBC_CLASS(ArgumentError), 0 );
944 }
945}
946
947
948//================================================================
951static void c_array_empty(mrbc_vm *vm, mrbc_value v[], int argc)
952{
953 int n = mrbc_array_size(v);
954
955 SET_BOOL_RETURN( !n );
956}
957
958
959//================================================================
962static void c_array_size(mrbc_vm *vm, mrbc_value v[], int argc)
963{
964 int n = mrbc_array_size(v);
965
967}
968
969
970//================================================================
973static void c_array_include(mrbc_vm *vm, mrbc_value v[], int argc)
974{
975 SET_BOOL_RETURN(0 < mrbc_array_include(&v[0], &v[1]));
976}
977
978
979//================================================================
982static void c_array_and(mrbc_vm *vm, mrbc_value v[], int argc)
983{
984 if( mrbc_type(v[1]) != MRBC_TT_ARRAY ) {
985 mrbc_raisef( vm, MRBC_CLASS(TypeError), "no implicit conversion into %s", "Array");
986 return;
987 }
988 mrbc_value result = mrbc_array_new(vm, 0);
989 for( int i = 0; i < v[0].array->n_stored; i++) {
990 mrbc_value *data = &v[0].array->data[i];
991 if (0 < mrbc_array_include(&v[1], data) && 0 == mrbc_array_include(&result, data))
992 {
993 mrbc_array_push(&result, data);
994 }
995 }
996 SET_RETURN(result);
997}
998
999
1000//================================================================
1003static void c_array_or(mrbc_vm *vm, mrbc_value v[], int argc)
1004{
1005 if( mrbc_type(v[1]) != MRBC_TT_ARRAY ) {
1006 mrbc_raisef( vm, MRBC_CLASS(TypeError), "no implicit conversion into %s", "Array");
1007 return;
1008 }
1009 mrbc_value result = mrbc_array_new(vm, 0);
1010 for( int i = 0; i < v[0].array->n_stored; i++) {
1011 mrbc_value *data = &v[0].array->data[i];
1012 if (0 == mrbc_array_include(&result, data))
1013 {
1014 mrbc_array_push(&result, data);
1015 }
1016 }
1017
1018 for( int i = 0; i < v[1].array->n_stored; i++) {
1019 mrbc_value *data = &v[1].array->data[i];
1020 if (0 == mrbc_array_include(&result, data))
1021 {
1022 mrbc_array_push(&result, data);
1023 }
1024 }
1025 SET_RETURN(result);
1026}
1027
1028
1029//================================================================
1032static void c_array_first(mrbc_vm *vm, mrbc_value v[], int argc)
1033{
1034 mrbc_value val = mrbc_array_get(v, 0);
1035 mrbc_incref(&val);
1036 SET_RETURN(val);
1037}
1038
1039
1040//================================================================
1043static void c_array_last(mrbc_vm *vm, mrbc_value v[], int argc)
1044{
1045 mrbc_value val = mrbc_array_get(v, -1);
1046 mrbc_incref(&val);
1047 SET_RETURN(val);
1048}
1049
1050
1051//================================================================
1054static void c_array_push(mrbc_vm *vm, mrbc_value v[], int argc)
1055{
1056 mrbc_array_push(&v[0], &v[1]);
1057 mrbc_set_tt( &v[1], MRBC_TT_EMPTY );
1058}
1059
1060
1061//================================================================
1064static void c_array_pop(mrbc_vm *vm, mrbc_value v[], int argc)
1065{
1066 /*
1067 in case of pop() -> object | nil
1068 */
1069 if( argc == 0 ) {
1070 mrbc_value val = mrbc_array_pop(v);
1071 SET_RETURN(val);
1072 return;
1073 }
1074
1075 /*
1076 in case of pop(n) -> Array
1077 */
1078 if( argc == 1 && mrbc_type(v[1]) == MRBC_TT_INTEGER ) {
1079 int pos = mrbc_array_size(&v[0]) - v[1].i;
1080 mrbc_value val = mrbc_array_divide(vm, &v[0], pos);
1081 SET_RETURN(val);
1082 return;
1083 }
1084
1085 mrbc_raise( vm, MRBC_CLASS(ArgumentError), 0 );
1086}
1087
1088
1089//================================================================
1092static void c_array_unshift(mrbc_vm *vm, mrbc_value v[], int argc)
1093{
1094 mrbc_array_unshift(&v[0], &v[1]);
1095 mrbc_set_tt( &v[1], MRBC_TT_EMPTY );
1096}
1097
1098
1099//================================================================
1102static void c_array_shift(mrbc_vm *vm, mrbc_value v[], int argc)
1103{
1104 /*
1105 in case of pop() -> object | nil
1106 */
1107 if( argc == 0 ) {
1109 SET_RETURN(val);
1110 return;
1111 }
1112
1113 /*
1114 in case of pop(n) -> Array
1115 */
1116 if( argc == 1 && mrbc_type(v[1]) == MRBC_TT_INTEGER ) {
1117 mrbc_value val = mrbc_array_divide(vm, &v[0], v[1].i);
1118
1119 // swap v[0] and val
1120 mrbc_array tmp = *v[0].array;
1121 v[0].array->data_size = val.array->data_size;
1122 v[0].array->n_stored = val.array->n_stored;
1123 v[0].array->data = val.array->data;
1124
1125 val.array->data_size = tmp.data_size;
1126 val.array->n_stored = tmp.n_stored;
1127 val.array->data = tmp.data;
1128
1129 SET_RETURN(val);
1130 return;
1131 }
1132
1133 mrbc_raise( vm, MRBC_CLASS(ArgumentError), 0 );
1134}
1135
1136
1137//================================================================
1140static void c_array_dup(mrbc_vm *vm, mrbc_value v[], int argc)
1141{
1142 SET_RETURN( mrbc_array_dup( vm, &v[0] ) );
1143}
1144
1145
1146//================================================================
1149static void c_array_min(mrbc_vm *vm, mrbc_value v[], int argc)
1150{
1151 // Subset of Array#min, not support min(n).
1152
1153 mrbc_value *p_min_value, *p_max_value;
1154
1155 mrbc_array_minmax(&v[0], &p_min_value, &p_max_value);
1156 if( p_min_value == NULL ) {
1158 return;
1159 }
1160
1161 mrbc_incref(p_min_value);
1162 SET_RETURN(*p_min_value);
1163}
1164
1165
1166//================================================================
1169static void c_array_max(mrbc_vm *vm, mrbc_value v[], int argc)
1170{
1171 // Subset of Array#max, not support max(n).
1172
1173 mrbc_value *p_min_value, *p_max_value;
1174
1175 mrbc_array_minmax(&v[0], &p_min_value, &p_max_value);
1176 if( p_max_value == NULL ) {
1178 return;
1179 }
1180
1181 mrbc_incref(p_max_value);
1182 SET_RETURN(*p_max_value);
1183}
1184
1185
1186//================================================================
1189static void c_array_minmax(mrbc_vm *vm, mrbc_value v[], int argc)
1190{
1191 // Subset of Array#minmax, not support minmax(n).
1192
1193 mrbc_value *p_min_value, *p_max_value;
1194 mrbc_value nil = mrbc_nil_value();
1195 mrbc_value ret = mrbc_array_new(vm, 2);
1196
1197 mrbc_array_minmax(&v[0], &p_min_value, &p_max_value);
1198 if( p_min_value == NULL ) p_min_value = &nil;
1199 if( p_max_value == NULL ) p_max_value = &nil;
1200
1201 mrbc_incref(p_min_value);
1202 mrbc_incref(p_max_value);
1203 mrbc_array_set(&ret, 0, p_min_value);
1204 mrbc_array_set(&ret, 1, p_max_value);
1205
1206 SET_RETURN(ret);
1207}
1208
1209
1210//================================================================
1213static void c_array_uniq(mrbc_vm *vm, mrbc_value v[], int argc)
1214{
1215 // subset of Array#uniq
1216
1217 if( mrbc_c_block_given(vm, v, argc) ) {
1218 mrbc_raise(vm, MRBC_CLASS(NotImplementedError), "Block are not supported");
1219 return;
1220 }
1221
1222 mrbc_value ret = mrbc_array_uniq( vm, &v[0] );
1223 SET_RETURN( ret );
1224}
1225
1226
1227//================================================================
1230static void c_array_uniq_self(mrbc_vm *vm, mrbc_value v[], int argc)
1231{
1232 // subset of Array#uniq!
1233
1234 if( mrbc_c_block_given(vm, v, argc) ) {
1235 mrbc_raise(vm, MRBC_CLASS(NotImplementedError), "Block are not supported");
1236 return;
1237 }
1238
1239 int n = mrbc_array_uniq_self( &v[0] );
1240 if( n == 0 ) SET_NIL_RETURN();
1241}
1242
1243
1244//================================================================
1247static void c_array_reverse(mrbc_vm *vm, mrbc_value v[], int argc)
1248{
1249 mrbc_value *self = &v[0];
1250 int n = mrbc_array_size(self);
1251 mrbc_value ret = mrbc_array_new(vm, n);
1252
1253 // Direct access for performance.
1254 for( int i = 0; i < n; i++ ) {
1255 mrbc_value *v1 = &self->array->data[n - i - 1];
1256 mrbc_incref(v1);
1257 ret.array->data[i] = *v1;
1258 }
1259 ret.array->n_stored = n;
1260
1261 SET_RETURN( ret );
1262}
1263
1264
1265//================================================================
1268static void c_array_reverse_self(mrbc_vm *vm, mrbc_value v[], int argc)
1269{
1270 mrbc_value *self = &v[0];
1271 int n = mrbc_array_size(self);
1272
1273 // Direct access for performance.
1274 for( int i = 0; i < n/2; i++ ) {
1275 mrbc_value v1 = self->array->data[i];
1276 self->array->data[i] = self->array->data[n - i - 1];
1277 self->array->data[n - i - 1] = v1;
1278 }
1279}
1280
1281//================================================================
1284static void c_array_deconstruct(struct VM *vm, mrbc_value v[], int argc)
1285{
1286 // Check argument count (must have no arguments)
1287 if (argc != 0) {
1288 mrbc_raise(vm, MRBC_CLASS(ArgumentError), "wrong number of arguments");
1289 return;
1290 }
1291 // For pattern matching - return self (not a copy)
1292 // (already an array, no conversion needed)
1293}
1294
1295
1296#if MRBC_USE_STRING
1297//================================================================
1300static void c_array_inspect(mrbc_vm *vm, mrbc_value v[], int argc)
1301{
1302 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) {
1303 mrbc_object_inspect(vm, v, argc);
1304 return;
1305 }
1306
1307 mrbc_value ret = mrbc_string_new_cstr(vm, "[");
1308
1309 for( int i = 0; i < mrbc_array_size(v); i++ ) {
1310 if( i != 0 ) mrbc_string_append_cstr( &ret, ", " );
1311
1312 mrbc_value v1 = mrbc_array_get(v, i);
1313 mrbc_value s1 = mrbc_send( vm, v, argc, &v1, "inspect", 0 );
1314 mrbc_string_append( &ret, &s1 );
1315 mrbc_string_delete( &s1 );
1316 }
1317
1318 mrbc_string_append_cstr( &ret, "]" );
1319
1320 SET_RETURN(ret);
1321}
1322
1323
1324//================================================================
1327static void c_array_join_1(mrbc_vm *vm, mrbc_value v[], int argc,
1328 mrbc_value *src, mrbc_value *ret, mrbc_value *separator)
1329{
1330 if( mrbc_array_size(src) == 0 ) return;
1331
1332 int i = 0;
1333 int flag_error = 0;
1334 while( !flag_error ) {
1335 if( mrbc_type(src->array->data[i]) == MRBC_TT_ARRAY ) {
1336 c_array_join_1(vm, v, argc, &src->array->data[i], ret, separator);
1337 } else {
1338 mrbc_value v1 = mrbc_send( vm, v, argc, &src->array->data[i], "to_s", 0 );
1339 flag_error |= mrbc_string_append( ret, &v1 );
1340 mrbc_decref(&v1);
1341 }
1342 if( ++i >= mrbc_array_size(src) ) break; // normal return.
1343 flag_error |= mrbc_string_append( ret, separator );
1344 }
1345}
1346
1347static void c_array_join(mrbc_vm *vm, mrbc_value v[], int argc)
1348{
1349 mrbc_value ret = mrbc_string_new(vm, NULL, 0);
1350 mrbc_value separator = (argc == 0) ? mrbc_string_new_cstr(vm, "") :
1351 mrbc_send( vm, v, argc, &v[1], "to_s", 0 );
1352
1353 c_array_join_1(vm, v, argc, &v[0], &ret, &separator );
1354 mrbc_decref(&separator);
1355
1356 SET_RETURN(ret);
1357}
1358
1359#endif
1360
1361
1362/* MRBC_AUTOGEN_METHOD_TABLE
1363
1364 CLASS("Array")
1365 FILE("_autogen_class_array.h")
1366
1367 METHOD( "new", c_array_new )
1368 METHOD( "+", c_array_add )
1369 METHOD( "-", c_array_difference )
1370 METHOD( "[]", c_array_get )
1371 METHOD( "at", c_array_get )
1372 METHOD( "[]=", c_array_set )
1373 METHOD( "<<", c_array_push )
1374 METHOD( "clear", c_array_clear )
1375 METHOD( "difference", c_array_difference )
1376 METHOD( "deconstruct", c_array_deconstruct )
1377 METHOD( "delete_at", c_array_delete_at )
1378 METHOD( "empty?", c_array_empty )
1379 METHOD( "size", c_array_size )
1380 METHOD( "length", c_array_size )
1381 METHOD( "count", c_array_size )
1382 METHOD( "include?", c_array_include )
1383 METHOD( "&", c_array_and )
1384 METHOD( "|", c_array_or )
1385 METHOD( "first", c_array_first )
1386 METHOD( "last", c_array_last )
1387 METHOD( "push", c_array_push )
1388 METHOD( "pop", c_array_pop )
1389 METHOD( "shift", c_array_shift )
1390 METHOD( "unshift", c_array_unshift )
1391 METHOD( "dup", c_array_dup )
1392 METHOD( "min", c_array_min )
1393 METHOD( "max", c_array_max )
1394 METHOD( "minmax", c_array_minmax )
1395 METHOD( "uniq", c_array_uniq )
1396 METHOD( "uniq!", c_array_uniq_self )
1397 METHOD( "reverse", c_array_reverse )
1398 METHOD( "reverse!", c_array_reverse_self )
1399
1400#if MRBC_USE_STRING
1401 METHOD( "inspect", c_array_inspect )
1402 METHOD( "to_s", c_array_inspect )
1403 METHOD( "join", c_array_join )
1404#endif
1405*/
1406#include "_autogen_class_array.h"
void * mrbc_raw_realloc(void *ptr, unsigned int size)
Definition alloc.c:806
static void mrbc_set_nil(mrbc_value *p)
Definition boxing_no.h:99
#define mrbc_immediate_value(...)
Definition boxing_no.h:75
#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.
#define mrbc_integer(o)
Definition boxing_no.h:58
int mrbc_array_push(mrbc_value *ary, mrbc_value *set_val)
Definition c_array.c:243
mrbc_value mrbc_array_pop(mrbc_value *ary)
Definition c_array.c:288
int mrbc_array_set(mrbc_value *ary, int idx, mrbc_value *set_val)
Definition c_array.c:169
mrbc_value mrbc_array_get(const mrbc_value *ary, int idx)
Definition c_array.c:207
mrbc_value * mrbc_array_get_p(const mrbc_value *ary, int idx)
Definition c_array.c:225
mrbc_value mrbc_array_new(mrbc_vm *vm, int size)
Definition c_array.c:83
mrbc_value mrbc_array_dup(mrbc_vm *vm, const mrbc_value *ary)
Definition c_array.c:486
mrbc_value mrbc_array_divide(mrbc_vm *vm, mrbc_value *src, int pos)
Definition c_array.c:516
mrbc_value mrbc_array_remove(mrbc_value *ary, int idx)
Definition c_array.c:386
int mrbc_array_uniq_self(mrbc_value *ary)
Definition c_array.c:573
void mrbc_array_minmax(mrbc_value *ary, mrbc_value **pp_min_value, mrbc_value **pp_max_value)
Definition c_array.c:452
int mrbc_array_resize(mrbc_value *ary, int size)
Definition c_array.c:147
mrbc_value mrbc_array_uniq(mrbc_vm *vm, const mrbc_value *ary)
Definition c_array.c:558
mrbc_value mrbc_array_shift(mrbc_value *ary)
Definition c_array.c:316
void mrbc_array_clear(mrbc_value *ary)
Definition c_array.c:409
int mrbc_array_insert(mrbc_value *ary, int idx, mrbc_value *set_val)
Definition c_array.c:337
int mrbc_array_push_m(mrbc_value *ary, mrbc_value *set_val)
Definition c_array.c:264
int mrbc_array_unshift(mrbc_value *ary, mrbc_value *set_val)
Definition c_array.c:304
int mrbc_array_index(const mrbc_value *ary, const mrbc_value *val)
Definition c_array.c:541
int mrbc_array_compare(const mrbc_value *v1, const mrbc_value *v2)
Definition c_array.c:432
void mrbc_array_delete(mrbc_value *ary)
Definition c_array.c:105
static void mrbc_array_delete_handle(mrbc_value *ary)
Definition c_array.h:106
static int mrbc_array_size(const mrbc_value *ary)
Definition c_array.h:84
struct RArray mrbc_array
Array object.
static int mrbc_array_include(const mrbc_value *ary, const mrbc_value *val)
Definition c_array.h:97
void mrbc_object_inspect(mrbc_vm *vm, mrbc_value v[], int argc)
Definition c_object.c:91
static mrbc_value mrbc_range_last(const mrbc_value *v)
Definition c_range.h:82
static int mrbc_range_exclude_end(const mrbc_value *v)
Definition c_range.h:98
static mrbc_value mrbc_range_first(const mrbc_value *v)
Definition c_range.h:66
void mrbc_string_delete(mrbc_value *str)
Definition c_string.c:107
mrbc_value mrbc_string_new(mrbc_vm *vm, const void *src, int len)
Definition c_string.c:64
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
void mrbc_raisef(struct VM *vm, struct RClass *exc_cls, const char *fstr,...)
Definition error.c:168
Include at once the necessary header files.
uint16_t n_stored
num of stored.
Definition c_array.h:47
uint16_t data_size
data buffer size.
Definition c_array.h:46
mrbc_value * data
pointer to allocated memory.
Definition c_array.h:48
mrbc_int_t i
Definition boxing_no.h:22
struct RArray * array
Definition boxing_no.h:31
Virtual Machine.
Definition vm.h:150
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
static void mrbc_decref_empty(mrbc_value *v)
Definition value.h:590
#define SET_NIL_RETURN()
Definition value.h:226
static void mrbc_incref(mrbc_value *v)
Definition value.h:557
@ E_INDEX_ERROR
Definition value.h:115
@ MRBC_TT_INTEGER
Integer.
Definition value.h:86
@ MRBC_TT_EMPTY
Definition value.h:80
@ MRBC_TT_RANGE
Range.
Definition value.h:99
@ MRBC_TT_ARRAY
Array.
Definition value.h:97
@ MRBC_TT_NIL
NilClass.
Definition value.h:81
@ MRBC_TT_CLASS
Class.
Definition value.h:90
#define SET_RETURN(n)
Definition value.h:221
static int mrbc_c_block_given(mrbc_vm *vm, mrbc_value v[], int argc)
Definition vm.h:241
struct VM mrbc_vm
Virtual Machine.
Global configuration of mruby/c VM's.