cpickle.c

来自「python s60 1.4.5版本的源代码」· C语言 代码 · 共 2,601 行 · 第 1/5 页

C
2,601
字号
    }

    if ((getinitargs_func = PyObject_GetAttr(args, __getinitargs___str))) {
        PyObject *element = 0;
        int i, len;

        UNLESS (class_args =
            PyObject_Call(getinitargs_func, empty_tuple, NULL))
            goto finally;

        if ((len = PyObject_Size(class_args)) < 0)
            goto finally;

        for (i = 0; i < len; i++) {
            UNLESS (element = PySequence_GetItem(class_args, i))
                goto finally;

            if (save(self, element, 0) < 0) {
                Py_DECREF(element);
                goto finally;
            }

            Py_DECREF(element);
        }
    }
    else {
        PyErr_Clear();
    }

    if (!self->bin) {
        UNLESS (name = ((PyClassObject *)class)->cl_name) {
            PyErr_SetString(PicklingError, "class has no name");
            goto finally;
        }

        UNLESS (module = whichmodule(class, name))
            goto finally;


        if ((module_size = PyString_Size(module)) < 0 ||
           (name_size = PyString_Size(name)) < 0)
          goto finally;

        module_str = PyString_AS_STRING((PyStringObject *)module);
        name_str   = PyString_AS_STRING((PyStringObject *)name);

        if ((*self->write_func)(self, &inst, 1) < 0)
            goto finally;

        if ((*self->write_func)(self, module_str, module_size) < 0)
            goto finally;

        if ((*self->write_func)(self, "\n", 1) < 0)
            goto finally;

        if ((*self->write_func)(self, name_str, name_size) < 0)
            goto finally;

        if ((*self->write_func)(self, "\n", 1) < 0)
            goto finally;
    }
    else if ((*self->write_func)(self, &obj, 1) < 0) {
        goto finally;
    }

    if ((getstate_func = PyObject_GetAttr(args, __getstate___str))) {
        UNLESS (state = PyObject_Call(getstate_func, empty_tuple, NULL))
            goto finally;
    }
    else {
        PyErr_Clear();

        UNLESS (state = PyObject_GetAttr(args, __dict___str)) {
            PyErr_Clear();
            res = 0;
            goto finally;
        }
    }

    if (!PyDict_Check(state)) {
        if (put2(self, args) < 0)
            goto finally;
    }
    else {
        if (put(self, args) < 0)
            goto finally;
    }

    if (save(self, state, 0) < 0)
        goto finally;

    if ((*self->write_func)(self, &build, 1) < 0)
        goto finally;

    res = 0;

finally:
    if (self->fast && !fast_save_leave(self, args))
	res = -1;

    Py_XDECREF(module);
    Py_XDECREF(class);
    Py_XDECREF(state);
    Py_XDECREF(getinitargs_func);
    Py_XDECREF(getstate_func);
    Py_XDECREF(class_args);

    return res;
}


static int
save_global(Picklerobject *self, PyObject *args, PyObject *name) {
    PyObject *global_name = 0, *module = 0, *mod = 0, *klass = 0;
    char *name_str, *module_str;
    int module_size, name_size, res = -1;

    static char global = GLOBAL;

    if (name) {
        global_name = name;
        Py_INCREF(global_name);
    }
    else {
        UNLESS (global_name = PyObject_GetAttr(args, __name___str))
            goto finally;
    }

    UNLESS (module = whichmodule(args, global_name))
        goto finally;

    if ((module_size = PyString_Size(module)) < 0 ||
        (name_size = PyString_Size(global_name)) < 0)
      goto finally;

    module_str = PyString_AS_STRING((PyStringObject *)module);
    name_str   = PyString_AS_STRING((PyStringObject *)global_name);

    mod = PyImport_ImportModule(module_str);
    if (mod == NULL) {
        /* Py_ErrClear(); ?? */
	cPickle_ErrFormat(PicklingError,
			  "Can't pickle %s: it's not found as %s.%s",
			  "OSS", args, module, global_name);
	goto finally;
    }
    klass = PyObject_GetAttrString(mod, name_str);
    if (klass == NULL) {
	cPickle_ErrFormat(PicklingError,
			  "Can't pickle %s: it's not found as %s.%s",
			  "OSS", args, module, global_name);
	goto finally;
    }
    if (klass != args) {
	Py_DECREF(klass);
	cPickle_ErrFormat(PicklingError,
			  "Can't pickle %s: it's not the same object as %s.%s",
			  "OSS", args, module, global_name);
	goto finally;
    }
    Py_DECREF(klass);

    if ((*self->write_func)(self, &global, 1) < 0)
        goto finally;

    if ((*self->write_func)(self, module_str, module_size) < 0)
        goto finally;

    if ((*self->write_func)(self, "\n", 1) < 0)
        goto finally;

    if ((*self->write_func)(self, name_str, name_size) < 0)
        goto finally;

    if ((*self->write_func)(self, "\n", 1) < 0)
        goto finally;

    if (put(self, args) < 0)
        goto finally;

    res = 0;

finally:
    Py_XDECREF(module);
    Py_XDECREF(global_name);
    Py_XDECREF(mod);

    return res;
}

