/// <summary> /// Reads a <see cref="TagTypeSignature"/> from the I/O handler. /// </summary> /// <param name="sig">Returns the <see cref="TagTypeSignature"/>.</param> /// <returns>true if successful, otherwise false.</returns> public bool Read(out TagTypeSignature sig) { uint s = Interop.ReadTypeBase(handle); sig = (TagTypeSignature)s; return(s != 0); }
public void WriteTagTypeSignatureTest() { // Arrange using (var iohandler = IOHandler.Open(null)) { TagTypeSignature sig = TagTypeSignature.MultiLocalizedUnicode; bool expected = true; // Act bool actual = iohandler.Write(sig); // Assert Assert.AreEqual(expected, actual); } }
/// <summary> /// Writes a <see cref="TagTypeSignature"/> to the I/O handler. /// </summary> /// <param name="sig">The <see cref="TagTypeSignature"/> to be written.</param> /// <returns>true if successful, otherwise false.</returns> public bool Write(TagTypeSignature sig) { return(Interop.WriteTypeBase(handle, (uint)sig)); }
public void PluginTagTypeTest() { // Arrange const TagSignature SigInt = (TagSignature)0x74747448; // 'tttH' const TagTypeSignature SigIntType = (TagTypeSignature)0x74747448; // 'tttH' PluginTag tag = new PluginTag { Base = new PluginBase { Magic = Cms.PluginMagicNumber, ExpectedVersion = (uint)Cms.EncodedCMMVersion, // >= 2.8 Type = PluginType.Tag, Next = IntPtr.Zero }, Signature = SigInt, Descriptor = new TagDescriptor { ElemCount = 1, nSupportedTypes = 1, SupportedTypes = new TagTypeSignature[TagDescriptor.MAX_TYPES_IN_LCMS_PLUGIN], Decider = IntPtr.Zero } }; tag.Descriptor.SupportedTypes[0] = SigIntType; int rawsize = Marshal.SizeOf(tag); IntPtr tagPlugin = Marshal.AllocHGlobal(rawsize); Marshal.StructureToPtr(tag, tagPlugin, false); // ensure delegates are not garbage collected from managed code var read = new TagTypeRead(Read); var write = new TagTypeWrite(Write); var duplicate = new TagTypeDuplicate(Duplicate); var free = new TagTypeFree(Free); PluginTagType tagType = new PluginTagType { Base = new PluginBase { Magic = Cms.PluginMagicNumber, ExpectedVersion = (uint)Cms.EncodedCMMVersion, // >= 2.8 Type = PluginType.TagType, Next = tagPlugin }, Handler = new TagTypeHandler { Signature = SigIntType, Read = Marshal.GetFunctionPointerForDelegate(read), Write = Marshal.GetFunctionPointerForDelegate(write), Duplicate = Marshal.GetFunctionPointerForDelegate(duplicate), Free = Marshal.GetFunctionPointerForDelegate(free) } }; rawsize = Marshal.SizeOf(tagType); IntPtr tagTypePlugin = Marshal.AllocHGlobal(rawsize); Marshal.StructureToPtr(tagType, tagTypePlugin, false); // Act try { using (var context = Context.Create(tagTypePlugin, IntPtr.Zero)) using (var profile = Profile.CreatePlaceholder(context)) { var errorHandler = new ErrorHandler(HandleError); context.SetErrorHandler(errorHandler); uint expected = 1234; bool written = profile.WriteTag(SigInt, expected); Assert.IsTrue(written); profile.Save(null, out uint bytesNeeded); Assert.AreNotEqual(0, bytesNeeded); byte[] profileMemory = new byte[bytesNeeded]; bool saved = profile.Save(profileMemory, out uint bytesWritten); Assert.IsTrue(saved); // close original profile to flush caches profile.Close(); // re-open profile from memory using (var profile2 = Profile.Open(context, profileMemory)) { IntPtr data = profile2.ReadTag(SigInt); uint[] u = new uint[1]; Marshal.Copy(data, (int[])(object)u, 0, 1); uint actual = u[0]; // Assert Assert.AreEqual(expected, actual); } } } finally { Marshal.DestroyStructure(tagPlugin, typeof(PluginTag)); Marshal.FreeHGlobal(tagPlugin); Marshal.DestroyStructure(tagTypePlugin, typeof(PluginTagType)); Marshal.FreeHGlobal(tagTypePlugin); } // allocates unmanaged memory for a single 'uint' and reads from i/o handler into it IntPtr Read(in TagTypeHandler self, IntPtr io, out uint nItems, uint tagSize) { TestContext.WriteLine($"Read(self: {self}, io: 0x{io:X}, out nItems, tagSize: {tagSize})"); using (var context = Context.FromHandle(self.ContextID)) using (var iohandler = IOHandler.FromHandle(io)) { nItems = 1; IntPtr ptr = Memory.Malloc(context, sizeof(uint)); if (ptr == IntPtr.Zero) { return(IntPtr.Zero); } // unsafe, but faster... unsafe { if (!iohandler.Read(ref *(uint *)ptr)) { return(IntPtr.Zero); } } // - or - // verifiable, but slower... //uint[] arr = new uint[1]; //if (!iohandler.Read(ref arr[0])) return IntPtr.Zero; //Marshal.Copy((int[])(object)arr, 0, ptr, 1); return(ptr); } } // uses the i/o handler to write a single 'uint' read from unmanaged memory 'ptr' int Write(in TagTypeHandler self, IntPtr io, IntPtr ptr, uint nItems) { TestContext.WriteLine($"Write(self: {self}, io: 0x{io:X}, ptr: 0x{ptr:X}, nItems: {nItems})"); using (var iohandler = IOHandler.FromHandle(io)) { // unsafe, but faster... unsafe { return(iohandler.Write(*(uint *)ptr) ? 1 : 0); } // - or - // verifiable, but slower... //uint[] arr = new uint[1]; //Marshal.Copy(ptr, (int[])(object)arr, 0, 1); //return iohandler.Write(arr[0]) ? 1 : 0; } } // duplicates the unmanaged memory 'ptr' into a new block of size 'n x sizeof(uint)' IntPtr Duplicate(in TagTypeHandler self, IntPtr ptr, uint n) { TestContext.WriteLine($"Duplicate(self: {self}, ptr: 0x{ptr:X}, n: {n})"); using (var context = Context.FromHandle(self.ContextID)) { return(Memory.Duplicate(context, ptr, n * sizeof(uint))); } } // frees the unmanaged memory 'ptr' void Free(in TagTypeHandler self, IntPtr ptr) { TestContext.WriteLine($"Free(self: {self}, ptr: 0x{ptr:X})"); using (var context = Context.FromHandle(self.ContextID)) { Memory.Free(context, ptr); } } void HandleError(IntPtr contextID, int errorCode, string errorText) { TestContext.WriteLine($"Error!!! contextID: {contextID}, errorCode: {errorCode}, errorText: '{errorText}'"); } }