Allow overlapping regions to be passed to `bytevector-copy!'.
authorLudovic Courtès <ludo@gnu.org>
Sun, 20 Nov 2011 00:10:58 +0000 (01:10 +0100)
committerLudovic Courtès <ludo@gnu.org>
Sun, 20 Nov 2011 00:10:58 +0000 (01:10 +0100)
Reported by Dmitry Chestnykh <dmitry@codingrobots.com>.
Fixes <http://debbugs.gnu.org/10070>.

* libguile/bytevectors.c (scm_bytevector_copy_x): Use `memmove', not
  `memcpy'.

* test-suite/tests/bytevectors.test ("2.2 General
  Operations")["bytevector-copy! overlapping"]: New test.

* doc/ref/api-data.texi (Bytevector Manipulation): Mention possible
  overlapping.

doc/ref/api-data.texi
libguile/bytevectors.c
test-suite/tests/bytevectors.test

index f9b39b6..5017165 100644 (file)
@@ -4546,7 +4546,8 @@ Fill bytevector @var{bv} with @var{fill}, a byte.
 @deffnx {C Function} scm_bytevector_copy_x (source, source_start, target, target_start, len)
 Copy @var{len} bytes from @var{source} into @var{target}, starting
 reading from @var{source-start} (a positive index within @var{source})
-and start writing at @var{target-start}.
+and start writing at @var{target-start}.  It is permitted for the
+@var{source} and @var{target} regions to overlap.
 @end deffn
 
 @deffn {Scheme Procedure} bytevector-copy bv
index 4aeae63..fff5355 100644 (file)
@@ -579,9 +579,9 @@ SCM_DEFINE (scm_bytevector_copy_x, "bytevector-copy!", 5, 0, 0,
   if (SCM_UNLIKELY (c_target_start + c_len > c_target_len))
     scm_out_of_range (FUNC_NAME, target_start);
 
-  memcpy (c_target + c_target_start,
-         c_source + c_source_start,
-         c_len);
+  memmove (c_target + c_target_start,
+          c_source + c_source_start,
+          c_len);
 
   return SCM_UNSPECIFIED;
 }
index 081e4ee..3007434 100644 (file)
@@ -1,6 +1,6 @@
 ;;;; bytevectors.test --- R6RS bytevectors. -*- mode: scheme; coding: utf-8; -*-
 ;;;;
-;;;; Copyright (C) 2009, 2010 Free Software Foundation, Inc.
+;;;; Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
 ;;;; Ludovic Courtès
 ;;;;
 ;;;; This library is free software; you can redistribute it and/or
     (and (bytevector=? (make-bytevector 20 7)
                        (make-bytevector 20 7))
          (not (bytevector=? (make-bytevector 20 7)
-                            (make-bytevector 20 0))))))
+                            (make-bytevector 20 0)))))
+
+  (pass-if "bytevector-copy! overlapping"
+    ;; See <http://debbugs.gnu.org/10070>.
+    (let ((b (u8-list->bytevector '(1 2 3 4 5 6 7 8))))
+      (bytevector-copy! b 0 b 3 4)
+      (bytevector->u8-list b)
+      (bytevector=? b #vu8(1 2 3 1 2 3 4 8)))))
 
 \f
 (with-test-prefix/c&e "2.3 Operations on Bytes and Octets"