public void SetLengthTest() { using (var m = new SafeHGlobalHandle(1000)) using (var ms = new NativeMemoryStream((IntPtr)m, m.Size)) { Assert.That(() => ms.SetLength(-1), Throws.TypeOf <ArgumentOutOfRangeException>()); Assert.That(() => ms.SetLength(1001), Throws.Exception); Assert.That(() => ms.SetLength(100), Throws.Nothing); } }
public void DisposedTest() { var ms = new NativeMemoryStream(20); ms.Dispose(); Assert.That(ms.CanRead, Is.False); Assert.That(ms.CanSeek, Is.False); Assert.That(ms.CanWrite, Is.False); Assert.That(() => ms.Capacity > 0, Throws.InstanceOf <ObjectDisposedException>()); Assert.That(() => ms.Read <int>(), Throws.InstanceOf <ObjectDisposedException>()); Assert.That(() => ms.Read(typeof(int)), Throws.InstanceOf <ObjectDisposedException>()); Assert.That(() => ms.Read(new byte[3], 0, 3), Throws.InstanceOf <ObjectDisposedException>()); Assert.That(() => ms.ReadByte(), Throws.InstanceOf <ObjectDisposedException>()); Assert.That(() => ms.ReadArray(typeof(byte), 1, false), Throws.InstanceOf <ObjectDisposedException>()); Assert.That(() => ms.ReadReference <int>(), Throws.InstanceOf <ObjectDisposedException>()); Assert.That(() => ms.ReadReference <string>(), Throws.InstanceOf <ObjectDisposedException>()); Assert.That(() => ms.Seek(0, SeekOrigin.Begin), Throws.InstanceOf <ObjectDisposedException>()); Assert.That(() => ms.SetLength(20), Throws.InstanceOf <ObjectDisposedException>()); Assert.That(() => ms.Write("X"), Throws.InstanceOf <ObjectDisposedException>()); Assert.That(() => ms.Write("X", CharSet.Ansi), Throws.InstanceOf <ObjectDisposedException>()); Assert.That(() => ms.Write(new[] { "X", "Y" }), Throws.InstanceOf <ObjectDisposedException>()); Assert.That(() => ms.Write(new byte[3], 0, 3), Throws.InstanceOf <ObjectDisposedException>()); Assert.That(() => ms.Write(new[] { 1, 2 }), Throws.InstanceOf <ObjectDisposedException>()); Assert.That(() => ms.Write(256), Throws.InstanceOf <ObjectDisposedException>()); Assert.That(() => ms.WriteByte(1), Throws.InstanceOf <ObjectDisposedException>()); Assert.That(() => ms.WriteObject(Guid.NewGuid()), Throws.InstanceOf <ObjectDisposedException>()); Assert.That(() => ms.WriteReference("X"), Throws.InstanceOf <ObjectDisposedException>()); Assert.That(() => ms.WriteReference(256), Throws.InstanceOf <ObjectDisposedException>()); Assert.That(() => ms.WriteReferenceObject(Guid.NewGuid()), Throws.InstanceOf <ObjectDisposedException>()); }
/// <summary> /// Marshals data from a managed list of strings to an unmanaged block of memory allocated by the <paramref name="memAlloc"/> method. /// </summary> /// <param name="values">The enumerated list of strings to marshal.</param> /// <param name="packing">The packing type for the strings.</param> /// <param name="memAlloc"> /// The function that allocates the memory for the block of strings (typically <see cref="Marshal.AllocCoTaskMem(int)"/> or <see cref="Marshal.AllocHGlobal(int)"/>. /// </param> /// <param name="bytesAllocated">The bytes allocated by the <paramref name="memAlloc"/> method.</param> /// <param name="charSet">The character set to use for the strings.</param> /// <param name="prefixBytes">Number of bytes preceding the trailing strings.</param> /// <returns> /// Pointer to the allocated native (unmanaged) array of strings stored using the <paramref name="packing"/> model and the character /// set defined by <paramref name="charSet"/>. /// </returns> public static IntPtr MarshalToPtr(this IEnumerable <string> values, StringListPackMethod packing, Func <int, IntPtr> memAlloc, out int bytesAllocated, CharSet charSet = CharSet.Auto, int prefixBytes = 0) { // Bail early if empty if (values is null || !values.Any()) { bytesAllocated = prefixBytes + (packing == StringListPackMethod.Concatenated ? StringHelper.GetCharSize(charSet) : IntPtr.Size); var ret = memAlloc(bytesAllocated); ret.FillMemory(0, bytesAllocated); return(ret); } // Write to memory stream using (var ms = new NativeMemoryStream(1024, 1024) { CharSet = charSet }) { ms.SetLength(ms.Position = prefixBytes); if (packing == StringListPackMethod.Packed) { foreach (var s in values) { ms.WriteReference(s); } ms.WriteReference(null); } else { foreach (var s in values) { if (string.IsNullOrEmpty(s)) { throw new ArgumentException("Concatenated string arrays cannot contain empty or null strings."); } ms.Write(s); } ms.Write(""); } ms.Flush(); // Copy to newly allocated memory using memAlloc bytesAllocated = (int)ms.Length; var ret = memAlloc(bytesAllocated); ms.Pointer.CopyTo(ret, bytesAllocated); return(ret); } }
/// <summary> /// Marshals data from a managed list of objects to an unmanaged block of memory allocated by the <paramref name="memAlloc"/> method. /// </summary> /// <param name="values">The enumerated list of objects to marshal.</param> /// <param name="memAlloc"> /// The function that allocates the memory for the block of objects (typically <see cref="Marshal.AllocCoTaskMem(int)"/> or <see cref="Marshal.AllocHGlobal(int)"/>. /// </param> /// <param name="bytesAllocated">The bytes allocated by the <paramref name="memAlloc"/> method.</param> /// <param name="referencePointers"> /// if set to <see langword="true"/> the pointer will be processed by storing a reference to the value; if <see langword="false"/>, /// the pointer value will be directly inserted into the array of pointers. /// </param> /// <param name="charSet">The character set to use for strings.</param> /// <param name="prefixBytes">Number of bytes preceding the allocated objects.</param> /// <returns>Pointer to the allocated native (unmanaged) array of objects stored using the character set defined by <paramref name="charSet"/>.</returns> public static IntPtr MarshalObjectsToPtr(this IEnumerable <object> values, Func <int, IntPtr> memAlloc, out int bytesAllocated, bool referencePointers = false, CharSet charSet = CharSet.Auto, int prefixBytes = 0) { // Bail early if empty if (values is null || !values.Any()) { bytesAllocated = prefixBytes + IntPtr.Size; var ret = memAlloc(bytesAllocated); ret.FillMemory(0, bytesAllocated); return(ret); } // Write to memory stream using (var ms = new NativeMemoryStream(1024, 1024) { CharSet = charSet }) { ms.SetLength(ms.Position = prefixBytes); foreach (var o in values) { if (referencePointers) { ms.WriteReferenceObject(o); } else { ms.WriteObject(o); } } if (referencePointers) { ms.WriteReference(null); } ms.Flush(); // Copy to newly allocated memory using memAlloc bytesAllocated = (int)ms.Length; var ret = memAlloc(bytesAllocated); ms.Pointer.CopyTo(ret, bytesAllocated); return(ret); } }