Maze / Library /PackageCache /com.unity.inputsystem@1.6.1 /InputSystem /Utilities /PrimitiveValue.cs
| using System; | |
| using System.Globalization; | |
| using System.Runtime.InteropServices; | |
| using Unity.Collections.LowLevel.Unsafe; | |
| ////REVIEW: add Vector2 and Vector3 as primitive value types? | |
| namespace UnityEngine.InputSystem.Utilities | |
| { | |
| /// <summary> | |
| /// A union holding a primitive value. | |
| /// </summary> | |
| /// <remarks> | |
| /// This structure is used for storing things such as default states for controls | |
| /// (see <see cref="Layouts.InputControlLayout.ControlItem.defaultState"/>). It can | |
| /// store one value of any primitive, non-reference C# type (bool, char, int, float, etc). | |
| /// </remarks> | |
| [] | |
| public struct PrimitiveValue : IEquatable<PrimitiveValue>, IConvertible | |
| { | |
| [] private TypeCode m_Type; | |
| [] private bool m_BoolValue; | |
| [] private char m_CharValue; | |
| [] private byte m_ByteValue; | |
| [] private sbyte m_SByteValue; | |
| [] private short m_ShortValue; | |
| [] private ushort m_UShortValue; | |
| [] private int m_IntValue; | |
| [] private uint m_UIntValue; | |
| [] private long m_LongValue; | |
| [] private ulong m_ULongValue; | |
| [] private float m_FloatValue; | |
| [] private double m_DoubleValue; | |
| internal unsafe byte* valuePtr => (byte*)UnsafeUtility.AddressOf(ref this) + 4; | |
| /// <summary> | |
| /// Type of value stored in the struct. <see cref="TypeCode.Empty"/> | |
| /// if the struct does not hold a value (i.e. has been default-initialized). | |
| /// </summary> | |
| /// <value>Type of value stored in the struct.</value> | |
| public TypeCode type => m_Type; | |
| /// <summary> | |
| /// If true, the struct does not contain a primitive value (i.e. has <see cref="type"/> | |
| /// <see cref="TypeCode.Empty"/>). | |
| /// </summary> | |
| /// <value>Whether the struct is holding a value or not.</value> | |
| public bool isEmpty => type == TypeCode.Empty; | |
| /// <summary> | |
| /// Create a PrimitiveValue holding a bool. | |
| /// </summary> | |
| /// <param name="value">A boolean value.</param> | |
| public PrimitiveValue(bool value) | |
| : this() | |
| { | |
| m_Type = TypeCode.Boolean; | |
| m_BoolValue = value; | |
| } | |
| /// <summary> | |
| /// Create a PrimitiveValue holding a character. | |
| /// </summary> | |
| /// <param name="value">A character.</param> | |
| public PrimitiveValue(char value) | |
| : this() | |
| { | |
| m_Type = TypeCode.Char; | |
| m_CharValue = value; | |
| } | |
| /// <summary> | |
| /// Create a PrimitiveValue holding a byte. | |
| /// </summary> | |
| /// <param name="value">A byte value.</param> | |
| public PrimitiveValue(byte value) | |
| : this() | |
| { | |
| m_Type = TypeCode.Byte; | |
| m_ByteValue = value; | |
| } | |
| /// <summary> | |
| /// Create a PrimitiveValue holding a signed byte. | |
| /// </summary> | |
| /// <param name="value">A signed byte value.</param> | |
| public PrimitiveValue(sbyte value) | |
| : this() | |
| { | |
| m_Type = TypeCode.SByte; | |
| m_SByteValue = value; | |
| } | |
| /// <summary> | |
| /// Create a PrimitiveValue holding a short. | |
| /// </summary> | |
| /// <param name="value">A short value.</param> | |
| public PrimitiveValue(short value) | |
| : this() | |
| { | |
| m_Type = TypeCode.Int16; | |
| m_ShortValue = value; | |
| } | |
| /// <summary> | |
| /// Create a PrimitiveValue holding an unsigned short. | |
| /// </summary> | |
| /// <param name="value">An unsigned short value.</param> | |
| public PrimitiveValue(ushort value) | |
| : this() | |
| { | |
| m_Type = TypeCode.UInt16; | |
| m_UShortValue = value; | |
| } | |
| /// <summary> | |
| /// Create a PrimitiveValue holding an int. | |
| /// </summary> | |
| /// <param name="value">An int value.</param> | |
| public PrimitiveValue(int value) | |
| : this() | |
| { | |
| m_Type = TypeCode.Int32; | |
| m_IntValue = value; | |
| } | |
| /// <summary> | |
| /// Create a PrimitiveValue holding an unsigned int. | |
| /// </summary> | |
| /// <param name="value">An unsigned int value.</param> | |
| public PrimitiveValue(uint value) | |
| : this() | |
| { | |
| m_Type = TypeCode.UInt32; | |
| m_UIntValue = value; | |
| } | |
| /// <summary> | |
| /// Create a PrimitiveValue holding a long. | |
| /// </summary> | |
| /// <param name="value">A long value.</param> | |
| public PrimitiveValue(long value) | |
| : this() | |
| { | |
| m_Type = TypeCode.Int64; | |
| m_LongValue = value; | |
| } | |
| /// <summary> | |
| /// Create a PrimitiveValue holding a ulong. | |
| /// </summary> | |
| /// <param name="value">An unsigned long value.</param> | |
| public PrimitiveValue(ulong value) | |
| : this() | |
| { | |
| m_Type = TypeCode.UInt64; | |
| m_ULongValue = value; | |
| } | |
| /// <summary> | |
| /// Create a PrimitiveValue holding a float. | |
| /// </summary> | |
| /// <param name="value">A float value.</param> | |
| public PrimitiveValue(float value) | |
| : this() | |
| { | |
| m_Type = TypeCode.Single; | |
| m_FloatValue = value; | |
| } | |
| /// <summary> | |
| /// Create a PrimitiveValue holding a double. | |
| /// </summary> | |
| /// <param name="value">A double value.</param> | |
| public PrimitiveValue(double value) | |
| : this() | |
| { | |
| m_Type = TypeCode.Double; | |
| m_DoubleValue = value; | |
| } | |
| /// <summary> | |
| /// Convert to another type of value. | |
| /// </summary> | |
| /// <param name="type">Type of value to convert to.</param> | |
| /// <returns>The converted value.</returns> | |
| /// <exception cref="ArgumentException">There is no conversion from the | |
| /// PrimitiveValue's current <see cref="PrimitiveValue.type"/> to | |
| /// <paramref name="type"/>.</exception> | |
| /// <remarks> | |
| /// This method simply calls the other conversion methods (<see cref="ToBoolean"/>, | |
| /// <see cref="ToChar"/>, etc) based on the current type of value. <c>ArgumentException</c> | |
| /// is thrown if there is no conversion from the current to the requested type. | |
| /// | |
| /// Every value can be converted to <c>TypeCode.Empty</c>. | |
| /// </remarks> | |
| /// <seealso cref="ToBoolean"/> | |
| /// <seealso cref="ToChar"/> | |
| /// <seealso cref="ToByte"/> | |
| /// <seealso cref="ToSByte"/> | |
| /// <seealso cref="ToInt16"/> | |
| /// <seealso cref="ToInt32"/> | |
| /// <seealso cref="ToInt64"/> | |
| /// <seealso cref="ToUInt16"/> | |
| /// <seealso cref="ToUInt32"/> | |
| /// <seealso cref="ToUInt64"/> | |
| /// <seealso cref="ToSingle"/> | |
| /// <seealso cref="ToDouble"/> | |
| public PrimitiveValue ConvertTo(TypeCode type) | |
| { | |
| switch (type) | |
| { | |
| case TypeCode.Boolean: return ToBoolean(); | |
| case TypeCode.Char: return ToChar(); | |
| case TypeCode.Byte: return ToByte(); | |
| case TypeCode.SByte: return ToSByte(); | |
| case TypeCode.Int16: return ToInt16(); | |
| case TypeCode.Int32: return ToInt32(); | |
| case TypeCode.Int64: return ToInt64(); | |
| case TypeCode.UInt16: return ToInt16(); | |
| case TypeCode.UInt32: return ToInt32(); | |
| case TypeCode.UInt64: return ToUInt64(); | |
| case TypeCode.Single: return ToSingle(); | |
| case TypeCode.Double: return ToDouble(); | |
| case TypeCode.Empty: return new PrimitiveValue(); | |
| } | |
| throw new ArgumentException($"Don't know how to convert PrimitiveValue to '{type}'", nameof(type)); | |
| } | |
| /// <summary> | |
| /// Compare this value to <paramref name="other"/>. | |
| /// </summary> | |
| /// <param name="other">Another value.</param> | |
| /// <returns>True if the two values are equal.</returns> | |
| /// <remarks> | |
| /// Equality is based on type and contents. The types of both values | |
| /// must be identical and the memory contents of each value must be | |
| /// bit-wise identical (i.e. things such as floating-point epsilons | |
| /// are not taken into account). | |
| /// </remarks> | |
| public unsafe bool Equals(PrimitiveValue other) | |
| { | |
| if (m_Type != other.m_Type) | |
| return false; | |
| var thisValuePtr = UnsafeUtility.AddressOf(ref m_DoubleValue); | |
| var otherValuePtr = UnsafeUtility.AddressOf(ref other.m_DoubleValue); | |
| return UnsafeUtility.MemCmp(thisValuePtr, otherValuePtr, sizeof(double)) == 0; | |
| } | |
| /// <summary> | |
| /// Compare this value to the value of <paramref name="obj"/>. | |
| /// </summary> | |
| /// <param name="obj">Either another PrimitiveValue or a boxed primitive | |
| /// value such as a byte, bool, etc.</param> | |
| /// <returns>True if the two values are equal.</returns> | |
| /// <remarks> | |
| /// If <paramref name="obj"/> is a boxed primitive value, it is automatically | |
| /// converted to a PrimitiveValue. | |
| /// </remarks> | |
| public override bool Equals(object obj) | |
| { | |
| if (ReferenceEquals(null, obj)) | |
| return false; | |
| if (obj is PrimitiveValue value) | |
| return Equals(value); | |
| if (obj is bool || obj is char || obj is byte || obj is sbyte || obj is short | |
| || obj is ushort || obj is int || obj is uint || obj is long || obj is ulong | |
| || obj is float || obj is double) | |
| return Equals(FromObject(obj)); | |
| return false; | |
| } | |
| /// <summary> | |
| /// Compare two PrimitiveValues for equality. | |
| /// </summary> | |
| /// <param name="left">First value.</param> | |
| /// <param name="right">Second value.</param> | |
| /// <returns>True if the two values are equal.</returns> | |
| /// <seealso cref="Equals(PrimitiveValue)"/> | |
| public static bool operator==(PrimitiveValue left, PrimitiveValue right) | |
| { | |
| return left.Equals(right); | |
| } | |
| /// <summary> | |
| /// Compare two PrimitiveValues for inequality. | |
| /// </summary> | |
| /// <param name="left">First value.</param> | |
| /// <param name="right">Second value.</param> | |
| /// <returns>True if the two values are not equal.</returns> | |
| /// <seealso cref="Equals(PrimitiveValue)"/> | |
| public static bool operator!=(PrimitiveValue left, PrimitiveValue right) | |
| { | |
| return !left.Equals(right); | |
| } | |
| /// <summary> | |
| /// Compute a hash code for the value. | |
| /// </summary> | |
| /// <returns>A hash code.</returns> | |
| public override unsafe int GetHashCode() | |
| { | |
| unchecked | |
| { | |
| fixed(double* valuePtr = &m_DoubleValue) | |
| { | |
| var hashCode = m_Type.GetHashCode(); | |
| hashCode = (hashCode * 397) ^ valuePtr->GetHashCode(); | |
| return hashCode; | |
| } | |
| } | |
| } | |
| /// <summary> | |
| /// Return a string representation of the value. | |
| /// </summary> | |
| /// <returns>A string representation of the value.</returns> | |
| /// <remarks> | |
| /// String versions of PrimitiveValues are always culture invariant. This means that | |
| /// floating-point values, for example, will <em>not</em> the decimal separator of | |
| /// the current culture. | |
| /// </remarks> | |
| /// <seealso cref="FromString"/> | |
| public override string ToString() | |
| { | |
| switch (type) | |
| { | |
| case TypeCode.Boolean: | |
| // Default ToString() uses "False" and "True". We want lowercase to match C# literals. | |
| return m_BoolValue ? "true" : "false"; | |
| case TypeCode.Char: | |
| return $"'{m_CharValue.ToString()}'"; | |
| case TypeCode.Byte: | |
| return m_ByteValue.ToString(CultureInfo.InvariantCulture.NumberFormat); | |
| case TypeCode.SByte: | |
| return m_SByteValue.ToString(CultureInfo.InvariantCulture.NumberFormat); | |
| case TypeCode.Int16: | |
| return m_ShortValue.ToString(CultureInfo.InvariantCulture.NumberFormat); | |
| case TypeCode.UInt16: | |
| return m_UShortValue.ToString(CultureInfo.InvariantCulture.NumberFormat); | |
| case TypeCode.Int32: | |
| return m_IntValue.ToString(CultureInfo.InvariantCulture.NumberFormat); | |
| case TypeCode.UInt32: | |
| return m_UIntValue.ToString(CultureInfo.InvariantCulture.NumberFormat); | |
| case TypeCode.Int64: | |
| return m_LongValue.ToString(CultureInfo.InvariantCulture.NumberFormat); | |
| case TypeCode.UInt64: | |
| return m_ULongValue.ToString(CultureInfo.InvariantCulture.NumberFormat); | |
| case TypeCode.Single: | |
| return m_FloatValue.ToString(CultureInfo.InvariantCulture.NumberFormat); | |
| case TypeCode.Double: | |
| return m_DoubleValue.ToString(CultureInfo.InvariantCulture.NumberFormat); | |
| default: | |
| return string.Empty; | |
| } | |
| } | |
| /// <summary> | |
| /// Parse the given string into a PrimitiveValue. | |
| /// </summary> | |
| /// <param name="value">A string containing a value.</param> | |
| /// <returns>The PrimitiveValue parsed from the string.</returns> | |
| /// <remarks> | |
| /// Integers are parsed as longs. Floating-point numbers are parsed as doubles. | |
| /// Hexadecimal notation is supported for integers. | |
| /// </remarks> | |
| /// <seealso cref="ToString()"/> | |
| public static PrimitiveValue FromString(string value) | |
| { | |
| if (string.IsNullOrEmpty(value)) | |
| return new PrimitiveValue(); | |
| // Bool. | |
| if (value.Equals("true", StringComparison.InvariantCultureIgnoreCase)) | |
| return new PrimitiveValue(true); | |
| if (value.Equals("false", StringComparison.InvariantCultureIgnoreCase)) | |
| return new PrimitiveValue(false); | |
| // Double. | |
| if (value.Contains('.') || value.Contains("e") || value.Contains("E") || | |
| value.Contains("infinity", StringComparison.InvariantCultureIgnoreCase)) | |
| { | |
| if (double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var doubleResult)) | |
| return new PrimitiveValue(doubleResult); | |
| } | |
| // Long. | |
| if (long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var longResult)) | |
| { | |
| return new PrimitiveValue(longResult); | |
| } | |
| // Try hex format. For whatever reason, HexNumber does not allow a 0x prefix so we manually | |
| // get rid of it. | |
| if (value.IndexOf("0x", StringComparison.InvariantCultureIgnoreCase) != -1) | |
| { | |
| var hexDigits = value.TrimStart(); | |
| if (hexDigits.StartsWith("0x")) | |
| hexDigits = hexDigits.Substring(2); | |
| if (long.TryParse(hexDigits, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var hexResult)) | |
| return new PrimitiveValue(hexResult); | |
| } | |
| ////TODO: allow trailing width specifier | |
| throw new NotImplementedException(); | |
| } | |
| /// <summary> | |
| /// Equivalent to <see cref="type"/>. | |
| /// </summary> | |
| /// <returns>Type code for value stored in struct.</returns> | |
| public TypeCode GetTypeCode() | |
| { | |
| return type; | |
| } | |
| /// <summary> | |
| /// Convert the value to a boolean. | |
| /// </summary> | |
| /// <param name="provider">Ignored.</param> | |
| /// <returns>Converted boolean value.</returns> | |
| public bool ToBoolean(IFormatProvider provider = null) | |
| { | |
| switch (type) | |
| { | |
| case TypeCode.Boolean: | |
| return m_BoolValue; | |
| case TypeCode.Char: | |
| return m_CharValue != default; | |
| case TypeCode.Byte: | |
| return m_ByteValue != default; | |
| case TypeCode.SByte: | |
| return m_SByteValue != default; | |
| case TypeCode.Int16: | |
| return m_ShortValue != default; | |
| case TypeCode.UInt16: | |
| return m_UShortValue != default; | |
| case TypeCode.Int32: | |
| return m_IntValue != default; | |
| case TypeCode.UInt32: | |
| return m_UIntValue != default; | |
| case TypeCode.Int64: | |
| return m_LongValue != default; | |
| case TypeCode.UInt64: | |
| return m_ULongValue != default; | |
| case TypeCode.Single: | |
| return !Mathf.Approximately(m_FloatValue, default); | |
| case TypeCode.Double: | |
| return NumberHelpers.Approximately(m_DoubleValue, default); | |
| default: | |
| return default; | |
| } | |
| } | |
| /// <summary> | |
| /// Convert the value to a byte. | |
| /// </summary> | |
| /// <param name="provider">Ignored.</param> | |
| /// <returns>Converted byte value.</returns> | |
| public byte ToByte(IFormatProvider provider = null) | |
| { | |
| return (byte)ToInt64(provider); | |
| } | |
| /// <summary> | |
| /// Convert the value to a char. | |
| /// </summary> | |
| /// <param name="provider">Ignored.</param> | |
| /// <returns>Converted char value.</returns> | |
| public char ToChar(IFormatProvider provider = null) | |
| { | |
| switch (type) | |
| { | |
| case TypeCode.Char: | |
| return m_CharValue; | |
| case TypeCode.Int16: | |
| case TypeCode.Int32: | |
| case TypeCode.Int64: | |
| case TypeCode.UInt16: | |
| case TypeCode.UInt32: | |
| case TypeCode.UInt64: | |
| return (char)ToInt64(provider); | |
| default: | |
| return default; | |
| } | |
| } | |
| /// <summary> | |
| /// Not supported. Throws <c>NotSupportedException</c>. | |
| /// </summary> | |
| /// <param name="provider">Ignored.</param> | |
| /// <returns>Does not return.</returns> | |
| /// <exception cref="NotSupportedException">Always thrown.</exception> | |
| public DateTime ToDateTime(IFormatProvider provider = null) | |
| { | |
| throw new NotSupportedException("Converting PrimitiveValue to DateTime"); | |
| } | |
| /// <summary> | |
| /// Convert the value to a decimal. | |
| /// </summary> | |
| /// <param name="provider">Ignored.</param> | |
| /// <returns>Value converted to decimal format.</returns> | |
| public decimal ToDecimal(IFormatProvider provider = null) | |
| { | |
| return new decimal(ToDouble(provider)); | |
| } | |
| /// <summary> | |
| /// Convert the value to a double. | |
| /// </summary> | |
| /// <param name="provider">Ignored.</param> | |
| /// <returns>Converted double value.</returns> | |
| public double ToDouble(IFormatProvider provider = null) | |
| { | |
| switch (type) | |
| { | |
| case TypeCode.Boolean: | |
| if (m_BoolValue) | |
| return 1; | |
| return 0; | |
| case TypeCode.Char: | |
| return m_CharValue; | |
| case TypeCode.Byte: | |
| return m_ByteValue; | |
| case TypeCode.SByte: | |
| return m_SByteValue; | |
| case TypeCode.Int16: | |
| return m_ShortValue; | |
| case TypeCode.UInt16: | |
| return m_UShortValue; | |
| case TypeCode.Int32: | |
| return m_IntValue; | |
| case TypeCode.UInt32: | |
| return m_UIntValue; | |
| case TypeCode.Int64: | |
| return m_LongValue; | |
| case TypeCode.UInt64: | |
| return m_ULongValue; | |
| case TypeCode.Single: | |
| return m_FloatValue; | |
| case TypeCode.Double: | |
| return m_DoubleValue; | |
| default: | |
| return default; | |
| } | |
| } | |
| /// <summary> | |
| /// Convert the value to a <c>short</c>. | |
| /// </summary> | |
| /// <param name="provider">Ignored.</param> | |
| /// <returns>Converted <c>short</c> value.</returns> | |
| public short ToInt16(IFormatProvider provider = null) | |
| { | |
| return (short)ToInt64(provider); | |
| } | |
| /// <summary> | |
| /// Convert the value to an <c>int</c> | |
| /// </summary> | |
| /// <param name="provider">Ignored.</param> | |
| /// <returns>Converted <c>int</c> value.</returns> | |
| public int ToInt32(IFormatProvider provider = null) | |
| { | |
| return (int)ToInt64(provider); | |
| } | |
| /// <summary> | |
| /// Convert the value to a <c>long</c> | |
| /// </summary> | |
| /// <param name="provider">Ignored.</param> | |
| /// <returns>Converted <c>long</c> value.</returns> | |
| public long ToInt64(IFormatProvider provider = null) | |
| { | |
| switch (type) | |
| { | |
| case TypeCode.Boolean: | |
| if (m_BoolValue) | |
| return 1; | |
| return 0; | |
| case TypeCode.Char: | |
| return m_CharValue; | |
| case TypeCode.Byte: | |
| return m_ByteValue; | |
| case TypeCode.SByte: | |
| return m_SByteValue; | |
| case TypeCode.Int16: | |
| return m_ShortValue; | |
| case TypeCode.UInt16: | |
| return m_UShortValue; | |
| case TypeCode.Int32: | |
| return m_IntValue; | |
| case TypeCode.UInt32: | |
| return m_UIntValue; | |
| case TypeCode.Int64: | |
| return m_LongValue; | |
| case TypeCode.UInt64: | |
| return (long)m_ULongValue; | |
| case TypeCode.Single: | |
| return (long)m_FloatValue; | |
| case TypeCode.Double: | |
| return (long)m_DoubleValue; | |
| default: | |
| return default; | |
| } | |
| } | |
| /// <summary> | |
| /// Convert the value to a <c>sbyte</c>. | |
| /// </summary> | |
| /// <param name="provider">Ignored.</param> | |
| /// <returns>Converted <c>sbyte</c> value.</returns> | |
| public sbyte ToSByte(IFormatProvider provider = null) | |
| { | |
| return (sbyte)ToInt64(provider); | |
| } | |
| /// <summary> | |
| /// Convert the value to a <c>float</c>. | |
| /// </summary> | |
| /// <param name="provider">Ignored.</param> | |
| /// <returns>Converted <c>float</c> value.</returns> | |
| public float ToSingle(IFormatProvider provider = null) | |
| { | |
| return (float)ToDouble(provider); | |
| } | |
| /// <summary> | |
| /// Convert the value to a <c>string</c>. | |
| /// </summary> | |
| /// <param name="provider">Ignored.</param> | |
| /// <returns>Converted <c>string</c> value.</returns> | |
| /// <remarks> | |
| /// Same as calling <see cref="ToString()"/>. | |
| /// </remarks> | |
| public string ToString(IFormatProvider provider) | |
| { | |
| return ToString(); | |
| } | |
| /// <summary> | |
| /// Not supported. | |
| /// </summary> | |
| /// <param name="conversionType">Ignored.</param> | |
| /// <param name="provider">Ignored.</param> | |
| /// <returns>Does not return.</returns> | |
| /// <exception cref="NotSupportedException">Always thrown.</exception> | |
| public object ToType(Type conversionType, IFormatProvider provider) | |
| { | |
| throw new NotSupportedException(); | |
| } | |
| /// <summary> | |
| /// Convert the value to a <c>ushort</c>. | |
| /// </summary> | |
| /// <param name="provider">Ignored.</param> | |
| /// <returns>Converted <c>ushort</c> value.</returns> | |
| public ushort ToUInt16(IFormatProvider provider = null) | |
| { | |
| return (ushort)ToUInt64(); | |
| } | |
| /// <summary> | |
| /// Convert the value to a <c>uint</c>. | |
| /// </summary> | |
| /// <param name="provider">Ignored.</param> | |
| /// <returns>Converted <c>uint</c> value.</returns> | |
| public uint ToUInt32(IFormatProvider provider = null) | |
| { | |
| return (uint)ToUInt64(); | |
| } | |
| /// <summary> | |
| /// Convert the value to a <c>ulong</c>. | |
| /// </summary> | |
| /// <param name="provider">Ignored.</param> | |
| /// <returns>Converted <c>ulong</c> value.</returns> | |
| public ulong ToUInt64(IFormatProvider provider = null) | |
| { | |
| switch (type) | |
| { | |
| case TypeCode.Boolean: | |
| if (m_BoolValue) | |
| return 1; | |
| return 0; | |
| case TypeCode.Char: | |
| return m_CharValue; | |
| case TypeCode.Byte: | |
| return m_ByteValue; | |
| case TypeCode.SByte: | |
| return (ulong)m_SByteValue; | |
| case TypeCode.Int16: | |
| return (ulong)m_ShortValue; | |
| case TypeCode.UInt16: | |
| return m_UShortValue; | |
| case TypeCode.Int32: | |
| return (ulong)m_IntValue; | |
| case TypeCode.UInt32: | |
| return m_UIntValue; | |
| case TypeCode.Int64: | |
| return (ulong)m_LongValue; | |
| case TypeCode.UInt64: | |
| return m_ULongValue; | |
| case TypeCode.Single: | |
| return (ulong)m_FloatValue; | |
| case TypeCode.Double: | |
| return (ulong)m_DoubleValue; | |
| default: | |
| return default; | |
| } | |
| } | |
| /// <summary> | |
| /// Return a boxed version of the value. | |
| /// </summary> | |
| /// <returns>A boxed GC heap object.</returns> | |
| /// <remarks> | |
| /// This method always allocates GC heap memory. | |
| /// </remarks> | |
| public object ToObject() | |
| { | |
| switch (m_Type) | |
| { | |
| case TypeCode.Boolean: return m_BoolValue; | |
| case TypeCode.Char: return m_CharValue; | |
| case TypeCode.Byte: return m_ByteValue; | |
| case TypeCode.SByte: return m_SByteValue; | |
| case TypeCode.Int16: return m_ShortValue; | |
| case TypeCode.UInt16: return m_UShortValue; | |
| case TypeCode.Int32: return m_IntValue; | |
| case TypeCode.UInt32: return m_UIntValue; | |
| case TypeCode.Int64: return m_LongValue; | |
| case TypeCode.UInt64: return m_ULongValue; | |
| case TypeCode.Single: return m_FloatValue; | |
| case TypeCode.Double: return m_DoubleValue; | |
| default: return null; | |
| } | |
| } | |
| /// <summary> | |
| /// Create a PrimitiveValue from the given "blittable"/struct value. | |
| /// </summary> | |
| /// <param name="value">A value.</param> | |
| /// <typeparam name="TValue">Type of value to convert. Must be either an <c>enum</c> | |
| /// or one of the C# primitive value types (<c>bool</c>, <c>int</c>, <c>float</c>, etc.).</typeparam> | |
| /// <returns>The PrimitiveValue converted from <paramref name="value"/>. If it is an | |
| /// <c>enum</c> type, the PrimitiveValue will hold a value of the enum's underlying | |
| /// type (i.e. <c>Type.GetEnumUnderlyingType</c>).</returns> | |
| /// <exception cref="ArgumentException">No conversion exists from the given <typeparamref name="TValue"/> | |
| /// type.</exception> | |
| public static PrimitiveValue From<TValue>(TValue value) | |
| where TValue : struct | |
| { | |
| var type = typeof(TValue); | |
| if (type.IsEnum) | |
| type = type.GetEnumUnderlyingType(); | |
| var typeCode = Type.GetTypeCode(type); | |
| switch (typeCode) | |
| { | |
| case TypeCode.Boolean: return new PrimitiveValue(Convert.ToBoolean(value)); | |
| case TypeCode.Char: return new PrimitiveValue(Convert.ToChar(value)); | |
| case TypeCode.Byte: return new PrimitiveValue(Convert.ToByte(value)); | |
| case TypeCode.SByte: return new PrimitiveValue(Convert.ToSByte(value)); | |
| case TypeCode.Int16: return new PrimitiveValue(Convert.ToInt16(value)); | |
| case TypeCode.Int32: return new PrimitiveValue(Convert.ToInt32(value)); | |
| case TypeCode.Int64: return new PrimitiveValue(Convert.ToInt64(value)); | |
| case TypeCode.UInt16: return new PrimitiveValue(Convert.ToUInt16(value)); | |
| case TypeCode.UInt32: return new PrimitiveValue(Convert.ToUInt32(value)); | |
| case TypeCode.UInt64: return new PrimitiveValue(Convert.ToUInt64(value)); | |
| case TypeCode.Single: return new PrimitiveValue(Convert.ToSingle(value)); | |
| case TypeCode.Double: return new PrimitiveValue(Convert.ToDouble(value)); | |
| } | |
| throw new ArgumentException( | |
| $"Cannot convert value '{value}' of type '{typeof(TValue).Name}' to PrimitiveValue", nameof(value)); | |
| } | |
| /// <summary> | |
| /// Create a PrimitiveValue from a boxed value. | |
| /// </summary> | |
| /// <param name="value">A value. If <c>null</c>, the result will be <c>default(PrimitiveValue)</c>. | |
| /// If it is a <c>string</c>, <see cref="FromString"/> is used. Otherwise must be either an <c>enum</c> | |
| /// or one of the C# primitive value types (<c>bool</c>, <c>int</c>, <c>float</c>, etc.). If it is an | |
| /// <c>enum</c> type, the PrimitiveValue will hold a value of the enum's underlying | |
| /// type (i.e. <c>Type.GetEnumUnderlyingType</c>).</param> | |
| /// <exception cref="ArgumentException">No conversion exists from the type of <paramref name="value"/>.</exception> | |
| public static PrimitiveValue FromObject(object value) | |
| { | |
| if (value == null) | |
| return new PrimitiveValue(); | |
| if (value is string stringValue) | |
| return FromString(stringValue); | |
| if (value is bool b) | |
| return new PrimitiveValue(b); | |
| if (value is char ch) | |
| return new PrimitiveValue(ch); | |
| if (value is byte bt) | |
| return new PrimitiveValue(bt); | |
| if (value is sbyte sbt) | |
| return new PrimitiveValue(sbt); | |
| if (value is short s) | |
| return new PrimitiveValue(s); | |
| if (value is ushort us) | |
| return new PrimitiveValue(us); | |
| if (value is int i) | |
| return new PrimitiveValue(i); | |
| if (value is uint ui) | |
| return new PrimitiveValue(ui); | |
| if (value is long l) | |
| return new PrimitiveValue(l); | |
| if (value is ulong ul) | |
| return new PrimitiveValue(ul); | |
| if (value is float f) | |
| return new PrimitiveValue(f); | |
| if (value is double d) | |
| return new PrimitiveValue(d); | |
| // Enum. | |
| if (value is Enum) | |
| { | |
| var underlyingType = value.GetType().GetEnumUnderlyingType(); | |
| var underlyingTypeCode = Type.GetTypeCode(underlyingType); | |
| switch (underlyingTypeCode) | |
| { | |
| case TypeCode.Byte: return new PrimitiveValue((byte)value); | |
| case TypeCode.SByte: return new PrimitiveValue((sbyte)value); | |
| case TypeCode.Int16: return new PrimitiveValue((short)value); | |
| case TypeCode.Int32: return new PrimitiveValue((int)value); | |
| case TypeCode.Int64: return new PrimitiveValue((long)value); | |
| case TypeCode.UInt16: return new PrimitiveValue((ushort)value); | |
| case TypeCode.UInt32: return new PrimitiveValue((uint)value); | |
| case TypeCode.UInt64: return new PrimitiveValue((ulong)value); | |
| } | |
| } | |
| throw new ArgumentException($"Cannot convert '{value}' to primitive value", nameof(value)); | |
| } | |
| /// <summary> | |
| /// Create a PrimitiveValue holding a bool. | |
| /// </summary> | |
| /// <param name="value">A boolean value.</param> | |
| /// <returns>A <c>PrimitiveValue</c> set to <paramref name="value"/></returns> | |
| public static implicit operator PrimitiveValue(bool value) | |
| { | |
| return new PrimitiveValue(value); | |
| } | |
| /// <summary> | |
| /// Create a PrimitiveValue holding a character. | |
| /// </summary> | |
| /// <param name="value">A character.</param> | |
| /// <returns>A <c>PrimitiveValue</c> set to <paramref name="value"/></returns> | |
| public static implicit operator PrimitiveValue(char value) | |
| { | |
| return new PrimitiveValue(value); | |
| } | |
| /// <summary> | |
| /// Create a PrimitiveValue holding a byte. | |
| /// </summary> | |
| /// <param name="value">A byte value.</param> | |
| /// <returns>A <c>PrimitiveValue</c> set to <paramref name="value"/></returns> | |
| public static implicit operator PrimitiveValue(byte value) | |
| { | |
| return new PrimitiveValue(value); | |
| } | |
| /// <summary> | |
| /// Create a PrimitiveValue holding a signed byte. | |
| /// </summary> | |
| /// <param name="value">A signed byte value.</param> | |
| /// <returns>A <c>PrimitiveValue</c> set to <paramref name="value"/></returns> | |
| public static implicit operator PrimitiveValue(sbyte value) | |
| { | |
| return new PrimitiveValue(value); | |
| } | |
| /// <summary> | |
| /// Create a PrimitiveValue holding a short. | |
| /// </summary> | |
| /// <param name="value">A short value.</param> | |
| /// <returns>A <c>PrimitiveValue</c> set to <paramref name="value"/></returns> | |
| public static implicit operator PrimitiveValue(short value) | |
| { | |
| return new PrimitiveValue(value); | |
| } | |
| /// <summary> | |
| /// Create a PrimitiveValue holding an unsigned short. | |
| /// </summary> | |
| /// <param name="value">An unsigned short value.</param> | |
| /// <returns>A <c>PrimitiveValue</c> set to <paramref name="value"/></returns> | |
| public static implicit operator PrimitiveValue(ushort value) | |
| { | |
| return new PrimitiveValue(value); | |
| } | |
| /// <summary> | |
| /// Create a PrimitiveValue holding an int. | |
| /// </summary> | |
| /// <param name="value">An int value.</param> | |
| /// <returns>A <c>PrimitiveValue</c> set to <paramref name="value"/></returns> | |
| public static implicit operator PrimitiveValue(int value) | |
| { | |
| return new PrimitiveValue(value); | |
| } | |
| /// <summary> | |
| /// Create a PrimitiveValue holding an unsigned int. | |
| /// </summary> | |
| /// <param name="value">An unsigned int value.</param> | |
| /// <returns>A <c>PrimitiveValue</c> set to <paramref name="value"/></returns> | |
| public static implicit operator PrimitiveValue(uint value) | |
| { | |
| return new PrimitiveValue(value); | |
| } | |
| /// <summary> | |
| /// Create a PrimitiveValue holding a long. | |
| /// </summary> | |
| /// <param name="value">A long value.</param> | |
| /// <returns>A <c>PrimitiveValue</c> set to <paramref name="value"/></returns> | |
| public static implicit operator PrimitiveValue(long value) | |
| { | |
| return new PrimitiveValue(value); | |
| } | |
| /// <summary> | |
| /// Create a PrimitiveValue holding a ulong. | |
| /// </summary> | |
| /// <param name="value">An unsigned long value.</param> | |
| /// <returns>A <c>PrimitiveValue</c> set to <paramref name="value"/></returns> | |
| public static implicit operator PrimitiveValue(ulong value) | |
| { | |
| return new PrimitiveValue(value); | |
| } | |
| /// <summary> | |
| /// Create a PrimitiveValue holding a float. | |
| /// </summary> | |
| /// <param name="value">A float value.</param> | |
| /// <returns>A <c>PrimitiveValue</c> set to <paramref name="value"/></returns> | |
| public static implicit operator PrimitiveValue(float value) | |
| { | |
| return new PrimitiveValue(value); | |
| } | |
| /// <summary> | |
| /// Create a PrimitiveValue holding a double. | |
| /// </summary> | |
| /// <param name="value">A double value.</param> | |
| /// <returns>A <c>PrimitiveValue</c> set to <paramref name="value"/></returns> | |
| public static implicit operator PrimitiveValue(double value) | |
| { | |
| return new PrimitiveValue(value); | |
| } | |
| // The following methods exist only to make the annoying Microsoft code analyzer happy. | |
| /// <summary> | |
| /// Constructs a <c>PrimitiveValue</c> from <paramref name="value"/>. | |
| /// </summary> | |
| /// <param name="value">The value to be stored in the returned <c>PrimitiveValue</c>.</param> | |
| /// <returns>A <c>PrimitiveValue</c> set to <paramref name="value"/></returns> | |
| public static PrimitiveValue FromBoolean(bool value) | |
| { | |
| return new PrimitiveValue(value); | |
| } | |
| /// <summary> | |
| /// Constructs a <c>PrimitiveValue</c> from <paramref name="value"/>. | |
| /// </summary> | |
| /// <param name="value">The value to be stored in the returned <c>PrimitiveValue</c>.</param> | |
| /// <returns>A <c>PrimitiveValue</c> set to <paramref name="value"/></returns> | |
| public static PrimitiveValue FromChar(char value) | |
| { | |
| return new PrimitiveValue(value); | |
| } | |
| /// <summary> | |
| /// Constructs a <c>PrimitiveValue</c> from <paramref name="value"/>. | |
| /// </summary> | |
| /// <param name="value">The value to be stored in the returned <c>PrimitiveValue</c>.</param> | |
| /// <returns>A <c>PrimitiveValue</c> set to <paramref name="value"/></returns> | |
| public static PrimitiveValue FromByte(byte value) | |
| { | |
| return new PrimitiveValue(value); | |
| } | |
| /// <summary> | |
| /// Constructs a <c>PrimitiveValue</c> from <paramref name="value"/>. | |
| /// </summary> | |
| /// <param name="value">The value to be stored in the returned <c>PrimitiveValue</c>.</param> | |
| /// <returns>A <c>PrimitiveValue</c> set to <paramref name="value"/></returns> | |
| public static PrimitiveValue FromSByte(sbyte value) | |
| { | |
| return new PrimitiveValue(value); | |
| } | |
| /// <summary> | |
| /// Constructs a <c>PrimitiveValue</c> from <paramref name="value"/>. | |
| /// </summary> | |
| /// <param name="value">The value to be stored in the returned <c>PrimitiveValue</c>.</param> | |
| /// <returns>A <c>PrimitiveValue</c> set to <paramref name="value"/></returns> | |
| public static PrimitiveValue FromInt16(short value) | |
| { | |
| return new PrimitiveValue(value); | |
| } | |
| /// <summary> | |
| /// Constructs a <c>PrimitiveValue</c> from <paramref name="value"/>. | |
| /// </summary> | |
| /// <param name="value">The value to be stored in the returned <c>PrimitiveValue</c>.</param> | |
| /// <returns>A <c>PrimitiveValue</c> set to <paramref name="value"/></returns> | |
| public static PrimitiveValue FromUInt16(ushort value) | |
| { | |
| return new PrimitiveValue(value); | |
| } | |
| /// <summary> | |
| /// Constructs a <c>PrimitiveValue</c> from <paramref name="value"/>. | |
| /// </summary> | |
| /// <param name="value">The value to be stored in the returned <c>PrimitiveValue</c>.</param> | |
| /// <returns>A <c>PrimitiveValue</c> set to <paramref name="value"/></returns> | |
| public static PrimitiveValue FromInt32(int value) | |
| { | |
| return new PrimitiveValue(value); | |
| } | |
| /// <summary> | |
| /// Constructs a <c>PrimitiveValue</c> from <paramref name="value"/>. | |
| /// </summary> | |
| /// <param name="value">The value to be stored in the returned <c>PrimitiveValue</c>.</param> | |
| /// <returns>A <c>PrimitiveValue</c> set to <paramref name="value"/></returns> | |
| public static PrimitiveValue FromUInt32(uint value) | |
| { | |
| return new PrimitiveValue(value); | |
| } | |
| /// <summary> | |
| /// Constructs a <c>PrimitiveValue</c> from <paramref name="value"/>. | |
| /// </summary> | |
| /// <param name="value">The value to be stored in the returned <c>PrimitiveValue</c>.</param> | |
| /// <returns>A <c>PrimitiveValue</c> set to <paramref name="value"/></returns> | |
| public static PrimitiveValue FromInt64(long value) | |
| { | |
| return new PrimitiveValue(value); | |
| } | |
| /// <summary> | |
| /// Constructs a <c>PrimitiveValue</c> from <paramref name="value"/>. | |
| /// </summary> | |
| /// <param name="value">The value to be stored in the returned <c>PrimitiveValue</c>.</param> | |
| /// <returns>A <c>PrimitiveValue</c> set to <paramref name="value"/></returns> | |
| public static PrimitiveValue FromUInt64(ulong value) | |
| { | |
| return new PrimitiveValue(value); | |
| } | |
| /// <summary> | |
| /// Constructs a <c>PrimitiveValue</c> from <paramref name="value"/>. | |
| /// </summary> | |
| /// <param name="value">The value to be stored in the returned <c>PrimitiveValue</c>.</param> | |
| /// <returns>A <c>PrimitiveValue</c> set to <paramref name="value"/></returns> | |
| public static PrimitiveValue FromSingle(float value) | |
| { | |
| return new PrimitiveValue(value); | |
| } | |
| /// <summary> | |
| /// Constructs a <c>PrimitiveValue</c> from <paramref name="value"/>. | |
| /// </summary> | |
| /// <param name="value">The value to be stored in the returned <c>PrimitiveValue</c>.</param> | |
| /// <returns>A <c>PrimitiveValue</c> set to <paramref name="value"/></returns> | |
| public static PrimitiveValue FromDouble(double value) | |
| { | |
| return new PrimitiveValue(value); | |
| } | |
| } | |
| } | |