static mrb_value mrb_ary_unshift_m(mrb_state *mrb, mrb_value self) { struct RArray *a = mrb_ary_ptr(self); mrb_value *vals; mrb_int len; mrb_get_args(mrb, "*", &vals, &len); if (ARY_SHARED_P(a) && a->aux.shared->refcnt == 1 /* shared only referenced from this array */ && a->ptr - a->aux.shared->ptr >= len) /* there's room for unshifted item */ { a->ptr -= len; } else { ary_modify(mrb, a); if (len == 0) return self; if (a->aux.capa < a->len + len) ary_expand_capa(mrb, a, a->len + len); value_move(a->ptr + len, a->ptr, a->len); } array_copy(a->ptr, vals, len); a->len += len; while (len--) { mrb_field_write_barrier_value(mrb, (struct RBasic*)a, vals[len]); } return self; }
mrb_value mrb_ary_unshift_m(mrb_state *mrb, mrb_value self) { struct RArray *a = mrb_ary_ptr(self); mrb_value *vals; int len; mrb_get_args(mrb, "*", &vals, &len); if ((a->flags & MRB_ARY_SHARED) && a->aux.shared->refcnt == 1 /* shared only referenced from this array */ && a->ptr - a->aux.shared->ptr >= len) /* there's room for unshifted item */ { a->ptr -= len; } else { ary_modify(mrb, a); if (len == 0) return self; if (a->aux.capa < a->len + len) ary_expand_capa(mrb, a, a->len + len); memmove(a->ptr + len, a->ptr, sizeof(mrb_value)*a->len); } memcpy(a->ptr, vals, sizeof(mrb_value)*len); a->len += len; mrb_write_barrier(mrb, (struct RBasic*)a); return self; }
/* self = [1,2,3] item = 0 self.unshift item p self #=> [0, 1, 2, 3] */ MRB_API mrb_value mrb_ary_unshift(mrb_state *mrb, mrb_value self, mrb_value item) { struct RArray *a = mrb_ary_ptr(self); mrb_int len = ARY_LEN(a); if (ARY_SHARED_P(a) && a->as.heap.aux.shared->refcnt == 1 /* shared only referenced from this array */ && a->as.heap.ptr - a->as.heap.aux.shared->ptr >= 1) /* there's room for unshifted item */ { a->as.heap.ptr--; a->as.heap.ptr[0] = item; } else { mrb_value *ptr; ary_modify(mrb, a); if (ARY_CAPA(a) < len + 1) ary_expand_capa(mrb, a, len + 1); ptr = ARY_PTR(a); value_move(ptr + 1, ptr, len); ptr[0] = item; } ARY_SET_LEN(a, len+1); mrb_field_write_barrier_value(mrb, (struct RBasic*)a, item); return self; }
static mrb_value mrb_ary_unshift_m(mrb_state *mrb, mrb_value self) { struct RArray *a = mrb_ary_ptr(self); mrb_value *vals, *ptr; mrb_int alen, len; mrb_get_args(mrb, "*!", &vals, &alen); len = ARY_LEN(a); if (alen > ARY_MAX_SIZE - len) { mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); } if (ARY_SHARED_P(a) && a->as.heap.aux.shared->refcnt == 1 /* shared only referenced from this array */ && a->as.heap.ptr - a->as.heap.aux.shared->ptr >= alen) /* there's room for unshifted item */ { ary_modify_check(mrb, a); a->as.heap.ptr -= len; ptr = a->as.heap.ptr; } else { ary_modify(mrb, a); if (alen == 0) return self; if (ARY_CAPA(a) < len + alen) ary_expand_capa(mrb, a, len + alen); ptr = ARY_PTR(a); value_move(ptr + alen, ptr, len); } array_copy(ptr, vals, alen); ARY_SET_LEN(a, len+alen); while (alen--) { mrb_field_write_barrier_value(mrb, (struct RBasic*)a, vals[alen]); } return self; }
MRB_API mrb_value mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_value rpl) { struct RArray *a = mrb_ary_ptr(ary); mrb_int tail, size; mrb_value *argv; mrb_int i, argc; ary_modify(mrb, a); /* len check */ if (len < 0) mrb_raisef(mrb, E_INDEX_ERROR, "negative length (%S)", mrb_fixnum_value(len)); /* range check */ if (head < 0) { head += a->len; if (head < 0) { mrb_raise(mrb, E_INDEX_ERROR, "index is out of array"); } } if (a->len < len || a->len < head + len) { len = a->len - head; } tail = head + len; /* size check */ if (mrb_array_p(rpl)) { argc = RARRAY_LEN(rpl); argv = RARRAY_PTR(rpl); } else { argc = 1; argv = &rpl; } size = head + argc; if (tail < a->len) size += a->len - tail; if (size > a->aux.capa) ary_expand_capa(mrb, a, size); if (head > a->len) { ary_fill_with_nil(a->ptr + a->len, head - a->len); } else if (head < a->len) { value_move(a->ptr + head + argc, a->ptr + tail, a->len - tail); } for (i = 0; i < argc; i++) { *(a->ptr + head + i) = *(argv + i); mrb_field_write_barrier_value(mrb, (struct RBasic*)a, argv[i]); } a->len = size; return ary; }
static void ary_replace(mrb_state *mrb, struct RArray *a, mrb_value *argv, int len) { ary_modify(mrb, a); if (a->aux.capa < len) ary_expand_capa(mrb, a, len); memcpy(a->ptr, argv, sizeof(mrb_value)*len); mrb_write_barrier(mrb, (struct RBasic*)a); a->len = len; }
static void ary_replace(mrb_state *mrb, struct RArray *a, mrb_value *argv, mrb_int len) { ary_modify(mrb, a); if (ARY_CAPA(a) < len) ary_expand_capa(mrb, a, len); array_copy(ARY_PTR(a), argv, len); mrb_write_barrier(mrb, (struct RBasic*)a); ARY_SET_LEN(a, len); }
void mrb_ary_push(mrb_state *mrb, mrb_value ary, mrb_value elem) /* mrb_ary_push */ { struct RArray *a = mrb_ary_ptr(ary); ary_modify(mrb, a); if (a->len == a->aux.capa) ary_expand_capa(mrb, a, a->len + 1); a->ptr[a->len++] = elem; mrb_write_barrier(mrb, (struct RBasic*)a); }
static void ary_concat(mrb_state *mrb, struct RArray *a, mrb_value *ptr, int blen) { int len = a->len + blen; ary_modify(mrb, a); if (a->aux.capa < len) ary_expand_capa(mrb, a, len); memcpy(a->ptr+a->len, ptr, sizeof(mrb_value)*blen); mrb_write_barrier(mrb, (struct RBasic*)a); a->len = len; }
MRB_API void mrb_ary_push(mrb_state *mrb, mrb_value ary, mrb_value elem) { struct RArray *a = mrb_ary_ptr(ary); mrb_int len = ARY_LEN(a); ary_modify(mrb, a); if (len == ARY_CAPA(a)) ary_expand_capa(mrb, a, len + 1); ARY_PTR(a)[len] = elem; ARY_SET_LEN(a, len+1); mrb_field_write_barrier_value(mrb, (struct RBasic*)a, elem); }
mrb_value mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_value rpl) { struct RArray *a = mrb_ary_ptr(ary); mrb_int tail, size; mrb_value *argv; mrb_int i, argc; ary_modify(mrb, a); /* range check */ if (head < 0) { head += a->len; if (head < 0) { mrb_raise(mrb, E_INDEX_ERROR, "index is out of array"); } } if (a->len < len || a->len < head + len) { len = a->len - head; } tail = head + len; /* size check */ if (mrb_array_p(rpl)) { argc = RARRAY_LEN(rpl); argv = RARRAY_PTR(rpl); } else { argc = 1; argv = &rpl; } size = head + argc; if (tail < a->len) size += a->len - tail; if (size > a->aux.capa) ary_expand_capa(mrb, a, size); if (head > a->len) { ary_fill_with_nil(a->ptr + a->len, (int)(head - a->len)); } else if (head < a->len) { memmove(a->ptr + head + argc, a->ptr + tail, sizeof(mrb_value)*(a->len - tail)); } for(i = 0; i < argc; i++) { *(a->ptr + head + i) = *(argv + i); } a->len = size; return ary; }
static void ary_concat(mrb_state *mrb, struct RArray *a, struct RArray *a2) { mrb_int len; if (ARY_LEN(a2) > ARY_MAX_SIZE - ARY_LEN(a)) { mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); } len = ARY_LEN(a) + ARY_LEN(a2); ary_modify(mrb, a); if (ARY_CAPA(a) < len) { ary_expand_capa(mrb, a, len); } array_copy(ARY_PTR(a)+ARY_LEN(a), ARY_PTR(a2), ARY_LEN(a2)); mrb_write_barrier(mrb, (struct RBasic*)a); ARY_SET_LEN(a, len); }
static mrb_value mrb_ary_push_m(mrb_state *mrb, mrb_value self) { mrb_value *argv; mrb_int len, len2, alen; struct RArray *a; mrb_get_args(mrb, "*!", &argv, &alen); a = mrb_ary_ptr(self); ary_modify(mrb, a); len = ARY_LEN(a); len2 = len + alen; if (ARY_CAPA(a) < len2) { ary_expand_capa(mrb, a, len2); } array_copy(ARY_PTR(a)+len, argv, alen); ARY_SET_LEN(a, len2); mrb_write_barrier(mrb, (struct RBasic*)a); return self; }
MRB_API mrb_value mrb_ary_resize(mrb_state *mrb, mrb_value ary, mrb_int new_len) { mrb_int old_len; struct RArray *a = mrb_ary_ptr(ary); ary_modify(mrb, a); old_len = RARRAY_LEN(ary); if (old_len != new_len) { a->len = new_len; if (new_len < old_len) { ary_shrink_capa(mrb, a); } else { ary_expand_capa(mrb, a, new_len); ary_fill_with_nil(a->ptr + old_len, new_len - old_len); } } return ary; }
static void ary_replace(mrb_state *mrb, struct RArray *a, struct RArray *b) { mrb_int len = ARY_LEN(b); ary_modify_check(mrb, a); if (a == b) return; if (ARY_SHARED_P(a)) { mrb_ary_decref(mrb, a->as.heap.aux.shared); a->as.heap.aux.capa = 0; a->as.heap.len = 0; a->as.heap.ptr = NULL; ARY_UNSET_SHARED_FLAG(a); } if (ARY_SHARED_P(b)) { shared_b: if (ARY_EMBED_P(a)) { ARY_UNSET_EMBED_FLAG(a); } else { mrb_free(mrb, a->as.heap.ptr); } a->as.heap.ptr = b->as.heap.ptr; a->as.heap.len = len; a->as.heap.aux.shared = b->as.heap.aux.shared; a->as.heap.aux.shared->refcnt++; ARY_SET_SHARED_FLAG(a); mrb_write_barrier(mrb, (struct RBasic*)a); return; } if (!MRB_FROZEN_P(b) && len > ARY_REPLACE_SHARED_MIN) { ary_make_shared(mrb, b); goto shared_b; } if (ARY_CAPA(a) < len) ary_expand_capa(mrb, a, len); array_copy(ARY_PTR(a), ARY_PTR(b), len); mrb_write_barrier(mrb, (struct RBasic*)a); ARY_SET_LEN(a, len); }
void mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val) /* rb_ary_store */ { struct RArray *a = mrb_ary_ptr(ary); ary_modify(mrb, a); /* range check */ if (n < 0) { n += a->len; if (n < 0) { mrb_raise(mrb, E_INDEX_ERROR, "index %ld out of array", n - a->len); } } if (a->len <= (int)n) { if (a->aux.capa <= (int)n) ary_expand_capa(mrb, a, n + 1); ary_fill_with_nil(a->ptr + a->len, n + 1 - a->len); a->len = n + 1; } a->ptr[n] = val; mrb_write_barrier(mrb, (struct RBasic*)a); }
/* self = [1,2,3] item = 0 self.unshift item p self #=> [0, 1, 2, 3] */ mrb_value mrb_ary_unshift(mrb_state *mrb, mrb_value self, mrb_value item) { struct RArray *a = mrb_ary_ptr(self); if ((a->flags & MRB_ARY_SHARED) && a->aux.shared->refcnt == 1 /* shared only referenced from this array */ && a->ptr - a->aux.shared->ptr >= 1) /* there's room for unshifted item */ { a->ptr--; a->ptr[0] = item; } else { ary_modify(mrb, a); if (a->aux.capa < a->len + 1) ary_expand_capa(mrb, a, a->len + 1); memmove(a->ptr + 1, a->ptr, sizeof(mrb_value)*a->len); a->ptr[0] = item; } a->len++; mrb_write_barrier(mrb, (struct RBasic*)a); return self; }
MRB_API void mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val) { struct RArray *a = mrb_ary_ptr(ary); ary_modify(mrb, a); /* range check */ if (n < 0) { n += a->len; if (n < 0) { mrb_raisef(mrb, E_INDEX_ERROR, "index %S out of array", mrb_fixnum_value(n - a->len)); } } if (a->len <= n) { if (a->aux.capa <= n) ary_expand_capa(mrb, a, n + 1); ary_fill_with_nil(a->ptr + a->len, n + 1 - a->len); a->len = n + 1; } a->ptr[n] = val; mrb_field_write_barrier_value(mrb, (struct RBasic*)a, val); }
MRB_API void mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val) { struct RArray *a = mrb_ary_ptr(ary); mrb_int len = ARY_LEN(a); ary_modify(mrb, a); /* range check */ if (n < 0) { n += len; if (n < 0) { mrb_raisef(mrb, E_INDEX_ERROR, "index %S out of array", mrb_fixnum_value(n - len)); } } if (len <= n) { if (ARY_CAPA(a) <= n) ary_expand_capa(mrb, a, n + 1); ary_fill_with_nil(ARY_PTR(a) + len, n + 1 - len); ARY_SET_LEN(a, n+1); } ARY_PTR(a)[n] = val; mrb_field_write_barrier_value(mrb, (struct RBasic*)a, val); }
MRB_API mrb_value mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_value rpl) { struct RArray *a = mrb_ary_ptr(ary); mrb_int alen = ARY_LEN(a); const mrb_value *argv; mrb_int argc; mrb_int tail; ary_modify(mrb, a); /* len check */ if (len < 0) mrb_raisef(mrb, E_INDEX_ERROR, "negative length (%S)", mrb_fixnum_value(len)); /* range check */ if (head < 0) { head += alen; if (head < 0) { mrb_raise(mrb, E_INDEX_ERROR, "index is out of array"); } } tail = head + len; if (alen < len || alen < tail) { len = alen - head; } /* size check */ if (mrb_array_p(rpl)) { argc = RARRAY_LEN(rpl); argv = RARRAY_PTR(rpl); if (argv == ARY_PTR(a)) { struct RArray *r; if (argc > 32767) { mrb_raise(mrb, E_ARGUMENT_ERROR, "too big recursive splice"); } r = ary_dup(mrb, a); argv = ARY_PTR(r); } } else { argc = 1; argv = &rpl; } if (head >= alen) { if (head > ARY_MAX_SIZE - argc) { mrb_raisef(mrb, E_INDEX_ERROR, "index %S too big", mrb_fixnum_value(head)); } len = head + argc; if (len > ARY_CAPA(a)) { ary_expand_capa(mrb, a, head + argc); } ary_fill_with_nil(ARY_PTR(a) + alen, head - alen); if (argc > 0) { array_copy(ARY_PTR(a) + head, argv, argc); } ARY_SET_LEN(a, len); } else { mrb_int newlen; if (alen - len > ARY_MAX_SIZE - argc) { mrb_raisef(mrb, E_INDEX_ERROR, "index %S too big", mrb_fixnum_value(alen + argc - len)); } newlen = alen + argc - len; if (newlen > ARY_CAPA(a)) { ary_expand_capa(mrb, a, newlen); } if (len != argc) { mrb_value *ptr = ARY_PTR(a); tail = head + len; value_move(ptr + head + argc, ptr + tail, alen - tail); ARY_SET_LEN(a, newlen); } if (argc > 0) { value_move(ARY_PTR(a) + head, argv, argc); } } mrb_write_barrier(mrb, (struct RBasic*)a); return ary; }