Пример #1
0
        public void RefStringTest()
        {
            using (var ms = new NativeMemoryStream(20, 20))
            {
                Assert.That(() => ms.WriteReference(""), Throws.Nothing);
                Assert.That(ms.Length, Is.EqualTo(2 + IntPtr.Size));
                Assert.That(ms.Position, Is.EqualTo(IntPtr.Size));
                Assert.That(ms.Capacity, Is.EqualTo(20));
                Assert.That(() => ms.WriteReference(testStr), Throws.Nothing);
                Assert.That(ms.Length, Is.EqualTo(24 + IntPtr.Size * 2));
                Assert.That(ms.Position, Is.EqualTo(IntPtr.Size * 2));
                Assert.That(() => ms.WriteReference((string)null), Throws.Nothing);
                Assert.That(ms.Length, Is.EqualTo(24 + IntPtr.Size * 3));
                Assert.That(ms.Position, Is.EqualTo(IntPtr.Size * 3));
                var ptrs = ms.Pointer.ToArray <IntPtr>(3);
                Assert.That(ptrs, Is.EquivalentTo(new[] { IntPtr.Zero, IntPtr.Zero, IntPtr.Zero }));
                ms.Flush();
                Assert.That(ms.Capacity, Is.EqualTo(40));
                ptrs = ms.Pointer.ToArray <IntPtr>(3);
                Assert.That(ptrs, Is.Not.EquivalentTo(new[] { IntPtr.Zero, IntPtr.Zero, IntPtr.Zero }));
                Assert.That(StringHelper.GetString(ptrs[0], ms.CharSet), Is.EqualTo(""));
                Assert.That(StringHelper.GetString(ptrs[1], ms.CharSet), Is.EqualTo(testStr));
                Assert.That(StringHelper.GetString(ptrs[2], ms.CharSet), Is.Null);

                TestContext.WriteLine(ms.Pointer.ToHexDumpString((int)ms.Length, 32));
                ms.Position = 0;

                Assert.That(ms.ReadReference <string>(), Is.EqualTo(string.Empty));
                Assert.That(ms.Position, Is.EqualTo(IntPtr.Size));
                Assert.That(ms.ReadReference <string>(), Is.EqualTo(testStr));
                Assert.That(ms.ReadReference <string>(), Is.Null);
                Assert.That(ms.Read <string>(), Is.EqualTo(string.Empty));
                Assert.That(ms.Read <string>(), Is.EqualTo(testStr));
            }
        }
Пример #2
0
        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>());
        }
Пример #3
0
        /// <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);
            }
        }
Пример #4
0
        public void RefStructTest()
        {
            using (var ms = new NativeMemoryStream(8, 16, 100))
            {
                Assert.That(() => ms.WriteReference(256), Throws.Nothing);
                var isz  = sizeof(int);
                var pcnt = 1;
                Assert.That(ms.Length, Is.EqualTo(Len()));
                Assert.That(ms.Position, Is.EqualTo(Pos()));
                Assert.That(ms.Capacity, Is.EqualTo(8));
                Assert.That(() => ms.WriteReference((ushort)256), Throws.Nothing);
                isz += sizeof(ushort); pcnt++;
                Assert.That(ms.Length, Is.EqualTo(Len()));
                Assert.That(ms.Position, Is.EqualTo(Pos()));
                Assert.That(ms.Capacity, Is.EqualTo(24));
                Assert.That(() => ms.WriteReference((long)1), Throws.Nothing);
                isz += sizeof(long); pcnt++;
                Assert.That(ms.Length, Is.EqualTo(Len()));
                Assert.That(ms.Position, Is.EqualTo(Pos()));
                Assert.That(ms.Capacity, Is.EqualTo(40));
                Assert.That(ms.Pointer.ToArray(IntPtr.Size == 4 ? typeof(uint) : typeof(ulong), pcnt), Is.EquivalentTo(new[] { 0, 0, 0 }));
                var newGuid = Guid.NewGuid();
                Assert.That(() => ms.WriteReference(newGuid), Throws.Nothing);
                isz += Marshal.SizeOf(typeof(Guid)); pcnt++;
                Assert.That(ms.Length, Is.EqualTo(Len()));
                Assert.That(ms.Position, Is.EqualTo(Pos()));
                Assert.That(ms.Capacity, Is.EqualTo(56));
                ms.Flush();
                Assert.That(ms.Length, Is.EqualTo(ms.Position));
                Assert.That(ms.Capacity, Is.GreaterThanOrEqualTo(ms.Length));
                var arr = ms.Pointer.ToArray(IntPtr.Size == 4 ? typeof(uint) : typeof(ulong), pcnt);
                Assert.That(arr, Is.Not.EquivalentTo(new[] { 0, 0, 0, 0 }));

                ms.Position = 0;

                Assert.That(ms.ReadReference <int>(), Is.EqualTo(256));
                Assert.That(ms.ReadReference <ushort>(), Is.EqualTo(256));
                Assert.That(ms.ReadReference <long>(), Is.EqualTo(1));
                Assert.That(ms.ReadReference <Guid>(), Is.EqualTo(newGuid));

                int Len() => Pos() + isz;
                int Pos() => pcnt *IntPtr.Size;
            }
        }
