cpickle.c
来自「python s60 1.4.5版本的源代码」· C语言 代码 · 共 2,601 行 · 第 1/5 页
C
2,601 行
}
static int
dump(Picklerobject *self, PyObject *args) {
static char stop = STOP;
if (save(self, args, 0) < 0)
return -1;
if ((*self->write_func)(self, &stop, 1) < 0)
return -1;
if ((*self->write_func)(self, NULL, 0) < 0)
return -1;
return 0;
}
static PyObject *
Pickle_clear_memo(Picklerobject *self, PyObject *args) {
if (!PyArg_ParseTuple(args,":clear_memo"))
return NULL;
if (self->memo)
PyDict_Clear(self->memo);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
Pickle_getvalue(Picklerobject *self, PyObject *args) {
int l, i, rsize, ssize, clear=1, lm;
long ik;
PyObject *k, *r;
char *s, *p, *have_get;
Pdata *data;
/* Can be called by Python code or C code */
if (args && !PyArg_ParseTuple(args, "|i:getvalue", &clear))
return NULL;
/* Check to make sure we are based on a list */
if (! Pdata_Check(self->file)) {
PyErr_SetString(PicklingError,
"Attempt to getvalue() a non-list-based pickler");
return NULL;
}
/* flush write buffer */
if (write_other(self, NULL, 0) < 0) return NULL;
data=(Pdata*)self->file;
l=data->length;
/* set up an array to hold get/put status */
if ((lm=PyDict_Size(self->memo)) < 0) return NULL;
lm++;
if (! (have_get=malloc((lm)*sizeof(char)))) return PyErr_NoMemory();
memset(have_get,0,lm);
/* Scan for gets. */
for (rsize=0, i=l; --i >= 0; ) {
k=data->data[i];
if (PyString_Check(k)) {
rsize += PyString_GET_SIZE(k);
}
else if (PyInt_Check(k)) { /* put */
ik=PyInt_AS_LONG((PyIntObject*)k);
if (ik >= lm || ik==0) {
PyErr_SetString(PicklingError,
"Invalid get data");
return NULL;
}
if (have_get[ik]) { /* with matching get */
if (ik < 256) rsize += 2;
else rsize+=5;
}
}
else if (! (PyTuple_Check(k) &&
PyTuple_GET_SIZE(k) == 2 &&
PyInt_Check((k=PyTuple_GET_ITEM(k,0))))
) {
PyErr_SetString(PicklingError,
"Unexpected data in internal list");
return NULL;
}
else { /* put */
ik=PyInt_AS_LONG((PyIntObject*)k);
if (ik >= lm || ik==0) {
PyErr_SetString(PicklingError,
"Invalid get data");
return NULL;
}
have_get[ik]=1;
if (ik < 256) rsize += 2;
else rsize+=5;
}
}
/* Now generate the result */
UNLESS (r=PyString_FromStringAndSize(NULL,rsize)) goto err;
s=PyString_AS_STRING((PyStringObject*)r);
for (i=0; i<l; i++) {
k=data->data[i];
if (PyString_Check(k)) {
ssize=PyString_GET_SIZE(k);
if (ssize) {
p=PyString_AS_STRING((PyStringObject*)k);
while (--ssize >= 0) *s++=*p++;
}
}
else if (PyTuple_Check(k)) { /* get */
ik=PyInt_AS_LONG((PyIntObject*)PyTuple_GET_ITEM(k,0));
if (ik < 256) {
*s++ = BINGET;
*s++ = (int)(ik & 0xff);
}
else {
*s++ = LONG_BINGET;
*s++ = (int)(ik & 0xff);
*s++ = (int)((ik >> 8) & 0xff);
*s++ = (int)((ik >> 16) & 0xff);
*s++ = (int)((ik >> 24) & 0xff);
}
}
else { /* put */
ik=PyInt_AS_LONG((PyIntObject*)k);
if (have_get[ik]) { /* with matching get */
if (ik < 256) {
*s++ = BINPUT;
*s++ = (int)(ik & 0xff);
}
else {
*s++ = LONG_BINPUT;
*s++ = (int)(ik & 0xff);
*s++ = (int)((ik >> 8) & 0xff);
*s++ = (int)((ik >> 16) & 0xff);
*s++ = (int)((ik >> 24) & 0xff);
}
}
}
}
if (clear) {
PyDict_Clear(self->memo);
Pdata_clear(data,0);
}
free(have_get);
return r;
err:
free(have_get);
return NULL;
}
static PyObject *
Pickler_dump(Picklerobject *self, PyObject *args) {
PyObject *ob;
int get=0;
UNLESS (PyArg_ParseTuple(args, "O|i:dump", &ob, &get))
return NULL;
if (dump(self, ob) < 0)
return NULL;
if (get) return Pickle_getvalue(self, NULL);
/* XXX Why does dump() return self? */
Py_INCREF(self);
return (PyObject*)self;
}
static struct PyMethodDef Pickler_methods[] = {
{"dump", (PyCFunction)Pickler_dump, 1,
"dump(object) --"
"Write an object in pickle format to the object's pickle stream\n"
},
{"clear_memo", (PyCFunction)Pickle_clear_memo, 1,
"clear_memo() -- Clear the picklers memo"},
{"getvalue", (PyCFunction)Pickle_getvalue, 1,
"getvalue() -- Finish picking a list-based pickle"},
{NULL, NULL} /* sentinel */
};
static Picklerobject *
newPicklerobject(PyObject *file, int bin) {
Picklerobject *self;
UNLESS (self = PyObject_New(Picklerobject, &Picklertype))
return NULL;
self->fp = NULL;
self->write = NULL;
self->memo = NULL;
self->arg = NULL;
self->pers_func = NULL;
self->inst_pers_func = NULL;
self->write_buf = NULL;
self->bin = bin;
self->fast = 0;
self->nesting = 0;
self->fast_container = 0;
self->fast_memo = NULL;
self->buf_size = 0;
self->dispatch_table = NULL;
if (file)
Py_INCREF(file);
else
file=Pdata_New();
UNLESS (self->file = file)
goto err;
UNLESS (self->memo = PyDict_New())
goto err;
if (PyFile_Check(file)) {
self->fp = PyFile_AsFile(file);
if (self->fp == NULL) {
PyErr_SetString(PyExc_ValueError, "I/O operation on closed file");
goto err;
}
self->write_func = write_file;
}
else if (PycStringIO_OutputCheck(file)) {
self->write_func = write_cStringIO;
}
else if (file == Py_None) {
self->write_func = write_none;
}
else {
self->write_func = write_other;
if (! Pdata_Check(file)) {
UNLESS (self->write = PyObject_GetAttr(file, write_str)) {
PyErr_Clear();
PyErr_SetString(PyExc_TypeError, "argument must have 'write' "
"attribute");
goto err;
}
}
UNLESS (self->write_buf =
(char *)malloc(WRITE_BUF_SIZE * sizeof(char))) {
PyErr_NoMemory();
goto err;
}
}
if (PyEval_GetRestricted()) {
/* Restricted execution, get private tables */
PyObject *m;
UNLESS (m=PyImport_Import(copy_reg_str)) goto err;
self->dispatch_table=PyObject_GetAttr(m, dispatch_table_str);
Py_DECREF(m);
UNLESS (self->dispatch_table) goto err;
}
else {
self->dispatch_table=dispatch_table;
Py_INCREF(dispatch_table);
}
return self;
err:
Py_DECREF((PyObject *)self);
return NULL;
}
static PyObject *
get_Pickler(PyObject *self, PyObject *args) {
PyObject *file = NULL;
int bin = 1;
if (!PyArg_ParseTuple(args, "|i:Pickler", &bin)) {
PyErr_Clear();
bin = 0;
if (!PyArg_ParseTuple(args, "O|i:Pickler", &file, &bin))
return NULL;
}
return (PyObject *)newPicklerobject(file, bin);
}
static void
Pickler_dealloc(Picklerobject *self) {
Py_XDECREF(self->write);
Py_XDECREF(self->memo);
Py_XDECREF(self->fast_memo);
Py_XDECREF(self->arg);
Py_XDECREF(self->file);
Py_XDECREF(self->pers_func);
Py_XDECREF(self->inst_pers_func);
Py_XDECREF(self->dispatch_table);
if (self->write_buf) {
free(self->write_buf);
}
PyObject_Del(self);
}
static PyObject *
Pickler_get_pers_func(Picklerobject *p)
{
if (p->pers_func == NULL)
PyErr_SetString(PyExc_AttributeError, "persistent_id");
else
Py_INCREF(p->pers_func);
return p->pers_func;
}
static int
Pickler_set_pers_func(Picklerobject *p, PyObject *v)
{
if (v == NULL) {
PyErr_SetString(PyExc_TypeError,
"attribute deletion is not supported");
return -1;
}
Py_XDECREF(p->pers_func);
Py_INCREF(v);
p->pers_func = v;
return 0;
}
static int
Pickler_set_inst_pers_func(Picklerobject *p, PyObject *v)
{
if (v == NULL) {
PyErr_SetString(PyExc_TypeError,
"attribute deletion is not supported");
return -1;
}
Py_XDECREF(p->inst_pers_func);
Py_INCREF(v);
p->inst_pers_func = v;
return 0;
}
static PyObject *
Pickler_get_memo(Picklerobject *p)
{
if (p->memo == NULL)
PyErr_SetString(PyExc_AttributeError, "memo");
else
Py_INCREF(p->memo);
return p->memo;
}
static int
Pickler_set_memo(Picklerobject *p, PyObject *v)
{
if (v == NULL) {
PyErr_SetString(PyExc_TypeError,
"attribute deletion is not supported");
return -1;
}
if (!PyDict_Check(v)) {
PyErr_SetString(PyExc_TypeError, "memo must be a dictionary");
return -1;
}
Py_XDECREF(p->memo);
Py_INCREF(v);
p->memo = v;
return 0;
}
static PyObject *
Pickler_get_error(Picklerobject *p)
{
/* why is this an attribute on the Pickler? */
Py_INCREF(PicklingError);
return PicklingError;
}
static PyMemberDef Pickler_members[] = {
{"binary", T_INT, offsetof(Picklerobject, bin)},
{"fast", T_INT, offsetof(Picklerobject, fast)},
{NULL}
};
static PyGetSetDef Pickler_getsets[] = {
{"persistent_id", (getter)Pickler_get_pers_func,
(setter)Pickler_set_pers_func},
{"inst_persistent_id", NULL, (setter)Pickler_set_inst_pers_func},
{"memo", (getter)Pickler_get_memo, (setter)Pickler_set_memo},
{"PicklingError", (getter)Pickler_get_error, NULL},
{NULL}
};
static char Picklertype__doc__[] =
"Objects that know how to pickle objects\n";
static PyTypeObject Picklertype = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"cPickle.Pickler", /*tp_name*/
sizeof(Picklerobject), /*tp_basicsize*/
0,
(destructor)Pickler_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* set below */ /* tp_getattro */
0, /* set below */ /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
Picklertype__doc__, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
Pickler_methods, /* tp_methods */
Pickler_members, /* tp_members */
Pickler_getsets, /* tp_getset */
};
static PyObject *
find_class(PyObject *py_module_name, PyObject *py_global_name, PyObject *fc) {
PyObject *global = 0, *module;
if (fc) {
if (fc==Py_None) {
PyErr_SetString(UnpicklingError,
"Global and instance pickles are not supported.");
return NULL;
}
return PyObject_CallFunction(fc, "OO", py_module_name, py_global_name);
}
module = PySys_GetObject("modules");
if (module == NULL)
return NULL;
module = PyDict_GetItem(module, py_module_name);
if (module == NULL) {
module = PyImport_Import(py_module_name);
if (!module)
return NULL;
global = PyObject_GetAttr(module, py_global_name);
Py_DECREF(module);
}
else
global = PyObject_GetAttr(module, py_global_name);
return global;
}
static int
marker(Unpicklerobject *self) {
if (self->num_marks < 1) {
PyErr_SetString(UnpicklingError, "could not find MARK");
return -1;
}
return self->marks[--self->num_marks];
}
static int
load_none(Unpicklerobject *self) {
PDATA_APPEND(self->stack, Py_None, -1);
return 0;
}
static int
bad_readline(void) {
PyErr_SetString(UnpicklingError, "pickle data was truncated");
return -1;
}
static int
load_int(Unpicklerobject *self) {
PyObject *py_int = 0;
char *endptr, *s;
int len, res = -1;
long l;
if ((len = (*self->readline_func)(self, &s)) < 0) return -1;
if (len < 2) return bad_readline();
UNLESS (s=pystrndup(s,len)) return -1;
errno = 0;
l = strtol(s, &endptr, 0);
if (errno || (*endptr != '\n') || (endptr[1] != '\0')) {
/* Hm, maybe we've got something long. Let's try reading
it as a Python long object. */
errno = 0;
py_int = PyLong_FromString(s, NULL, 0);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?