using System; using System.Collections.Generic; using System.Runtime.InteropServices; namespace NTwain.Data { /// /// Class to read common TWAIN values. /// public static class TypeReader { /// /// Reads a TWAIN value. /// /// The base address. /// The offset. /// The TWAIN type. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "1#")] public static object ReadValue(IntPtr baseAddress, ref int offset, ItemType type) { object val = null; switch (type) { case ItemType.Int8: val = (sbyte)Marshal.ReadByte(baseAddress, offset); break; case ItemType.UInt8: val = Marshal.ReadByte(baseAddress, offset); break; case ItemType.Bool: case ItemType.UInt16: val = (ushort)Marshal.ReadInt16(baseAddress, offset); break; case ItemType.Int16: val = Marshal.ReadInt16(baseAddress, offset); break; case ItemType.UInt32: val = (uint)Marshal.ReadInt32(baseAddress, offset); break; case ItemType.Int32: val = Marshal.ReadInt32(baseAddress, offset); break; case ItemType.Fix32: TWFix32 f32 = new TWFix32(); f32.Whole = Marshal.ReadInt16(baseAddress, offset); f32.Fraction = (ushort)Marshal.ReadInt16(baseAddress, offset + 2); val = f32; break; case ItemType.Frame: TWFrame frame = new TWFrame(); frame.Left = (TWFix32)ReadValue(baseAddress, ref offset, ItemType.Fix32); frame.Top = (TWFix32)ReadValue(baseAddress, ref offset, ItemType.Fix32); frame.Right = (TWFix32)ReadValue(baseAddress, ref offset, ItemType.Fix32); frame.Bottom = (TWFix32)ReadValue(baseAddress, ref offset, ItemType.Fix32); return frame; // no need to update offset again after reading fix32 case ItemType.String128: case ItemType.String255: case ItemType.String32: case ItemType.String64: val = Marshal.PtrToStringAnsi(new IntPtr(baseAddress.ToInt64() + offset)); break; case ItemType.Handle: val = Marshal.ReadIntPtr(baseAddress, offset); break; } offset += GetItemTypeSize(type); return val; } static readonly Dictionary __sizes = GenerateSizes(); private static Dictionary GenerateSizes() { var sizes = new Dictionary(); sizes[ItemType.Int8] = 1; sizes[ItemType.UInt8] = 1; sizes[ItemType.Int16] = 2; sizes[ItemType.UInt16] = 2; sizes[ItemType.Bool] = 2; sizes[ItemType.Int32] = 4; sizes[ItemType.UInt32] = 4; sizes[ItemType.Fix32] = 4; sizes[ItemType.Frame] = 16; sizes[ItemType.String32] = TwainConst.String32; sizes[ItemType.String64] = TwainConst.String64; sizes[ItemType.String128] = TwainConst.String128; sizes[ItemType.String255] = TwainConst.String255; // TODO: find out if it should be fixed 4 bytes or intptr size sizes[ItemType.Handle] = IntPtr.Size; return sizes; } /// /// Gets the byte size of the item type. /// /// /// public static int GetItemTypeSize(ItemType type) { if (__sizes.ContainsKey(type)) { return __sizes[type]; } return 0; } } }