vector-copy!: fix for impersonated overlapping regions

Ensure memmove-like behavior when source and destination
overlap.
This commit is contained in:
Matthew Flatt 2018-01-24 14:31:29 -07:00
parent e2e469240f
commit a12a4a51b0
3 changed files with 34 additions and 2 deletions

View File

@ -732,6 +732,13 @@
(err/rt-test (read (open-input-string "#1234567890(0)")) exn:fail:out-of-memory?))
(test #t vector? (make-vector 0))
(let ([b (vector 1 2 3)])
(vector-copy! b 0 b 1)
(test '#(2 3 3) values b))
(let ([b (vector 2 3 4)])
(vector-copy! b 1 b 0 2)
(test '#(2 2 3) values b))
(define f (make-string 3 #\*))
(test "?**" 'string-set! (begin (string-set! f 0 #\?) f))
(arity-test string-set! 3 3)

View File

@ -223,6 +223,20 @@
(define-values (a b c) (vector->values b2))
(test '(1 2 3) list a b c)))
;; vector-copy! and chaperones
(let ([b (vector 1 2 3)])
(let ([b2 (impersonate-vector b
(lambda (b i v) v)
(lambda (b i v) v))])
(vector-copy! b 0 b2 1)
(test '#(2 3 3) values b)))
(let ([b (vector 2 3 4)])
(let ([b2 (impersonate-vector b
(lambda (b i v) v)
(lambda (b i v) v))])
(vector-copy! b 1 b2 0 2)
(test '#(2 2 3) values b)))
(define unsafe-chaperone-vector-name "unsafe-chaperone-vector")
(define unsafe-impersonate-vector-name "unsafe-impersonate-vector")
(define chaperone-vector*-name "chaperone-vector*")

View File

@ -825,8 +825,19 @@ static Scheme_Object *vector_copy_bang(int argc, Scheme_Object *argv[])
if (slow) {
int i, o;
for (i = istart, o = ostart; i < ifinish; i++, o++) {
scheme_chaperone_vector_set(argv[0], o, scheme_chaperone_vector_ref(argv[2], i));
if ((s2 == s1)
&& (((istart <= ostart) && (ifinish > ostart))
|| ((ostart <= istart) && (ofinish > istart)))
&& (istart < ostart)) {
/* ranges overlap and shifting up: copy from end */
for (i = ifinish, o = ofinish; i-- > istart; ) {
o--;
scheme_chaperone_vector_set(argv[0], o, scheme_chaperone_vector_ref(argv[2], i));
}
} else {
for (i = istart, o = ostart; i < ifinish; i++, o++) {
scheme_chaperone_vector_set(argv[0], o, scheme_chaperone_vector_ref(argv[2], i));
}
}
} else {
memmove(SCHEME_VEC_ELS(s1) + ostart,