From fb62105f427c3c52eaa53bc5185e700f91a35804 Mon Sep 17 00:00:00 2001 From: David Hall Date: Sat, 17 Aug 2019 16:07:02 -0600 Subject: [PATCH] Added TypeConverter, MinValue/MaxValue fields, comparison operators, and fixed inconsistent handling of Int32 conversions. --- Core/InteropServices/SizeT.cs | 147 +++++++++++++++++++++++++++++++----------- 1 file changed, 111 insertions(+), 36 deletions(-) diff --git a/Core/InteropServices/SizeT.cs b/Core/InteropServices/SizeT.cs index 607b947f..2a986156 100644 --- a/Core/InteropServices/SizeT.cs +++ b/Core/InteropServices/SizeT.cs @@ -1,13 +1,18 @@ using System; +using System.ComponentModel; +using System.Globalization; using System.Runtime.InteropServices; -using System.Runtime.Serialization; namespace Vanara.PInvoke { /// Managed instance of the SIZE_T type. [StructLayout(LayoutKind.Sequential), Serializable] + [TypeConverter(typeof(SizeTTypeConverter))] public struct SizeT : IEquatable, IComparable, IConvertible, IComparable { + /// Represents the smallest possible value of . This field is constant. + public static readonly SizeT MinValue = 0; + private UIntPtr val; /// Initializes a new instance of the struct. @@ -18,6 +23,11 @@ namespace Vanara.PInvoke /// The value. public SizeT(ulong value) => val = new UIntPtr(value); + /// + /// Represents the largest possible value of . This property is determined by the maximum bit-size of a pointer. + /// + public static SizeT MaxValue => UIntPtr.Size == 8 ? ulong.MaxValue : uint.MaxValue; + /// Gets the value. /// The value. public ulong Value { get => val.ToUInt64(); private set => val = new UIntPtr(value); } @@ -25,7 +35,7 @@ namespace Vanara.PInvoke /// Performs an implicit conversion from to . /// The value. /// The result of the conversion. - public static implicit operator SizeT(int value) => new SizeT((uint)value); + public static implicit operator SizeT(int value) => value >= 0 ? new SizeT((uint)value) : throw new ArgumentOutOfRangeException(); /// Performs an implicit conversion from to . /// The value. @@ -35,7 +45,7 @@ namespace Vanara.PInvoke /// Performs an implicit conversion from to . /// The value. /// The result of the conversion. - public static implicit operator SizeT(long value) => new SizeT((ulong)value); + public static implicit operator SizeT(long value) => value >= 0 ? new SizeT((ulong)value) : throw new ArgumentOutOfRangeException(); /// Performs an implicit conversion from to . /// The value. @@ -45,12 +55,12 @@ namespace Vanara.PInvoke /// Performs an implicit conversion from to . /// The value. /// The result of the conversion. - public static implicit operator int(SizeT value) => (int)value.Value; + public static implicit operator int(SizeT value) => (int)value.val.ToUInt32(); /// Performs an implicit conversion from to . /// The value. /// The result of the conversion. - public static implicit operator uint(SizeT value) => (uint)value.Value; + public static implicit operator uint(SizeT value) => value.val.ToUInt32(); /// Performs an implicit conversion from to . /// The value. @@ -62,9 +72,62 @@ namespace Vanara.PInvoke /// The result of the conversion. public static implicit operator ulong(SizeT value) => value.Value; + /// Indicates whether two instances are not equal. + /// The first integral size to compare. + /// The second integral size to compare. + /// + /// if the value of is not equal to the value of ; otherwise, . + /// + public static bool operator !=(SizeT s1, SizeT s2) => !s1.Equals(s2); + + /// Indicates whether a specified is less than another specified . + /// The first integral size to compare. + /// The second integral size to compare. + /// + /// if the value of is less than the value of ; otherwise, . + /// + public static bool operator <(SizeT s1, SizeT s2) => (s1.CompareTo(s2) < 0) ? true : false; + + /// Indicates whether a specified is less than or equal to another specified . + /// The first integral size to compare. + /// The second integral size to compare. + /// + /// if the value of is less than or equal to the value of ; + /// otherwise, . + /// + public static bool operator <=(SizeT s1, SizeT s2) => (s1.CompareTo(s2) <= 0) ? true : false; + + /// Indicates whether two instances are equal. + /// The first integral size to compare. + /// The second integral size to compare. + /// + /// if the value of is equal to the value of ; otherwise, . + /// + public static bool operator ==(SizeT s1, SizeT s2) => s1.Equals(s2); + + /// Indicates whether a specified is greater than another specified . + /// The first integral size to compare. + /// The second integral size to compare. + /// + /// if the value of is greater than the value of ; otherwise, . + /// + public static bool operator >(SizeT s1, SizeT s2) => (s1.CompareTo(s2) > 0) ? true : false; + + /// Indicates whether a specified is greater than or equal to another specified . + /// The first integral size to compare. + /// The second integral size to compare. + /// + /// if the value of is greater than or equal to the value of ; + /// otherwise, . + /// + public static bool operator >=(SizeT s1, SizeT s2) => (s1.CompareTo(s2) >= 0) ? true : false; + /// public int CompareTo(SizeT other) => Value.CompareTo(other.Value); + /// + public override bool Equals(object obj) => obj is SizeT s ? Equals(s) : Value.Equals(obj); + /// public bool Equals(SizeT other) => Value.Equals(other.Value); @@ -86,46 +149,58 @@ namespace Vanara.PInvoke /// bool IConvertible.ToBoolean(IFormatProvider provider) => ((IConvertible)Value).ToBoolean(provider); - /// - char IConvertible.ToChar(IFormatProvider provider) => ((IConvertible)Value).ToChar(provider); - - /// - sbyte IConvertible.ToSByte(IFormatProvider provider) => ((IConvertible)Value).ToSByte(provider); - /// byte IConvertible.ToByte(IFormatProvider provider) => ((IConvertible)Value).ToByte(provider); /// - short IConvertible.ToInt16(IFormatProvider provider) => ((IConvertible)Value).ToInt16(provider); - - /// - ushort IConvertible.ToUInt16(IFormatProvider provider) => ((IConvertible)Value).ToUInt16(provider); - - /// - int IConvertible.ToInt32(IFormatProvider provider) => ((IConvertible)Value).ToInt32(provider); - - /// - uint IConvertible.ToUInt32(IFormatProvider provider) => ((IConvertible)Value).ToUInt32(provider); - - /// - long IConvertible.ToInt64(IFormatProvider provider) => ((IConvertible)Value).ToInt64(provider); - - /// - ulong IConvertible.ToUInt64(IFormatProvider provider) => ((IConvertible)Value).ToUInt64(provider); - - /// - float IConvertible.ToSingle(IFormatProvider provider) => ((IConvertible)Value).ToSingle(provider); - - /// - double IConvertible.ToDouble(IFormatProvider provider) => ((IConvertible)Value).ToDouble(provider); - - /// - decimal IConvertible.ToDecimal(IFormatProvider provider) => ((IConvertible)Value).ToDecimal(provider); + char IConvertible.ToChar(IFormatProvider provider) => ((IConvertible)Value).ToChar(provider); /// DateTime IConvertible.ToDateTime(IFormatProvider provider) => ((IConvertible)Value).ToDateTime(provider); + /// + decimal IConvertible.ToDecimal(IFormatProvider provider) => ((IConvertible)Value).ToDecimal(provider); + + /// + double IConvertible.ToDouble(IFormatProvider provider) => ((IConvertible)Value).ToDouble(provider); + + /// + short IConvertible.ToInt16(IFormatProvider provider) => ((IConvertible)Value).ToInt16(provider); + + /// + int IConvertible.ToInt32(IFormatProvider provider) => ((IConvertible)Value).ToInt32(provider); + + /// + long IConvertible.ToInt64(IFormatProvider provider) => ((IConvertible)Value).ToInt64(provider); + + /// + sbyte IConvertible.ToSByte(IFormatProvider provider) => ((IConvertible)Value).ToSByte(provider); + + /// + float IConvertible.ToSingle(IFormatProvider provider) => ((IConvertible)Value).ToSingle(provider); + /// object IConvertible.ToType(Type conversionType, IFormatProvider provider) => ((IConvertible)Value).ToBoolean(provider); + + /// + ushort IConvertible.ToUInt16(IFormatProvider provider) => ((IConvertible)Value).ToUInt16(provider); + + /// + uint IConvertible.ToUInt32(IFormatProvider provider) => ((IConvertible)Value).ToUInt32(provider); + + /// + ulong IConvertible.ToUInt64(IFormatProvider provider) => ((IConvertible)Value).ToUInt64(provider); + + internal class SizeTTypeConverter : UInt64Converter + { + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + { + if (!(value is SizeT sz)) throw new ArgumentException(); + return base.ConvertTo(context, culture, sz.Value, destinationType); + } + + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) => + new SizeT((ulong)base.ConvertFrom(context, culture, value)); + } } } \ No newline at end of file