Пример #5
0
        public void MixedReadWriteTest()
        {
            using (var m = new SafeHGlobalHandle(512))
            {
                var  str  = "Test1";
                var  guid = Guid.NewGuid();
                var  lVal = 1208L;
                byte b    = 18;
                using (var ms = new NativeMemoryStream(m)
                {
                    CharSet = CharSet.Unicode
                })
                {
                    Assert.That(() => ms.WriteReference(str), Throws.Nothing);
                    Assert.That(() => ms.Write(str), Throws.Nothing);
                    Assert.That(() => ms.WriteReference(guid), Throws.Nothing);
                    Assert.That(() => ms.Write(guid), Throws.Nothing);
                    Assert.That(() => ms.WriteReference(lVal), Throws.Nothing);
                    Assert.That(() => ms.Write(lVal), Throws.Nothing);
                    Assert.That(() => ms.WriteReference(b), Throws.Nothing);
                    Assert.That(() => ms.Write(b), Throws.Nothing);
                    Assert.That(() => ms.WriteReference(str), Throws.Nothing);

                    ms.Flush();
                    ms.Position = 0;

                    Assert.That(ms.ReadReference <string>(CharSet.Unicode), Is.EqualTo(str));
                    Assert.That(ms.Read <string>(CharSet.Unicode), Is.EqualTo(str));
                    Assert.That(ms.ReadReference <Guid>(), Is.EqualTo(guid));
                    Assert.That(ms.Read <Guid>(), Is.EqualTo(guid));
                    Assert.That(ms.ReadReference <long>(), Is.EqualTo(lVal));
                    Assert.That(ms.Read <long>(), Is.EqualTo(lVal));
                    Assert.That(ms.ReadReference <byte>(), Is.EqualTo(b));
                    Assert.That(ms.Read <byte>(), Is.EqualTo(b));
                    Assert.That(ms.ReadReference <string>(CharSet.Unicode), Is.EqualTo(str));
                }
            }
        }
Пример #6
0
        public void ReadWriteOnlyTest()
        {
            using (var m = new SafeHGlobalHandle(10))
                using (var ms = new NativeMemoryStream((IntPtr)m, m.Size))
                {
                    Assert.That(ms.CanWrite, Is.False);
                    Assert.That(ms.CanSeek, Is.True);
                    Assert.That(ms.CanRead, Is.True);

                    Assert.That(() => ms.Write("X"), Throws.InstanceOf <NotSupportedException>());
                    Assert.That(() => ms.Write("X", CharSet.Ansi), Throws.InstanceOf <NotSupportedException>());
                    Assert.That(() => ms.Write(new[] { "X", "Y" }), Throws.InstanceOf <NotSupportedException>());
                    Assert.That(() => ms.Write(new byte[3], 0, 3), Throws.InstanceOf <NotSupportedException>());
                    Assert.That(() => ms.Write(new[] { 1, 2 }), Throws.InstanceOf <NotSupportedException>());
                    Assert.That(() => ms.Write(256), Throws.InstanceOf <NotSupportedException>());
                    Assert.That(() => ms.WriteByte(1), Throws.InstanceOf <NotSupportedException>());
                    Assert.That(() => ms.WriteObject(Guid.NewGuid()), Throws.InstanceOf <NotSupportedException>());
                    Assert.That(() => ms.WriteReference("X"), Throws.InstanceOf <NotSupportedException>());
                    Assert.That(() => ms.WriteReference(256), Throws.InstanceOf <NotSupportedException>());
                    Assert.That(() => ms.WriteReferenceObject(Guid.NewGuid()), Throws.InstanceOf <NotSupportedException>());
                }

            using (var ms = new NativeMemoryStream(10, 10, 20, FileAccess.Write))
            {
                Assert.That(ms.CanWrite, Is.True);
                Assert.That(ms.CanSeek, Is.True);
                Assert.That(ms.CanRead, Is.False);

                Assert.That(() => ms.Read <int>(), Throws.InstanceOf <NotSupportedException>());
                Assert.That(() => ms.Read(typeof(int)), Throws.InstanceOf <NotSupportedException>());
                Assert.That(() => ms.Read(new byte[3], 0, 3), Throws.InstanceOf <NotSupportedException>());
                Assert.That(() => ms.ReadByte(), Throws.InstanceOf <NotSupportedException>());
                Assert.That(() => ms.ReadArray(typeof(byte), 1, false), Throws.InstanceOf <NotSupportedException>());
                Assert.That(() => ms.ReadReference <int>(), Throws.InstanceOf <NotSupportedException>());
                Assert.That(() => ms.ReadReference <string>(), Throws.InstanceOf <NotSupportedException>());
            }
        }
Пример #7
0
        /// <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);
            }
        }