Beispiel #1
0
        /// <summary>
        /// Convert a Python value to an instance of a primitive managed type.
        /// </summary>
        private static bool ToPrimitive(IntPtr value, Type obType, out object result, bool setError)
        {
            TypeCode tc = Type.GetTypeCode(obType);

            result = null;
            IntPtr op = IntPtr.Zero;

            switch (tc)
            {
            case TypeCode.String:
                string st = Runtime.GetManagedString(value);
                if (st == null)
                {
                    goto type_error;
                }
                result = st;
                return(true);

            case TypeCode.Int32:
            {
                // Python3 always use PyLong API
                nint num = Runtime.PyLong_AsSignedSize_t(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > Int32.MaxValue || num < Int32.MinValue)
                {
                    goto overflow;
                }
                result = (int)num;
                return(true);
            }

            case TypeCode.Boolean:
                result = Runtime.PyObject_IsTrue(value) != 0;
                return(true);

            case TypeCode.Byte:
            {
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        op     = Runtime.PyBytes_AS_STRING(value);
                        result = (byte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }

                nint num = Runtime.PyLong_AsSignedSize_t(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > Byte.MaxValue || num < Byte.MinValue)
                {
                    goto overflow;
                }
                result = (byte)num;
                return(true);
            }

            case TypeCode.SByte:
            {
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        op     = Runtime.PyBytes_AS_STRING(value);
                        result = (byte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }

                nint num = Runtime.PyLong_AsSignedSize_t(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > SByte.MaxValue || num < SByte.MinValue)
                {
                    goto overflow;
                }
                result = (sbyte)num;
                return(true);
            }

            case TypeCode.Char:
            {
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        op     = Runtime.PyBytes_AS_STRING(value);
                        result = (byte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }
                else if (Runtime.PyObject_TypeCheck(value, Runtime.PyUnicodeType))
                {
                    if (Runtime.PyUnicode_GetSize(value) == 1)
                    {
                        op = Runtime.PyUnicode_AsUnicode(value);
                        Char[] buff = new Char[1];
                        Marshal.Copy(op, buff, 0, 1);
                        result = buff[0];
                        return(true);
                    }
                    goto type_error;
                }
                nint num = Runtime.PyLong_AsSignedSize_t(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > Char.MaxValue || num < Char.MinValue)
                {
                    goto overflow;
                }
                result = (char)num;
                return(true);
            }

            case TypeCode.Int16:
            {
                nint num = Runtime.PyLong_AsSignedSize_t(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > Int16.MaxValue || num < Int16.MinValue)
                {
                    goto overflow;
                }
                result = (short)num;
                return(true);
            }

            case TypeCode.Int64:
            {
                if (Runtime.Is32Bit)
                {
                    if (!Runtime.PyLong_Check(value))
                    {
                        goto type_error;
                    }
                    long num = Runtime.PyExplicitlyConvertToInt64(value);
                    if (num == -1 && Exceptions.ErrorOccurred())
                    {
                        goto convert_error;
                    }
                    result = num;
                    return(true);
                }
                else
                {
                    nint num = Runtime.PyLong_AsSignedSize_t(value);
                    if (num == -1 && Exceptions.ErrorOccurred())
                    {
                        goto convert_error;
                    }
                    result = (long)num;
                    return(true);
                }
            }

            case TypeCode.UInt16:
            {
                nint num = Runtime.PyLong_AsSignedSize_t(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > UInt16.MaxValue || num < UInt16.MinValue)
                {
                    goto overflow;
                }
                result = (ushort)num;
                return(true);
            }

            case TypeCode.UInt32:
            {
                nuint num = Runtime.PyLong_AsUnsignedSize_t(value);
                if (num == unchecked ((nuint)(-1)) && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > UInt32.MaxValue)
                {
                    goto overflow;
                }
                result = (uint)num;
                return(true);
            }

            case TypeCode.UInt64:
            {
                ulong num = Runtime.PyLong_AsUnsignedLongLong(value);
                if (num == ulong.MaxValue && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                result = num;
                return(true);
            }

            case TypeCode.Single:
            {
                double num = Runtime.PyFloat_AsDouble(value);
                if (num == -1.0 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > Single.MaxValue || num < Single.MinValue)
                {
                    if (!double.IsInfinity(num))
                    {
                        goto overflow;
                    }
                }
                result = (float)num;
                return(true);
            }

            case TypeCode.Double:
            {
                double num = Runtime.PyFloat_AsDouble(value);
                if (num == -1.0 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                result = num;
                return(true);
            }

            default:
                goto type_error;
            }

convert_error:
            if (op != value)
            {
                Runtime.XDecref(op);
            }
            if (!setError)
            {
                Exceptions.Clear();
            }
            return(false);

type_error:
            if (setError)
            {
                string tpName = Runtime.PyObject_GetTypeName(value);
                Exceptions.SetError(Exceptions.TypeError, $"'{tpName}' value cannot be converted to {obType}");
            }
            return(false);

overflow:
            // C# level overflow error
            if (op != value)
            {
                Runtime.XDecref(op);
            }
            if (setError)
            {
                Exceptions.SetError(Exceptions.OverflowError, "value too large to convert");
            }
            return(false);
        }
Beispiel #2
0
        /// <summary>
        /// Convert a Python value to an instance of a primitive managed type.
        /// </summary>
        private static bool ToPrimitive(IntPtr value, Type obType, out object result, bool setError)
        {
            IntPtr   overflow = Exceptions.OverflowError;
            TypeCode tc       = Type.GetTypeCode(obType);

            result = null;
            IntPtr op;
            int    ival;

            switch (tc)
            {
            case TypeCode.String:
                string st = Runtime.GetManagedString(value);
                if (st == null)
                {
                    goto type_error;
                }
                result = st;
                return(true);

            case TypeCode.Int32:
                // Python3 always use PyLong API
                op = Runtime.PyNumber_Long(value);
                if (op == IntPtr.Zero)
                {
                    Exceptions.Clear();
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                long ll = (long)Runtime.PyLong_AsLongLong(op);
                Runtime.XDecref(op);
                if (ll == -1 && Exceptions.ErrorOccurred())
                {
                    goto overflow;
                }
                if (ll > Int32.MaxValue || ll < Int32.MinValue)
                {
                    goto overflow;
                }
                result = (int)ll;
                return(true);

            case TypeCode.Boolean:
                result = Runtime.PyObject_IsTrue(value) != 0;
                return(true);

            case TypeCode.Byte:
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        op     = Runtime.PyBytes_AS_STRING(value);
                        result = (byte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }

                op = Runtime.PyNumber_Int(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                ival = (int)Runtime.PyInt_AsLong(op);
                Runtime.XDecref(op);

                if (ival > Byte.MaxValue || ival < Byte.MinValue)
                {
                    goto overflow;
                }
                byte b = (byte)ival;
                result = b;
                return(true);

            case TypeCode.SByte:
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        op     = Runtime.PyBytes_AS_STRING(value);
                        result = (byte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }

                op = Runtime.PyNumber_Int(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                ival = (int)Runtime.PyInt_AsLong(op);
                Runtime.XDecref(op);

                if (ival > SByte.MaxValue || ival < SByte.MinValue)
                {
                    goto overflow;
                }
                sbyte sb = (sbyte)ival;
                result = sb;
                return(true);

            case TypeCode.Char:
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        op     = Runtime.PyBytes_AS_STRING(value);
                        result = (byte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }
                else if (Runtime.PyObject_TypeCheck(value, Runtime.PyUnicodeType))
                {
                    if (Runtime.PyUnicode_GetSize(value) == 1)
                    {
                        op = Runtime.PyUnicode_AsUnicode(value);
                        Char[] buff = new Char[1];
                        Marshal.Copy(op, buff, 0, 1);
                        result = buff[0];
                        return(true);
                    }
                    goto type_error;
                }

                op = Runtime.PyNumber_Int(value);
                if (op == IntPtr.Zero)
                {
                    goto type_error;
                }
                ival = Runtime.PyInt_AsLong(op);
                Runtime.XDecref(op);
                if (ival > Char.MaxValue || ival < Char.MinValue)
                {
                    goto overflow;
                }
                result = (char)ival;
                return(true);

            case TypeCode.Int16:
                op = Runtime.PyNumber_Int(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                ival = (int)Runtime.PyInt_AsLong(op);
                Runtime.XDecref(op);
                if (ival > Int16.MaxValue || ival < Int16.MinValue)
                {
                    goto overflow;
                }
                short s = (short)ival;
                result = s;
                return(true);

            case TypeCode.Int64:
                op = Runtime.PyNumber_Long(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                long l = (long)Runtime.PyLong_AsLongLong(op);
                Runtime.XDecref(op);
                if ((l == -1) && Exceptions.ErrorOccurred())
                {
                    goto overflow;
                }
                result = l;
                return(true);

            case TypeCode.UInt16:
                op = Runtime.PyNumber_Int(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                ival = (int)Runtime.PyInt_AsLong(op);
                Runtime.XDecref(op);
                if (ival > UInt16.MaxValue || ival < UInt16.MinValue)
                {
                    goto overflow;
                }
                ushort us = (ushort)ival;
                result = us;
                return(true);

            case TypeCode.UInt32:
                op = Runtime.PyNumber_Long(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }

                uint ui;
                try
                {
                    ui = Convert.ToUInt32(Runtime.PyLong_AsUnsignedLong(op));
                } catch (OverflowException)
                {
                    // Probably wasn't an overflow in python but was in C# (e.g. if cpython
                    // longs are 64 bit then 0xFFFFFFFF + 1 will not overflow in
                    // PyLong_AsUnsignedLong)
                    Runtime.XDecref(op);
                    goto overflow;
                }


                if (Exceptions.ErrorOccurred())
                {
                    Runtime.XDecref(op);
                    goto overflow;
                }

                IntPtr check = Runtime.PyLong_FromUnsignedLong(ui);
                int    err   = Runtime.PyObject_Compare(check, op);
                Runtime.XDecref(check);
                Runtime.XDecref(op);
                if (0 != err || Exceptions.ErrorOccurred())
                {
                    goto overflow;
                }

                result = ui;
                return(true);

            case TypeCode.UInt64:
                op = Runtime.PyNumber_Long(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                ulong ul = (ulong)Runtime.PyLong_AsUnsignedLongLong(op);
                Runtime.XDecref(op);
                if (Exceptions.ErrorOccurred())
                {
                    goto overflow;
                }
                result = ul;
                return(true);


            case TypeCode.Single:
                op = Runtime.PyNumber_Float(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                double dd = Runtime.PyFloat_AsDouble(op);
                Runtime.CheckExceptionOccurred();
                Runtime.XDecref(op);
                if (dd > Single.MaxValue || dd < Single.MinValue)
                {
                    if (!double.IsInfinity(dd))
                    {
                        goto overflow;
                    }
                }
                result = (float)dd;
                return(true);

            case TypeCode.Double:
                op = Runtime.PyNumber_Float(value);
                if (op == IntPtr.Zero)
                {
                    goto type_error;
                }
                double d = Runtime.PyFloat_AsDouble(op);
                Runtime.CheckExceptionOccurred();
                Runtime.XDecref(op);
                result = d;
                return(true);
            }


type_error:

            if (setError)
            {
                string tpName = Runtime.PyObject_GetTypeName(value);
                Exceptions.SetError(Exceptions.TypeError, $"'{tpName}' value cannot be converted to {obType}");
            }

            return(false);

overflow:

            if (setError)
            {
                Exceptions.SetError(Exceptions.OverflowError, "value too large to convert");
            }

            return(false);
        }
Beispiel #3
0
        /// <summary>
        /// Convert a Python value to an instance of a primitive managed type.
        /// </summary>
        private static bool ToPrimitive(IntPtr value, Type obType, out object result, bool setError)
        {
            TypeCode tc = Type.GetTypeCode(obType);

            result = null;
            IntPtr op = IntPtr.Zero;

            switch (tc)
            {
            case TypeCode.String:
                string st = Runtime.GetManagedString(value);
                if (st == null)
                {
                    goto type_error;
                }
                result = st;
                return(true);

            case TypeCode.Int32:
            {
                // Python3 always use PyLong API
                long num = Runtime.PyLong_AsLongLong(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > Int32.MaxValue || num < Int32.MinValue)
                {
                    goto overflow;
                }
                result = (int)num;
                return(true);
            }

            case TypeCode.Boolean:
                result = Runtime.PyObject_IsTrue(value) != 0;
                return(true);

            case TypeCode.Byte:
            {
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        op     = Runtime.PyBytes_AS_STRING(value);
                        result = (byte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }

                int num = Runtime.PyLong_AsLong(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > Byte.MaxValue || num < Byte.MinValue)
                {
                    goto overflow;
                }
                result = (byte)num;
                return(true);
            }

            case TypeCode.SByte:
            {
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        op     = Runtime.PyBytes_AS_STRING(value);
                        result = (byte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }

                int num = Runtime.PyLong_AsLong(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > SByte.MaxValue || num < SByte.MinValue)
                {
                    goto overflow;
                }
                result = (sbyte)num;
                return(true);
            }

            case TypeCode.Char:
            {
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        op     = Runtime.PyBytes_AS_STRING(value);
                        result = (byte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }
                else if (Runtime.PyObject_TypeCheck(value, Runtime.PyUnicodeType))
                {
                    if (Runtime.PyUnicode_GetSize(value) == 1)
                    {
                        op = Runtime.PyUnicode_AsUnicode(value);
                        Char[] buff = new Char[1];
                        Marshal.Copy(op, buff, 0, 1);
                        result = buff[0];
                        return(true);
                    }
                    goto type_error;
                }
                int num = Runtime.PyLong_AsLong(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > Char.MaxValue || num < Char.MinValue)
                {
                    goto overflow;
                }
                result = (char)num;
                return(true);
            }

            case TypeCode.Int16:
            {
                int num = Runtime.PyLong_AsLong(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > Int16.MaxValue || num < Int16.MinValue)
                {
                    goto overflow;
                }
                result = (short)num;
                return(true);
            }

            case TypeCode.Int64:
            {
                long num = (long)Runtime.PyLong_AsLongLong(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                result = num;
                return(true);
            }

            case TypeCode.UInt16:
            {
                long num = Runtime.PyLong_AsLong(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > UInt16.MaxValue || num < UInt16.MinValue)
                {
                    goto overflow;
                }
                result = (ushort)num;
                return(true);
            }

            case TypeCode.UInt32:
            {
                op = value;
                if (Runtime.PyObject_TYPE(value) != Runtime.PyLongType)
                {
                    op = Runtime.PyNumber_Long(value);
                    if (op == IntPtr.Zero)
                    {
                        goto convert_error;
                    }
                }
                if (Runtime.Is32Bit || Runtime.IsWindows)
                {
                    uint num = Runtime.PyLong_AsUnsignedLong32(op);
                    if (num == uint.MaxValue && Exceptions.ErrorOccurred())
                    {
                        goto convert_error;
                    }
                    result = num;
                }
                else
                {
                    ulong num = Runtime.PyLong_AsUnsignedLong64(op);
                    if (num == ulong.MaxValue && Exceptions.ErrorOccurred())
                    {
                        goto convert_error;
                    }
                    try
                    {
                        result = Convert.ToUInt32(num);
                    }
                    catch (OverflowException)
                    {
                        // Probably wasn't an overflow in python but was in C# (e.g. if cpython
                        // longs are 64 bit then 0xFFFFFFFF + 1 will not overflow in
                        // PyLong_AsUnsignedLong)
                        goto overflow;
                    }
                }
                return(true);
            }

            case TypeCode.UInt64:
            {
                op = value;
                if (Runtime.PyObject_TYPE(value) != Runtime.PyLongType)
                {
                    op = Runtime.PyNumber_Long(value);
                    if (op == IntPtr.Zero)
                    {
                        goto convert_error;
                    }
                }
                ulong num = Runtime.PyLong_AsUnsignedLongLong(op);
                if (num == ulong.MaxValue && Exceptions.ErrorOccurred())
                {
                    goto overflow;
                }
                result = num;
                return(true);
            }

            case TypeCode.Single:
            {
                double num = Runtime.PyFloat_AsDouble(value);
                if (num == -1.0 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > Single.MaxValue || num < Single.MinValue)
                {
                    if (!double.IsInfinity(num))
                    {
                        goto overflow;
                    }
                }
                result = (float)num;
                return(true);
            }

            case TypeCode.Double:
            {
                double num = Runtime.PyFloat_AsDouble(value);
                if (num == -1.0 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                result = num;
                return(true);
            }

            default:
                goto type_error;
            }

convert_error:
            if (op != value)
            {
                Runtime.XDecref(op);
            }
            if (!setError)
            {
                Exceptions.Clear();
            }
            return(false);

type_error:
            if (setError)
            {
                string tpName = Runtime.PyObject_GetTypeName(value);
                Exceptions.SetError(Exceptions.TypeError, $"'{tpName}' value cannot be converted to {obType}");
            }
            return(false);

overflow:
            // C# level overflow error
            if (op != value)
            {
                Runtime.XDecref(op);
            }
            if (setError)
            {
                Exceptions.SetError(Exceptions.OverflowError, "value too large to convert");
            }
            return(false);
        }
Beispiel #4
0
        /// <summary>
        /// Convert a Python value to an instance of a primitive managed type.
        /// </summary>
        private static bool ToPrimitive(IntPtr value, Type obType, out object result, bool setError)
        {
            IntPtr   overflow = Exceptions.OverflowError;
            TypeCode tc       = Type.GetTypeCode(obType);

            result = null;
            IntPtr op;
            int    ival;

            switch (tc)
            {
            case TypeCode.String:
                string st = Runtime.GetManagedString(value);
                if (st == null)
                {
                    goto type_error;
                }
                result = st;
                return(true);

            case TypeCode.Int32:
                // Trickery to support 64-bit platforms.
                if (Runtime.IsPython2 && Runtime.Is32Bit)
                {
                    op = Runtime.PyNumber_Int(value);

                    // As of Python 2.3, large ints magically convert :(
                    if (Runtime.PyLong_Check(op))
                    {
                        Runtime.XDecref(op);
                        goto overflow;
                    }

                    if (op == IntPtr.Zero)
                    {
                        if (Exceptions.ExceptionMatches(overflow))
                        {
                            goto overflow;
                        }
                        goto type_error;
                    }
                    ival = (int)Runtime.PyInt_AsLong(op);
                    Runtime.XDecref(op);
                    result = ival;
                    return(true);
                }
                else     // Python3 always use PyLong API
                {
                    op = Runtime.PyNumber_Long(value);
                    if (op == IntPtr.Zero)
                    {
                        Exceptions.Clear();
                        if (Exceptions.ExceptionMatches(overflow))
                        {
                            goto overflow;
                        }
                        goto type_error;
                    }
                    long ll = (long)Runtime.PyLong_AsLongLong(op);
                    Runtime.XDecref(op);
                    if (ll == -1 && Exceptions.ErrorOccurred())
                    {
                        goto overflow;
                    }
                    if (ll > Int32.MaxValue || ll < Int32.MinValue)
                    {
                        goto overflow;
                    }
                    result = (int)ll;
                    return(true);
                }

            case TypeCode.Boolean:
                result = Runtime.PyObject_IsTrue(value) != 0;
                return(true);

            case TypeCode.Byte:
#if PYTHON3
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        op     = Runtime.PyBytes_AS_STRING(value);
                        result = (byte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }
#elif PYTHON2
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyStringType))
                {
                    if (Runtime.PyString_Size(value) == 1)
                    {
                        op     = Runtime.PyString_AsString(value);
                        result = (byte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }
#endif

                op = Runtime.PyNumber_Int(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                ival = (int)Runtime.PyInt_AsLong(op);
                Runtime.XDecref(op);

                if (ival > Byte.MaxValue || ival < Byte.MinValue)
                {
                    goto overflow;
                }
                byte b = (byte)ival;
                result = b;
                return(true);

            case TypeCode.SByte:
#if PYTHON3
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        op     = Runtime.PyBytes_AS_STRING(value);
                        result = (byte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }
#elif PYTHON2
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyStringType))
                {
                    if (Runtime.PyString_Size(value) == 1)
                    {
                        op     = Runtime.PyString_AsString(value);
                        result = (sbyte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }
#endif

                op = Runtime.PyNumber_Int(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                ival = (int)Runtime.PyInt_AsLong(op);
                Runtime.XDecref(op);

                if (ival > SByte.MaxValue || ival < SByte.MinValue)
                {
                    goto overflow;
                }
                sbyte sb = (sbyte)ival;
                result = sb;
                return(true);

            case TypeCode.Char:
#if PYTHON3
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        op     = Runtime.PyBytes_AS_STRING(value);
                        result = (byte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }
#elif PYTHON2
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyStringType))
                {
                    if (Runtime.PyString_Size(value) == 1)
                    {
                        op     = Runtime.PyString_AsString(value);
                        result = (char)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }
#endif
                else if (Runtime.PyObject_TypeCheck(value, Runtime.PyUnicodeType))
                {
                    if (Runtime.PyUnicode_GetSize(value) == 1)
                    {
                        op = Runtime.PyUnicode_AsUnicode(value);
                        Char[] buff = new Char[1];
                        Marshal.Copy(op, buff, 0, 1);
                        result = buff[0];
                        return(true);
                    }
                    goto type_error;
                }

                op = Runtime.PyNumber_Int(value);
                if (op == IntPtr.Zero)
                {
                    goto type_error;
                }
                ival = Runtime.PyInt_AsLong(op);
                Runtime.XDecref(op);
                if (ival > Char.MaxValue || ival < Char.MinValue)
                {
                    goto overflow;
                }
                result = (char)ival;
                return(true);

            case TypeCode.Int16:
                op = Runtime.PyNumber_Int(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                ival = (int)Runtime.PyInt_AsLong(op);
                Runtime.XDecref(op);
                if (ival > Int16.MaxValue || ival < Int16.MinValue)
                {
                    goto overflow;
                }
                short s = (short)ival;
                result = s;
                return(true);

            case TypeCode.Int64:
                op = Runtime.PyNumber_Long(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                long l = (long)Runtime.PyLong_AsLongLong(op);
                Runtime.XDecref(op);
                if ((l == -1) && Exceptions.ErrorOccurred())
                {
                    goto overflow;
                }
                result = l;
                return(true);

            case TypeCode.UInt16:
                op = Runtime.PyNumber_Int(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                ival = (int)Runtime.PyInt_AsLong(op);
                Runtime.XDecref(op);
                if (ival > UInt16.MaxValue || ival < UInt16.MinValue)
                {
                    goto overflow;
                }
                ushort us = (ushort)ival;
                result = us;
                return(true);

            case TypeCode.UInt32:
                op = Runtime.PyNumber_Long(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                uint ui = (uint)Runtime.PyLong_AsUnsignedLong(op);

                if (Exceptions.ErrorOccurred())
                {
                    Runtime.XDecref(op);
                    goto overflow;
                }

                IntPtr check = Runtime.PyLong_FromUnsignedLong(ui);
                int    err   = Runtime.PyObject_Compare(check, op);
                Runtime.XDecref(check);
                Runtime.XDecref(op);
                if (0 != err || Exceptions.ErrorOccurred())
                {
                    goto overflow;
                }

                result = ui;
                return(true);

            case TypeCode.UInt64:
                op = Runtime.PyNumber_Long(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                ulong ul = (ulong)Runtime.PyLong_AsUnsignedLongLong(op);
                Runtime.XDecref(op);
                if (Exceptions.ErrorOccurred())
                {
                    goto overflow;
                }
                result = ul;
                return(true);


            case TypeCode.Single:
                op = Runtime.PyNumber_Float(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                double dd = Runtime.PyFloat_AsDouble(op);
                Runtime.XDecref(op);
                if (dd > Single.MaxValue || dd < Single.MinValue)
                {
                    goto overflow;
                }
                result = (float)dd;
                return(true);

            case TypeCode.Double:
                op = Runtime.PyNumber_Float(value);
                if (op == IntPtr.Zero)
                {
                    goto type_error;
                }
                double d = Runtime.PyFloat_AsDouble(op);
                Runtime.XDecref(op);
                if (d > Double.MaxValue || d < Double.MinValue)
                {
                    goto overflow;
                }
                result = d;
                return(true);
            }


type_error:

            if (setError)
            {
                string tpName = Runtime.PyObject_GetTypeName(value);
                Exceptions.SetError(Exceptions.TypeError, $"'{tpName}' value cannot be converted to {obType}");
            }

            return(false);

overflow:

            if (setError)
            {
                Exceptions.SetError(Exceptions.OverflowError, "value too large to convert");
            }

            return(false);
        }
Beispiel #5
0
        //====================================================================
        // Convert a Python value to an instance of a primitive managed type.
        //====================================================================

        static bool ToPrimitive(IntPtr value, Type obType, out Object result,
                                bool setError)
        {
            IntPtr   overflow = Exceptions.OverflowError;
            TypeCode tc       = Type.GetTypeCode(obType);

            result = null;
            IntPtr op;
            int    ival;

            switch (tc)
            {
            case TypeCode.String:
                string st = Runtime.GetManagedString(value);
                if (st == null)
                {
                    goto type_error;
                }
                result = st;
                return(true);

            case TypeCode.Int32:
#if !(PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35)
                // Trickery to support 64-bit platforms.
                if (IntPtr.Size == 4)
                {
                    op = Runtime.PyNumber_Int(value);

                    // As of Python 2.3, large ints magically convert :(
                    if (Runtime.PyLong_Check(op))
                    {
                        Runtime.Decref(op);
                        goto overflow;
                    }

                    if (op == IntPtr.Zero)
                    {
                        if (Exceptions.ExceptionMatches(overflow))
                        {
                            goto overflow;
                        }
                        goto type_error;
                    }
                    ival = (int)Runtime.PyInt_AsLong(op);
                    Runtime.Decref(op);
                    result = ival;
                    return(true);
                }
                else
                {
#else
                // When using Python3 always use the PyLong API
                {
#endif
                    op = Runtime.PyNumber_Long(value);
                    if (op == IntPtr.Zero)
                    {
                        Exceptions.Clear();
                        if (Exceptions.ExceptionMatches(overflow))
                        {
                            goto overflow;
                        }
                        goto type_error;
                    }
                    long ll = (long)Runtime.PyLong_AsLongLong(op);
                    Runtime.Decref(op);
                    if ((ll == -1) && Exceptions.ErrorOccurred())
                    {
                        goto overflow;
                    }
                    if (ll > Int32.MaxValue || ll < Int32.MinValue)
                    {
                        goto overflow;
                    }
                    result = (int)ll;
                    return(true);
                }

            case TypeCode.Boolean:
                result = (Runtime.PyObject_IsTrue(value) != 0);
                return(true);

            case TypeCode.Byte:
#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35)
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        op     = Runtime.PyBytes_AS_STRING(value);
                        result = (byte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }
#else
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyStringType))
                {
                    if (Runtime.PyString_Size(value) == 1)
                    {
                        op     = Runtime.PyString_AS_STRING(value);
                        result = (byte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }
#endif

                op = Runtime.PyNumber_Int(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                ival = (int)Runtime.PyInt_AsLong(op);
                Runtime.Decref(op);

                if (ival > Byte.MaxValue || ival < Byte.MinValue)
                {
                    goto overflow;
                }
                byte b = (byte)ival;
                result = b;
                return(true);

            case TypeCode.SByte:
#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35)
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        op     = Runtime.PyBytes_AS_STRING(value);
                        result = (byte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }
#else
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyStringType))
                {
                    if (Runtime.PyString_Size(value) == 1)
                    {
                        op     = Runtime.PyString_AS_STRING(value);
                        result = (sbyte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }
#endif

                op = Runtime.PyNumber_Int(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                ival = (int)Runtime.PyInt_AsLong(op);
                Runtime.Decref(op);

                if (ival > SByte.MaxValue || ival < SByte.MinValue)
                {
                    goto overflow;
                }
                sbyte sb = (sbyte)ival;
                result = sb;
                return(true);

            case TypeCode.Char:
#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35)
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        op     = Runtime.PyBytes_AS_STRING(value);
                        result = (byte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }
#else
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyStringType))
                {
                    if (Runtime.PyString_Size(value) == 1)
                    {
                        op     = Runtime.PyString_AS_STRING(value);
                        result = (char)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }
#endif
                else if (Runtime.PyObject_TypeCheck(value,
                                                    Runtime.PyUnicodeType))
                {
                    if (Runtime.PyUnicode_GetSize(value) == 1)
                    {
                        op = Runtime.PyUnicode_AS_UNICODE(value);
#if (!UCS4)
                        // 2011-01-02: Marshal as character array because the cast
                        // result = (char)Marshal.ReadInt16(op); throws an OverflowException
                        // on negative numbers with Check Overflow option set on the project
                        Char[] buff = new Char[1];
                        Marshal.Copy(op, buff, 0, 1);
                        result = buff[0];
#else
                        // XXX this is probably NOT correct?
                        result = (char)Marshal.ReadInt32(op);
#endif
                        return(true);
                    }
                    goto type_error;
                }

                op = Runtime.PyNumber_Int(value);
                if (op == IntPtr.Zero)
                {
                    goto type_error;
                }
                ival = Runtime.PyInt_AsLong(op);
                Runtime.Decref(op);
                if (ival > Char.MaxValue || ival < Char.MinValue)
                {
                    goto overflow;
                }
                result = (char)ival;
                return(true);

            case TypeCode.Int16:
                op = Runtime.PyNumber_Int(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                ival = (int)Runtime.PyInt_AsLong(op);
                Runtime.Decref(op);
                if (ival > Int16.MaxValue || ival < Int16.MinValue)
                {
                    goto overflow;
                }
                short s = (short)ival;
                result = s;
                return(true);

            case TypeCode.Int64:
                op = Runtime.PyNumber_Long(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                long l = (long)Runtime.PyLong_AsLongLong(op);
                Runtime.Decref(op);
                if ((l == -1) && Exceptions.ErrorOccurred())
                {
                    goto overflow;
                }
                result = l;
                return(true);

            case TypeCode.UInt16:
                op = Runtime.PyNumber_Int(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                ival = (int)Runtime.PyInt_AsLong(op);
                Runtime.Decref(op);
                if (ival > UInt16.MaxValue || ival < UInt16.MinValue)
                {
                    goto overflow;
                }
                ushort us = (ushort)ival;
                result = us;
                return(true);

            case TypeCode.UInt32:
                op = Runtime.PyNumber_Long(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                uint ui = (uint)Runtime.PyLong_AsUnsignedLong(op);

                if (Exceptions.ErrorOccurred())
                {
                    Runtime.Decref(op);
                    goto overflow;
                }

                IntPtr check = Runtime.PyLong_FromUnsignedLong(ui);
                int err      = Runtime.PyObject_Compare(check, op);
                Runtime.Decref(check);
                Runtime.Decref(op);
                if (0 != err || Exceptions.ErrorOccurred())
                {
                    goto overflow;
                }

                result = ui;
                return(true);

            case TypeCode.UInt64:
                op = Runtime.PyNumber_Long(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                ulong ul = (ulong)Runtime.PyLong_AsUnsignedLongLong(op);
                Runtime.Decref(op);
                if (Exceptions.ErrorOccurred())
                {
                    goto overflow;
                }
                result = ul;
                return(true);


            case TypeCode.Single:
                op = Runtime.PyNumber_Float(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                double dd = Runtime.PyFloat_AsDouble(op);
                Runtime.Decref(op);
                if (dd > Single.MaxValue || dd < Single.MinValue)
                {
                    goto overflow;
                }
                result = (float)dd;
                return(true);

            case TypeCode.Double:
                op = Runtime.PyNumber_Float(value);
                if (op == IntPtr.Zero)
                {
                    goto type_error;
                }
                double d = Runtime.PyFloat_AsDouble(op);
                Runtime.Decref(op);
                if (d > Double.MaxValue || d < Double.MinValue)
                {
                    goto overflow;
                }
                result = d;
                return(true);
            }


type_error:

            if (setError)
            {
                string format = "'{0}' value cannot be converted to {1}";
                string tpName = Runtime.PyObject_GetTypeName(value);
                string error  = String.Format(format, tpName, obType);
                Exceptions.SetError(Exceptions.TypeError, error);
            }

            return(false);

overflow:

            if (setError)
            {
                string error = "value too large to convert";
                Exceptions.SetError(Exceptions.OverflowError, error);
            }

            return(false);
        }
Beispiel #6
0
        /// <summary>
        /// Convert a Python value to an instance of a primitive managed type.
        /// </summary>
        private static bool ToPrimitive(IntPtr value, Type obType, out object result, bool setError)
        {
            TypeCode tc = Type.GetTypeCode(obType);

            result = null;
            IntPtr op = IntPtr.Zero;

            switch (tc)
            {
            case TypeCode.Object:
                if (obType == typeof(TimeSpan))
                {
                    op = Runtime.PyObject_Str(value);
                    TimeSpan ts;
                    var      arr = Runtime.GetManagedString(op).Split(',');
                    string   sts = arr.Length == 1 ? arr[0] : arr[1];
                    if (!TimeSpan.TryParse(sts, out ts))
                    {
                        goto type_error;
                    }
                    Runtime.XDecref(op);

                    int days = 0;
                    if (arr.Length > 1)
                    {
                        if (!int.TryParse(arr[0].Split(' ')[0].Trim(), out days))
                        {
                            goto type_error;
                        }
                    }
                    result = ts.Add(TimeSpan.FromDays(days));
                    return(true);
                }
                break;

            case TypeCode.String:
                string st = Runtime.GetManagedString(value);
                if (st == null)
                {
                    goto type_error;
                }
                result = st;
                return(true);

            case TypeCode.Int32:
            {
                // Python3 always use PyLong API
                op = Runtime.PyNumber_Long(value);
                if (op == IntPtr.Zero && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                nint num = Runtime.PyLong_AsSignedSize_t(op);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > Int32.MaxValue || num < Int32.MinValue)
                {
                    goto overflow;
                }
                result = (int)num;
                return(true);
            }

            case TypeCode.Boolean:
                result = Runtime.PyObject_IsTrue(value) != 0;
                return(true);

            case TypeCode.Byte:
            {
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        op     = Runtime.PyBytes_AS_STRING(value);
                        result = (byte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }

                nint num = Runtime.PyLong_AsSignedSize_t(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > Byte.MaxValue || num < Byte.MinValue)
                {
                    goto overflow;
                }
                result = (byte)num;
                return(true);
            }

            case TypeCode.SByte:
            {
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        op     = Runtime.PyBytes_AS_STRING(value);
                        result = (byte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }

                nint num = Runtime.PyLong_AsSignedSize_t(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > SByte.MaxValue || num < SByte.MinValue)
                {
                    goto overflow;
                }
                result = (sbyte)num;
                return(true);
            }

            case TypeCode.Char:
            {
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        op     = Runtime.PyBytes_AS_STRING(value);
                        result = (byte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }
                else if (Runtime.PyObject_TypeCheck(value, Runtime.PyUnicodeType))
                {
                    if (Runtime.PyUnicode_GetSize(value) == 1)
                    {
                        op = Runtime.PyUnicode_AsUnicode(value);
                        Char[] buff = new Char[1];
                        Marshal.Copy(op, buff, 0, 1);
                        result = buff[0];
                        return(true);
                    }
                    goto type_error;
                }
                nint num = Runtime.PyLong_AsSignedSize_t(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > Char.MaxValue || num < Char.MinValue)
                {
                    goto overflow;
                }
                result = (char)num;
                return(true);
            }

            case TypeCode.Int16:
            {
                op = Runtime.PyNumber_Long(value);
                if (op == IntPtr.Zero && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                nint num = Runtime.PyLong_AsSignedSize_t(op);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > Int16.MaxValue || num < Int16.MinValue)
                {
                    goto overflow;
                }
                result = (short)num;
                return(true);
            }

            case TypeCode.Int64:
            {
                if (Runtime.Is32Bit)
                {
                    if (!Runtime.PyLong_Check(value))
                    {
                        goto type_error;
                    }
                    long num = Runtime.PyExplicitlyConvertToInt64(value);
                    if (num == -1 && Exceptions.ErrorOccurred())
                    {
                        goto convert_error;
                    }
                    result = num;
                    return(true);
                }
                else
                {
                    op = Runtime.PyNumber_Long(value);
                    if (op == IntPtr.Zero && Exceptions.ErrorOccurred())
                    {
                        goto convert_error;
                    }
                    nint num = Runtime.PyLong_AsSignedSize_t(op);
                    if (num == -1 && Exceptions.ErrorOccurred())
                    {
                        goto convert_error;
                    }
                    result = (long)num;
                    return(true);
                }
            }

            case TypeCode.UInt16:
            {
                op = Runtime.PyNumber_Long(value);
                if (op == IntPtr.Zero && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                nint num = Runtime.PyLong_AsSignedSize_t(op);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > UInt16.MaxValue || num < UInt16.MinValue)
                {
                    goto overflow;
                }
                result = (ushort)num;
                return(true);
            }

            case TypeCode.UInt32:
            {
                op = Runtime.PyNumber_Long(value);
                if (op == IntPtr.Zero && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                nuint num = Runtime.PyLong_AsUnsignedSize_t(op);
                if (num == unchecked ((nuint)(-1)) && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > UInt32.MaxValue)
                {
                    goto overflow;
                }
                result = (uint)num;
                return(true);
            }

            case TypeCode.UInt64:
            {
                op = Runtime.PyNumber_Long(value);
                if (op == IntPtr.Zero && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                ulong num = Runtime.PyLong_AsUnsignedLongLong(op);
                if (num == ulong.MaxValue && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                result = num;
                return(true);
            }

            case TypeCode.Single:
            {
                double num = Runtime.PyFloat_AsDouble(value);
                if (num == -1.0 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > Single.MaxValue || num < Single.MinValue)
                {
                    if (!double.IsInfinity(num))
                    {
                        goto overflow;
                    }
                }
                result = (float)num;
                return(true);
            }

            case TypeCode.Double:
            {
                double num = Runtime.PyFloat_AsDouble(value);
                if (num == -1.0 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                result = num;
                return(true);
            }

            case TypeCode.Decimal:
                op = Runtime.PyObject_Str(value);
                decimal m;
                string  sm = Runtime.GetManagedString(op);
                if (!Decimal.TryParse(sm, NumberStyles.Number | NumberStyles.AllowExponent, nfi, out m))
                {
                    goto type_error;
                }
                Runtime.XDecref(op);
                result = m;
                return(true);

            case TypeCode.DateTime:
                op = Runtime.PyObject_Str(value);
                DateTime dt;
                string   sdt = Runtime.GetManagedString(op);
                if (!DateTime.TryParse(sdt, out dt))
                {
                    goto type_error;
                }
                Runtime.XDecref(op);
                result = sdt.EndsWith("+00:00") ? dt.ToUniversalTime() : dt;
                return(true);

            default:
                goto type_error;
            }

convert_error:
            if (op != value)
            {
                Runtime.XDecref(op);
            }
            if (!setError)
            {
                Exceptions.Clear();
            }
            return(false);

type_error:
            if (setError)
            {
                string tpName = Runtime.PyObject_GetTypeName(value);
                Exceptions.SetError(Exceptions.TypeError, $"'{tpName}' value cannot be converted to {obType}");
            }
            return(false);

overflow:
            // C# level overflow error
            if (op != value)
            {
                Runtime.XDecref(op);
            }
            if (setError)
            {
                Exceptions.SetError(Exceptions.OverflowError, "value too large to convert");
            }
            return(false);
        }
Beispiel #7
0
        /// <summary>
        /// Convert a Python value to an instance of a primitive managed type.
        /// </summary>
        private static bool ToPrimitive(IntPtr value, Type obType, out object result, bool setError)
        {
            IntPtr   overflow = Exceptions.OverflowError;
            TypeCode tc       = Type.GetTypeCode(obType);

            result = null;
            IntPtr op;
            int    ival;

            switch (tc)
            {
            case TypeCode.Object:
                if (obType == typeof(TimeSpan))
                {
                    op = Runtime.PyObject_Str(value);
                    TimeSpan ts;
                    var      arr = Runtime.GetManagedString(op).Split(',');
                    string   sts = arr.Length == 1 ? arr[0] : arr[1];
                    if (!TimeSpan.TryParse(sts, out ts))
                    {
                        goto type_error;
                    }
                    Runtime.XDecref(op);

                    int days = 0;
                    if (arr.Length > 1)
                    {
                        if (!int.TryParse(arr[0].Split(' ')[0].Trim(), out days))
                        {
                            goto type_error;
                        }
                    }
                    result = ts.Add(TimeSpan.FromDays(days));
                    return(true);
                }
                break;

            case TypeCode.String:
                string st = Runtime.GetManagedString(value);
                if (st == null)
                {
                    goto type_error;
                }
                result = st;
                return(true);

            case TypeCode.Int32:
                // Trickery to support 64-bit platforms.
                if (Runtime.IsPython2 && Runtime.Is32Bit)
                {
                    op = Runtime.PyNumber_Int(value);

                    // As of Python 2.3, large ints magically convert :(
                    if (Runtime.PyLong_Check(op))
                    {
                        Runtime.XDecref(op);
                        goto overflow;
                    }

                    if (op == IntPtr.Zero)
                    {
                        if (Exceptions.ExceptionMatches(overflow))
                        {
                            goto overflow;
                        }
                        goto type_error;
                    }
                    ival = (int)Runtime.PyInt_AsLong(op);
                    Runtime.XDecref(op);
                    result = ival;
                    return(true);
                }
                else     // Python3 always use PyLong API
                {
                    op = Runtime.PyNumber_Long(value);
                    if (op == IntPtr.Zero)
                    {
                        Exceptions.Clear();
                        if (Exceptions.ExceptionMatches(overflow))
                        {
                            goto overflow;
                        }
                        goto type_error;
                    }
                    long ll = (long)Runtime.PyLong_AsLongLong(op);
                    Runtime.XDecref(op);
                    if (ll == -1 && Exceptions.ErrorOccurred())
                    {
                        goto overflow;
                    }
                    if (ll > Int32.MaxValue || ll < Int32.MinValue)
                    {
                        goto overflow;
                    }
                    result = (int)ll;
                    return(true);
                }

            case TypeCode.Boolean:
                result = Runtime.PyObject_IsTrue(value) != 0;
                return(true);

            case TypeCode.Byte:
#if PYTHON3
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        op     = Runtime.PyBytes_AS_STRING(value);
                        result = (byte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }
#elif PYTHON2
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyStringType))
                {
                    if (Runtime.PyString_Size(value) == 1)
                    {
                        op     = Runtime.PyString_AsString(value);
                        result = (byte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }
#endif

                op = Runtime.PyNumber_Int(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                ival = (int)Runtime.PyInt_AsLong(op);
                Runtime.XDecref(op);

                if (ival > Byte.MaxValue || ival < Byte.MinValue)
                {
                    goto overflow;
                }
                byte b = (byte)ival;
                result = b;
                return(true);

            case TypeCode.SByte:
#if PYTHON3
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        op     = Runtime.PyBytes_AS_STRING(value);
                        result = (byte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }
#elif PYTHON2
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyStringType))
                {
                    if (Runtime.PyString_Size(value) == 1)
                    {
                        op     = Runtime.PyString_AsString(value);
                        result = (sbyte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }
#endif

                op = Runtime.PyNumber_Int(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                ival = (int)Runtime.PyInt_AsLong(op);
                Runtime.XDecref(op);

                if (ival > SByte.MaxValue || ival < SByte.MinValue)
                {
                    goto overflow;
                }
                sbyte sb = (sbyte)ival;
                result = sb;
                return(true);

            case TypeCode.Char:
#if PYTHON3
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        op     = Runtime.PyBytes_AS_STRING(value);
                        result = (byte)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }
#elif PYTHON2
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyStringType))
                {
                    if (Runtime.PyString_Size(value) == 1)
                    {
                        op     = Runtime.PyString_AsString(value);
                        result = (char)Marshal.ReadByte(op);
                        return(true);
                    }
                    goto type_error;
                }
#endif
                else if (Runtime.PyObject_TypeCheck(value, Runtime.PyUnicodeType))
                {
                    if (Runtime.PyUnicode_GetSize(value) == 1)
                    {
                        op = Runtime.PyUnicode_AsUnicode(value);
                        Char[] buff = new Char[1];
                        Marshal.Copy(op, buff, 0, 1);
                        result = buff[0];
                        return(true);
                    }
                    goto type_error;
                }

                op = Runtime.PyNumber_Int(value);
                if (op == IntPtr.Zero)
                {
                    goto type_error;
                }
                ival = Runtime.PyInt_AsLong(op);
                Runtime.XDecref(op);
                if (ival > Char.MaxValue || ival < Char.MinValue)
                {
                    goto overflow;
                }
                result = (char)ival;
                return(true);

            case TypeCode.Int16:
                op = Runtime.PyNumber_Int(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                ival = (int)Runtime.PyInt_AsLong(op);
                Runtime.XDecref(op);
                if (ival > Int16.MaxValue || ival < Int16.MinValue)
                {
                    goto overflow;
                }
                short s = (short)ival;
                result = s;
                return(true);

            case TypeCode.Int64:
                op = Runtime.PyNumber_Long(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                long l = (long)Runtime.PyLong_AsLongLong(op);
                Runtime.XDecref(op);
                if ((l == -1) && Exceptions.ErrorOccurred())
                {
                    goto overflow;
                }
                result = l;
                return(true);

            case TypeCode.UInt16:
                op = Runtime.PyNumber_Int(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                ival = (int)Runtime.PyInt_AsLong(op);
                Runtime.XDecref(op);
                if (ival > UInt16.MaxValue || ival < UInt16.MinValue)
                {
                    goto overflow;
                }
                ushort us = (ushort)ival;
                result = us;
                return(true);

            case TypeCode.UInt32:
                op = Runtime.PyNumber_Long(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                uint ui = (uint)Runtime.PyLong_AsUnsignedLong(op);

                if (Exceptions.ErrorOccurred())
                {
                    Runtime.XDecref(op);
                    goto overflow;
                }

                IntPtr check = Runtime.PyLong_FromUnsignedLong(ui);
                int    err   = Runtime.PyObject_Compare(check, op);
                Runtime.XDecref(check);
                Runtime.XDecref(op);
                if (0 != err || Exceptions.ErrorOccurred())
                {
                    goto overflow;
                }

                result = ui;
                return(true);

            case TypeCode.UInt64:
                op = Runtime.PyNumber_Long(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                ulong ul = (ulong)Runtime.PyLong_AsUnsignedLongLong(op);
                Runtime.XDecref(op);
                if (Exceptions.ErrorOccurred())
                {
                    goto overflow;
                }
                result = ul;
                return(true);


            case TypeCode.Single:
                op = Runtime.PyNumber_Float(value);
                if (op == IntPtr.Zero)
                {
                    if (Exceptions.ExceptionMatches(overflow))
                    {
                        goto overflow;
                    }
                    goto type_error;
                }
                double dd = Runtime.PyFloat_AsDouble(op);
                Runtime.CheckExceptionOccurred();
                Runtime.XDecref(op);
                if (dd > Single.MaxValue || dd < Single.MinValue)
                {
                    if (!double.IsInfinity(dd))
                    {
                        goto overflow;
                    }
                }
                result = (float)dd;
                return(true);

            case TypeCode.Double:
                op = Runtime.PyNumber_Float(value);
                if (op == IntPtr.Zero)
                {
                    goto type_error;
                }
                double d = Runtime.PyFloat_AsDouble(op);
                Runtime.CheckExceptionOccurred();
                Runtime.XDecref(op);
                result = d;
                return(true);

            case TypeCode.Decimal:
                op = Runtime.PyObject_Str(value);
                decimal m;
                string  sm = Runtime.GetManagedString(op);
                if (!Decimal.TryParse(sm, NumberStyles.Number, nfi, out m))
                {
                    goto type_error;
                }
                Runtime.XDecref(op);
                result = m;
                return(true);

            case TypeCode.DateTime:
                op = Runtime.PyObject_Str(value);
                DateTime dt;
                string   sdt = Runtime.GetManagedString(op);
                if (!DateTime.TryParse(sdt, out dt))
                {
                    goto type_error;
                }
                Runtime.XDecref(op);
                result = sdt.EndsWith("+00:00") ? dt.ToUniversalTime() : dt;
                return(true);
            }


type_error:

            if (setError)
            {
                string tpName = Runtime.PyObject_GetTypeName(value);
                Exceptions.SetError(Exceptions.TypeError, $"'{tpName}' value cannot be converted to {obType}");
            }

            return(false);

overflow:

            if (setError)
            {
                Exceptions.SetError(Exceptions.OverflowError, "value too large to convert");
            }

            return(false);
        }
Beispiel #8
0
        /// <summary>
        /// Convert a Python value to an instance of a primitive managed type.
        /// </summary>
        private static bool ToPrimitive(BorrowedReference value, Type obType, out object?result, bool setError)
        {
            result = null;
            if (obType.IsEnum)
            {
                if (setError)
                {
                    Exceptions.SetError(Exceptions.TypeError, "since Python.NET 3.0 int can not be converted to Enum implicitly. Use Enum(int_value)");
                }
                return(false);
            }

            TypeCode tc = Type.GetTypeCode(obType);

            switch (tc)
            {
            case TypeCode.String:
                string?st = Runtime.GetManagedString(value);
                if (st == null)
                {
                    goto type_error;
                }
                result = st;
                return(true);

            case TypeCode.Int32:
            {
                // Python3 always use PyLong API
                nint num = Runtime.PyLong_AsSignedSize_t(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > Int32.MaxValue || num < Int32.MinValue)
                {
                    goto overflow;
                }
                result = (int)num;
                return(true);
            }

            case TypeCode.Boolean:
                if (value == Runtime.PyTrue)
                {
                    result = true;
                    return(true);
                }
                if (value == Runtime.PyFalse)
                {
                    result = false;
                    return(true);
                }
                if (setError)
                {
                    goto type_error;
                }
                return(false);

            case TypeCode.Byte:
            {
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        IntPtr bytePtr = Runtime.PyBytes_AsString(value);
                        result = (byte)Marshal.ReadByte(bytePtr);
                        return(true);
                    }
                    goto type_error;
                }

                nint num = Runtime.PyLong_AsSignedSize_t(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > Byte.MaxValue || num < Byte.MinValue)
                {
                    goto overflow;
                }
                result = (byte)num;
                return(true);
            }

            case TypeCode.SByte:
            {
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        IntPtr bytePtr = Runtime.PyBytes_AsString(value);
                        result = (sbyte)Marshal.ReadByte(bytePtr);
                        return(true);
                    }
                    goto type_error;
                }

                nint num = Runtime.PyLong_AsSignedSize_t(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > SByte.MaxValue || num < SByte.MinValue)
                {
                    goto overflow;
                }
                result = (sbyte)num;
                return(true);
            }

            case TypeCode.Char:
            {
                if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType))
                {
                    if (Runtime.PyBytes_Size(value) == 1)
                    {
                        IntPtr bytePtr = Runtime.PyBytes_AsString(value);
                        result = (char)Marshal.ReadByte(bytePtr);
                        return(true);
                    }
                    goto type_error;
                }
                else if (Runtime.PyObject_TypeCheck(value, Runtime.PyUnicodeType))
                {
                    if (Runtime.PyUnicode_GetLength(value) == 1)
                    {
                        IntPtr unicodePtr = Runtime.PyUnicode_AsUnicode(value);
                        Char[] buff       = new Char[1];
                        Marshal.Copy(unicodePtr, buff, 0, 1);
                        result = buff[0];
                        return(true);
                    }
                    goto type_error;
                }
                nint num = Runtime.PyLong_AsSignedSize_t(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > Char.MaxValue || num < Char.MinValue)
                {
                    goto overflow;
                }
                result = (char)num;
                return(true);
            }

            case TypeCode.Int16:
            {
                nint num = Runtime.PyLong_AsSignedSize_t(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > Int16.MaxValue || num < Int16.MinValue)
                {
                    goto overflow;
                }
                result = (short)num;
                return(true);
            }

            case TypeCode.Int64:
            {
                if (Runtime.Is32Bit)
                {
                    if (!Runtime.PyLong_Check(value))
                    {
                        goto type_error;
                    }
                    long?num = Runtime.PyLong_AsLongLong(value);
                    if (num is null)
                    {
                        goto convert_error;
                    }
                    result = num.Value;
                    return(true);
                }
                else
                {
                    nint num = Runtime.PyLong_AsSignedSize_t(value);
                    if (num == -1 && Exceptions.ErrorOccurred())
                    {
                        goto convert_error;
                    }
                    result = (long)num;
                    return(true);
                }
            }

            case TypeCode.UInt16:
            {
                nint num = Runtime.PyLong_AsSignedSize_t(value);
                if (num == -1 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > UInt16.MaxValue || num < UInt16.MinValue)
                {
                    goto overflow;
                }
                result = (ushort)num;
                return(true);
            }

            case TypeCode.UInt32:
            {
                nuint num = Runtime.PyLong_AsUnsignedSize_t(value);
                if (num == unchecked ((nuint)(-1)) && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > UInt32.MaxValue)
                {
                    goto overflow;
                }
                result = (uint)num;
                return(true);
            }

            case TypeCode.UInt64:
            {
                ulong?num = Runtime.PyLong_AsUnsignedLongLong(value);
                if (num is null)
                {
                    goto convert_error;
                }
                result = num.Value;
                return(true);
            }

            case TypeCode.Single:
            {
                if (!Runtime.PyFloat_Check(value) && !Runtime.PyInt_Check(value))
                {
                    goto type_error;
                }
                double num = Runtime.PyFloat_AsDouble(value);
                if (num == -1.0 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                if (num > Single.MaxValue || num < Single.MinValue)
                {
                    if (!double.IsInfinity(num))
                    {
                        goto overflow;
                    }
                }
                result = (float)num;
                return(true);
            }

            case TypeCode.Double:
            {
                if (!Runtime.PyFloat_Check(value) && !Runtime.PyInt_Check(value))
                {
                    goto type_error;
                }
                double num = Runtime.PyFloat_AsDouble(value);
                if (num == -1.0 && Exceptions.ErrorOccurred())
                {
                    goto convert_error;
                }
                result = num;
                return(true);
            }

            default:
                goto type_error;
            }

convert_error:
            if (!setError)
            {
                Exceptions.Clear();
            }
            return(false);

type_error:
            if (setError)
            {
                string tpName = Runtime.PyObject_GetTypeName(value);
                Exceptions.SetError(Exceptions.TypeError, $"'{tpName}' value cannot be converted to {obType}");
            }
            return(false);

overflow:
            // C# level overflow error
            if (setError)
            {
                Exceptions.SetError(Exceptions.OverflowError, "value too large to convert");
            }
            return(false);
        }