#include "Python.h"
#include "cStringIO.h"
+#include "structmember.h"
#ifndef Py_eval_input
#include <graminit.h>
*read_str, *readline_str, *__main___str, *__basicnew___str,
*copy_reg_str, *dispatch_table_str, *safe_constructors_str;
-#ifndef PyList_SET_ITEM
-#define PyList_SET_ITEM(op, i, v) (((PyListObject *)(op))->ob_item[i] = (v))
-#endif
-#ifndef PyList_GET_SIZE
-#define PyList_GET_SIZE(op) (((PyListObject *)(op))->ob_size)
-#endif
-#ifndef PyTuple_SET_ITEM
-#define PyTuple_SET_ITEM(op, i, v) (((PyTupleObject *)(op))->ob_item[i] = (v))
-#endif
-#ifndef PyTuple_GET_SIZE
-#define PyTuple_GET_SIZE(op) (((PyTupleObject *)(op))->ob_size)
-#endif
-#ifndef PyString_GET_SIZE
-#define PyString_GET_SIZE(op) (((PyStringObject *)(op))->ob_size)
-#endif
-
/*************************************************************************
Internal Data type for pickle data. */
}
typedef struct Picklerobject {
- PyObject_HEAD
- FILE *fp;
- PyObject *write;
- PyObject *file;
- PyObject *memo;
- PyObject *arg;
- PyObject *pers_func;
- PyObject *inst_pers_func;
- int bin;
- int fast; /* Fast mode doesn't save in memo, don't use if circ ref */
- int (*write_func)(struct Picklerobject *, char *, int);
- char *write_buf;
- int buf_size;
- PyObject *dispatch_table;
+ PyObject_HEAD
+ FILE *fp;
+ PyObject *write;
+ PyObject *file;
+ PyObject *memo;
+ PyObject *arg;
+ PyObject *pers_func;
+ PyObject *inst_pers_func;
+ int bin;
+ int fast; /* Fast mode doesn't save in memo, don't use if circ ref */
+ int (*write_func)(struct Picklerobject *, char *, int);
+ char *write_buf;
+ int buf_size;
+ PyObject *dispatch_table;
+ int fast_container; /* count nested container dumps */
} Picklerobject;
+#define FAST_LIMIT 2000
+
staticforward PyTypeObject Picklertype;
typedef struct Unpicklerobject {
/* object with write method */
ARG_TUP(self, py_str);
if (self->arg) {
- junk = PyObject_CallObject(self->write, self->arg);
+ junk = PyObject_Call(self->write, self->arg, NULL);
FREE_ARG_TUP(self);
}
if (junk) Py_DECREF(junk);
ARG_TUP(self, bytes);
if (self->arg) {
- str = PyObject_CallObject(self->read, self->arg);
+ str = PyObject_Call(self->read, self->arg, NULL);
FREE_ARG_TUP(self);
}
if (! str) return -1;
static int
put(Picklerobject *self, PyObject *ob) {
- if (ob->ob_refcnt < 2 || self->fast)
+ if (ob->ob_refcnt < 2 || self->fast)
return 0;
return put2(self, ob);
int res = -1;
PyObject *py_ob_id = 0, *memo_len = 0, *t = 0;
- if (self->fast) return 0;
+ if (self->fast)
+ return 0;
if ((p = PyDict_Size(self->memo)) < 0)
goto finally;
static int
save_tuple(Picklerobject *self, PyObject *args) {
PyObject *element = 0, *py_tuple_id = 0;
- int len, i, has_key, res = -1;
+ int len, i, res = -1;
static char tuple = TUPLE;
goto finally;
if (len) {
- if ((has_key = cPickle_PyMapping_HasKey(self->memo, py_tuple_id)) < 0)
- goto finally;
-
- if (has_key) {
+ if (PyDict_GetItem(self->memo, py_tuple_id)) {
if (self->bin) {
static char pop_mark = POP_MARK;
static int
save_list(Picklerobject *self, PyObject *args) {
PyObject *element = 0;
- int s_len, len, i, using_appends, res = -1;
+ int s_len, len, i, using_appends, res = -1, unfast = 0;
char s[3];
static char append = APPEND, appends = APPENDS;
+ if (self->fast && self->fast_container++ > FAST_LIMIT) {
+ self->fast = 0;
+ unfast = 1;
+ }
+
if (self->bin) {
s[0] = EMPTY_LIST;
s_len = 1;
res = 0;
finally:
+ if (self->fast || unfast) {
+ self->fast_container--;
+ if (unfast && self->fast_container < FAST_LIMIT)
+ self->fast = 1;
+ }
return res;
}
static int
save_dict(Picklerobject *self, PyObject *args) {
PyObject *key = 0, *value = 0;
- int i, len, res = -1, using_setitems;
+ int i, len, res = -1, using_setitems, unfast = 0;
char s[3];
static char setitem = SETITEM, setitems = SETITEMS;
+ if (self->fast && self->fast_container++ > FAST_LIMIT) {
+ self->fast = 0;
+ unfast = 1;
+ }
+
if (self->bin) {
s[0] = EMPTY_DICT;
len = 1;
res = 0;
finally:
+ if (self->fast || unfast) {
+ self->fast_container--;
+ if (unfast && self->fast_container < FAST_LIMIT)
+ self->fast = 1;
+ }
+
return res;
}
PyObject *class = 0, *module = 0, *name = 0, *state = 0,
*getinitargs_func = 0, *getstate_func = 0, *class_args = 0;
char *module_str, *name_str;
- int module_size, name_size, res = -1;
+ int module_size, name_size, res = -1, unfast = 0;
static char inst = INST, obj = OBJ, build = BUILD;
+ if (self->fast && self->fast_container++ > FAST_LIMIT) {
+ self->fast = 0;
+ unfast = 1;
+ }
+
if ((*self->write_func)(self, &MARKv, 1) < 0)
goto finally;
int i, len;
UNLESS (class_args =
- PyObject_CallObject(getinitargs_func, empty_tuple))
+ PyObject_Call(getinitargs_func, empty_tuple, NULL))
goto finally;
if ((len = PyObject_Size(class_args)) < 0)
}
if ((getstate_func = PyObject_GetAttr(args, __getstate___str))) {
- UNLESS (state = PyObject_CallObject(getstate_func, empty_tuple))
+ UNLESS (state = PyObject_Call(getstate_func, empty_tuple, NULL))
goto finally;
}
else {
res = 0;
finally:
+ if (self->fast || unfast) {
+ self->fast_container--;
+ if (unfast && self->fast_container < FAST_LIMIT)
+ self->fast = 1;
+ }
+
Py_XDECREF(module);
Py_XDECREF(class);
Py_XDECREF(state);
Py_INCREF(args);
ARG_TUP(self, args);
if (self->arg) {
- pid = PyObject_CallObject(f, self->arg);
+ pid = PyObject_Call(f, self->arg, NULL);
FREE_ARG_TUP(self);
}
if (! pid) return -1;
}
if (args->ob_refcnt > 1) {
- int has_key;
-
UNLESS (py_ob_id = PyLong_FromVoidPtr(args))
goto finally;
- if ((has_key = cPickle_PyMapping_HasKey(self->memo, py_ob_id)) < 0)
- goto finally;
-
- if (has_key) {
+ if (PyDict_GetItem(self->memo, py_ob_id)) {
if (get(self, py_ob_id) < 0)
goto finally;
Py_INCREF(args);
ARG_TUP(self, args);
if (self->arg) {
- t = PyObject_CallObject(__reduce__, self->arg);
+ t = PyObject_Call(__reduce__, self->arg, NULL);
FREE_ARG_TUP(self);
}
if (! t) goto finally;
PyErr_Clear();
if ((__reduce__ = PyObject_GetAttr(args, __reduce___str))) {
- UNLESS (t = PyObject_CallObject(__reduce__, empty_tuple))
+ UNLESS (t = PyObject_Call(__reduce__, empty_tuple, NULL))
goto finally;
}
else {
static PyObject *
Pickle_clear_memo(Picklerobject *self, PyObject *args) {
- if (args && ! PyArg_ParseTuple(args,":clear_memo")) return NULL;
- if (self->memo) PyDict_Clear(self->memo);
- Py_INCREF(Py_None);
- return Py_None;
+ if (!PyArg_ParseTuple(args,":clear_memo"))
+ return NULL;
+ if (self->memo)
+ PyDict_Clear(self->memo);
+ Py_INCREF(Py_None);
+ return Py_None;
}
static PyObject *
char *s, *p, *have_get;
Pdata *data;
- if (args && ! PyArg_ParseTuple(args,"|i:getvalue",&clear)) return NULL;
+ /* 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");
+ "Attempt to getvalue() a non-list-based pickler");
return NULL;
- }
+ }
/* flush write buffer */
if (write_other(self, NULL, 0) < 0) return NULL;
if (get) return Pickle_getvalue(self, NULL);
+ /* XXX Why does dump() return self? */
Py_INCREF(self);
return (PyObject*)self;
}
self->write_buf = NULL;
self->bin = bin;
self->fast = 0;
+ self->fast_container = 0;
self->buf_size = 0;
self->dispatch_table = NULL;
static PyObject *
get_Pickler(PyObject *self, PyObject *args) {
- PyObject *file=NULL;
- int bin;
+ PyObject *file = NULL;
+ int bin = 1;
- bin=1;
- if (! PyArg_ParseTuple(args, "|i:Pickler", &bin)) {
+ if (!PyArg_ParseTuple(args, "|i:Pickler", &bin)) {
PyErr_Clear();
- bin=0;
- if (! PyArg_ParseTuple(args, "O|i:Pickler", &file, &bin))
- return NULL;
- }
+ bin = 0;
+ if (!PyArg_ParseTuple(args, "O|i:Pickler", &file, &bin))
+ return NULL;
+ }
return (PyObject *)newPicklerobject(file, bin);
}
PyObject_Del(self);
}
-
static PyObject *
-Pickler_getattr(Picklerobject *self, char *name) {
-
- switch (*name) {
- case 'p':
- if (strcmp(name, "persistent_id") == 0) {
- if (!self->pers_func) {
- PyErr_SetString(PyExc_AttributeError, name);
- return NULL;
- }
-
- Py_INCREF(self->pers_func);
- return self->pers_func;
- }
- break;
- case 'm':
- if (strcmp(name, "memo") == 0) {
- if (!self->memo) {
- PyErr_SetString(PyExc_AttributeError, name);
- return NULL;
- }
-
- Py_INCREF(self->memo);
- return self->memo;
- }
- break;
- case 'P':
- if (strcmp(name, "PicklingError") == 0) {
- Py_INCREF(PicklingError);
- return PicklingError;
- }
- break;
- case 'b':
- if (strcmp(name, "binary")==0)
- return PyInt_FromLong(self->bin);
- break;
- case 'f':
- if (strcmp(name, "fast")==0)
- return PyInt_FromLong(self->fast);
- break;
- case 'g':
- if (strcmp(name, "getvalue")==0 && ! Pdata_Check(self->file)) {
- PyErr_SetString(PyExc_AttributeError, name);
- return NULL;
- }
- break;
- }
- return Py_FindMethod(Pickler_methods, (PyObject *)self, name);
+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;
}
-
-int
-Pickler_setattr(Picklerobject *self, char *name, PyObject *value) {
-
- if (! value) {
+static int
+Pickler_set_pers_func(Picklerobject *p, PyObject *v)
+{
+ if (v == NULL) {
PyErr_SetString(PyExc_TypeError,
- "attribute deletion is not supported");
+ "attribute deletion is not supported");
return -1;
}
+ Py_XDECREF(p->pers_func);
+ Py_INCREF(v);
+ p->pers_func = v;
+ return 0;
+}
- if (strcmp(name, "persistent_id") == 0) {
- Py_XDECREF(self->pers_func);
- self->pers_func = value;
- Py_INCREF(value);
- return 0;
- }
-
- if (strcmp(name, "inst_persistent_id") == 0) {
- Py_XDECREF(self->inst_pers_func);
- self->inst_pers_func = value;
- Py_INCREF(value);
- 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;
+}
- if (strcmp(name, "memo") == 0) {
- if (! PyDict_Check(value)) {
- PyErr_SetString(PyExc_TypeError, "memo must be a dictionary");
- return -1;
- }
- Py_XDECREF(self->memo);
- self->memo = value;
- Py_INCREF(value);
- 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;
+}
- if (strcmp(name, "binary")==0) {
- self->bin=PyObject_IsTrue(value);
- return 0;
+static int
+Pickler_set_memo(Picklerobject *p, PyObject *v)
+{
+ if (v == NULL) {
+ PyErr_SetString(PyExc_TypeError,
+ "attribute deletion is not supported");
+ return -1;
}
-
- if (strcmp(name, "fast")==0) {
- self->fast=PyObject_IsTrue(value);
- return 0;
+ 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;
+}
- PyErr_SetString(PyExc_AttributeError, name);
- return -1;
+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)},
+};
+
+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}
+};
static char Picklertype__doc__[] =
-"Objects that know how to pickle objects\n"
-;
+"Objects that know how to pickle objects\n";
static PyTypeObject Picklertype = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"Pickler", /*tp_name*/
- sizeof(Picklerobject), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- /* methods */
- (destructor)Pickler_dealloc, /*tp_dealloc*/
- (printfunc)0, /*tp_print*/
- (getattrfunc)Pickler_getattr, /*tp_getattr*/
- (setattrfunc)Pickler_setattr, /*tp_setattr*/
- (cmpfunc)0, /*tp_compare*/
- (reprfunc)0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- (hashfunc)0, /*tp_hash*/
- (ternaryfunc)0, /*tp_call*/
- (reprfunc)0, /*tp_str*/
-
- /* Space for future expansion */
- 0L,0L,0L,0L,
- Picklertype__doc__ /* Documentation string */
+ 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 */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ PyObject_GenericSetAttr, /* 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 *
else goto err;
}
-
- if ((has_key = cPickle_PyMapping_HasKey(safe_constructors, cls)) < 0)
- goto err;
-
+ /* Is safe_constructors always a dict? */
+ has_key = cPickle_PyMapping_HasKey(safe_constructors, cls);
if (!has_key)
if (!(safe = PyObject_GetAttr(cls, __safe_for_unpickling___str)) ||
!PyObject_IsTrue(safe)) {
else {
ARG_TUP(self, pid);
if (self->arg) {
- pid = PyObject_CallObject(self->pers_func, self->arg);
+ pid = PyObject_Call(self->pers_func, self->arg, NULL);
FREE_ARG_TUP(self);
}
}
else {
ARG_TUP(self, pid);
if (self->arg) {
- pid = PyObject_CallObject(self->pers_func, self->arg);
+ pid = PyObject_Call(self->pers_func, self->arg, NULL);
FREE_ARG_TUP(self);
}
if (! pid) return -1;
junk=0;
ARG_TUP(self, value);
if (self->arg) {
- junk = PyObject_CallObject(append_method, self->arg);
+ junk = PyObject_Call(append_method, self->arg, NULL);
FREE_ARG_TUP(self);
}
if (! junk) {
if ((__setstate__ = PyObject_GetAttr(inst, __setstate___str))) {
ARG_TUP(self, value);
if (self->arg) {
- junk = PyObject_CallObject(__setstate__, self->arg);
+ junk = PyObject_Call(__setstate__, self->arg, NULL);
FREE_ARG_TUP(self);
}
Py_DECREF(__setstate__);
}
if (strcmp(name, "memo") == 0) {
- if (! PyDict_Check(value)) {
- PyErr_SetString(PyExc_TypeError, "memo must be a dictionary");
- return -1;
+ if (!PyDict_Check(value)) {
+ PyErr_SetString(PyExc_TypeError, "memo must be a dictionary");
+ return -1;
}
Py_XDECREF(self->memo);
self->memo = value;
init_stuff(PyObject *module_dict) {
PyObject *copy_reg, *t, *r;
-#define INIT_STR(S) UNLESS(S ## _str=PyString_FromString(#S)) return -1;
+#define INIT_STR(S) UNLESS(S ## _str=PyString_InternFromString(#S)) return -1;
INIT_STR(__class__);
INIT_STR(__getinitargs__);
return -1;
UNLESS (safe_constructors = PyObject_GetAttr(copy_reg,
- safe_constructors_str))
+ safe_constructors_str))
return -1;
Py_DECREF(copy_reg);