mrb_value mrb_ary_shift(mrb_state *mrb, mrb_value self) { struct RArray *a = mrb_ary_ptr(self); mrb_value val; if (a->len == 0) return mrb_nil_value(); if (a->flags & MRB_ARY_SHARED) { L_SHIFT: val = a->ptr[0]; a->ptr++; a->len--; return val; } if (a->len > ARY_SHIFT_SHARED_MIN) { ary_make_shared(mrb, a); goto L_SHIFT; } else { mrb_value *ptr = a->ptr; int size = a->len; val = *ptr; while((int)(--size)) { *ptr = *(ptr+1); ++ptr; } --a->len; } return val; }
MRB_API mrb_value mrb_ary_shift(mrb_state *mrb, mrb_value self) { struct RArray *a = mrb_ary_ptr(self); mrb_int len = ARY_LEN(a); mrb_value val; ary_modify_check(mrb, a); if (len == 0) return mrb_nil_value(); if (ARY_SHARED_P(a)) { L_SHIFT: val = a->as.heap.ptr[0]; a->as.heap.ptr++; a->as.heap.len--; return val; } if (len > ARY_SHIFT_SHARED_MIN) { ary_make_shared(mrb, a); goto L_SHIFT; } else { mrb_value *ptr = ARY_PTR(a); mrb_int size = len; val = *ptr; while (--size) { *ptr = *(ptr+1); ++ptr; } ARY_SET_LEN(a, len-1); } return val; }
static mrb_value ary_subseq(mrb_state *mrb, struct RArray *a, int beg, int len) { struct RArray *b; ary_make_shared(mrb, a); b = (struct RArray*)mrb_obj_alloc(mrb, MRB_TT_ARRAY, mrb->array_class); b->ptr = a->ptr + beg; b->len = len; b->aux.shared = a->aux.shared; b->aux.shared->refcnt++; b->flags |= MRB_ARY_SHARED; return mrb_obj_value(b); }
static mrb_value ary_subseq(mrb_state *mrb, struct RArray *a, mrb_int beg, mrb_int len) { struct RArray *b; if (!ARY_SHARED_P(a) && len <= ARY_SHIFT_SHARED_MIN) { return mrb_ary_new_from_values(mrb, len, ARY_PTR(a)+beg); } ary_make_shared(mrb, a); b = (struct RArray*)mrb_obj_alloc(mrb, MRB_TT_ARRAY, mrb->array_class); b->as.heap.ptr = a->as.heap.ptr + beg; b->as.heap.len = len; b->as.heap.aux.shared = a->as.heap.aux.shared; b->as.heap.aux.shared->refcnt++; ARY_SET_SHARED_FLAG(b); return mrb_obj_value(b); }
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); }