static int
save_pers(Picklerobject *self, PyObject *args, PyObject *f) {
    PyObject *pid = 0;
    int size, res = -1;

    static char persid = PERSID, binpersid = BINPERSID;

    Py_INCREF(args);
    ARG_TUP(self, args);
    if (self->arg) {
        pid = PyObject_Call(f, self->arg, NULL);
        FREE_ARG_TUP(self);
    }
    if (! pid) return -1;

    if (pid != Py_None) {
        if (!self->bin) {
            if (!PyString_Check(pid)) {
                PyErr_SetString(PicklingError,
                    "persistent id must be string");
                goto finally;
            }

            if ((*self->write_func)(self, &persid, 1) < 0)
                goto finally;

            if ((size = PyString_Size(pid)) < 0)
                goto finally;

            if ((*self->write_func)(self,
                PyString_AS_STRING((PyStringObject *)pid), size) < 0)
                goto finally;

            if ((*self->write_func)(self, "\n", 1) < 0)
                goto finally;

            res = 1;
            goto finally;
        }
        else if (save(self, pid, 1) >= 0) {
            if ((*self->write_func)(self, &binpersid, 1) < 0)
                res = -1;
            else
                res = 1;
        }

        goto finally;
    }

    res = 0;

finally:
    Py_XDECREF(pid);

    return res;
}


static int
save_reduce(Picklerobject *self, PyObject *callable,
            PyObject *tup, PyObject *state, PyObject *ob) {
    static char reduce = REDUCE, build = BUILD;

    if (save(self, callable, 0) < 0)
        return -1;

    if (save(self, tup, 0) < 0)
        return -1;

    if ((*self->write_func)(self, &reduce, 1) < 0)
        return -1;

    if (ob != NULL) {
        if (state && !PyDict_Check(state)) {
            if (put2(self, ob) < 0)
                return -1;
        }
        else {
            if (put(self, ob) < 0)
                return -1;
        }
    }

    if (state) {
        if (save(self, state, 0) < 0)
            return -1;

        if ((*self->write_func)(self, &build, 1) < 0)
            return -1;
    }

    return 0;
}

