using System; using System.ComponentModel; using System.Globalization; using System.Runtime.InteropServices; 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; /// Represents the zero value of . This field is constant. public static readonly SizeT Zero = default; private UIntPtr val; /// Initializes a new instance of the struct. /// The value. public SizeT(uint value) => val = (UIntPtr)value; /// Initializes a new instance of the struct. /// 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); } /// Performs an implicit conversion from to . /// The value. /// The result of the conversion. public static implicit operator SizeT(int value) => value >= 0 ? new SizeT((uint)value) : throw new ArgumentOutOfRangeException(); /// Performs an implicit conversion from to . /// The value. /// The result of the conversion. public static implicit operator SizeT(uint value) => new SizeT(value); /// Performs an implicit conversion from to . /// The value. /// The result of the conversion. public static implicit operator SizeT(long value) => value >= 0 ? new SizeT((ulong)value) : throw new ArgumentOutOfRangeException(); /// Performs an implicit conversion from to . /// The value. /// The result of the conversion. public static implicit operator SizeT(ulong value) => new SizeT(value); /// Performs an implicit conversion from to . /// The value. /// The result of the conversion. public static implicit operator int(SizeT value) => ((IConvertible)value).ToInt32(null); /// Performs an implicit conversion from to . /// The value. /// The result of the conversion. public static implicit operator uint(SizeT value) => ((IConvertible)value).ToUInt32(null); /// Performs an implicit conversion from to . /// The value. /// The result of the conversion. public static implicit operator long(SizeT value) => ((IConvertible)value).ToInt64(null); /// Performs an implicit conversion from to . /// The value. /// 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); /// public override int GetHashCode() => Value.GetHashCode(); /// public TypeCode GetTypeCode() => Value.GetTypeCode(); /// public override string ToString() => Value.ToString(); /// public string ToString(IFormatProvider provider) => Value.ToString(provider); /// int IComparable.CompareTo(object obj) => Value.CompareTo(Convert.ChangeType(obj, typeof(ulong))); /// bool IConvertible.ToBoolean(IFormatProvider provider) => ((IConvertible)Value).ToBoolean(provider); /// byte IConvertible.ToByte(IFormatProvider provider) { var ul = Value; if (ul < (ulong)byte.MaxValue) return (byte)ul; if (ul == uint.MaxValue || ul == ulong.MaxValue) return byte.MaxValue; throw new OverflowException(); } /// char IConvertible.ToChar(IFormatProvider provider) => ((IConvertible)Value).ToChar(provider); /// DateTime IConvertible.ToDateTime(IFormatProvider provider) => ((IConvertible)Value).ToDateTime(provider); /// decimal IConvertible.ToDecimal(IFormatProvider provider) { var ul = Value; if (ul < decimal.MaxValue) return (decimal)ul; if (ul == uint.MaxValue || ul == ulong.MaxValue) return decimal.MaxValue; throw new OverflowException(); } /// double IConvertible.ToDouble(IFormatProvider provider) { var ul = Value; if (ul < double.MaxValue) return ul; if (ul == uint.MaxValue || ul == ulong.MaxValue) return double.MaxValue; throw new OverflowException(); } /// short IConvertible.ToInt16(IFormatProvider provider) { var ul = Value; if (ul < (ulong)short.MaxValue) return (short)ul; if (ul == uint.MaxValue || ul == ulong.MaxValue) return short.MaxValue; throw new OverflowException(); } /// int IConvertible.ToInt32(IFormatProvider provider) { var ul = Value; if (ul < int.MaxValue) return (int)ul; if (ul == uint.MaxValue || ul == ulong.MaxValue) return int.MaxValue; throw new OverflowException(); } /// long IConvertible.ToInt64(IFormatProvider provider) { var ul = Value; if (ul < long.MaxValue) return (long)ul; if (ul == uint.MaxValue || ul == ulong.MaxValue) return long.MaxValue; throw new OverflowException(); } /// sbyte IConvertible.ToSByte(IFormatProvider provider) { var ul = Value; if (ul < (ulong)sbyte.MaxValue) return (sbyte)ul; if (ul == uint.MaxValue || ul == ulong.MaxValue) return sbyte.MaxValue; throw new OverflowException(); } /// float IConvertible.ToSingle(IFormatProvider provider) { var ul = Value; if (ul < float.MaxValue) return ul; if (ul == uint.MaxValue || ul == ulong.MaxValue) return float.MaxValue; throw new OverflowException(); } /// object IConvertible.ToType(Type conversionType, IFormatProvider provider) => ((IConvertible)Value).ToType(conversionType, provider); /// ushort IConvertible.ToUInt16(IFormatProvider provider) { var ul = Value; if (ul < (ulong)ushort.MaxValue) return (ushort)ul; if (ul == uint.MaxValue || ul == ulong.MaxValue) return ushort.MaxValue; throw new OverflowException(); } /// uint IConvertible.ToUInt32(IFormatProvider provider) { var ul = Value; if (ul < uint.MaxValue) return (uint)ul; if (ul == uint.MaxValue || ul == ulong.MaxValue) return uint.MaxValue; throw new OverflowException(); } /// ulong IConvertible.ToUInt64(IFormatProvider provider) => Value; 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)); } } }