diff --git a/vlib/builtin/array.v b/vlib/builtin/array.v index 0636598f2b..16952c13ff 100644 --- a/vlib/builtin/array.v +++ b/vlib/builtin/array.v @@ -10,9 +10,10 @@ pub struct array { pub: element_size int // size in bytes of one element in the array. pub mut: - data voidptr - len int // length of the array. - cap int // capacity of the array. + data voidptr + offset int // in bytes (should be `size_t`) + len int // length of the array. + cap int // capacity of the array. } // array.data uses a void pointer, which allows implementing arrays without generics and without generating @@ -95,11 +96,13 @@ fn (mut a array) ensure_cap(required int) { cap *= 2 } new_size := cap * a.element_size - a.data = if a.data != voidptr(0) { - unsafe { realloc_data(a.data, a.cap * a.element_size, new_size) } - } else { - vcalloc(new_size) + new_data := vcalloc(new_size) + if a.data != voidptr(0) { + unsafe { C.memcpy(new_data, a.data, a.len * a.element_size) } + // TODO: the old data may be leaked when no GC is used (ref-counting?) } + a.data = new_data + a.offset = 0 a.cap = cap } @@ -307,14 +310,13 @@ fn (a array) slice(start int, _end int) array { panic('array.slice: slice bounds out of range ($start < 0)') } } - mut data := &byte(0) - unsafe { - data = &byte(a.data) + start * a.element_size - } + offset := start * a.element_size + data := unsafe { &byte(a.data) + offset } l := end - start res := array{ element_size: a.element_size data: data + offset: a.offset + offset len: l cap: l } @@ -384,13 +386,15 @@ fn (a &array) slice_clone(start int, _end int) array { } } mut data := &byte(0) + offset := start * a.element_size unsafe { - data = &byte(a.data) + start * a.element_size + data = &byte(a.data) + offset } l := end - start res := array{ element_size: a.element_size data: data + offset: offset len: l cap: l } @@ -484,7 +488,7 @@ pub fn (a &array) free() { // if a.is_slice { // return // } - unsafe { free(a.data) } + unsafe { free(&byte(a.data) - a.offset) } } [unsafe] diff --git a/vlib/v/tests/array_slice_test.v b/vlib/v/tests/array_slice_test.v index d56890988d..bcc3b796c1 100644 --- a/vlib/v/tests/array_slice_test.v +++ b/vlib/v/tests/array_slice_test.v @@ -60,3 +60,22 @@ fn test_pointer_array_slice() { mut arr := [1, 2, 3] pointer_array_slice(mut arr) } + +fn test_push_to_orig() { + mut orig := [1, 2, 3, 4] + slice := orig[1..3] + for _ in 0 .. 1000 { + orig << 9 + } + orig[2] = 7 + slice2 := orig[1..3] + assert slice == [2, 3] || slice == [2, 7] + assert slice2 == [2, 7] +} + +fn test_self_slice_push() { + mut a := [1, 2, 3] + a = a[1..] + a << 4 + assert a == [2, 3, 4] +}