static int
save(Picklerobject *self, PyObject *args, int  pers_save) {
    PyTypeObject *type;
    PyObject *py_ob_id = 0, *__reduce__ = 0, *t = 0, *arg_tup = 0,
             *callable = 0, *state = 0;
    int res = -1, tmp, size;

    if (self->nesting++ > Py_GetRecursionLimit()){
	    PyErr_SetString(PyExc_RuntimeError,
			    "maximum recursion depth exceeded");
	    goto finally;
    }

    if (!pers_save && self->pers_func) {
        if ((tmp = save_pers(self, args, self->pers_func)) != 0) {
            res = tmp;
            goto finally;
        }
    }

    if (args == Py_None) {
        res = save_none(self, args);
        goto finally;
    }

    type = args->ob_type;

    switch (type->tp_name[0]) {
        case 'i':
            if (type == &PyInt_Type) {
                res = save_int(self, args);
                goto finally;
            }
            break;

        case 'l':
            if (type == &PyLong_Type) {
                res = save_long(self, args);
                goto finally;
            }
            break;

        case 'f':
            if (type == &PyFloat_Type) {
                res = save_float(self, args);
                goto finally;
            }
            break;

        case 't':
            if (type == &PyTuple_Type && PyTuple_Size(args)==0) {
                if (self->bin) res = save_empty_tuple(self, args);
                else          res = save_tuple(self, args);
                goto finally;
            }
            break;

        case 's':
            if ((type == &PyString_Type) && (PyString_GET_SIZE(args) < 2)) {
                res = save_string(self, args, 0);
                goto finally;
            }

#ifdef Py_USING_UNICODE
        case 'u':
            if ((type == &PyUnicode_Type) && (PyString_GET_SIZE(args) < 2)) {
                res = save_unicode(self, args, 0);
                goto finally;
            }
#endif
    }

    if (args->ob_refcnt > 1) {
        UNLESS (py_ob_id = PyLong_FromVoidPtr(args))
            goto finally;

	if (PyDict_GetItem(self->memo, py_ob_id)) {
            if (get(self, py_ob_id) < 0)
                goto finally;

            res = 0;
            goto finally;
        }
    }

    switch (type->tp_name[0]) {
        case 's':
            if (type == &PyString_Type) {
                res = save_string(self, args, 1);
                goto finally;
            }
            break;

#ifdef Py_USING_UNICODE
        case 'u':
            if (type == &PyUnicode_Type) {
                res = save_unicode(self, args, 1);
                goto finally;
            }
            break;
#endif

        case 't':
            if (type == &PyTuple_Type) {
                res = save_tuple(self, args);
                goto finally;
            }
	    if (type == &PyType_Type) {
		res = save_global(self, args, NULL);
		goto finally;
	    }
            break;

        case 'l':
            if (type == &PyList_Type) {
                res = save_list(self, args);
                goto finally;
            }
            break;

        case 'd':
            if (type == &PyDict_Type) {
                res = save_dict(self, args);
                goto finally;
            }
            break;

        case 'i':
            if (type == &PyInstance_Type) {
                res = save_inst(self, args);
                goto finally;
            }
            break;

        case 'c':
            if (type == &PyClass_Type) {
                res = save_global(self, args, NULL);
                goto finally;
            }
            break;

        case 'f':
            if (type == &PyFunction_Type) {
                res = save_global(self, args, NULL);
                goto finally;
            }
            break;

        case 'b':
            if (type == &PyCFunction_Type) {
                res = save_global(self, args, NULL);
                goto finally;
            }
    }

    if (!pers_save && self->inst_pers_func) {
        if ((tmp = save_pers(self, args, self->inst_pers_func)) != 0) {
            res = tmp;
            goto finally;
        }
    }

    if (PyType_IsSubtype(type, &PyType_Type)) {
	res = save_global(self, args, NULL);
	goto finally;
    }

    if ((__reduce__ = PyDict_GetItem(dispatch_table, (PyObject *)type))) {
        Py_INCREF(__reduce__);

        Py_INCREF(args);
        ARG_TUP(self, args);
        if (self->arg) {
            t = PyObject_Call(__reduce__, self->arg, NULL);
            FREE_ARG_TUP(self);
        }
        if (! t) goto finally;
    }
    else {
        PyErr_Clear();

        if ((__reduce__ = PyObject_GetAttr(args, __reduce___str))) {
            UNLESS (t = PyObject_Call(__reduce__, empty_tuple, NULL))
                goto finally;
        }
        else {
            PyErr_Clear();
        }
    }

    if (t) {
        if (PyString_Check(t)) {
            res = save_global(self, args, t);
            goto finally;
        }

        if (!PyTuple_Check(t)) {
            cPickle_ErrFormat(PicklingError, "Value returned by %s must "
                "be a tuple", "O", __reduce__);
            goto finally;
        }

        size = PyTuple_Size(t);

        if ((size != 3) && (size != 2)) {
            cPickle_ErrFormat(PicklingError, "tuple returned by %s must "
                "contain only two or three elements", "O", __reduce__);
                goto finally;
        }

        callable = PyTuple_GET_ITEM(t, 0);

        arg_tup = PyTuple_GET_ITEM(t, 1);

        if (size > 2) {
            state = PyTuple_GET_ITEM(t, 2);
        }

        UNLESS (PyTuple_Check(arg_tup) || arg_tup==Py_None) {
            cPickle_ErrFormat(PicklingError, "Second element of tuple "
                "returned by %s must be a tuple", "O", __reduce__);
            goto finally;
        }

        res = save_reduce(self, callable, arg_tup, state, args);
        goto finally;
    }

    PyErr_SetObject(UnpickleableError, args);

finally:
    self->nesting--;
    Py_XDECREF(py_ob_id);
    Py_XDECREF(__reduce__);
    Py_XDECREF(t);

    return res;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?