Swift: how to add an offset to memcpy (...)

How to add an offset for an array to call memcpy (...)?

I have an array String:

var source = ["a","b","c","d"]
var dest = [String](count:n, repeatedValue: "")
memcpy(&dest, source, UInt(2 * sizeof(String))

This copy ["a", "b"] in dest. It is obvious. How can I copy ["b", "c"]?

+4
source share
3 answers

Do not use memcpy or other low-level "C" statements on objects. This will not work for many reasons.

Use the slice operator:

var source = ["a","b","c","d"]
var dest = Array(source[1...2])
println("dest: \(dest)")

conclusion:

dest: [b, c]

Unicode handled correctly:

var source = ["🇪🇸", "😂", "a","b","c","d"]
var dest = Array(source[1...2])
println("dest: \(dest)")

conclusion:

dest: [😂, a]

+5
source

, -, , , : ( String) , . UTF-8, UTF-16, . , , - (.. == ). , swift , memcpy, NSArray!

, , , , , Swift Array , :

source dest - : , - @+ sizeof (), n- - @+ (n-1) * sizeof (type).

, , dest, 0 , 1.

0

I'm still new to Swift, and using the methods with “Unsafe” in the title still bothers me, but I'm sure this is a useful method to call memcpy () and specify an offset for the destination and / or source address. But this only works for byte arrays, i.e. [UInt8]. Definitely not for strings, as @zaph explains.

public class SystemMisc {

   /// Wrapper for the memcpy() method that allows specification of an offset for the destination
   /// and/or the source addresses.
   ///
   /// This version for when destination is a normal Swift byte array.
   ///
   /// - Parameters:
   ///   - destPointer:    Address for destination byte array, typically Swift [UInt8].
   ///   - destOffset:     Offset to be added to the destination address, may be zero.
   ///   - sourcePointer:  Address for source byte array, typically Swift [UInt8].
   ///   - sourceOffset:   Offset to be added to the source address, may be zero.
   ///   - byteLength:     Number of bytes to be copied.
   public static func memoryCopy(_ destPointer : UnsafeRawPointer, _ destOffset : Int,
                                 _ sourcePointer : UnsafeRawPointer, _ sourceOffset : Int,
                                 _ byteLength : Int) {

      memoryCopy(UnsafeMutableRawPointer(mutating: destPointer), destOffset,
                 sourcePointer, sourceOffset, byteLength)
   }


   /// Wrapper for the memcpy() method that allows specification of an offset for the destination 
   /// and/or the source addresses.
   ///
   /// This version for when destination address is already available as an UnsafeMutableRawPointer, 
   /// for example if caller has used UnsafeMutableRawPointer() to create it or is working with 
   /// unmanaged memory. The destPointer argument may also be a converted pointer, as done by the 
   /// above wrapper method.
   ///
   /// - Parameters:
   ///   - destPointer:    Address for destination byte array, see above notes.
   ///   - destOffset:     Offset to be added to the destination address, may be zero.
   ///   - sourcePointer:  Address for source byte array, typically Swift [UInt8].
   ///   - sourceOffset:   Offset to be added to the source address, may be zero.
   ///   - byteLength:     Number of bytes to be copied.
   public static func memoryCopy(_ destPointer : UnsafeMutableRawPointer, _ destOffset : Int,
                                 _ sourcePointer : UnsafeRawPointer, _ sourceOffset : Int,
                                 _ byteLength : Int) {

      memcpy(destPointer.advanced(by: destOffset),
             sourcePointer.advanced(by: sourceOffset),
             byteLength)
   }
}

And here is some kind of test code:

  // Test the memoryCopy() method, using extra UnsafeMutableRawPointer conversion

  let destArray1 : [UInt8] = [ 0, 1, 2, 3 ]  // Note - doesn't need to be var
  let sourceArray1 : [UInt8] = [ 42, 43, 44, 45 ]

  SystemMisc.memoryCopy(destArray1, 1, sourceArray1, 1, 2)

  assert(destArray1[0] == 0 && destArray1[1] == 43 && destArray1[2] == 44 && destArray1[3] == 3)


  // Test the memoryCopy() method, providing UnsafeMutableRawPointer for destination

  var destArray2 : [UInt8] = [ 0, 1, 2, 3 ]
  let sourceArray2 : [UInt8] = [ 42, 43, 44, 45 ]

  let destArray2Pointer = UnsafeMutableRawPointer(&destArray2)

  SystemMisc.memoryCopy(destArray2Pointer, 1, sourceArray2, 1, 2)

  assert(destArray2[0] == 0 && destArray2[1] == 43 && destArray2[2] == 44 && destArray2[3] == 3)
0
source

All Articles