diff options
Diffstat (limited to 'src/array.c')
| -rw-r--r-- | src/array.c | 508 |
1 files changed, 311 insertions, 197 deletions
diff --git a/src/array.c b/src/array.c index 187a8404d..804c946da 100644 --- a/src/array.c +++ b/src/array.c @@ -10,15 +10,14 @@ #include "mruby/string.h" #include "mruby/class.h" -//#define ARY_DEFAULT_LEN 16 #define ARY_DEFAULT_LEN 4 #define ARY_SHRINK_RATIO 5 /* must be larger than 2 */ -#ifdef LONG_MAX -# define ARY_MAX_SIZE (LONG_MAX / sizeof(mrb_value)) +#ifdef INT_MAX +# define ARY_MAX_SIZE (INT_MAX / sizeof(mrb_value)) #endif static inline mrb_value -ary_elt(mrb_value ary, long offset) +ary_elt(mrb_value ary, int offset) { if (RARRAY_LEN(ary) == 0) return mrb_nil_value(); if (offset < 0 || RARRAY_LEN(ary) <= offset) { @@ -28,12 +27,12 @@ ary_elt(mrb_value ary, long offset) } static struct RArray* -ary_new_capa(mrb_state *mrb, size_t capa) +ary_new_capa(mrb_state *mrb, int capa) { struct RArray *a; - size_t blen; + int blen; -#ifdef LONG_MAX +#ifdef INT_MAX if (capa > ARY_MAX_SIZE) { mrb_raise(mrb, E_ARGUMENT_ERROR, "ary size too big"); } @@ -47,16 +46,15 @@ ary_new_capa(mrb_state *mrb, size_t capa) } a = (struct RArray*)mrb_obj_alloc(mrb, MRB_TT_ARRAY, mrb->array_class); - a->buf = mrb_malloc(mrb, blen); - memset(a->buf, 0, blen); - a->capa = capa; + a->ptr = (mrb_value *)mrb_calloc(mrb, blen, 1); + a->aux.capa = capa; a->len = 0; return a; } mrb_value -mrb_ary_new_capa(mrb_state *mrb, size_t capa) +mrb_ary_new_capa(mrb_state *mrb, int capa) { struct RArray *a = ary_new_capa(mrb, capa); return mrb_obj_value(a); @@ -69,14 +67,14 @@ mrb_ary_new(mrb_state *mrb) } mrb_value -mrb_ary_new_from_values(mrb_state *mrb, size_t size, mrb_value *vals) +mrb_ary_new_from_values(mrb_state *mrb, int size, mrb_value *vals) { mrb_value ary; struct RArray *a; ary = mrb_ary_new_capa(mrb, size); a = mrb_ary_ptr(ary); - memcpy(a->buf, vals, sizeof(mrb_value)*size); + memcpy(a->ptr, vals, sizeof(mrb_value)*size); a->len = size; return ary; @@ -91,22 +89,70 @@ mrb_assoc_new(mrb_state *mrb, mrb_value car, mrb_value cdr) return mrb_ary_new_from_values(mrb, 2, arv); } -void -ary_fill_with_nil(mrb_value *buf, size_t size) +static void +ary_fill_with_nil(mrb_value *ptr, int size) { mrb_value nil = mrb_nil_value(); while((int)(size--)) { - *buf++ = nil; + *ptr++ = nil; } } -void -mrb_ary_expand_capa(mrb_state *mrb, struct RArray *a, size_t len) +static void +ary_modify(mrb_state *mrb, struct RArray *a) +{ + if (a->flags & MRB_ARY_SHARED) { + struct mrb_shared_array *shared = a->aux.shared; + + if (shared->refcnt == 1 && a->ptr == shared->ptr) { + a->ptr = shared->ptr; + a->aux.capa = a->len; + mrb_free(mrb, shared); + } + else { + mrb_value *ptr, *p; + int len; + + p = a->ptr; + len = a->len * sizeof(mrb_value); + ptr = (mrb_value *)mrb_malloc(mrb, len); + if (p) { + memcpy(ptr, p, len); + } + a->ptr = ptr; + a->aux.capa = a->len; + mrb_ary_decref(mrb, shared); + } + a->flags &= ~MRB_ARY_SHARED; + } +} + +static void +ary_make_shared(mrb_state *mrb, struct RArray *a) +{ + if (!(a->flags & MRB_ARY_SHARED)) { + struct mrb_shared_array *shared = (struct mrb_shared_array *)mrb_malloc(mrb, sizeof(struct mrb_shared_array)); + + shared->refcnt = 1; + if (a->aux.capa > a->len) { + a->ptr = shared->ptr = (mrb_value *)mrb_realloc(mrb, a->ptr, sizeof(mrb_value)*a->len+1); + } + else { + shared->ptr = a->ptr; + } + shared->len = a->len; + a->aux.shared = shared; + a->flags |= MRB_ARY_SHARED; + } +} + +static void +ary_expand_capa(mrb_state *mrb, struct RArray *a, int len) { - size_t capa = a->capa; + int capa = a->aux.capa; -#ifdef LONG_MAX +#ifdef INT_MAX if (len > ARY_MAX_SIZE) { mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); } @@ -121,20 +167,20 @@ mrb_ary_expand_capa(mrb_state *mrb, struct RArray *a, size_t len) } } -#ifdef LONG_MAX +#ifdef INT_MAX if (capa > ARY_MAX_SIZE) capa = ARY_MAX_SIZE; /* len <= capa <= ARY_MAX_SIZE */ #endif - if (capa > a->capa) { - a->capa = capa; - a->buf = mrb_realloc(mrb, a->buf, sizeof(mrb_value)*capa); + if (capa > a->aux.capa) { + a->aux.capa = capa; + a->ptr = (mrb_value *)mrb_realloc(mrb, a->ptr, sizeof(mrb_value)*capa); } } -void -mrb_ary_shrink_capa(mrb_state *mrb, struct RArray *a) +static void +ary_shrink_capa(mrb_state *mrb, struct RArray *a) { - size_t capa = a->capa; + int capa = a->aux.capa; if (capa < ARY_DEFAULT_LEN * 2) return; if (capa <= a->len * ARY_SHRINK_RATIO) return; @@ -147,9 +193,9 @@ mrb_ary_shrink_capa(mrb_state *mrb, struct RArray *a) } } while(capa > a->len * ARY_SHRINK_RATIO); - if (capa > a->len && capa < a->capa) { - a->capa = capa; - a->buf = mrb_realloc(mrb, a->buf, sizeof(mrb_value)*capa); + if (capa > a->len && capa < a->aux.capa) { + a->aux.capa = capa; + a->ptr = (mrb_value *)mrb_realloc(mrb, a->ptr, sizeof(mrb_value)*capa); } } @@ -160,29 +206,37 @@ mrb_ary_s_create(mrb_state *mrb, mrb_value self) int len; mrb_get_args(mrb, "*", &vals, &len); - return mrb_ary_new_from_values(mrb, (size_t)len, vals); + return mrb_ary_new_from_values(mrb, (int)len, vals); +} + +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; } void mrb_ary_concat(mrb_state *mrb, mrb_value self, mrb_value other) { - struct RArray *a1 = mrb_ary_ptr(self); struct RArray *a2 = mrb_ary_ptr(other); - size_t len = a1->len + a2->len; - if (a1->capa < len) mrb_ary_expand_capa(mrb, a1, len); - memcpy(a1->buf+a1->len, a2->buf, sizeof(mrb_value)*a2->len); - mrb_write_barrier(mrb, (struct RBasic*)a1); - a1->len = len; + ary_concat(mrb, mrb_ary_ptr(self), a2->ptr, a2->len); } mrb_value mrb_ary_concat_m(mrb_state *mrb, mrb_value self) { - mrb_value other; + mrb_value *ptr; + int blen; - mrb_get_args(mrb, "A", &other); - mrb_ary_concat(mrb, self, other); + mrb_get_args(mrb, "a", &ptr, &blen); + ary_concat(mrb, mrb_ary_ptr(self), ptr, blen); return self; } @@ -191,15 +245,16 @@ mrb_ary_plus(mrb_state *mrb, mrb_value self) { struct RArray *a1 = mrb_ary_ptr(self); struct RArray *a2; - mrb_value other; mrb_value ary; + mrb_value *ptr; + int blen; - mrb_get_args(mrb, "A", &other); - ary = mrb_ary_new_capa(mrb, a1->len + RARRAY_LEN(other)); + mrb_get_args(mrb, "a", &ptr, &blen); + ary = mrb_ary_new_capa(mrb, a1->len + blen); a2 = mrb_ary_ptr(ary); - memcpy(a2->buf, a1->buf, sizeof(mrb_value)*a1->len); - memcpy(a2->buf + a1->len, RARRAY_PTR(other), sizeof(mrb_value)*RARRAY_LEN(other)); - a2->len = a1->len + RARRAY_LEN(other); + memcpy(a2->ptr, a1->ptr, sizeof(mrb_value)*a1->len); + memcpy(a2->ptr + a1->len, ptr, sizeof(mrb_value)*blen); + a2->len = a1->len + blen; return ary; } @@ -228,12 +283,12 @@ mrb_ary_cmp(mrb_state *mrb, mrb_value ary1) mrb_value ary2; struct RArray *a1, *a2; mrb_value r = mrb_nil_value(); - long i, len; + int i, len; mrb_get_args(mrb, "o", &ary2); if (mrb_type(ary2) != MRB_TT_ARRAY) return mrb_nil_value(); a1 = RARRAY(ary1); a2 = RARRAY(ary2); - if (a1->len == a2->len && a1->buf == a2->buf) return mrb_fixnum_value(0); + if (a1->len == a2->len && a1->ptr == a2->ptr) return mrb_fixnum_value(0); else { len = RARRAY_LEN(ary1); if (len > RARRAY_LEN(ary2)) { @@ -248,22 +303,32 @@ mrb_ary_cmp(mrb_state *mrb, mrb_value ary1) return mrb_fixnum_value((len == 0)? 0: (len > 0)? 1: -1); } -void -mrb_ary_replace(mrb_state *mrb, struct RArray *a, mrb_value *argv, size_t len) +static void +ary_replace(mrb_state *mrb, struct RArray *a, mrb_value *argv, int len) { - if (a->capa < len) mrb_ary_expand_capa(mrb, a, len); - memcpy(a->buf, argv, sizeof(mrb_value)*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; } +void +mrb_ary_replace(mrb_state *mrb, mrb_value self, mrb_value other) +{ + struct RArray *a2 = mrb_ary_ptr(other); + + ary_replace(mrb, mrb_ary_ptr(self), a2->ptr, a2->len); +} + mrb_value mrb_ary_replace_m(mrb_state *mrb, mrb_value self) { mrb_value other; - mrb_get_args(mrb, "o", &other); - mrb_ary_replace(mrb, mrb_ary_ptr(self), RARRAY_PTR(other), RARRAY_LEN(other)); + mrb_get_args(mrb, "A", &other); + mrb_ary_replace(mrb, self, other); return self; } @@ -274,9 +339,8 @@ mrb_ary_times(mrb_state *mrb, mrb_value self) struct RArray *a1 = mrb_ary_ptr(self); struct RArray *a2; mrb_value ary; - mrb_value *buf; + mrb_value *ptr; mrb_int times; - //size_t len; mrb_get_args(mrb, "i", ×); if (times < 0) { @@ -286,38 +350,32 @@ mrb_ary_times(mrb_state *mrb, mrb_value self) ary = mrb_ary_new_capa(mrb, a1->len * times); a2 = mrb_ary_ptr(ary); - buf = a2->buf; + ptr = a2->ptr; while(times--) { - memcpy(buf, a1->buf, sizeof(mrb_value)*(a1->len)); - buf += a1->len; + memcpy(ptr, a1->ptr, sizeof(mrb_value)*(a1->len)); + ptr += a1->len; a2->len += a1->len; } return ary; } -static void -ary_reverse(struct RArray *a) -{ - mrb_value *p1, *p2; - - p1 = a->buf; - p2 = a->buf + a->len - 1; - - while(p1 < p2) { - mrb_value tmp = *p1; - *p1++ = *p2; - *p2-- = tmp; - } -} - mrb_value mrb_ary_reverse_bang(mrb_state *mrb, mrb_value self) { struct RArray *a = mrb_ary_ptr(self); if (a->len > 1) { - ary_reverse(a); + mrb_value *p1, *p2; + + p1 = a->ptr; + p2 = a->ptr + a->len - 1; + + while(p1 < p2) { + mrb_value tmp = *p1; + *p1++ = *p2; + *p2-- = tmp; + } } return self; } @@ -325,33 +383,41 @@ mrb_ary_reverse_bang(mrb_state *mrb, mrb_value self) mrb_value mrb_ary_reverse(mrb_state *mrb, mrb_value self) { - struct RArray *a = mrb_ary_ptr(self); + struct RArray *a = mrb_ary_ptr(self), *b; mrb_value ary; ary = mrb_ary_new_capa(mrb, a->len); + b = mrb_ary_ptr(ary); if (a->len > 0) { - mrb_ary_replace(mrb, mrb_ary_ptr(ary), a->buf, a->len); - ary_reverse(mrb_ary_ptr(ary)); + mrb_value *p1, *p2, *e; + + p1 = a->ptr; + e = p1 + a->len; + p2 = b->ptr + a->len - 1; + while(p1 < e) { + *p2-- = *p1++; + } + b->len = a->len; } return ary; } mrb_value -mrb_ary_new4(mrb_state *mrb, long n, const mrb_value *elts) +mrb_ary_new4(mrb_state *mrb, int n, const mrb_value *elts) { mrb_value ary; - ary = mrb_ary_new_capa(mrb, n);//mrb_ary_new2(n); + ary = mrb_ary_new_capa(mrb, n); if (n > 0 && elts) { memcpy(RARRAY_PTR(ary), elts, sizeof(mrb_value)*n); - RARRAY_LEN(ary) = n; //ARY_SET_LEN(ary, n); + RARRAY_LEN(ary) = n; } return ary; } mrb_value -mrb_ary_new_elts(mrb_state *mrb, long n, const mrb_value *elts) +mrb_ary_new_elts(mrb_state *mrb, int n, const mrb_value *elts) { return mrb_ary_new4(mrb, n, elts); } @@ -361,22 +427,14 @@ mrb_ary_push(mrb_state *mrb, mrb_value ary, mrb_value elem) /* mrb_ary_push */ { struct RArray *a = mrb_ary_ptr(ary); - if (a->len == a->capa) mrb_ary_expand_capa(mrb, a, a->len + 1); - a->buf[a->len++] = elem; + 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); } mrb_value -mrb_ary_pop(mrb_state *mrb, mrb_value ary) -{ - struct RArray *a = mrb_ary_ptr(ary); - - if (a->len == 0) return mrb_nil_value(); - - return a->buf[--a->len]; -} - -mrb_value mrb_ary_push_m(mrb_state *mrb, mrb_value self) { mrb_value *argv; @@ -391,30 +449,45 @@ mrb_ary_push_m(mrb_state *mrb, mrb_value self) } mrb_value -mrb_ary_pop_m(mrb_state *mrb, mrb_value self) +mrb_ary_pop(mrb_state *mrb, mrb_value ary) { - struct RArray *a = mrb_ary_ptr(self); + struct RArray *a = mrb_ary_ptr(ary); - return ((a->len == 0)? mrb_nil_value(): mrb_ary_pop(mrb, self)); + if (a->len == 0) return mrb_nil_value(); + return a->ptr[--a->len]; } +#define ARY_SHIFT_SHARED_MIN 10 + mrb_value mrb_ary_shift(mrb_state *mrb, mrb_value self) { struct RArray *a = mrb_ary_ptr(self); - mrb_value *buf = a->buf; - size_t size = a->len; mrb_value val; - if (size == 0) return mrb_nil_value(); - - val = *buf; - while((int)(--size)) { - *buf = *(buf+1); - ++buf; + 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; } - --a->len; + 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; } @@ -427,10 +500,20 @@ mrb_ary_unshift(mrb_state *mrb, mrb_value self, mrb_value item) { struct RArray *a = mrb_ary_ptr(self); - if (a->capa < a->len + 1) mrb_ary_expand_capa(mrb, a, a->len + 1); - memmove(a->buf + 1, a->buf, sizeof(mrb_value)*a->len); - memcpy(a->buf, &item, sizeof(mrb_value)); - a->len += 1; + 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; @@ -444,10 +527,19 @@ mrb_ary_unshift_m(mrb_state *mrb, mrb_value self) int len; mrb_get_args(mrb, "*", &vals, &len); - if (len == 0) return self; - if (a->capa < a->len + len) mrb_ary_expand_capa(mrb, a, a->len + len); - memmove(a->buf + len, a->buf, sizeof(mrb_value)*a->len); - memcpy(a->buf, vals, sizeof(mrb_value)*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); @@ -461,9 +553,9 @@ mrb_ary_ref(mrb_state *mrb, mrb_value ary, mrb_int n) /* range check */ if (n < 0) n += a->len; - if (n < 0 || a->len <= (size_t)n) return mrb_nil_value(); + if (n < 0 || a->len <= (int)n) return mrb_nil_value(); - return a->buf[n]; + return a->ptr[n]; } void @@ -471,18 +563,22 @@ mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val) /* rb_ary_s { 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); + n += a->len; + if (n < 0) { + mrb_raise(mrb, E_INDEX_ERROR, "index %ld out of array", n - a->len); + } } - if (a->len <= (size_t)n) { - if (a->capa <= (size_t)n) mrb_ary_expand_capa(mrb, a, n + 1); - ary_fill_with_nil(a->buf + a->len, n + 1 - 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->buf[n] = val; + a->ptr[n] = val; mrb_write_barrier(mrb, (struct RBasic*)a); } @@ -491,14 +587,17 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val { struct RArray *a = mrb_ary_ptr(ary); mrb_int tail; - size_t size; + int size; mrb_value *argv; 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"); + head += a->len; + if (head < 0) { + mrb_raise(mrb, E_INDEX_ERROR, "index is out of array"); + } } tail = head + len; @@ -515,17 +614,18 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val if (tail < a->len) size += a->len - tail; - if (size > a->capa) mrb_ary_expand_capa(mrb, a, size); + if (size > a->aux.capa) + ary_expand_capa(mrb, a, size); if (head > a->len) { - ary_fill_with_nil(a->buf + a->len, (size_t)(head - a->len)); + ary_fill_with_nil(a->ptr + a->len, (int)(head - a->len)); } else if (head < a->len) { - memmove(a->buf + head + argc, a->buf + tail, sizeof(mrb_value)*(a->len - tail)); + memmove(a->ptr + head + argc, a->ptr + tail, sizeof(mrb_value)*(a->len - tail)); } for(i = 0; i < argc; i++) { - *(a->buf + head + i) = *(argv + i); + *(a->ptr + head + i) = *(argv + i); } a->len = size; @@ -539,6 +639,32 @@ mrb_ary_alen(mrb_state *mrb, mrb_value ary) return RARRAY_LEN(ary); } +void +mrb_ary_decref(mrb_state *mrb, struct mrb_shared_array *shared) +{ + shared->refcnt--; + if (shared->refcnt == 0) { + mrb_free(mrb, shared->ptr); + mrb_free(mrb, shared); + } +} + +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); +} + mrb_value mrb_ary_aget(mrb_state *mrb, mrb_value self) { @@ -556,13 +682,13 @@ mrb_ary_aget(mrb_state *mrb, mrb_value self) if (mrb_type(argv[0]) != MRB_TT_FIXNUM) { mrb_raise(mrb, E_TYPE_ERROR, "expected Fixnum"); } - len = mrb_fixnum(argv[0]); if (index < 0) index += a->len; - if (index < 0 || a->len < (size_t)index) return mrb_nil_value(); - if ((len = mrb_fixnum(argv[0])) < 0) return mrb_nil_value(); - if (a->len == (size_t)index) return mrb_ary_new(mrb); - if ((size_t)len > a->len - index) len = a->len - index; - return mrb_ary_new_from_values(mrb, len, a->buf + index); + if (index < 0 || a->len < (int)index) return mrb_nil_value(); + len = mrb_fixnum(argv[0]); + if (len < 0) return mrb_nil_value(); + if (a->len == (int)index) return mrb_ary_new(mrb); + if ((int)len > a->len - index) len = a->len - index; + return ary_subseq(mrb, a, index, len); default: mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); @@ -606,24 +732,25 @@ mrb_ary_delete_at(mrb_state *mrb, mrb_value self) struct RArray *a = mrb_ary_ptr(self); mrb_int index; mrb_value val; - mrb_value *buf; - size_t len; + mrb_value *ptr; + int len; mrb_get_args(mrb, "i", &index); if (index < 0) index += a->len; - if (index < 0 || a->len <= (size_t)index) return mrb_nil_value(); + if (index < 0 || a->len <= (int)index) return mrb_nil_value(); - val = a->buf[index]; + ary_modify(mrb, a); + val = a->ptr[index]; - buf = a->buf + index; + ptr = a->ptr + index; len = a->len - index; while((int)(--len)) { - *buf = *(buf+1); - ++buf; + *ptr = *(ptr+1); + ++ptr; } --a->len; - mrb_ary_shrink_capa(mrb, a); + ary_shrink_capa(mrb, a); return val; } @@ -632,30 +759,27 @@ mrb_value mrb_ary_first(mrb_state *mrb, mrb_value self) { struct RArray *a = mrb_ary_ptr(self); - //mrb_value ary; - size_t size; - mrb_value *vals; - int len; + int size; - mrb_get_args(mrb, "*", &vals, &len); - if (len > 1) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); + if (mrb_get_args(mrb, "|i", &size) == 0) { + return (a->len > 0)? a->ptr[0]: mrb_nil_value(); + } + if (size < 0) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "negative array size"); } - if (len == 0) return (a->len > 0)? a->buf[0]: mrb_nil_value(); - - /* len == 1 */ - size = mrb_fixnum(*vals); if (size > a->len) size = a->len; - return mrb_ary_new_from_values(mrb, size, a->buf); + if (a->flags & MRB_ARY_SHARED) { + return ary_subseq(mrb, a, 0, size); + } + return mrb_ary_new_from_values(mrb, size, a->ptr); } mrb_value mrb_ary_last(mrb_state *mrb, mrb_value self) { struct RArray *a = mrb_ary_ptr(self); - //mrb_value ary; - size_t size; + int size; mrb_value *vals; int len; @@ -664,19 +788,25 @@ mrb_ary_last(mrb_state *mrb, mrb_value self) mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); } - if (len == 0) return (a->len > 0)? a->buf[a->len - 1]: mrb_nil_value(); + if (len == 0) return (a->len > 0)? a->ptr[a->len - 1]: mrb_nil_value(); /* len == 1 */ size = mrb_fixnum(*vals); + if (size < 0) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "negative array size"); + } if (size > a->len) size = a->len; - return mrb_ary_new_from_values(mrb, size, a->buf + a->len - size); + if ((a->flags & MRB_ARY_SHARED) || size > ARY_DEFAULT_LEN) { + return ary_subseq(mrb, a, a->len - size, size); + } + return mrb_ary_new_from_values(mrb, size, a->ptr + a->len - size); } mrb_value mrb_ary_index_m(mrb_state *mrb, mrb_value self) { mrb_value obj; - long i; + int i; mrb_get_args(mrb, "o", &obj); for (i = 0; i < RARRAY_LEN(self); i++) { @@ -691,7 +821,7 @@ mrb_value mrb_ary_rindex_m(mrb_state *mrb, mrb_value self) { mrb_value obj; - long i; + int i; mrb_get_args(mrb, "o", &obj); for (i = RARRAY_LEN(self) - 1; i >= 0; i--) { @@ -727,7 +857,8 @@ mrb_ary_clear(mrb_state *mrb, mrb_value self) struct RArray *a = mrb_ary_ptr(self); a->len = 0; - mrb_ary_shrink_capa(mrb, a); + ary_modify(mrb, a); + ary_shrink_capa(mrb, a); return self; } @@ -747,7 +878,7 @@ mrb_check_array_type(mrb_state *mrb, mrb_value ary) } mrb_value -mrb_ary_entry(mrb_value ary, long offset) +mrb_ary_entry(mrb_value ary, int offset) { if (offset < 0) { offset += RARRAY_LEN(ary); @@ -755,58 +886,43 @@ mrb_ary_entry(mrb_value ary, long offset) return ary_elt(ary, offset); } -void -mrb_mem_clear(mrb_value *mem, long size) -{ - while (size--) { - *mem++ = mrb_nil_value(); - } -} - -mrb_value -mrb_ary_tmp_new(mrb_state *mrb, long capa) -{ - return mrb_ary_new_capa(mrb, capa);//ary_new(0, capa); -} - static mrb_value inspect_ary(mrb_state *mrb, mrb_value ary, mrb_value list) { - long i; + int i; mrb_value s, arystr; - char *head = "["; - char *sep = ", "; - char *tail = "]"; + char head[] = { '[' }; + char sep[] = { ',', ' ' }; + char tail[] = { ']' }; /* check recursive */ for(i=0; i<RARRAY_LEN(list); i++) { if (mrb_obj_equal(mrb, ary, RARRAY_PTR(list)[i])) { - return mrb_str_new2(mrb, "[...]"); + return mrb_str_new(mrb, "[...]", 5); } } mrb_ary_push(mrb, list, ary); arystr = mrb_str_buf_new(mrb, 64); - mrb_str_buf_cat(mrb, arystr, head, strlen(head)); + mrb_str_buf_cat(mrb, arystr, head, sizeof(head)); for(i=0; i<RARRAY_LEN(ary); i++) { int ai = mrb_gc_arena_save(mrb); if (i > 0) { - mrb_str_buf_cat(mrb, arystr, sep, strlen(sep)); + mrb_str_buf_cat(mrb, arystr, sep, sizeof(sep)); } if (mrb_type(RARRAY_PTR(ary)[i]) == MRB_TT_ARRAY) { s = inspect_ary(mrb, RARRAY_PTR(ary)[i], list); } else { s = mrb_inspect(mrb, RARRAY_PTR(ary)[i]); } - //mrb_str_buf_append(mrb, arystr, s); mrb_str_buf_cat(mrb, arystr, RSTRING_PTR(s), RSTRING_LEN(s)); mrb_gc_arena_restore(mrb, ai); } - mrb_str_buf_cat(mrb, arystr, tail, strlen(tail)); + mrb_str_buf_cat(mrb, arystr, tail, sizeof(tail)); mrb_ary_pop(mrb, list); return arystr; @@ -824,7 +940,7 @@ inspect_ary(mrb_state *mrb, mrb_value ary, mrb_value list) static mrb_value mrb_ary_inspect(mrb_state *mrb, mrb_value ary) { - if (RARRAY_LEN(ary) == 0) return mrb_str_new2(mrb, "[]"); + if (RARRAY_LEN(ary) == 0) return mrb_str_new(mrb, "[]", 2); #if 0 /* THREAD */ return mrb_exec_recursive(inspect_ary_r, ary, 0); #else @@ -835,7 +951,7 @@ mrb_ary_inspect(mrb_state *mrb, mrb_value ary) static mrb_value join_ary(mrb_state *mrb, mrb_value ary, mrb_value sep, mrb_value list) { - long i; + int i; mrb_value result, val, tmp; /* check recursive */ @@ -851,7 +967,6 @@ join_ary(mrb_state *mrb, mrb_value ary, mrb_value sep, mrb_value list) for(i=0; i<RARRAY_LEN(ary); i++) { if (i > 0 && !mrb_nil_p(sep)) { - //mrb_str_buf_append(mrb, result, sep); // segv (encoding error?) mrb_str_buf_cat(mrb, result, RSTRING_PTR(sep), RSTRING_LEN(sep)); } @@ -864,7 +979,6 @@ join_ary(mrb_state *mrb, mrb_value ary, mrb_value sep, mrb_value list) case MRB_TT_STRING: str_join: - //mrb_str_buf_append(mrb, result, val); mrb_str_buf_cat(mrb, result, RSTRING_PTR(val), RSTRING_LEN(val)); break; @@ -898,7 +1012,7 @@ mrb_ary_join(mrb_state *mrb, mrb_value ary, mrb_value sep) /* * call-seq: - * ary.join(sep=nil) -> str + * ary.join(sep="") -> str * * Returns a string created by converting each element of the array to * a string, separated by <i>sep</i>. @@ -912,7 +1026,7 @@ mrb_ary_join_m(mrb_state *mrb, mrb_value ary) { mrb_value sep = mrb_nil_value(); - mrb_get_args(mrb, "|o", &sep); + mrb_get_args(mrb, "|S", &sep); return mrb_ary_join(mrb, ary, sep); } @@ -951,7 +1065,7 @@ mrb_ary_equal(mrb_state *mrb, mrb_value ary1) } if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return mrb_false_value(); else { - long i; + int i; for (i=0; i<RARRAY_LEN(ary1); i++) { if (!mrb_equal(mrb, ary_elt(ary1, i), ary_elt(ary2, i))) @@ -980,7 +1094,7 @@ mrb_ary_eql(mrb_state *mrb, mrb_value ary1) if (mrb_type(ary2) != MRB_TT_ARRAY) return mrb_false_value(); if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return mrb_false_value(); else { - long i; + int i; for (i=0; i<RARRAY_LEN(ary1); i++) { if (!mrb_eql(mrb, ary_elt(ary1, i), ary_elt(ary2, i))) @@ -1010,13 +1124,13 @@ mrb_init_array(mrb_state *mrb) mrb_define_method(mrb, a, "concat", mrb_ary_concat_m, ARGS_REQ(1)); /* 15.2.12.5.8 */ mrb_define_method(mrb, a, "delete_at", mrb_ary_delete_at, ARGS_REQ(1)); /* 15.2.12.5.9 */ mrb_define_method(mrb, a, "empty?", mrb_ary_empty_p, ARGS_NONE()); /* 15.2.12.5.12 */ - mrb_define_method(mrb, a, "first", mrb_ary_first, ARGS_ANY()); /* 15.2.12.5.13 */ + mrb_define_method(mrb, a, "first", mrb_ary_first, ARGS_OPT(1)); /* 15.2.12.5.13 */ mrb_define_method(mrb, a, "index", mrb_ary_index_m, ARGS_REQ(1)); /* 15.2.12.5.14 */ mrb_define_method(mrb, a, "initialize_copy", mrb_ary_replace_m, ARGS_REQ(1)); /* 15.2.12.5.16 */ mrb_define_method(mrb, a, "join", mrb_ary_join_m, ARGS_ANY()); /* 15.2.12.5.17 */ mrb_define_method(mrb, a, "last", mrb_ary_last, ARGS_ANY()); /* 15.2.12.5.18 */ mrb_define_method(mrb, a, "length", mrb_ary_size, ARGS_NONE()); /* 15.2.12.5.19 */ - mrb_define_method(mrb, a, "pop", mrb_ary_pop_m, ARGS_NONE()); /* 15.2.12.5.21 */ + mrb_define_method(mrb, a, "pop", mrb_ary_pop, ARGS_NONE()); /* 15.2.12.5.21 */ mrb_define_method(mrb, a, "push", mrb_ary_push_m, ARGS_ANY()); /* 15.2.12.5.22 */ mrb_define_method(mrb, a, "replace", mrb_ary_replace_m, ARGS_REQ(1)); /* 15.2.12.5.23 */ mrb_define_method(mrb, a, "reverse", mrb_ary_reverse, ARGS_NONE()); /* 15.2.12.5.24 */ @@ -1031,5 +1145,5 @@ mrb_init_array(mrb_state *mrb) mrb_define_alias(mrb, a, "to_s", "inspect"); /* 15.2.12.5.32 (x) */ mrb_define_method(mrb, a, "==", mrb_ary_equal, ARGS_REQ(1)); /* 15.2.12.5.33 (x) */ mrb_define_method(mrb, a, "eql?", mrb_ary_eql, ARGS_REQ(1)); /* 15.2.12.5.34 (x) */ - mrb_define_method(mrb, a, "<=>", mrb_ary_cmp, ARGS_REQ(1)); /* 15.2.12.5.36 (x) */ + mrb_define_method(mrb, a, "<=>", mrb_ary_cmp, ARGS_REQ(1)); /* 15.2.12.5.36 (x) */ } |
