Beispiel #1
0
static CYTHON_INLINE PyObject* __Pyx_PyFrozenSet_New(PyObject* it) {
    if (it) {
        PyObject* result;
#if CYTHON_COMPILING_IN_PYPY
        // PyPy currently lacks PyFrozenSet_CheckExact() and PyFrozenSet_New()
        PyObject* args;
        args = PyTuple_Pack(1, it);
        if (unlikely(!args))
            return NULL;
        result = PyObject_Call((PyObject*)&PyFrozenSet_Type, args, NULL);
        Py_DECREF(args);
        return result;
#else
        if (PyFrozenSet_CheckExact(it)) {
            Py_INCREF(it);
            return it;
        }
        result = PyFrozenSet_New(it);
        if (unlikely(!result))
            return NULL;
        if (likely(PySet_GET_SIZE(result)))
            return result;
        // empty frozenset is a singleton
        // seems wasteful, but CPython does the same
        Py_DECREF(result);
#endif
    }
#if CYTHON_COMPILING_IN_CPYTHON
    return PyFrozenSet_Type.tp_new(&PyFrozenSet_Type, $empty_tuple, NULL);
#else
    return PyObject_Call((PyObject*)&PyFrozenSet_Type, $empty_tuple, NULL);
#endif
}
Beispiel #2
0
/* Replace LOAD_CONST c1. LOAD_CONST c2 ... LOAD_CONST cn BUILD_TUPLE n
   with    LOAD_CONST (c1, c2, ... cn).
   The consts table must still be in list form so that the
   new constant (c1, c2, ... cn) can be appended.
   Called with codestr pointing to the first LOAD_CONST.
   Bails out with no change if one or more of the LOAD_CONSTs is missing.
   Also works for BUILD_LIST and BUILT_SET when followed by an "in" or "not in"
   test; for BUILD_SET it assembles a frozenset rather than a tuple.
*/
static int
tuple_of_constants(unsigned char *codestr, Py_ssize_t n, PyObject *consts)
{
    PyObject *newconst, *constant;
    Py_ssize_t i, arg, len_consts;

    /* Pre-conditions */
    assert(PyList_CheckExact(consts));
    assert(codestr[n*3] == BUILD_TUPLE || codestr[n*3] == BUILD_LIST || codestr[n*3] == BUILD_SET);
    assert(GETARG(codestr, (n*3)) == n);
    for (i=0 ; i<n ; i++)
        assert(codestr[i*3] == LOAD_CONST);

    /* Buildup new tuple of constants */
    newconst = PyTuple_New(n);
    if (newconst == NULL)
        return 0;
    len_consts = PyList_GET_SIZE(consts);
    for (i=0 ; i<n ; i++) {
        arg = GETARG(codestr, (i*3));
        assert(arg < len_consts);
        constant = PyList_GET_ITEM(consts, arg);
        Py_INCREF(constant);
        PyTuple_SET_ITEM(newconst, i, constant);
    }

    /* If it's a BUILD_SET, use the PyTuple we just built to create a
      PyFrozenSet, and use that as the constant instead: */
    if (codestr[n*3] == BUILD_SET) {
        PyObject *tuple = newconst;
        newconst = PyFrozenSet_New(tuple);
        Py_DECREF(tuple);
        if (newconst == NULL)
            return 0;
    }

    /* Append folded constant onto consts */
    if (PyList_Append(consts, newconst)) {
        Py_DECREF(newconst);
        return 0;
    }
    Py_DECREF(newconst);

    /* Write NOPs over old LOAD_CONSTS and
       add a new LOAD_CONST newconst on top of the BUILD_TUPLE n */
    memset(codestr, NOP, n*3);
    codestr[n*3] = LOAD_CONST;
    SETARG(codestr, (n*3), len_consts);
    return 1;
}
Beispiel #3
0
/* Intern selected string constants */
static int
intern_string_constants(PyObject *tuple)
{
    int modified = 0;
    Py_ssize_t i;

    for (i = PyTuple_GET_SIZE(tuple); --i >= 0; ) {
        PyObject *v = PyTuple_GET_ITEM(tuple, i);
        if (PyUnicode_CheckExact(v)) {
            if (PyUnicode_READY(v) == -1) {
                PyErr_Clear();
                continue;
            }
            if (all_name_chars(v)) {
                PyObject *w = v;
                PyUnicode_InternInPlace(&v);
                if (w != v) {
                    PyTuple_SET_ITEM(tuple, i, v);
                    modified = 1;
                }
            }
        }
        else if (PyTuple_CheckExact(v)) {
            intern_string_constants(v);
        }
        else if (PyFrozenSet_CheckExact(v)) {
            PyObject *w = v;
            PyObject *tmp = PySequence_Tuple(v);
            if (tmp == NULL) {
                PyErr_Clear();
                continue;
            }
            if (intern_string_constants(tmp)) {
                v = PyFrozenSet_New(tmp);
                if (v == NULL) {
                    PyErr_Clear();
                }
                else {
                    PyTuple_SET_ITEM(tuple, i, v);
                    Py_DECREF(w);
                    modified = 1;
                }
            }
            Py_DECREF(tmp);
        }
    }
    return modified;
}
Beispiel #4
0
static CYTHON_INLINE PyObject* __Pyx_PyFrozenSet_New(PyObject* it) {
    if (it) {
        PyObject* result;
        if (PyFrozenSet_CheckExact(it)) {
            Py_INCREF(it);
            return it;
        }
        result = PyFrozenSet_New(it);
        if (unlikely(!result))
            return NULL;
        if (likely(PySet_GET_SIZE(result)))
            return result;
        // empty frozenset is a singleton
        // seems wasteful, but CPython does the same
        Py_DECREF(result);
    }
    #if CYTHON_COMPILING_IN_CPYTHON
    return PyFrozenSet_Type.tp_new(&PyFrozenSet_Type, $empty_tuple, NULL);
    #else
    return PyObject_Call((PyObject*)&PyFrozenSet_Type, $empty_tuple, NULL);
    #endif
}
Beispiel #5
0
PyObject*
_PyCode_ConstantKey(PyObject *op)
{
    PyObject *key;

    /* Py_None and Py_Ellipsis are singleton */
    if (op == Py_None || op == Py_Ellipsis
       || PyLong_CheckExact(op)
       || PyBool_Check(op)
       || PyBytes_CheckExact(op)
       || PyUnicode_CheckExact(op)
          /* code_richcompare() uses _PyCode_ConstantKey() internally */
       || PyCode_Check(op)) {
        key = PyTuple_Pack(2, Py_TYPE(op), op);
    }
    else if (PyFloat_CheckExact(op)) {
        double d = PyFloat_AS_DOUBLE(op);
        /* all we need is to make the tuple different in either the 0.0
         * or -0.0 case from all others, just to avoid the "coercion".
         */
        if (d == 0.0 && copysign(1.0, d) < 0.0)
            key = PyTuple_Pack(3, Py_TYPE(op), op, Py_None);
        else
            key = PyTuple_Pack(2, Py_TYPE(op), op);
    }
    else if (PyComplex_CheckExact(op)) {
        Py_complex z;
        int real_negzero, imag_negzero;
        /* For the complex case we must make complex(x, 0.)
           different from complex(x, -0.) and complex(0., y)
           different from complex(-0., y), for any x and y.
           All four complex zeros must be distinguished.*/
        z = PyComplex_AsCComplex(op);
        real_negzero = z.real == 0.0 && copysign(1.0, z.real) < 0.0;
        imag_negzero = z.imag == 0.0 && copysign(1.0, z.imag) < 0.0;
        /* use True, False and None singleton as tags for the real and imag
         * sign, to make tuples different */
        if (real_negzero && imag_negzero) {
            key = PyTuple_Pack(3, Py_TYPE(op), op, Py_True);
        }
        else if (imag_negzero) {
            key = PyTuple_Pack(3, Py_TYPE(op), op, Py_False);
        }
        else if (real_negzero) {
            key = PyTuple_Pack(3, Py_TYPE(op), op, Py_None);
        }
        else {
            key = PyTuple_Pack(2, Py_TYPE(op), op);
        }
    }
    else if (PyTuple_CheckExact(op)) {
        Py_ssize_t i, len;
        PyObject *tuple;

        len = PyTuple_GET_SIZE(op);
        tuple = PyTuple_New(len);
        if (tuple == NULL)
            return NULL;

        for (i=0; i < len; i++) {
            PyObject *item, *item_key;

            item = PyTuple_GET_ITEM(op, i);
            item_key = _PyCode_ConstantKey(item);
            if (item_key == NULL) {
                Py_DECREF(tuple);
                return NULL;
            }

            PyTuple_SET_ITEM(tuple, i, item_key);
        }

        key = PyTuple_Pack(3, Py_TYPE(op), op, tuple);
        Py_DECREF(tuple);
    }
    else if (PyFrozenSet_CheckExact(op)) {
        Py_ssize_t pos = 0;
        PyObject *item;
        Py_hash_t hash;
        Py_ssize_t i, len;
        PyObject *tuple, *set;

        len = PySet_GET_SIZE(op);
        tuple = PyTuple_New(len);
        if (tuple == NULL)
            return NULL;

        i = 0;
        while (_PySet_NextEntry(op, &pos, &item, &hash)) {
            PyObject *item_key;

            item_key = _PyCode_ConstantKey(item);
            if (item_key == NULL) {
                Py_DECREF(tuple);
                return NULL;
            }

            assert(i < len);
            PyTuple_SET_ITEM(tuple, i, item_key);
            i++;
        }
        set = PyFrozenSet_New(tuple);
        Py_DECREF(tuple);
        if (set == NULL)
            return NULL;

        key = PyTuple_Pack(3, Py_TYPE(op), op, set);
        Py_DECREF(set);
        return key;
    }
    else {
        /* for other types, use the object identifier as a unique identifier
         * to ensure that they are seen as unequal. */
        PyObject *obj_id = PyLong_FromVoidPtr(op);
        if (obj_id == NULL)
            return NULL;

        key = PyTuple_Pack(3, Py_TYPE(op), op, obj_id);
        Py_DECREF(obj_id);
    }
    return key;
}
Beispiel #6
0
// Returns a new reference.
static PyObject*
decode_val(DecodeBuffer* input, TType type, PyObject* typeargs, long string_limit, long container_limit) {
    switch (type) {

    case T_BOOL: {
        int8_t v = readByte(input);
        if (INT_CONV_ERROR_OCCURRED(v)) {
            return NULL;
        }

        switch (v) {
        case 0:
            Py_RETURN_FALSE;
        case 1:
            Py_RETURN_TRUE;
        // Don't laugh.  This is a potentially serious issue.
        default:
            PyErr_SetString(PyExc_TypeError, "boolean out of range");
            return NULL;
        }
        break;
    }
    case T_I08: {
        int8_t v = readByte(input);
        if (INT_CONV_ERROR_OCCURRED(v)) {
            return NULL;
        }

        return PyInt_FromLong(v);
    }
    case T_I16: {
        int16_t v = readI16(input);
        if (INT_CONV_ERROR_OCCURRED(v)) {
            return NULL;
        }
        return PyInt_FromLong(v);
    }
    case T_I32: {
        int32_t v = readI32(input);
        if (INT_CONV_ERROR_OCCURRED(v)) {
            return NULL;
        }
        return PyInt_FromLong(v);
    }

    case T_I64: {
        int64_t v = readI64(input);
        if (INT_CONV_ERROR_OCCURRED(v)) {
            return NULL;
        }
        // TODO(dreiss): Find out if we can take this fastpath always when
        //               sizeof(long) == sizeof(long long).
        if (CHECK_RANGE(v, LONG_MIN, LONG_MAX)) {
            return PyInt_FromLong((long) v);
        }

        return PyLong_FromLongLong(v);
    }

    case T_DOUBLE: {
        double v = readDouble(input);
        if (v == -1.0 && PyErr_Occurred()) {
            return false;
        }
        return PyFloat_FromDouble(v);
    }

    case T_STRING: {
        Py_ssize_t len = readI32(input);
        char* buf;
        if (!readBytes(input, &buf, len)) {
            return NULL;
        }
        if (!check_length_limit(len, string_limit)) {
            return NULL;
        }

        if (is_utf8(typeargs))
            return PyUnicode_DecodeUTF8(buf, len, 0);
        else
            return PyString_FromStringAndSize(buf, len);
    }

    case T_LIST:
    case T_SET: {
        SetListTypeArgs parsedargs;
        int32_t len;
        PyObject* ret = NULL;
        int i;
        bool use_tuple = false;

        if (!parse_set_list_args(&parsedargs, typeargs)) {
            return NULL;
        }

        if (!checkTypeByte(input, parsedargs.element_type)) {
            return NULL;
        }

        len = readI32(input);
        if (!check_length_limit(len, container_limit)) {
            return NULL;
        }

        use_tuple = type == T_LIST && parsedargs.immutable;
        ret = use_tuple ? PyTuple_New(len) : PyList_New(len);
        if (!ret) {
            return NULL;
        }

        for (i = 0; i < len; i++) {
            PyObject* item = decode_val(input, parsedargs.element_type, parsedargs.typeargs, string_limit, container_limit);
            if (!item) {
                Py_DECREF(ret);
                return NULL;
            }
            if (use_tuple) {
                PyTuple_SET_ITEM(ret, i, item);
            } else  {
                PyList_SET_ITEM(ret, i, item);
            }
        }

        // TODO(dreiss): Consider biting the bullet and making two separate cases
        //               for list and set, avoiding this post facto conversion.
        if (type == T_SET) {
            PyObject* setret;
            setret = parsedargs.immutable ? PyFrozenSet_New(ret) : PySet_New(ret);
            Py_DECREF(ret);
            return setret;
        }
        return ret;
    }

    case T_MAP: {
        int32_t len;
        int i;
        MapTypeArgs parsedargs;
        PyObject* ret = NULL;

        if (!parse_map_args(&parsedargs, typeargs)) {
            return NULL;
        }

        if (!checkTypeByte(input, parsedargs.ktag)) {
            return NULL;
        }
        if (!checkTypeByte(input, parsedargs.vtag)) {
            return NULL;
        }

        len = readI32(input);
        if (!check_length_limit(len, container_limit)) {
            return NULL;
        }

        ret = PyDict_New();
        if (!ret) {
            goto error;
        }

        for (i = 0; i < len; i++) {
            PyObject* k = NULL;
            PyObject* v = NULL;
            k = decode_val(input, parsedargs.ktag, parsedargs.ktypeargs, string_limit, container_limit);
            if (k == NULL) {
                goto loop_error;
            }
            v = decode_val(input, parsedargs.vtag, parsedargs.vtypeargs, string_limit, container_limit);
            if (v == NULL) {
                goto loop_error;
            }
            if (PyDict_SetItem(ret, k, v) == -1) {
                goto loop_error;
            }

            Py_DECREF(k);
            Py_DECREF(v);
            continue;

            // Yuck!  Destructors, anyone?
loop_error:
            Py_XDECREF(k);
            Py_XDECREF(v);
            goto error;
        }

        if (parsedargs.immutable) {
            PyObject* thrift = PyImport_ImportModule("thrift.Thrift");
            PyObject* cls = NULL;
            PyObject* arg = NULL;
            if (!thrift) {
                goto error;
            }
            cls = PyObject_GetAttrString(thrift, "TFrozenDict");
            if (!cls) {
                goto error;
            }
            arg = PyTuple_New(1);
            PyTuple_SET_ITEM(arg, 0, ret);
            return PyObject_CallObject(cls, arg);
        }

        return ret;

error:
        Py_XDECREF(ret);
        return NULL;
    }

    case T_STRUCT: {
        StructTypeArgs parsedargs;
        if (!parse_struct_args(&parsedargs, typeargs)) {
            return NULL;
        }

        return decode_struct(input, Py_None, parsedargs.klass, parsedargs.spec, string_limit, container_limit);
    }

    case T_STOP:
    case T_VOID:
    case T_UTF16:
    case T_UTF8:
    case T_U64:
    default:
        PyErr_SetString(PyExc_TypeError, "Unexpected TType");
        return NULL;
    }
}