diff --git a/Modules/cPickle.c b/Modules/cPickle.c index b80548ec748..3be9282712b 100644 --- a/Modules/cPickle.c +++ b/Modules/cPickle.c @@ -59,59 +59,60 @@ static char cPickle_module_documentation[] = #include "Python.h" #include "cStringIO.h" #include "graminit.h" +#include "mymath.h" #include -static PyObject *ErrorObject; - -#ifdef __cplusplus -#define ARG(T, N) T N -#define ARGDECL(T, N) -#else -#define ARG(T, N) N -#define ARGDECL(T, N) T N; -#endif - #define UNLESS(E) if (!(E)) -#define ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;} -#define UNLESS_ASSIGN(V,E) ASSIGN(V,E) UNLESS(V) -#define DEL_LIST_SLICE(list, from, to) \ - (PyList_SetSlice(list, from, to, empty_list)) +#define DEL_LIST_SLICE(list, from, to) (PyList_SetSlice(list, from, to, NULL)) -#define APPEND 'a' -#define BUILD 'b' -#define DUP '2' -#define GET 'g' -#define BINGET 'h' -#define INST 'i' -#define OBJ 'o' -#define MARK '(' -static char MARKv = MARK; -#define PUT 'p' -#define BINPUT 'q' -#define POP '0' -#define SETITEM 's' -#define STOP '.' -#define CLASS 'c' -#define DICT 'd' -#define LIST 'l' -#define TUPLE 't' -#define NONE 'N' -#define INT 'I' -#define BININT 'J' -#define BININT1 'K' -#define BININT2 'M' -#define BININT3 'O' -#define LONG 'L' -#define FLOAT 'F' -#define STRING 'S' -#define BINSTRING 'T' +#define WRITE_BUF_SIZE 256 + + +#define MARK '(' +#define STOP '.' +#define POP '0' +#define POP_MARK '1' +#define DUP '2' +#define FLOAT 'F' +#ifdef FORMAT_1_3 +#define BINFLOAT 'G' +#endif +#define INT 'I' +#define BININT 'J' +#define BININT1 'K' +#define LONG 'L' +#define BININT2 'M' +#define NONE 'N' +#define PERSID 'P' +#define BINPERSID 'Q' +#define REDUCE 'R' +#define STRING 'S' +#define BINSTRING 'T' #define SHORT_BINSTRING 'U' -#define PERSID 'P' +#define APPEND 'a' +#define BUILD 'b' +#define GLOBAL 'c' +#define DICT 'd' +#define EMPTY_DICT '}' +#define APPENDS 'e' +#define GET 'g' +#define BINGET 'h' +#define INST 'i' +#define LONG_BINGET 'j' +#define LIST 'l' +#define EMPTY_LIST ']' +#define OBJ 'o' +#define PUT 'p' +#define BINPUT 'q' +#define LONG_BINPUT 'r' +#define SETITEM 's' +#define TUPLE 't' +#define EMPTY_TUPLE ')' +#define SETITEMS 'u' - -PyTypeObject *BuiltinFunctionType; +static char MARKv = MARK; /* atol function from string module */ static PyObject *atol_func; @@ -119,3645 +120,3765 @@ static PyObject *atol_func; static PyObject *PicklingError; static PyObject *UnpicklingError; +static PyObject *dispatch_table; +static PyObject *safe_constructors; static PyObject *class_map; -static PyObject *empty_list, *empty_tuple; +static PyObject *empty_tuple; -static PyObject *save(); +static PyObject *__class___str, *__getinitargs___str, *__dict___str, + *__getstate___str, *__setstate___str, *__name___str, *__reduce___str, + *write_str, *__safe_for_unpickling___str, *append_str, + *read_str, *readline_str; +/* __builtins__ module */ +static PyObject *builtins; -typedef struct -{ - PyObject_HEAD - FILE *fp; - PyObject *write; - PyObject *file; - PyObject *memo; - PyObject *arg; - PyObject *pers_func; - char *mark; - int bin; - int (*write_func)(); +static int save(); +static int put2(); + +typedef struct { + PyObject_HEAD + FILE *fp; + PyObject *write; + PyObject *file; + PyObject *memo; + PyObject *arg; + PyObject *pers_func; + PyObject *inst_pers_func; + int bin; + int (*write_func)(); + char *write_buf; + int buf_size; } Picklerobject; -staticforward PyTypeObject Picklertype; +static PyTypeObject Picklertype; -typedef struct -{ - PyObject_HEAD - FILE *fp; - PyObject *file; - PyObject *readline; - PyObject *read; - PyObject *memo; - PyObject *arg; - PyObject *stack; - PyObject *mark; - PyObject *pers_func; - int *marks; - int num_marks; - int marks_size; - int (*read_func)(); - int (*readline_func)(); +typedef struct { + PyObject_HEAD + FILE *fp; + PyObject *file; + PyObject *readline; + PyObject *read; + PyObject *memo; + PyObject *arg; + PyObject *stack; + PyObject *mark; + PyObject *pers_func; + PyObject *last_string; + int *marks; + int num_marks; + int marks_size; + int (*read_func)(); + int (*readline_func)(); + int buf_size; + char *buf; } Unpicklerobject; -staticforward PyTypeObject Unpicklertype; +static PyTypeObject Unpicklertype; - -static int -write_file(ARG(Picklerobject *, self), ARG(char *, s), ARG(int, n)) - ARGDECL(Picklerobject *, self) - ARGDECL(char *, s) - ARGDECL(int, n) +int +cPickle_PyMapping_HasKey(o, key) + PyObject *o; + PyObject *key; { - if (fwrite(s, sizeof(char), n, self->fp) != n) - { - PyErr_SetFromErrno(PyExc_IOError); - return -1; - } + PyObject *v; - return n; -} - - -static int -write_cStringIO(ARG(Picklerobject *, self), ARG(char *, s), ARG(int, n)) - ARGDECL(Picklerobject *, self) - ARGDECL(char *, s) - ARGDECL(int, n) -{ - if ((*PycStringIO_cwrite)((PyObject *)self->file, s, n) != n) - { - return -1; - } - - return n; -} - - -static int -write_other(ARG(Picklerobject *, self), ARG(char *, s), ARG(int, n)) - ARGDECL(Picklerobject *, self) - ARGDECL(char *, s) - ARGDECL(int, n) -{ - PyObject *py_str, *junk; - - UNLESS(py_str = PyString_FromStringAndSize(s, n)) - return -1; - - UNLESS(self->arg) - UNLESS(self->arg = PyTuple_New(1)) + if (v = PyObject_GetItem(o,key)) { - Py_DECREF(py_str); - return -1; + Py_DECREF(v); + return 1; } - if (PyTuple_SetItem(self->arg, 0, py_str) == -1) - { - Py_DECREF(py_str); - return -1; - } - - Py_INCREF(py_str); - UNLESS(junk = PyObject_CallObject(self->write, self->arg)) - { - Py_DECREF(py_str); - return -1; - } - - Py_DECREF(junk); - - return n; + PyErr_Clear(); + return 0; } - -static int -read_file(ARG(Unpicklerobject *, self), ARG(char **, s), ARG(int, n)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(char **, s) - ARGDECL(int, n) +PyObject * +#ifdef HAVE_STDARG_PROTOTYPES +/* VARARGS 2 */ +PyErr_Format(PyObject *ErrType, char *stringformat, char *format, ...) +#else +/* VARARGS */ +PyErr_Format(va_alist) va_dcl +#endif { - if (fread(*s, sizeof(char), n, self->fp) != n) - { - if (feof(self->fp)) + va_list va; + PyObject *args=0, *retval=0; +#ifdef HAVE_STDARG_PROTOTYPES + va_start(va, format); +#else + PyObject *ErrType; + char *stringformat, *format; + va_start(va); + ErrType = va_arg(va, PyObject *); + stringformat = va_arg(va, char *); + format = va_arg(va, char *); +#endif + + if(format) args = Py_VaBuildValue(format, va); + va_end(va); + if(format && ! args) return NULL; + if(stringformat && !(retval=PyString_FromString(stringformat))) return NULL; + + if(retval) { - PyErr_SetNone(PyExc_EOFError); - return -1; + if(args) + { + PyObject *v; + v=PyString_Format(retval, args); + Py_DECREF(retval); + Py_DECREF(args); + if(! v) return NULL; + retval=v; + } } - - PyErr_SetFromErrno(PyExc_IOError); - return -1; - } - - return n; -} - - -static int -readline_file(ARG(Unpicklerobject *, self), ARG(char **, s)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(char **, s) -{ - int size, i; - char *str; - - UNLESS(str = (char *)malloc(100)) - { - PyErr_SetString(PyExc_MemoryError, "out of memory"); - return -1; - } - - size = 100; - i = 0; - - while (1) - { - for (; i < size; i++) - { - if (feof(self->fp) || (str[i] = getc(self->fp)) == '\n') + else + if(args) retval=args; + else { - str[i] = 0; - *s = str; - return i; + PyErr_SetObject(ErrType,Py_None); + return NULL; } + PyErr_SetObject(ErrType,retval); + Py_DECREF(retval); + return NULL; +} + +static int +write_file(Picklerobject *self, char *s, int n) { + if (s == NULL) { + return 0; } - UNLESS(str = realloc(str, size += 100)) - { - PyErr_SetString(PyExc_MemoryError, "out of memory"); - return -1; + if ((int)fwrite(s, sizeof(char), n, self->fp) != n) { + PyErr_SetFromErrno(PyExc_IOError); + return -1; } - } + + return n; +} + + +static int +write_cStringIO(Picklerobject *self, char *s, int n) { + if (s == NULL) { + return 0; + } + + if (PycStringIO->cwrite((PyObject *)self->file, s, n) != n) { + return -1; + } + + return n; +} + + +static int +write_other(Picklerobject *self, char *s, int n) { + PyObject *py_str = 0, *junk = 0; + int res = -1; + + if (s == NULL) { + UNLESS(self->buf_size) return 0; + UNLESS(py_str = + PyString_FromStringAndSize(self->write_buf, self->buf_size)) + goto finally; + } + else { + if (self->buf_size && (n + self->buf_size) > WRITE_BUF_SIZE) { + if (write_other(self, NULL, 0) < 0) + goto finally; + } + + if (n > WRITE_BUF_SIZE) { + UNLESS(py_str = + PyString_FromStringAndSize(s, n)) + goto finally; + } + else { + memcpy(self->write_buf + self->buf_size, s, n); + self->buf_size += n; + res = n; + goto finally; + } + } + + UNLESS(self->arg) + UNLESS(self->arg = PyTuple_New(1)) + goto finally; + + Py_INCREF(py_str); + if (PyTuple_SetItem(self->arg, 0, py_str) < 0) + goto finally; + + UNLESS(junk = PyObject_CallObject(self->write, self->arg)) + goto finally; + Py_DECREF(junk); + + self->buf_size = 0; + + res = n; + +finally: + Py_XDECREF(py_str); + + return res; +} + + +static int +read_file(Unpicklerobject *self, char **s, int n) { + + if (self->buf_size == 0) { + int size; + + size = ((n < 32) ? 32 : n); + UNLESS(self->buf = (char *)malloc(size * sizeof(char))) { + PyErr_NoMemory(); + return -1; + } + + self->buf_size = size; + } + else if (n > self->buf_size) { + UNLESS(self->buf = (char *)realloc(self->buf, n * sizeof(char))) { + PyErr_NoMemory(); + return -1; + } + + self->buf_size = n; + } + + if ((int)fread(self->buf, sizeof(char), n, self->fp) != n) { + if (feof(self->fp)) { + PyErr_SetNone(PyExc_EOFError); + return -1; + } + + PyErr_SetFromErrno(PyExc_IOError); + return -1; + } + + *s = self->buf; + + return n; +} + + +static int +readline_file(Unpicklerobject *self, char **s) { + int i; + + if (self->buf_size == 0) { + UNLESS(self->buf = (char *)malloc(40 * sizeof(char))) { + PyErr_NoMemory(); + return -1; + } + + self->buf_size = 40; + } + + i = 0; + while (1) { + for (; i < (self->buf_size - 1); i++) { + if (feof(self->fp) || (self->buf[i] = getc(self->fp)) == '\n') { + self->buf[i + 1] = '\0'; + *s = self->buf; + return i + 1; + } + } + + UNLESS(self->buf = (char *)realloc(self->buf, + (self->buf_size * 2) * sizeof(char))) { + PyErr_NoMemory(); + return -1; + } + + self->buf_size *= 2; + } + } static int -read_cStringIO(ARG(Unpicklerobject *, self), ARG(char **, s), ARG(int, n)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(char **, s) - ARGDECL(int, n) -{ - char *ptr; +read_cStringIO(Unpicklerobject *self, char **s, int n) { + char *ptr; - if ((*PycStringIO_cread)((PyObject *)self->file, &ptr, n) != n) - { - PyErr_SetNone(PyExc_EOFError); - return -1; - } - - memcpy(*s, ptr, n); - return n; -} - - -static int -readline_cStringIO(ARG(Unpicklerobject *, self), ARG(char **, s)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(char **, s) -{ - int n; - char *ptr, *str; - - if ((n = (*PycStringIO_creadline)((PyObject *)self->file, &ptr)) == -1) - { - return -1; - } - - UNLESS(str = (char *)malloc(n * sizeof(char) + 1)) - { - PyErr_SetString(PyExc_MemoryError, "out of memory"); - return -1; - } - - memcpy(str, ptr, n); - - str[((str[n - 1] == '\n') ? --n : n)] = 0; - - *s = str; - return n; -} - - -static int -read_other(ARG(Unpicklerobject *, self), ARG(char **, s), ARG(int, n)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(char **, s) - ARGDECL(int, n) -{ - PyObject *bytes, *str; - - UNLESS(bytes = PyInt_FromLong(n)) - { - if (!PyErr_Occurred()) - PyErr_SetNone(PyExc_EOFError); - - return -1; - } - - UNLESS(self->arg) - UNLESS(self->arg = PyTuple_New(1)) - { - Py_DECREF(bytes); - return -1; - } - - if (PyTuple_SetItem(self->arg, 0, bytes) == -1) - { - Py_DECREF(bytes); - return -1; - } - Py_INCREF(bytes); - - UNLESS(str = PyObject_CallObject(self->read, self->arg)) - { - Py_DECREF(bytes); - return -1; - } - - memcpy(*s, PyString_AsString(str), n); - - Py_DECREF(bytes); - Py_DECREF(str); - - return n; -} - - -static int -readline_other(ARG(Unpicklerobject *, self), ARG(char **, s)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(char **, s) -{ - PyObject *str; - char *c_str; - int size; - - UNLESS(str = PyObject_CallObject(self->readline, empty_tuple)) - { - return -1; - } - - size = PyString_Size(str); - - UNLESS(c_str = (char *)malloc((size + 1) * sizeof(char))) - { - PyErr_SetString(PyExc_MemoryError, "out of memory"); - return -1; - } - - memcpy(c_str, PyString_AsString(str), size); - - if (size > 0) - { - c_str[((c_str[size - 1] == '\n') ? --size : size)] = 0; - } - - *s = c_str; - - Py_DECREF(str); - - return size; -} - - -static int -put(ARG(Picklerobject *, self), ARG(PyObject *, ob)) - ARGDECL(Picklerobject *, self) - ARGDECL(PyObject *, ob) -{ - char c_str[30]; - int p, len; - PyObject *py_ob_id = 0, *memo_len = 0; - - if ((p = PyDict_Size(self->memo)) == -1) - return -1; - - if (!self->bin || (p >= 256)) - { - c_str[0] = PUT; - sprintf(c_str + 1, "%d\n", p); - len = strlen(c_str); - } - else - { - c_str[0] = BINPUT; - c_str[1] = p; - len = 2; - } - - if ((*self->write_func)(self, c_str, len) == -1) - return -1; - - UNLESS(py_ob_id = PyInt_FromLong((long)ob)) - return -1; - - UNLESS(memo_len = PyInt_FromLong(p)) - goto err; - - if (PyDict_SetItem(self->memo, py_ob_id, memo_len) == -1) - goto err; - - Py_DECREF(py_ob_id); - Py_DECREF(memo_len); - - return 1; - -err: - Py_XDECREF(py_ob_id); - Py_XDECREF(memo_len); - - return -1; -} - - -static int -safe(ARG(PyObject *, ob)) - ARGDECL(PyObject *, ob) -{ - PyTypeObject *type; - PyObject *this_item; - int len, res, i; - - type = ob->ob_type; - - if (type == &PyInt_Type || - type == &PyFloat_Type || - type == &PyString_Type || - ob == Py_None) - { - return 1; - } - - if (type == &PyTuple_Type) - { - len = PyTuple_Size(ob); - for (i = 0; i < len; i++) - { - UNLESS(this_item = PyTuple_GET_ITEM((PyTupleObject *)ob, i)) + if (PycStringIO->cread((PyObject *)self->file, &ptr, n) != n) { + PyErr_SetNone(PyExc_EOFError); return -1; - - if ((res = safe(this_item)) == 1) - continue; - - return res; } - return 1; - } + *s = ptr; - return 0; + return n; +} + + +static int +readline_cStringIO(Unpicklerobject *self, char **s) { + int n; + char *ptr; + + if ((n = PycStringIO->creadline((PyObject *)self->file, &ptr)) < 0) { + return -1; + } + + *s = ptr; + + return n; +} + + +static int +read_other(Unpicklerobject *self, char **s, int n) { + PyObject *bytes, *str; + int res = -1; + + UNLESS(bytes = PyInt_FromLong(n)) { + if (!PyErr_Occurred()) + PyErr_SetNone(PyExc_EOFError); + + goto finally; + } + + UNLESS(self->arg) + UNLESS(self->arg = PyTuple_New(1)) + goto finally; + + Py_INCREF(bytes); + if (PyTuple_SetItem(self->arg, 0, bytes) < 0) + goto finally; + + UNLESS(str = PyObject_CallObject(self->read, self->arg)) + goto finally; + + Py_XDECREF(self->last_string); + self->last_string = str; + + *s = PyString_AsString(str); + + res = n; + +finally: + Py_XDECREF(bytes); + + return res; +} + + +static int +readline_other(Unpicklerobject *self, char **s) { + PyObject *str; + int str_size; + + UNLESS(str = PyObject_CallObject(self->readline, empty_tuple)) { + return -1; + } + + str_size = PyString_Size(str); + + Py_XDECREF(self->last_string); + self->last_string = str; + + *s = PyString_AsString(str); + + return str_size; +} + + +static char * +strndup(char *s, int l) +{ + char *r; + UNLESS(r=malloc((l+1)*sizeof(char))) return (char*)PyErr_NoMemory(); + memcpy(r,s,l); + r[l]=0; + return r; +} + + +static int +get(Picklerobject *self, PyObject *id) { + PyObject *value = 0; + long c_value; + char s[30]; + int len; + + UNLESS(value = PyDict_GetItem(self->memo, id)) + return -1; + + UNLESS(value = PyTuple_GetItem(value, 0)) + return -1; + + c_value = PyInt_AsLong(value); + + if (!self->bin) { + s[0] = GET; + sprintf(s + 1, "%ld\n", c_value); + len = strlen(s); + } + else { + if (c_value < 256) { + s[0] = BINGET; + s[1] = (int)(c_value & 0xff); + len = 2; + } + else { + s[0] = LONG_BINGET; + s[1] = (int)(c_value & 0xff); + s[2] = (int)((c_value >> 8) & 0xff); + s[3] = (int)((c_value >> 16) & 0xff); + s[4] = (int)((c_value >> 24) & 0xff); + len = 5; + } + } + + if ((*self->write_func)(self, s, len) < 0) + return -1; + + return 0; +} + + +static int +put(Picklerobject *self, PyObject *ob) { + if (ob->ob_refcnt < 2) + return 0; + + return put2(self, ob); +} + + +static int +put2(Picklerobject *self, PyObject *ob) { + char c_str[30]; + int p, len, res = -1; + PyObject *py_ob_id = 0, *memo_len = 0, *t = 0; + if ((p = PyDict_Size(self->memo)) < 0) + goto finally; + + if (!self->bin) { + c_str[0] = PUT; + sprintf(c_str + 1, "%d\n", p); + len = strlen(c_str); + } + else { + if (p >= 256) { + c_str[0] = LONG_BINPUT; + c_str[1] = (int)(p & 0xff); + c_str[2] = (int)((p >> 8) & 0xff); + c_str[3] = (int)((p >> 16) & 0xff); + c_str[4] = (int)((p >> 24) & 0xff); + len = 5; + } + else { + c_str[0] = BINPUT; + c_str[1] = p; + len = 2; + } + } + + if ((*self->write_func)(self, c_str, len) < 0) + goto finally; + + UNLESS(py_ob_id = PyInt_FromLong((long)ob)) + goto finally; + + UNLESS(memo_len = PyInt_FromLong(p)) + goto finally; + + UNLESS(t = PyTuple_New(2)) + goto finally; + + PyTuple_SET_ITEM(t, 0, memo_len); + Py_INCREF(memo_len); + PyTuple_SET_ITEM(t, 1, ob); + Py_INCREF(ob); + + if (PyDict_SetItem(self->memo, py_ob_id, t) < 0) + goto finally; + + res = 0; + +finally: + Py_XDECREF(py_ob_id); + Py_XDECREF(memo_len); + Py_XDECREF(t); + + return res; } static PyObject * -whichmodule(ARG(PyObject *, class)) - ARGDECL(PyObject *, class) -{ - int has_key, i, j; - PyObject *module = 0, *modules_dict = 0, *class_name = 0, *class_name_attr = 0, - *name = 0; - char *name_str, *class_name_str; +whichmodule(PyObject *global, PyObject *global_name) { + int i, j; + PyObject *module = 0, *modules_dict = 0, + *global_name_attr = 0, *name = 0; - static PyObject *__main__str; - - if ((has_key = PyMapping_HasKey(class_map, class)) == -1) - return NULL; - - if (has_key) - { - return ((module = PyDict_GetItem(class_map, class)) ? module : NULL); - } - - UNLESS(modules_dict = PySys_GetObject("modules")) - return NULL; - - UNLESS(class_name = ((PyClassObject *)class)->cl_name) - { - PyErr_SetString(PicklingError, "class has no name"); - return NULL; - } - - UNLESS(class_name_str = PyString_AsString(class_name)) - return NULL; - - i = 0; - while ((j = PyDict_Next(modules_dict, &i, &name, &module))) - { - UNLESS(name_str = PyString_AsString(name)) - return NULL; - - if (!strcmp(name_str, "__main__")) - continue; - - UNLESS(class_name_attr = PyObject_GetAttr(module, class_name)) - { - PyErr_Clear(); - continue; + if (module = PyDict_GetItem(class_map, global)) { + Py_INCREF(module); + return module; + } + else { + PyErr_Clear(); } - if (class_name_attr != class) - { - Py_DECREF(class_name_attr); - continue; - } - - Py_DECREF(class_name_attr); - - break; - } - - if (!j) /* previous while exited normally */ - { - UNLESS(__main__str) - UNLESS(__main__str = PyString_FromString("__main__")) + UNLESS(modules_dict = PySys_GetObject("modules")) return NULL; - name = __main__str; - } - else /* previous while exited via break */ - { - Py_INCREF(name); - } - - PyDict_SetItem(class_map, class, name); + i = 0; + while (j = PyDict_Next(modules_dict, &i, &name, &module)) { + UNLESS(global_name_attr = PyObject_GetAttr(module, global_name)) { + PyErr_Clear(); + continue; + } - return name; + if (global_name_attr != global) { + Py_DECREF(global_name_attr); + continue; + } + + Py_DECREF(global_name_attr); + + break; + } + + if (!j) { + PyErr_Format(PicklingError, "Could not find module for %s.", + "O", global_name); + return NULL; + } + + PyDict_SetItem(class_map, global, name); + + Py_INCREF(name); + return name; } -static PyObject * -save_none(ARG(Picklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Picklerobject *, self) - ARGDECL(PyObject *, args) -{ - static char none[] = { NONE }; +static int +save_none(Picklerobject *self, PyObject *args) { + static char none = NONE; + if ((*self->write_func)(self, &none, 1) < 0) + return -1; - if ((*self->write_func)(self, none, 1) == -1) - return NULL; - - Py_INCREF(Py_None); - return Py_None; + return 0; } -static PyObject * -save_int(ARG(Picklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Picklerobject *, self) - ARGDECL(PyObject *, args) -{ - char c_str[25]; - long l = PyInt_AS_LONG((PyIntObject *)args); - int len; +static int +save_int(Picklerobject *self, PyObject *args) { + char c_str[32]; + long l = PyInt_AS_LONG((PyIntObject *)args); + int len = 0; - if (!self->bin) - { - c_str[0] = INT; - sprintf(c_str + 1, "%ld\n", l); - if ((*self->write_func)(self, c_str, strlen(c_str)) == -1) - return NULL; - } - else - { - c_str[1] = (int)(l & 0xff); - c_str[2] = (int)((l >> 8) & 0xff); - c_str[3] = (int)((l >> 16) & 0xff); - c_str[4] = (int)((l >> 24) & 0xff); + if (!self->bin || sizeof(long) == 8 && (l >> 32)) { + /* Save extra-long ints in non-binary mode, so that + we can use python long parsing code to restore, + if necessary. */ + c_str[0] = INT; + sprintf(c_str + 1, "%ld\n", l); + if ((*self->write_func)(self, c_str, strlen(c_str)) < 0) + return -1; + } + else { + c_str[1] = (int)( l & 0xff); + c_str[2] = (int)((l >> 8) & 0xff); + c_str[3] = (int)((l >> 16) & 0xff); + c_str[4] = (int)((l >> 24) & 0xff); - if (!c_str[4]) - { - if (!c_str[3]) - { - if (!c_str[2]) - { - c_str[0] = BININT3; - len = 2; + if ((c_str[4] == 0) && (c_str[3] == 0)) { + if (c_str[2] == 0) { + c_str[0] = BININT1; + len = 2; + } + else { + c_str[0] = BININT2; + len = 3; + } + } + else { + c_str[0] = BININT; + len = 5; + } + + if ((*self->write_func)(self, c_str, len) < 0) + return -1; + } + + return 0; +} + + +static int +save_long(Picklerobject *self, PyObject *args) { + int size, res = -1; + PyObject *repr = 0; + + static char l = LONG; + + UNLESS(repr = PyObject_Repr(args)) + goto finally; + + if ((size = PyString_Size(repr)) < 0) + goto finally; + + if ((*self->write_func)(self, &l, 1) < 0) + goto finally; + + if ((*self->write_func)(self, + PyString_AS_STRING((PyStringObject *)repr), size) < 0) + goto finally; + + if ((*self->write_func)(self, "\n", 1) < 0) + goto finally; + + res = 0; + +finally: + Py_XDECREF(repr); + + return res; +} + + +static int +save_float(Picklerobject *self, PyObject *args) { + double x = PyFloat_AS_DOUBLE((PyFloatObject *)args); + +#ifdef FORMAT_1_3 + if (self->bin) { + int s, e, i = -1; + double f; + long fhi, flo; + char str[9], *p = str; + + *p = BINFLOAT; + p++; + + if (x < 0) { + s = 1; + x = -x; } else - { - c_str[0] = BININT2; - len = 3; + s = 0; + + f = frexp(x, &e); + + /* Normalize f to be in the range [1.0, 2.0) */ + if (0.5 <= f && f < 1.0) { + f *= 2.0; + e--; } - } - else - { - c_str[0] = BININT1; - len = 4; - } + else if (f == 0.0) { + e = 0; + } + else { + PyErr_SetString(PyExc_SystemError, + "frexp() result out of range"); + return -1; + } + + if (e >= 1024) { + /* XXX 1024 itself is reserved for Inf/NaN */ + PyErr_SetString(PyExc_OverflowError, + "float too large to pack with d format"); + return -1; + } + else if (e < -1022) { + /* Gradual underflow */ + f = ldexp(f, 1022 + e); + e = 0; + } + else { + e += 1023; + f -= 1.0; /* Get rid of leading 1 */ + } + + /* fhi receives the high 28 bits; flo the low 24 bits (== 52 bits) */ + f *= 268435456.0; /* 2**28 */ + fhi = (long) floor(f); /* Truncate */ + f -= (double)fhi; + f *= 16777216.0; /* 2**24 */ + flo = (long) floor(f + 0.5); /* Round */ + + /* First byte */ + *p = (s<<7) | (e>>4); + p++; + + /* Second byte */ + *p = ((e&0xF)<<4) | (fhi>>24); + p++; + + /* Third byte */ + *p = (fhi>>16) & 0xFF; + p++; + + /* Fourth byte */ + *p = (fhi>>8) & 0xFF; + p++; + + /* Fifth byte */ + *p = fhi & 0xFF; + p++; + + /* Sixth byte */ + *p = (flo>>16) & 0xFF; + p++; + + /* Seventh byte */ + *p = (flo>>8) & 0xFF; + p++; + + /* Eighth byte */ + *p = flo & 0xFF; + + if ((*self->write_func)(self, str, 9) < 0) + return -1; + } + else +#endif + { + char c_str[250]; + c_str[0] = FLOAT; + sprintf(c_str + 1, "%f\n", x); + + if ((*self->write_func)(self, c_str, strlen(c_str)) < 0) + return -1; + } + + return 0; +} + + +static int +save_string(Picklerobject *self, PyObject *args) { + int size, len; + + size = PyString_Size(args); + + if (!self->bin) { + PyObject *repr; + char *repr_str; + + static char string = STRING; + + UNLESS(repr = PyObject_Repr(args)) + return -1; + + repr_str = PyString_AS_STRING((PyStringObject *)repr); + len = PyString_Size(repr); + + if ((*self->write_func)(self, &string, 1) < 0) + return -1; + + if ((*self->write_func)(self, repr_str, len) < 0) + return -1; + + if ((*self->write_func)(self, "\n", 1) < 0) + return -1; + + Py_XDECREF(repr); + } + else { + int i; + char c_str[5]; + + size = PyString_Size(args); + + if (size < 256) { + c_str[0] = SHORT_BINSTRING; + c_str[1] = size; + len = 2; + } + else { + c_str[0] = BINSTRING; + for (i = 1; i < 5; i++) + c_str[i] = (int)(size >> ((i - 1) * 8)); + len = 5; + } + + if ((*self->write_func)(self, c_str, len) < 0) + return -1; + + if ((*self->write_func)(self, + PyString_AS_STRING((PyStringObject *)args), size) < 0) + return -1; + } + + if (size > 1) + if (put(self, args) < 0) + return -1; + + return 0; +} + + +static int +save_tuple(Picklerobject *self, PyObject *args) { + PyObject *element = 0, *py_tuple_id = 0; + int len, i, has_key, res = -1; + + static char tuple = TUPLE; + + if ((*self->write_func)(self, &MARKv, 1) < 0) + goto finally; + + if ((len = PyTuple_Size(args)) < 0) + goto finally; + + for (i = 0; i < len; i++) { + UNLESS(element = PyTuple_GET_ITEM((PyTupleObject *)args, i)) + goto finally; + + if (save(self, element, 0) < 0) + goto finally; + } + + UNLESS(py_tuple_id = PyInt_FromLong((long)args)) + goto finally; + + if (len) { + if (has_key = cPickle_PyMapping_HasKey(self->memo, py_tuple_id) < 0) + goto finally; + + if (has_key) { + if (self->bin) { + static char pop_mark = POP_MARK; + + if ((*self->write_func)(self, &pop_mark, 1) < 0) + goto finally; + } + else { + static char pop = POP; + + for (i = 0; i <= len; i++) { + if ((*self->write_func)(self, &pop, 1) < 0) + goto finally; + } + } + + if (get(self, py_tuple_id) < 0) + goto finally; + + res = 0; + goto finally; + } + } + + if ((*self->write_func)(self, &tuple, 1) < 0) { + goto finally; + } + + if (put(self, args) < 0) + goto finally; + + res = 0; + +finally: + Py_XDECREF(py_tuple_id); + + return res; +} + +static int +save_empty_tuple(Picklerobject *self, PyObject *args) { + static char tuple = EMPTY_TUPLE; + + return (*self->write_func)(self, &tuple, 1); +} + + +static int +save_list(Picklerobject *self, PyObject *args) { + PyObject *element = 0; + int s_len, len, i, using_appends, res = -1; + char s[3]; + + static char append = APPEND, appends = APPENDS; + + if(self->bin) { + s[0] = EMPTY_LIST; + s_len = 1; + } + else { + s[0] = MARK; + s[1] = LIST; + s_len = 2; + } + + if ((len = PyList_Size(args)) < 0) + goto finally; + + if ((*self->write_func)(self, s, s_len) < 0) + goto finally; + + if (len == 0) + { + if (put(self, args) < 0) + goto finally; } else { - c_str[0] = BININT; - len = 5; + if (put2(self, args) < 0) + goto finally; } - if ((*self->write_func)(self, c_str, len) == -1) - return NULL; - } + if (using_appends = (self->bin && (len > 1))) + if ((*self->write_func)(self, &MARKv, 1) < 0) + goto finally; - Py_INCREF(Py_None); - return Py_None; + for (i = 0; i < len; i++) { + UNLESS(element = PyList_GET_ITEM((PyListObject *)args, i)) + goto finally; + + if (save(self, element, 0) < 0) + goto finally; + + if (!using_appends) { + if ((*self->write_func)(self, &append, 1) < 0) + goto finally; + } + } + + if (using_appends) { + if ((*self->write_func)(self, &appends, 1) < 0) + goto finally; + } + + res = 0; + +finally: + + return res; } -static PyObject * -save_long(ARG(Picklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Picklerobject *, self) - ARGDECL(PyObject *, args) -{ - char *c_str; - int size; - PyObject *repr = 0; +static int +save_dict(Picklerobject *self, PyObject *args) { + PyObject *key = 0, *value = 0; + int i, len, res = -1, using_setitems; + char s[3]; - UNLESS(repr = PyObject_Repr(args)) - return NULL; + static char setitem = SETITEM, setitems = SETITEMS; - if ((size = PyString_Size(repr)) == -1) - { - Py_DECREF(repr); - return NULL; - } + if (self->bin) { + s[0] = EMPTY_DICT; + len = 1; + } + else { + s[0] = MARK; + s[1] = DICT; + len = 2; + } - UNLESS(c_str = (char *)malloc((size + 2) * sizeof(char))) - { - Py_DECREF(repr); - PyErr_SetString(PyExc_MemoryError, "out of memory"); - return NULL; - } + if ((*self->write_func)(self, s, len) < 0) + goto finally; - c_str[0] = LONG; - memcpy(c_str + 1, PyString_AS_STRING((PyStringObject *)repr), size); - c_str[size + 1] = '\n'; + if ((len = PyDict_Size(args)) < 0) + goto finally; - Py_DECREF(repr); + if (len == 0) + { + if (put(self, args) < 0) + goto finally; + } + else + { + if (put2(self, args) < 0) + goto finally; + } - if ((*self->write_func)(self, c_str, size + 2) == -1) - { - free(c_str); - return NULL; - } + if (using_setitems = (self->bin && (PyDict_Size(args) > 1))) + if ((*self->write_func)(self, &MARKv, 1) < 0) + goto finally; - free(c_str); + i = 0; + while (PyDict_Next(args, &i, &key, &value)) { + if (save(self, key, 0) < 0) + goto finally; - Py_INCREF(Py_None); - return Py_None; + if (save(self, value, 0) < 0) + goto finally; + + if (!using_setitems) { + if ((*self->write_func)(self, &setitem, 1) < 0) + goto finally; + } + } + + if (using_setitems) { + if ((*self->write_func)(self, &setitems, 1) < 0) + goto finally; + } + + res = 0; + +finally: + + return res; } -static PyObject * -save_float(ARG(Picklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Picklerobject *, self) - ARGDECL(PyObject *, args) -{ - char c_str[250]; +static int +save_inst(Picklerobject *self, PyObject *args) { + 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; - c_str[0] = FLOAT; - sprintf(c_str + 1, "%f\n", PyFloat_AS_DOUBLE((PyFloatObject *)args)); + static char inst = INST, obj = OBJ, build = BUILD; - if ((*self->write_func)(self, c_str, strlen(c_str)) == -1) - return NULL; + if ((*self->write_func)(self, &MARKv, 1) < 0) + goto finally; - Py_INCREF(Py_None); - return Py_None; -} + UNLESS(class = PyObject_GetAttr(args, __class___str)) + goto finally; - -static PyObject * -save_string(ARG(Picklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Picklerobject *, self) - ARGDECL(PyObject *, args) -{ - char *c_str; - int size, len; - - if (!self->bin) - { - PyObject *repr; - char *repr_str; - - UNLESS(repr = PyObject_Repr(args)) - return NULL; - - repr_str = PyString_AS_STRING((PyStringObject *)repr); - size = PyString_Size(repr); - - UNLESS(c_str = (char *)malloc((size + 2) * sizeof(char))) - { - PyErr_SetString(PyExc_MemoryError, "out of memory"); - return NULL; - } - - c_str[0] = STRING; - memcpy(c_str + 1, repr_str, size); - c_str[size + 1] = '\n'; - - len = size + 2; - - Py_XDECREF(repr); - } - else - { - size = PyString_Size(args); - - UNLESS(c_str = (char *)malloc((size + 30) * sizeof(char))) - { - PyErr_SetString(PyExc_MemoryError, "out of memory"); - return NULL; + if (self->bin) { + if (save(self, class, 0) < 0) + goto finally; } - if (size < 256) - { - c_str[0] = SHORT_BINSTRING; - c_str[1] = size; - len = 2; + if (getinitargs_func = PyObject_GetAttr(args, __getinitargs___str)) { + PyObject *element = 0; + int i, len; + + UNLESS(class_args = + PyObject_CallObject(getinitargs_func, empty_tuple)) + goto finally; + + if ((len = PyObject_Length(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 - { - c_str[0] = BINSTRING; - sprintf(c_str + 1, "%d\n", size); - len = strlen(c_str); + else { + PyErr_Clear(); } - memcpy(c_str + len, PyString_AS_STRING((PyStringObject *)args), size); + if (!self->bin) { + UNLESS(name = ((PyClassObject *)class)->cl_name) { + PyErr_SetString(PicklingError, "class has no name"); + goto finally; + } - len += size; - } + UNLESS(module = whichmodule(class, name)) + goto finally; + + module_str = PyString_AS_STRING((PyStringObject *)module); + module_size = PyString_Size(module); + name_str = PyString_AS_STRING((PyStringObject *)name); + name_size = PyString_Size(name); - if ((*self->write_func)(self, c_str, len) == -1) - { - free(c_str); - return NULL; - } + if ((*self->write_func)(self, &inst, 1) < 0) + goto finally; - free(c_str); + if ((*self->write_func)(self, module_str, module_size) < 0) + goto finally; - if (args->ob_refcnt > 1) - { - if (put(self, args) == -1) - { - return NULL; + 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_CallObject(getstate_func, empty_tuple)) + 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; } - } - Py_INCREF(Py_None); - return Py_None; + if (save(self, state, 0) < 0) + goto finally; + + if ((*self->write_func)(self, &build, 1) < 0) + goto finally; + + res = 0; + +finally: + Py_XDECREF(module); + Py_XDECREF(class); + Py_XDECREF(state); + Py_XDECREF(getinitargs_func); + Py_XDECREF(getstate_func); + Py_XDECREF(class_args); + + return res; } -static PyObject * -save_tuple(ARG(Picklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Picklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *element = 0, *junk = 0, *py_tuple_id = 0; - int len, i, dict_size; +static int +save_global(Picklerobject *self, PyObject *args, PyObject *name) { + PyObject *global_name = 0, *module = 0; + char *name_str, *module_str; + int module_size, name_size, res = -1; - static char tuple = TUPLE; + static char global = GLOBAL; - if ((*self->write_func)(self, &MARKv, 1) == -1) - return NULL; - - UNLESS(py_tuple_id = PyInt_FromLong((long)args)) return NULL; - - if ((len = PyTuple_Size(args)) == -1) - goto err; - - for (i = 0; i < len; i++) - { - UNLESS(element = PyTuple_GET_ITEM((PyTupleObject *)args, i)) - goto err; - - dict_size = PyDict_Size(self->memo); - - UNLESS(junk = save(self, element)) - goto err; - Py_DECREF(junk); - - if (((PyDict_Size(self->memo) - dict_size) > 1) && - PyMapping_HasKey(self->memo, py_tuple_id)) + if (name) { - char c_str[30]; - long c_value; - int c_str_len; - PyObject *value; - static char pop = POP; - - while (i-- >= 0) - { - if ((*self->write_func)(self, &pop, 1) == -1) - goto err; - } - - UNLESS(value = PyDict_GetItem(self->memo, py_tuple_id)) - goto err; - - c_value = PyInt_AsLong(value); - - if (self->bin && (c_value < 256)) - { - c_str[0] = BINGET; - c_str[1] = c_value; - c_str_len = 2; - } - else - { - c_str[0] = GET; - sprintf(c_str + 1, "%ld\n", c_value); - c_str_len = strlen(c_str); - } - - if ((*self->write_func)(self, c_str, c_str_len) == -1) - goto err; - - break; + global_name = name; + Py_INCREF(global_name); } - } - - if (i >= len) - { - if ((*self->write_func)(self, &tuple, 1) == -1) - goto err; - - if (args->ob_refcnt > 1) + else { - if (put(self, args) == -1) - { - goto err; - } - } - } - - Py_DECREF(py_tuple_id); - - Py_INCREF(Py_None); - return Py_None; - -err: - Py_XDECREF(py_tuple_id); - - return NULL; -} - - -static PyObject * -save_list(ARG(Picklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Picklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *element = 0, *junk = 0; - int len, i, safe_val; - static char append = APPEND, list = LIST; - - if ((*self->write_func)(self, &MARKv, 1) == -1) - return NULL; - - if ((len = PyList_Size(args)) == -1) - return NULL; - - for (i = 0; i < len; i++) - { - UNLESS(element = PyList_GET_ITEM((PyListObject *)args, i)) - return NULL; - - if ((safe_val = safe(element)) == -1) - return NULL; - UNLESS(safe_val) - break; - - UNLESS(junk = save(self, element)) - return NULL; - Py_DECREF(junk); - } - - if (args->ob_refcnt > 1) - { - if (put(self, args) == -1) - { - return NULL; - } - } - - if ((*self->write_func)(self, &list, 1) == -1) - return NULL; - - for (; i < len; i++) - { - UNLESS(element = PyList_GET_ITEM((PyListObject *)args, i)) - return NULL; - - UNLESS(junk = save(self, element)) - return NULL; - Py_DECREF(junk); - - if ((*self->write_func)(self, &append, 1) == -1) - return NULL; - } - - Py_INCREF(Py_None); - return Py_None; -} - - -static PyObject * -save_dict(ARG(Picklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Picklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *key = 0, *value = 0, *junk = 0; - int i, safe_key, safe_value; - - static char setitem = SETITEM, dict = DICT; - - if ((*self->write_func)(self, &MARKv, 1) == -1) - return NULL; - - i = 0; - - while (PyDict_Next(args, &i, &key, &value)) - { - if ((safe_key = safe(key)) == -1) - return NULL; - - UNLESS(safe_key) - break; - - if ((safe_value = safe(value)) == -1) - return NULL; - - UNLESS(safe_value) - break; - - UNLESS(junk = save(self, key)) - return NULL; - Py_DECREF(junk); - - UNLESS(junk = save(self, value)) - return NULL; - Py_DECREF(junk); - } - - if ((*self->write_func)(self, &dict, 1) == -1) - return NULL; - - if (args->ob_refcnt > 1) - { - if (put(self, args) == -1) - { - return NULL; - } - } - - while (PyDict_Next(args, &i, &key, &value)) - { - UNLESS(junk = save(self, key)) - return NULL; - Py_DECREF(junk); - - UNLESS(junk = save(self, value)) - return NULL; - Py_DECREF(junk); - - if ((*self->write_func)(self, &setitem, 1) == -1) - return NULL; - } - - Py_INCREF(Py_None); - return Py_None; -} - - -static PyObject * -save_inst(ARG(Picklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Picklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *class = 0, *module = 0, *name = 0, - *junk = 0, *state = 0, *getinitargs_func = 0, *getstate_func = 0; - char *module_str, *name_str, *c_str; - int module_size, name_size, size; - static char build = BUILD; - - if ((*self->write_func)(self, &MARKv, 1) == -1) - return NULL; - - UNLESS(class = PyObject_GetAttrString(args, "__class__")) - return NULL; - - if (self->bin) - { - UNLESS(junk = save(self, class)) - goto err; - Py_DECREF(junk); - } - - if ((getinitargs_func = PyObject_GetAttrString(args, "__getinitargs__"))) - { - PyObject *class_args = 0, *element = 0; - int i, len; - - UNLESS(class_args = PyObject_CallObject(getinitargs_func, empty_tuple)) - { - Py_DECREF(getinitargs_func); - goto err; + UNLESS(global_name = PyObject_GetAttr(args, __name___str)) + goto finally; } - if ((len = PyObject_Length(class_args)) == -1) - { - Py_DECREF(class_args); - goto err; - } - - for (i = 0; i < len; i++) - { - UNLESS(element = PySequence_GetItem(class_args, i)) - { - Py_DECREF(class_args); - goto err; - } - - UNLESS(junk = save(self, element)) - { - Py_DECREF(element); Py_DECREF(class_args); - goto err; - } - - Py_DECREF(junk); - Py_DECREF(element); - } - - Py_DECREF(class_args); - } - else - { - PyErr_Clear(); - } - - if (!self->bin) - { - UNLESS(module = whichmodule(class)) - goto err; - - UNLESS(name = ((PyClassObject *)class)->cl_name) - { - PyErr_SetString(PicklingError, "class has no name"); - goto err; - } + UNLESS(module = whichmodule(args, global_name)) + goto finally; module_str = PyString_AS_STRING((PyStringObject *)module); module_size = PyString_Size(module); - name_str = PyString_AS_STRING((PyStringObject *)name); - name_size = PyString_Size(name); + name_str = PyString_AS_STRING((PyStringObject *)global_name); + name_size = PyString_Size(global_name); - size = name_size + module_size + 3; + if ((*self->write_func)(self, &global, 1) < 0) + goto finally; - UNLESS(c_str = (char *)malloc(size * sizeof(char))) - { - PyErr_SetString(PyExc_MemoryError, "out of memory"); - return NULL; - } + if ((*self->write_func)(self, module_str, module_size) < 0) + goto finally; - c_str[0] = INST; - memcpy(c_str + 1, module_str, module_size); - c_str[module_size + 1] = '\n'; - memcpy(c_str + module_size + 2, name_str, name_size); - c_str[module_size + name_size + 2] = '\n'; + if ((*self->write_func)(self, "\n", 1) < 0) + goto finally; - if ((*self->write_func)(self, c_str, size) == -1) - { - free(c_str); - goto err; - } + if ((*self->write_func)(self, name_str, name_size) < 0) + goto finally; - free(c_str); - } + if ((*self->write_func)(self, "\n", 1) < 0) + goto finally; - if (args->ob_refcnt > 1) - { - if (put(self, args) == -1) - { - goto err; - } - } + if (put(self, args) < 0) + goto finally; - if ((getstate_func = PyObject_GetAttrString(args, "__getstate__"))) - { - UNLESS(state = PyObject_CallObject(getstate_func, empty_tuple)) - { - Py_DECREF(getstate_func); - goto err; - } - } - else - { - PyErr_Clear(); + res = 0; - UNLESS(state = PyObject_GetAttrString(args, "__dict__")) - goto err; - } +finally: + Py_XDECREF(module); + Py_XDECREF(global_name); - UNLESS(junk = save(self, state)) - goto err; - Py_DECREF(junk); - - Py_XDECREF(getinitargs_func); - Py_XDECREF(getstate_func); - Py_XDECREF(module); - Py_XDECREF(state); - - if ((*self->write_func)(self, &build, 1) == -1) - return NULL; - - Py_INCREF(Py_None); - return Py_None; - -err: - Py_XDECREF(getinitargs_func); - Py_XDECREF(getstate_func); - Py_XDECREF(module); - Py_XDECREF(state); - - return NULL; + return res; } +static int +save_pers(Picklerobject *self, PyObject *args, PyObject *f) { + PyObject *pid = 0; + int size, res = -1; -static PyObject * -save_class(ARG(Picklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Picklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *module = 0, *name = 0; - char *name_str, *module_str, *c_str; - int module_size, name_size, size; + static char persid = PERSID, binpersid = BINPERSID; - UNLESS(module = whichmodule(args)) - return NULL; - - UNLESS(name = ((PyClassObject *)args)->cl_name) - { - PyErr_SetString(PicklingError, "class has no name"); - goto err; - } - - module_str = PyString_AS_STRING((PyStringObject *)module); - module_size = PyString_Size(module); - name_str = PyString_AS_STRING((PyStringObject *)name); - name_size = PyString_Size(name); - - size = name_size + module_size + 3; - - UNLESS(c_str = (char *)malloc(size * sizeof(char))) - { - PyErr_SetString(PyExc_MemoryError, "out of memory"); - return NULL; - } - - c_str[0] = CLASS; - memcpy(c_str + 1, module_str, module_size); - c_str[module_size + 1] = '\n'; - memcpy(c_str + module_size + 2, name_str, name_size); - c_str[module_size + name_size + 2] = '\n'; - - if ((*self->write_func)(self, c_str, size) == -1) - { - free(c_str); - goto err; - } - - free(c_str); - - if (args->ob_refcnt > 1) - { - if (put(self, args) == -1) - { - goto err; - } - } - - Py_DECREF(module); - - Py_INCREF(Py_None); - return Py_None; - -err: - Py_XDECREF(module); - - return NULL; -} - - -static PyObject * -save(ARG(Picklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Picklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyTypeObject *type; - char *error_str, *name_c; - PyObject *name, *name_repr; - - if (self->pers_func) - { - PyObject *pid; - int size; - UNLESS(self->arg) - UNLESS(self->arg = PyTuple_New(1)) - return NULL; + UNLESS(self->arg = PyTuple_New(1)) + goto finally; - if (PyTuple_SetItem(self->arg, 0, args) == -1) - return NULL; - Py_INCREF(args); + Py_INCREF(args); + if (PyTuple_SetItem(self->arg, 0, args) < 0) + goto finally; - UNLESS(pid = PyObject_CallObject(self->pers_func, self->arg)) - return NULL; + UNLESS(pid = PyObject_CallObject(f, self->arg)) + goto finally; - if (pid != Py_None) - { - char *pid_str; + if (pid != Py_None) { + if (!self->bin) { + if (!PyString_Check(pid)) { + PyErr_SetString(PicklingError, + "persistent id must be string"); + goto finally; + } - if ((size = PyString_Size(pid)) == -1) - { - Py_DECREF(pid); - return NULL; - } + if ((*self->write_func)(self, &persid, 1) < 0) + goto finally; - UNLESS(pid_str = (char *)malloc((2 + size) * sizeof(char))) - { - PyErr_SetString(PyExc_MemoryError, "out of memory"); - Py_DECREF(pid); - return NULL; - } + if ((size = PyString_Size(pid)) < 0) + goto finally; - pid_str[0] = PERSID; - memcpy(pid_str + 1, PyString_AS_STRING((PyStringObject *)pid), size); - pid_str[size + 1] = '\n'; + if ((*self->write_func)(self, + PyString_AS_STRING((PyStringObject *)pid), size) < 0) + goto finally; - Py_DECREF(pid); - - if ((*self->write_func)(self, pid_str, size + 2) == -1) - { - free(pid_str); - return NULL; - } + 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; + } - free(pid_str); - - Py_INCREF(Py_None); - return Py_None; + goto finally; } - Py_DECREF(pid); - } + res = 0; - if (args == Py_None) - { - return save_none(self, args); - } +finally: + Py_XDECREF(pid); - type = args->ob_type; + return res; +} - if (type == &PyInt_Type) - { - return save_int(self, args); - } - if (type == &PyLong_Type) - { - return save_long(self, args); - } +static int +save_reduce(Picklerobject *self, PyObject *callable, + PyObject *tup, PyObject *state, PyObject *ob) { + static char reduce = REDUCE, build = BUILD; - if (type == &PyFloat_Type) - { - return save_float(self, args); - } + if (save(self, callable, 0) < 0) + return -1; - if (args->ob_refcnt > 1) - { - long ob_id; - int has_key; - PyObject *py_ob_id; + if (save(self, tup, 0) < 0) + return -1; - ob_id = (long)args; - - UNLESS(py_ob_id = PyInt_FromLong(ob_id)) - return NULL; + if ((*self->write_func)(self, &reduce, 1) < 0) + return -1; - if ((has_key = PyMapping_HasKey(self->memo, py_ob_id)) == -1) + if (ob != NULL) { - Py_DECREF(py_ob_id); - return 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; } - if (has_key) - { - PyObject *value; - long c_value; - char get_str[30]; - int len; + return 0; +} - UNLESS(value = PyDict_GetItem(self->memo, py_ob_id)) - { - Py_DECREF(py_ob_id); - return NULL; - } - Py_DECREF(py_ob_id); +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, *junk = 0; + int res = -1, tmp, size; - c_value = PyInt_AsLong(value); - - if (self->bin && (c_value < 256)) - { - get_str[0] = BINGET; - get_str[1] = c_value; - len = 2; - } - else - { - get_str[0] = GET; - sprintf(get_str + 1, "%ld\n", c_value); - len = strlen(get_str); - } - - if ((*self->write_func)(self, get_str, len) == -1) - return NULL; - - Py_INCREF(Py_None); - return Py_None; + if (!pers_save && self->pers_func) { + if ((tmp = save_pers(self, args, self->pers_func)) != 0) { + res = tmp; + goto finally; + } } - Py_DECREF(py_ob_id); - } + if (args == Py_None) { + res = save_none(self, args); + goto finally; + } - if (type == &PyString_Type) - { - return save_string(self, args); - } + type = args->ob_type; - if (type == &PyTuple_Type) - { - return save_tuple(self, args); - } + switch (type->tp_name[0]) { + case 'i': + if (type == &PyInt_Type) { + res = save_int(self, args); + goto finally; + } + break; - if (type == &PyList_Type) - { - return save_list(self, args); - } + case 'l': + if (type == &PyLong_Type) { + res = save_long(self, args); + goto finally; + } + break; - if (type == &PyDict_Type) - { - return save_dict(self, args); - } + case 'f': + if (type == &PyFloat_Type) { + res = save_float(self, args); + goto finally; + } + break; - if (type == &PyInstance_Type) - { - return save_inst(self, args); - } + 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; + } - if (type == &PyClass_Type) - { - return save_class(self, args); - } + case 's': + if ((type == &PyString_Type) && (PyString_Size(args) < 2)) { + res = save_string(self, args); + goto finally; + } + } - if (PyObject_HasAttrString(args, "__class__")) - { - return save_inst(self, args); - } + if (args->ob_refcnt > 1) { + long ob_id; + int has_key; - UNLESS(name = PyObject_GetAttrString((PyObject *)type, "__name__")) - return NULL; + ob_id = (long)args; - UNLESS(name_repr = PyObject_Repr(name)) - { - Py_DECREF(name); - } + UNLESS(py_ob_id = PyInt_FromLong(ob_id)) + goto finally; - name_c = PyString_AsString(name_repr); + if ((has_key = cPickle_PyMapping_HasKey(self->memo, py_ob_id)) < 0) + goto finally; - UNLESS(error_str = (char *)malloc((strlen(name_c) + 25) * sizeof(char))) - { - PyErr_SetString(PyExc_MemoryError, "out of memory"); - Py_DECREF(name); - Py_DECREF(name_repr); - return NULL; - } + if (has_key) { + if (get(self, py_ob_id) < 0) + goto finally; - sprintf(error_str, "Cannot pickle %s objects.", name_c); + res = 0; + goto finally; + } + } - Py_DECREF(name); - Py_DECREF(name_repr); + switch (type->tp_name[0]) { + case 's': + if (type == &PyString_Type) { + res = save_string(self, args); + goto finally; + } - PyErr_SetString(PicklingError, error_str); + case 't': + if (type == &PyTuple_Type) { + res = save_tuple(self, args); + goto finally; + } - free(error_str); - - return NULL; + case 'l': + if (type == &PyList_Type) { + res = save_list(self, args); + goto finally; + } + + case 'd': + if (type == &PyDict_Type) { + res = save_dict(self, args); + goto finally; + } + + case 'i': + if (type == &PyInstance_Type) { + res = save_inst(self, args); + goto finally; + } + + case 'c': + if (type == &PyClass_Type) { + res = save_global(self, args, NULL); + goto finally; + } + + case 'f': + if (type == &PyFunction_Type) { + res = save_global(self, args, NULL); + goto finally; + } + + 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 (__reduce__ = PyDict_GetItem(dispatch_table, (PyObject *)type)) { + Py_INCREF(__reduce__); + + UNLESS(self->arg) + UNLESS(self->arg = PyTuple_New(1)) + goto finally; + + Py_INCREF(args); + if (PyTuple_SetItem(self->arg, 0, args) < 0) + goto finally; + + UNLESS(t = PyObject_CallObject(__reduce__, self->arg)) + goto finally; + } + else { + PyErr_Clear(); + + if (__reduce__ = PyObject_GetAttr(args, __reduce___str)) { + UNLESS(t = PyObject_CallObject(__reduce__, empty_tuple)) + goto finally; + } + else { + PyErr_Clear(); + } + } + + if (t) { + if (PyString_Check(t)) { + res = save_global(self, args, t); + goto finally; + } + + if (!PyTuple_Check(t)) { + PyErr_Format(PicklingError, "Value returned by %s must " + "be a tuple", "O", __reduce__); + goto finally; + } + + size = PyTuple_Size(t); + + if ((size != 3) && (size != 2)) { + PyErr_Format(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)) { + PyErr_Format(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; + } + + /* + if (PyObject_HasAttrString(args, "__class__")) { + res = save_inst(self, args); + goto finally; + } + */ + + PyErr_Format(PicklingError, "Cannot pickle %s objects.", + "O", (PyObject *)type); + +finally: + Py_XDECREF(py_ob_id); + Py_XDECREF(__reduce__); + Py_XDECREF(t); + + return res; +} + + +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 * +Pickler_dump(Picklerobject *self, PyObject *args) { + PyObject *ob; + + UNLESS(PyArg_ParseTuple(args, "O", &ob)) + return NULL; + + if (dump(self, ob) < 0) + return NULL; + + Py_INCREF(Py_None); + return Py_None; } static PyObject * -Pickler_dump(ARG(Picklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Picklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *junk; - static char stop = STOP; +dump_special(Picklerobject *self, PyObject *args) { + static char stop = STOP; - UNLESS(PyArg_Parse(args, "O", &args)) return NULL; + PyObject *callable, *arg_tup, *state = NULL; + + UNLESS(PyArg_ParseTuple(args, "OO|O", &callable, &arg_tup, &state)) + return NULL; - UNLESS(junk = save(self, args)) return NULL; - Py_DECREF(junk); + UNLESS(PyTuple_Check(arg_tup)) { + PyErr_SetString(PicklingError, "Second arg to dump_special must " + "be tuple"); + return NULL; + } - if ((*self->write_func)(self, &stop, 1) == -1) - return NULL; + if (save_reduce(self, callable, arg_tup, state, NULL) < 0) + return NULL; - Py_INCREF(Py_None); - return Py_None; -} + if ((*self->write_func)(self, &stop, 1) < 0) + return NULL; + if ((*self->write_func)(self, NULL, 0) < 0) + return NULL; -static PyObject * -write(ARG(Picklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Picklerobject *, self) - ARGDECL(PyObject *, args) -{ - char *ptr; - int size; - - UNLESS(ptr = PyString_AsString(args)) - return NULL; - - if ((size = PyString_Size(args)) == -1) - return NULL; - - if ((*self->write_func)(self, ptr, size) == -1) - return NULL; - - Py_INCREF(Py_None); - return Py_None; + Py_INCREF(Py_None); + return Py_None; } static struct PyMethodDef Pickler_methods[] = { - {"save", (PyCFunction)save, 0, ""}, - {"dump", (PyCFunction)Pickler_dump, 0, ""}, - {"save_none", (PyCFunction)save_none, 0, ""}, - {"save_int", (PyCFunction)save_int, 0, ""}, - {"save_long", (PyCFunction)save_long, 0, ""}, - {"save_float", (PyCFunction)save_float, 0, ""}, - {"save_string", (PyCFunction)save_string, 0, ""}, - {"save_tuple", (PyCFunction)save_tuple, 0, ""}, - {"save_list", (PyCFunction)save_list, 0, ""}, - {"save_dict", (PyCFunction)save_dict, 0, ""}, - {"save_inst", (PyCFunction)save_inst, 0, ""}, - {"save_class", (PyCFunction)save_class, 0, ""}, - {"write", (PyCFunction)write, 0, ""}, - {NULL, NULL} /* sentinel */ + {"dump", (PyCFunction)Pickler_dump, 1, ""}, + {"dump_special", (PyCFunction)dump_special, 1, ""}, + {NULL, NULL} /* sentinel */ }; static Picklerobject * -newPicklerobject(ARG(PyObject *, file), ARG(int, bin)) - ARGDECL(PyObject *, file) - ARGDECL(int, bin) -{ - Picklerobject *self; - PyObject *memo = 0; +newPicklerobject(PyObject *file, int bin) { + Picklerobject *self; - UNLESS(memo = PyDict_New()) goto err; - - UNLESS(self = PyObject_NEW(Picklerobject, &Picklertype)) - goto err; - - if (PyFile_Check(file)) - { - self->fp = PyFile_AsFile(file); - self->write_func = write_file; - self->write = NULL; - } - else if (PycStringIO_OutputCheck(file)) - { - self->fp = NULL; - self->write_func = write_cStringIO; - self->write = NULL; - } - else - { - PyObject *write; + UNLESS(self = PyObject_NEW(Picklerobject, &Picklertype)) + return NULL; self->fp = NULL; - self->write_func = write_other; + 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->buf_size = 0; - UNLESS(write = PyObject_GetAttrString(file, "write")) - goto err; + Py_INCREF(file); + self->file = file; - self->write = write; - } + UNLESS(self->memo = PyDict_New()) { + Py_XDECREF((PyObject *)self); + return NULL; + } - Py_INCREF(file); + if (PyFile_Check(file)) { + self->fp = PyFile_AsFile(file); + self->write_func = write_file; + } + else if (PycStringIO_OutputCheck(file)) { + self->write_func = write_cStringIO; + } + else { + self->write_func = write_other; - self->file = file; - self->bin = bin; - self->memo = memo; - self->arg = NULL; - self->pers_func = NULL; + UNLESS(self->write = PyObject_GetAttr(file, write_str)) + { + PyErr_Clear(); + PyErr_SetString(PyExc_TypeError, "argument must have 'write' " + "attribute"); + Py_XDECREF((PyObject *)self); + return NULL; + } - return self; + UNLESS(self->write_buf = + (char *)malloc(WRITE_BUF_SIZE * sizeof(char))) { + PyErr_NoMemory(); + Py_XDECREF((PyObject *)self); + return NULL; + } + } -err: - Py_XDECREF((PyObject *)self); - Py_XDECREF(memo); - return NULL; + return self; } static PyObject * -get_Pickler(ARG(PyObject *, self), ARG(PyObject *, args)) - ARGDECL(PyObject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *file; - int bin = 0; +get_Pickler(PyObject *self, PyObject *args) { + PyObject *file; + int bin = 0; - UNLESS(PyArg_ParseTuple(args, "O|i", &file, &bin)) return NULL; - return (PyObject *)newPicklerobject(file, bin); + UNLESS(PyArg_ParseTuple(args, "O|i", &file, &bin)) return NULL; + return (PyObject *)newPicklerobject(file, bin); } static void -Pickler_dealloc(ARG(Picklerobject *, self)) - ARGDECL(Picklerobject *, self) -{ - Py_XDECREF(self->write); - Py_XDECREF(self->memo); - Py_XDECREF(self->arg); - Py_XDECREF(self->file); - Py_XDECREF(self->pers_func); - PyMem_DEL(self); +Pickler_dealloc(Picklerobject *self) { + Py_XDECREF(self->write); + Py_XDECREF(self->memo); + Py_XDECREF(self->arg); + Py_XDECREF(self->file); + Py_XDECREF(self->pers_func); + Py_XDECREF(self->inst_pers_func); + + if (self->write_buf) { + free(self->write_buf); + } + + PyMem_DEL(self); } static PyObject * -Pickler_getattr(ARG(Picklerobject *, self), ARG(char *, name)) - ARGDECL(Picklerobject *, self) - ARGDECL(char *, name) -{ - if (!strcmp(name, "persistent_id")) - { - if (!self->pers_func) - { - PyErr_SetString(PyExc_NameError, name); - return NULL; +Pickler_getattr(Picklerobject *self, char *name) { + 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; } - Py_INCREF(self->pers_func); - return self->pers_func; - } + if (strcmp(name, "memo") == 0) { + if (!self->memo) { + PyErr_SetString(PyExc_AttributeError, name); + return NULL; + } - if (!strcmp(name, "memo")) - { - if (!self->memo) - { - PyErr_SetString(PyExc_NameError, name); - return NULL; + Py_INCREF(self->memo); + return self->memo; } - Py_INCREF(self->memo); - return self->memo; - } - - if (!strcmp(name, "PicklingError")) - { - Py_INCREF(PicklingError); - return PicklingError; - } + if (strcmp(name, "PicklingError") == 0) { + Py_INCREF(PicklingError); + return PicklingError; + } - return Py_FindMethod(Pickler_methods, (PyObject *)self, name); + return Py_FindMethod(Pickler_methods, (PyObject *)self, name); } int -Pickler_setattr(ARG(Picklerobject *, self), ARG(char *, name), ARG(PyObject *, value)) - ARGDECL(Picklerobject *, self) - ARGDECL(char *, name) - ARGDECL(PyObject *, value) -{ - if (!strcmp(name, "persistent_id")) - { - Py_XDECREF(self->pers_func); - self->pers_func = value; - Py_INCREF(value); - return 0; - } +Pickler_setattr(Picklerobject *self, char *name, PyObject *value) { + if (strcmp(name, "persistent_id") == 0) { + Py_XDECREF(self->pers_func); + self->pers_func = value; + Py_INCREF(value); + return 0; + } - return -1; + if (strcmp(name, "inst_persistent_id") == 0) { + Py_XDECREF(self->inst_pers_func); + self->inst_pers_func = value; + Py_INCREF(value); + return 0; + } + + PyErr_SetString(PyExc_AttributeError, name); + return -1; } static char Picklertype__doc__[] = ""; -static PyTypeObject Picklertype = { - PyObject_HEAD_INIT(&PyType_Type) - 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*/ +static PyTypeObject Picklertype_value() { + PyTypeObject Picklertype = { + PyObject_HEAD_INIT(&PyType_Type) + 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 */ -}; + /* Space for future expansion */ + 0L,0L,0L,0L, + Picklertype__doc__ /* Documentation string */ + }; + return Picklertype; +} -static PyObject * -find_class(ARG(char *, module_name), ARG(char *, class_name)) - ARGDECL(char *, module_name) - ARGDECL(char *, class_name) +PyObject * +PyImport_ImportModuleNi(char *module_name) { - PyObject *import = 0, *class = 0, *py_module_name = 0, *py_class_name = 0, - *t = 0; - char *error_str; - int has_key; + char *import_str; + int size, i; + PyObject *import; - UNLESS(py_module_name = PyString_FromString(module_name)) - return NULL; + static PyObject *eval_dict = 0; - UNLESS(py_class_name = PyString_FromString(class_name)) - goto err; - - UNLESS(t = PyTuple_New(2)) - goto err; - - UNLESS(PyTuple_SET_ITEM((PyTupleObject *)t, 0, py_module_name)) - goto err; - Py_INCREF(py_module_name); - - UNLESS(PyTuple_SET_ITEM((PyTupleObject *)t, 1, py_class_name)) - goto err; - Py_INCREF(py_module_name); - - if ((has_key = PyMapping_HasKey(class_map, t)) == -1) - goto err; - - if (has_key) - { - UNLESS(class = PyDict_GetItem(class_map, t)) - goto err; - - Py_INCREF(class); - - Py_DECREF(py_module_name); - Py_DECREF(py_class_name); - Py_DECREF(t); - - return class; - } - - if (!(import = PyImport_ImportModule(module_name)) || - !(class = PyObject_GetAttrString(import, class_name))) - { - UNLESS(error_str = (char *)malloc((strlen(module_name) + - strlen(class_name) + 40) * sizeof(char))) - { - PyErr_SetString(PyExc_MemoryError, "out of memory"); - goto err; + size = strlen(module_name); + for (i = 0; i < size; i++) { + if (((module_name[i] < 'A') || (module_name[i] > 'z')) && + (module_name[i] != '_')) { + PyErr_SetString(PyExc_ImportError, "module name contains " + "invalid characters."); + return NULL; + } } - sprintf(error_str, "Failed to import class %s from module %s", - class_name, module_name); - - PyErr_SetString(PyExc_SystemError, error_str); - - free(error_str); - goto err; - } - - if (class->ob_type == BuiltinFunctionType) - { - UNLESS(error_str = (char *)malloc((strlen(module_name) + - strlen(class_name) + 45) * sizeof(char))) - { - PyErr_SetString(PyExc_MemoryError, "out of memory"); - goto err; - } - - sprintf(error_str, "Imported object %s from module %s is not a class", - class_name, module_name); - - PyErr_SetString(PyExc_SystemError, error_str); - - free(error_str); - goto err; - } - - if (PyDict_SetItem(class_map, t, class) == -1) - goto err; - - Py_DECREF(t); - Py_DECREF(py_module_name); - Py_DECREF(py_class_name); - Py_DECREF(import); - - return class; - -err: - Py_XDECREF(import); - Py_XDECREF(class); - Py_XDECREF(t); - Py_XDECREF(py_module_name); - Py_XDECREF(py_class_name); - - return NULL; -} - - -int -marker(ARG(Unpicklerobject *, self)) - ARGDECL(Unpicklerobject *, self) -{ - if (!self->num_marks) - return -1; - - return self->marks[--self->num_marks]; -} - - -static PyObject * -load_none(ARG(Unpicklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(PyObject *, args) -{ - if (PyList_Append(self->stack, Py_None) == -1) - return NULL; - - Py_INCREF(Py_None); - return Py_None; -} - - -static PyObject * -load_int(ARG(Unpicklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *py_int = 0; - char *s, *endptr; - int len; - long l; - - if ((len = (*self->readline_func)(self, &s)) == -1) - return NULL; - - errno = 0; - l = strtol(s, &endptr, 0); - - free(s); - - if (errno || strlen(endptr)) - { - PyErr_SetString(PyExc_ValueError, "could not convert string to int"); - goto err; - } - - UNLESS(py_int = PyInt_FromLong(l)) - goto err; - - if (PyList_Append(self->stack, py_int) == -1) - goto err; - - Py_DECREF(py_int); - - Py_INCREF(Py_None); - return Py_None; - -err: - Py_XDECREF(py_int); - - return NULL; -} - - -static PyObject * -load_binint(ARG(Unpicklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *py_int = 0; - char *s; - unsigned char c; - long l; - - UNLESS(s = (char *)malloc(4 * sizeof(char))) - { - PyErr_SetString(PyExc_MemoryError, "out of memory"); - return NULL; - } - - if ((*self->read_func)(self, &s, 4) == -1) - { - free(s); - return NULL; - } - - c = (unsigned char)s[0]; - l = (long)c; - c = (unsigned char)s[1]; - l |= (long)c << 8; - c = (unsigned char)s[2]; - l |= (long)c << 16; - c = (unsigned char)s[3]; - l |= (long)c << 24; - - free(s); - - UNLESS(py_int = PyInt_FromLong(l)) - return NULL; - - if (PyList_Append(self->stack, py_int) == -1) - { - Py_DECREF(py_int); - return NULL; - } - - Py_DECREF(py_int); - - Py_INCREF(Py_None); - return Py_None; -} - - -static PyObject * -load_binint1(ARG(Unpicklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *py_int = 0; - char *s; - unsigned char c; - long l; - - UNLESS(s = (char *)malloc(3 * sizeof(char))) - { - PyErr_SetString(PyExc_MemoryError, "out of memory"); - return NULL; - } - - if ((*self->read_func)(self, &s, 3) == -1) - { - free(s); - return NULL; - } - - c = (unsigned char)s[0]; - l = (long)c; - c = (unsigned char)s[1]; - l |= (long)c << 8; - c = (unsigned char)s[2]; - l |= (long)c << 16; - - free(s); - - UNLESS(py_int = PyInt_FromLong(l)) - return NULL; - - if (PyList_Append(self->stack, py_int) == -1) - { - Py_DECREF(py_int); - return NULL; - } - - Py_DECREF(py_int); - - Py_INCREF(Py_None); - return Py_None; -} - - -static PyObject * -load_binint2(ARG(Unpicklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *py_int = 0; - char *s; - unsigned char c; - long l; - - UNLESS(s = (char *)malloc(2 * sizeof(char))) - { - PyErr_SetString(PyExc_MemoryError, "out of memory"); - return NULL; - } - - if ((*self->read_func)(self, &s, 2) == -1) - return NULL; - - c = (unsigned char)s[0]; - l = (long)c; - c = (unsigned char)s[1]; - l |= (long)c << 8; - - free(s); - - UNLESS(py_int = PyInt_FromLong(l)) - return NULL; - - if (PyList_Append(self->stack, py_int) == -1) - { - Py_DECREF(py_int); - return NULL; - } - - Py_DECREF(py_int); - - Py_INCREF(Py_None); - return Py_None; -} - - -static PyObject * -load_binint3(ARG(Unpicklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *py_int = 0; - char *s; - unsigned char c; - long l; - - UNLESS(s = (char *)malloc(sizeof(char))) - { - PyErr_SetString(PyExc_MemoryError, "out of memory"); - return NULL; - } - - if ((*self->read_func)(self, &s, 1) == -1) - { - free(s); - return NULL; - } - - c = (unsigned char)s[0]; - l = (long)c; - - free(s); - - UNLESS(py_int = PyInt_FromLong(l)) - return NULL; - - if (PyList_Append(self->stack, py_int) == -1) - { - Py_DECREF(py_int); - return NULL; - } - - Py_DECREF(py_int); - - Py_INCREF(Py_None); - return Py_None; -} - - -static PyObject * -load_long(ARG(Unpicklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *py_str = 0, *l = 0; - char *s; - int len; - - static PyObject *arg; - - if ((len = (*self->readline_func)(self, &s)) == -1) - return NULL; - - UNLESS(py_str = PyString_FromStringAndSize(s, len)) - { - free(s); - return NULL; - } - - free(s); - - UNLESS(arg) - { - UNLESS(arg = Py_BuildValue("(Oi)", py_str, 0)) - return NULL; - } - else - { - if (PyTuple_SetItem(arg, 0, py_str) == -1) - goto err; - Py_INCREF(py_str); - } - - UNLESS(l = PyObject_CallObject(atol_func, arg)) - goto err; - - if (PyList_Append(self->stack, l) == -1) - goto err; - - Py_DECREF(py_str); - Py_DECREF(l); - - Py_INCREF(Py_None); - return Py_None; - -err: - Py_XDECREF(l); - Py_XDECREF(py_str); - - return NULL; -} - - -static PyObject * -load_float(ARG(Unpicklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *py_float = 0; - char *s, *endptr; - int len; - double d; - - if ((len = (*self->readline_func)(self, &s)) == -1) - return NULL; - - errno = 0; - d = strtod(s, &endptr); - - free(s); - - if (errno || strlen(endptr)) - { - PyErr_SetString(PyExc_ValueError, "could not convert string to long"); - goto err; - } - - UNLESS(py_float = PyFloat_FromDouble(d)) - goto err; - - if (PyList_Append(self->stack, py_float) == -1) - goto err; - - Py_DECREF(py_float); - - Py_INCREF(Py_None); - return Py_None; - -err: - Py_XDECREF(py_float); - - return NULL; -} - - -static PyObject * -load_string(ARG(Unpicklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *str = 0; - char *s; - int len; - static PyObject *eval_dict = 0; - - UNLESS(eval_dict) - UNLESS(eval_dict = Py_BuildValue("{s{}}", "__builtins__")) - return NULL; - - if ((len = (*self->readline_func)(self, &s)) == -1) - return NULL; - - UNLESS(str = PyRun_String(s, eval_input, eval_dict, eval_dict)) - { - free(s); - goto err; - } - - free(s); - - if (PyList_Append(self->stack, str) == -1) - goto err; - - Py_DECREF(str); - - Py_INCREF(Py_None); - return Py_None; - -err: - Py_XDECREF(str); - - return NULL; -} - - -static PyObject * -load_binstring(ARG(Unpicklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *py_string = 0; - char *s; - int len, i; - - if ((len = (*self->readline_func)(self, &s)) == -1) - return NULL; - - i = atoi(s); - - if (i > len) - { - free(s); - - UNLESS(s = (char *)malloc(i * sizeof(char))) - { - PyErr_SetString(PyExc_MemoryError, "out of memory"); - return NULL; - } - } - - if ((*self->read_func)(self, &s, i) == -1) - { - free(s); - return NULL; - } - - UNLESS(py_string = PyString_FromStringAndSize(s, i)) - { - free(s); - return NULL; - } - - free(s); - - if (PyList_Append(self->stack, py_string) == -1) - goto err; - - Py_DECREF(py_string); - - Py_INCREF(Py_None); - return Py_None; - -err: - Py_XDECREF(py_string); - - return NULL; -} - - -static PyObject * -load_short_binstring(ARG(Unpicklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *py_string = 0; - char *s; - unsigned char l; - - - UNLESS(s = (char *)malloc(sizeof(char))) - { - PyErr_SetString(PyExc_MemoryError, "out of memory"); - return NULL; - } - - if ((*self->read_func)(self, &s, 1) == -1) - { - free(s); - return NULL; - } - - l = (unsigned char)s[0]; - - if (l > 1) - { - free(s); - - UNLESS(s = (char *)malloc(l * sizeof(char))) - { - PyErr_SetString(PyExc_MemoryError, "out of memory"); - return NULL; - } - } - - if ((*self->read_func)(self, &s, l) == -1) - { - free(s); - return NULL; - } - - UNLESS(py_string = PyString_FromStringAndSize(s, l)) - { - free(s); - return NULL; - } - - free(s); - - if (PyList_Append(self->stack, py_string) == -1) - { - Py_DECREF(py_string); - return NULL; - } - - Py_DECREF(py_string); - - Py_INCREF(Py_None); - return Py_None; -} - - -static PyObject * -load_tuple(ARG(Unpicklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *tup = 0, *slice = 0, *list = 0; - int i, j; - - if ((i = marker(self)) == -1) - return NULL; - - if ((j = PyList_Size(self->stack)) == -1) - goto err; - - UNLESS(slice = PyList_GetSlice(self->stack, i, j)) - goto err; - - UNLESS(tup = PySequence_Tuple(slice)) - goto err; - - UNLESS(list = PyList_New(1)) - goto err; - - if (PyList_SetItem(list, 0, tup) == -1) - goto err; - - Py_INCREF(tup); - - if (PyList_SetSlice(self->stack, i, j, list) == -1) - goto err; - - Py_DECREF(tup); - Py_DECREF(list); - Py_DECREF(slice); - - Py_INCREF(Py_None); - return Py_None; - -err: - Py_XDECREF(tup); - Py_XDECREF(list); - Py_XDECREF(slice); - - return NULL; -} - - -static PyObject * -load_list(ARG(Unpicklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *list = 0, *slice = 0; - int i, j; - - if ((i = marker(self)) == -1) - return NULL; - - if ((j = PyList_Size(self->stack)) == -1) - goto err; - - UNLESS(slice = PyList_GetSlice(self->stack, i, j)) - goto err; - - UNLESS(list = PyList_New(1)) - goto err; - - if (PyList_SetItem(list, 0, slice) == -1) - goto err; - Py_INCREF(slice); - - if (PyList_SetSlice(self->stack, i, j, list) == -1) - goto err; - - Py_DECREF(list); - Py_DECREF(slice); - - Py_INCREF(Py_None); - return Py_None; - -err: - Py_XDECREF(list); - Py_XDECREF(slice); - - return NULL; -} - - -static PyObject * -load_dict(ARG(Unpicklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *list = 0, *dict = 0, *key = 0, *value = 0; - int i, j, k; - - if ((i = marker(self)) == -1) - return NULL; - - if ((j = PyList_Size(self->stack)) == -1) - goto err; - - UNLESS(dict = PyDict_New()) - goto err; - - for (k = i; k < j; k += 2) - { - UNLESS(key = PyList_GET_ITEM((PyListObject *)self->stack, k)) - goto err; - - UNLESS(value = PyList_GET_ITEM((PyListObject *)self->stack, k + 1)) - goto err; - - if (PyDict_SetItem(dict, key, value) == -1) - goto err; - } - - UNLESS(list = PyList_New(1)) - goto err; - - if (PyList_SetItem(list, 0, dict) == -1) - goto err; - Py_INCREF(dict); - - if (PyList_SetSlice(self->stack, i, j, list) == -1) - goto err; - - Py_DECREF(list); - Py_DECREF(dict); - - Py_INCREF(Py_None); - return Py_None; - -err: - Py_XDECREF(dict); - Py_XDECREF(list); - - return NULL; -} - - -static PyObject * -load_obj(ARG(Unpicklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *class = 0, *slice = 0, *tup = 0, *obj = 0; - long i; - int len; - - if ((i = marker(self)) == -1) - return NULL; - - class = PyList_GET_ITEM((PyListObject *)self->stack, i); - Py_INCREF(class); - - if ((len = PyList_Size(self->stack)) == -1) - goto err; - - UNLESS(slice = PyList_GetSlice(self->stack, i + 1, len)) - goto err; - - UNLESS(tup = PySequence_Tuple(slice)) - goto err; - - if (DEL_LIST_SLICE(self->stack, i, len) == -1) - goto err; - - UNLESS(obj = PyInstance_New(class, tup, NULL)) - goto err; - - if (PyList_Append(self->stack, obj) == -1) - goto err; - - Py_DECREF(class); - Py_DECREF(slice); - Py_DECREF(tup); - Py_DECREF(obj); - - Py_INCREF(Py_None); - return Py_None; - -err: - Py_XDECREF(class); - Py_XDECREF(slice); - Py_XDECREF(tup); - Py_XDECREF(obj); - - return NULL; -} - - -static PyObject * -load_inst(ARG(Unpicklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *arg_tup = 0, *arg_slice = 0, *class = 0, *obj = 0; - int i, j; - char *s, *module_name, *class_name; - - if ((i = marker(self)) == -1) - return NULL; - - if ((j = PyList_Size(self->stack)) == -1) - goto err; - - UNLESS(arg_slice = PyList_GetSlice(self->stack, i, j)) - goto err; - - UNLESS(arg_tup = PySequence_Tuple(arg_slice)) - goto err; - - if (DEL_LIST_SLICE(self->stack, i, j) == -1) - goto err; - - if ((*self->readline_func)(self, &s) == -1) - goto err; - - module_name = s; - - if ((*self->readline_func)(self, &s) == -1) - { - free(module_name); - goto err; - } - - class_name = s; - - UNLESS(class = find_class(module_name, class_name)) - { - free(module_name); - free(class_name); - goto err; - } - - free(module_name); - free(class_name); - - UNLESS(obj = PyInstance_New(class, arg_tup, NULL)) - goto err; - - if (PyList_Append(self->stack, obj) == -1) - goto err; - - Py_DECREF(arg_slice); - Py_DECREF(arg_tup); - Py_DECREF(class); - Py_DECREF(obj); - - Py_INCREF(Py_None); - return Py_None; - -err: - Py_XDECREF(arg_slice); - Py_XDECREF(arg_tup); - Py_XDECREF(class); - Py_XDECREF(obj); - - return NULL; -} - - -static PyObject * -load_class(ARG(Unpicklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *class = 0; - char *s, *module_name, *class_name; - - if ((*self->readline_func)(self, &s) == -1) - return NULL; - - module_name = s; - - if ((*self->readline_func)(self, &s) == -1) - { - free(module_name); - return NULL; - } - - class_name = s; - - UNLESS(class = find_class(module_name, class_name)) - { - free(module_name); - free(class_name); - return NULL; - } - - free(module_name); - free(class_name); - - if (PyList_Append(self->stack, class) == -1) - goto err; - - Py_DECREF(class); - - Py_INCREF(Py_None); - return Py_None; - -err: - Py_XDECREF(class); - - return NULL; -} - - -static PyObject * -load_persid(ARG(Unpicklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *pid = 0, *pers_load_val = 0; - char *s; - int len; - - if (self->pers_func) - { - if ((len = (*self->readline_func)(self, &s)) == -1) - return NULL; - - UNLESS(pid = PyString_FromStringAndSize(s, len)) - { - free(s); - return NULL; - } - - free(s); - - UNLESS(self->arg) - UNLESS(self->arg = PyTuple_New(1)) - goto err; - - if (PyTuple_SetItem(self->arg, 0, pid) == -1) - goto err; - Py_INCREF(pid); - - UNLESS(pers_load_val = PyObject_CallObject(self->pers_func, self->arg)) - goto err; - - if (PyList_Append(self->stack, pers_load_val) == -1) - goto err; - - Py_DECREF(pid); - Py_DECREF(pers_load_val); - - Py_INCREF(Py_None); - return Py_None; - } - - Py_INCREF(Py_None); - return Py_None; - -err: - Py_XDECREF(pid); - Py_XDECREF(pers_load_val); - - return NULL; -} - - -static PyObject * -load_pop(ARG(Unpicklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(PyObject *, args) -{ - int len; - - if ((len = PyList_Size(self->stack)) == -1) - return NULL; - - if (DEL_LIST_SLICE(self->stack, len - 1, len) == -1) - return NULL; - - Py_INCREF(Py_None); - return Py_None; -} - - -static PyObject * -load_dup(ARG(Unpicklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *last; - int len; - - if ((len = PyList_Size(self->stack)) == -1) - return NULL; - - UNLESS(last = PyList_GetItem(self->stack, len - 1)) - return NULL; - - if (PyList_Append(self->stack, last) == -1) - return NULL; - - Py_INCREF(Py_None); - return Py_None; -} - - -static PyObject * -load_get(ARG(Unpicklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *py_str = 0, *value = 0; - char *s; - int len; - - if ((len = (*self->readline_func)(self, &s)) == -1) - return NULL; - - UNLESS(py_str = PyString_FromStringAndSize(s, len)) - { - free(s); - return NULL; - } - - free(s); - - UNLESS(value = PyDict_GetItem(self->memo, py_str)) - goto err; - - if (PyList_Append(self->stack, value) == -1) - goto err; - - Py_DECREF(py_str); - - Py_INCREF(Py_None); - return Py_None; - -err: - Py_XDECREF(py_str); - - return NULL; -} - - -static PyObject * -load_binget(ARG(Unpicklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *py_key = 0, *value = 0; - char *s; - unsigned char key; - - UNLESS(s = (char *)malloc(sizeof(char))) - { - PyErr_SetString(PyExc_MemoryError, "out of memory"); - return NULL; - } - - if ((*self->read_func)(self, &s, 1) == -1) - { - free(s); - return NULL; - } - - key = (unsigned char)s[0]; - free(s); - - UNLESS(py_key = PyInt_FromLong((long)key)) - return NULL; - - UNLESS(value = PyDict_GetItem(self->memo, py_key)) - goto err; - - if (PyList_Append(self->stack, value) == -1) - return NULL; - - Py_DECREF(py_key); - - Py_INCREF(Py_None); - return Py_None; - -err: - Py_XDECREF(py_key); - - return NULL; -} - - -static PyObject * -load_put(ARG(Unpicklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *py_str = 0, *value = 0; - int len; - char *s; - - if ((len = (*self->readline_func)(self, &s)) == -1) - return NULL; - - UNLESS(py_str = PyString_FromStringAndSize(s, len)) - { - free(s); - return NULL; - } - - free(s); - - if ((len = PyList_Size(self->stack)) == -1) - goto err; - - UNLESS(value = PyList_GetItem(self->stack, len - 1)) - goto err; - - if (PyDict_SetItem(self->memo, py_str, value) == -1) - goto err; - - Py_DECREF(py_str); - - Py_INCREF(Py_None); - return Py_None; - -err: - Py_XDECREF(py_str); - - return NULL; -} - - -static PyObject * -load_binput(ARG(Unpicklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *py_key = 0, *value = 0; - char *s; - unsigned char key; - int len; - - UNLESS(s = (char *)malloc(sizeof(char))) - { - PyErr_SetString(PyExc_MemoryError, "out of memory"); - return NULL; - } - - if ((*self->read_func)(self, &s, 1) == -1) - return NULL; - - key = (unsigned char)s[0]; - - free(s); - - UNLESS(py_key = PyInt_FromLong((long)key)) - return NULL; - - if ((len = PyList_Size(self->stack)) == -1) - goto err; - - UNLESS(value = PyList_GetItem(self->stack, len - 1)) - goto err; - - if (PyDict_SetItem(self->memo, py_key, value) == -1) - goto err; - - Py_DECREF(py_key); - - Py_INCREF(Py_None); - return Py_None; - -err: - Py_XDECREF(py_key); - - return NULL; -} - - -static PyObject * -load_append(ARG(Unpicklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *value = 0, *list = 0; - int len; - static PyObject *append_str = 0; - - UNLESS(append_str) - UNLESS(append_str = PyString_FromString("append")) - return NULL; - - if ((len = PyList_Size(self->stack)) == -1) - return NULL; - - UNLESS(value = PyList_GetItem(self->stack, len - 1)) - return NULL; - Py_INCREF(value); - - if (DEL_LIST_SLICE(self->stack, len - 1, len) == -1) - goto err; - - UNLESS(list = PyList_GetItem(self->stack, len - 2)) - goto err; - - if (PyList_Check(list)) - { - if (PyList_Append(list, value) == -1) - goto err; - } - else - { - PyObject *append_method, *junk; - - UNLESS(append_method = PyObject_GetAttr(list, append_str)) - return NULL; - - UNLESS(self->arg) - UNLESS(self->arg = PyTuple_New(1)) - { - Py_DECREF(append_method); - goto err; - } - - if (PyTuple_SetItem(self->arg, 0, value) == -1) - { - Py_DECREF(append_method); - goto err; - } - Py_INCREF(value); - - UNLESS(junk = PyObject_CallObject(append_method, self->arg)) - { - Py_DECREF(append_method); - goto err; - } - Py_DECREF(junk); - - Py_DECREF(append_method); - } - - Py_DECREF(value); - - Py_INCREF(Py_None); - return Py_None; - -err: - Py_XDECREF(value); - - return NULL; -} - - -static PyObject * -load_setitem(ARG(Unpicklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *value = 0, *key = 0, *dict = 0; - int len; - - if ((len = PyList_Size(self->stack)) == -1) - return NULL; - - UNLESS(value = PyList_GetItem(self->stack, len - 1)) - return NULL; - Py_INCREF(value); - - UNLESS(key = PyList_GetItem(self->stack, len - 2)) - goto err; - Py_INCREF(key); - - if (DEL_LIST_SLICE(self->stack, len - 2, len) == -1) - goto err; - - UNLESS(dict = PyList_GetItem(self->stack, len - 3)) - goto err; - - if (PyObject_SetItem(dict, key, value) == -1) - goto err; - - Py_DECREF(value); - Py_DECREF(key); - - Py_INCREF(Py_None); - return Py_None; - -err: - Py_XDECREF(value); - Py_XDECREF(key); - - return NULL; -} - - -static PyObject * -load_build(ARG(Unpicklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *value = 0, *inst = 0, *instdict = 0, *d_key = 0, *d_value = 0, - *junk = 0; - static PyObject *py_string__dict__; - int len, i; - - UNLESS(py_string__dict__) - UNLESS(py_string__dict__ = PyString_FromString("__dict__")) - return NULL; - - if ((len = PyList_Size(self->stack)) == -1) - goto err; - - UNLESS(value = PyList_GetItem(self->stack, len - 1)) - goto err; - Py_INCREF(value); - - if (DEL_LIST_SLICE(self->stack, len - 1, len) == -1) - goto err; - - UNLESS(inst = PyList_GetItem(self->stack, len - 2)) - goto err; - - UNLESS(PyObject_HasAttrString(inst, "__setstate__")) - { - UNLESS(instdict = PyObject_GetAttr(inst, py_string__dict__)) - goto err; - - i = 0; - while (PyDict_Next(value, &i, &d_key, &d_value)) - { - if (PyObject_SetItem(instdict, d_key, d_value) == -1) - goto err; - } - } - else - { - UNLESS(junk = PyObject_CallMethod(inst, "__setstate__", "O", value)) - goto err; - Py_DECREF(junk); - } - - Py_DECREF(value); - Py_XDECREF(instdict); - - Py_INCREF(Py_None); - return Py_None; - -err: - Py_XDECREF(value); - Py_XDECREF(instdict); - - return NULL; -} - - -static PyObject * -load_mark(ARG(Unpicklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(PyObject *, args) -{ - int len; - - if ((len = PyList_Size(self->stack)) == -1) - return NULL; - - if (!self->num_marks) - { - UNLESS(self->marks = (int *)malloc(20 * sizeof(int))) - { - PyErr_SetString(PyExc_MemoryError, "out of memory"); - return NULL; - } - - self->marks_size = 20; - } - else if ((self->num_marks + 1) > self->marks_size) - { - UNLESS(self->marks = (int *)realloc(self->marks, (self->marks_size + 20) * sizeof(int))) - { - PyErr_SetString(PyExc_MemoryError, "out of memory"); - return NULL; - } - - self->marks_size += 20; - } - - self->marks[self->num_marks++] = len; - - Py_INCREF(Py_None); - return Py_None; -} - - -static PyObject * -load_eof(ARG(Unpicklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyErr_SetNone(PyExc_EOFError); - return NULL; -} - - -static PyObject * -Unpickler_load(ARG(Unpicklerobject *, self), ARG(PyObject *, args)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *stack = 0, *key = 0, *junk = 0, *err = 0, - *val = 0, *str = 0, *key_repr = 0; - char c; - char *c_str; - int len; - - c_str=&c; - - UNLESS(stack = PyList_New(0)) - goto err; - - self->stack = stack; - self->num_marks = 0; - - while (1) - { - if ((*self->read_func)(self, &c_str, 1) == -1) - break; - - switch (c_str[0]) - { - case NONE: - UNLESS(junk = load_none(self, NULL)) - break; - continue; - - case BININT: - UNLESS(junk = load_binint(self, NULL)) - break; - continue; - - case BININT1: - UNLESS(junk = load_binint1(self, NULL)) - break; - continue; - - case BININT2: - UNLESS(junk = load_binint2(self, NULL)) - break; - continue; - - case BININT3: - UNLESS(junk = load_binint3(self, NULL)) - break; - continue; - - case INT: - UNLESS(junk = load_int(self, NULL)) - break; - continue; - - case LONG: - UNLESS(junk = load_long(self, NULL)) - break; - continue; - - case FLOAT: - UNLESS(junk = load_float(self, NULL)) - break; - continue; - - case BINSTRING: - UNLESS(junk = load_binstring(self, NULL)) - break; - continue; - - case SHORT_BINSTRING: - UNLESS(junk = load_short_binstring(self, NULL)) - break; - continue; - - case STRING: - UNLESS(junk = load_string(self, NULL)) - break; - Py_DECREF(junk); - continue; - - case TUPLE: - UNLESS(junk = load_tuple(self, NULL)) - break; - Py_DECREF(junk); - continue; - - case LIST: - UNLESS(junk = load_list(self, NULL)) - break; - Py_DECREF(junk); - continue; - - case DICT: - UNLESS(junk = load_dict(self, NULL)) - break; - Py_DECREF(junk); - continue; - - case OBJ: - UNLESS(junk = load_obj(self, NULL)) - break; - Py_DECREF(junk); - continue; - - case INST: - UNLESS(junk = load_inst(self, NULL)) - break; - Py_DECREF(junk); - continue; - - case CLASS: - UNLESS(junk = load_class(self, NULL)) - break; - Py_DECREF(junk); - continue; - - case APPEND: - UNLESS(junk = load_append(self, NULL)) - break; - Py_DECREF(junk); - continue; - - case BUILD: - UNLESS(junk = load_build(self, NULL)) - break; - Py_DECREF(junk); - continue; - - case DUP: - UNLESS(junk = load_dup(self, NULL)) - break; - Py_DECREF(junk); - continue; - - case BINGET: - UNLESS(junk = load_binget(self, NULL)) - break; - Py_DECREF(junk); - continue; - - case GET: - UNLESS(junk = load_get(self, NULL)) - break; - Py_DECREF(junk); - continue; - - case MARK: - UNLESS(junk = load_mark(self, NULL)) - break; - Py_DECREF(junk); - continue; - - case BINPUT: - UNLESS(junk = load_binput(self, NULL)) - break; - Py_DECREF(junk); - continue; - - case PUT: - UNLESS(junk = load_put(self, NULL)) - break; - Py_DECREF(junk); - continue; - - case POP: - UNLESS(junk = load_pop(self, NULL)) - break; - Py_DECREF(junk); - continue; - - case SETITEM: - UNLESS(junk = load_setitem(self, NULL)) - break; - Py_DECREF(junk); - continue; - - case STOP: - break; - - case PERSID: - UNLESS(junk = load_persid(self, NULL)) - break; - Py_DECREF(junk); - continue; - - default: - UNLESS(key = PyString_FromStringAndSize(c_str, 1)) - return NULL; - - UNLESS(key_repr = PyObject_Repr(key)) - return NULL; - - UNLESS(str = PyString_FromStringAndSize(NULL, 19 + PyString_Size(key_repr))) - return NULL; - - sprintf(PyString_AS_STRING((PyStringObject *)str), - "invalid load key, \%s.", PyString_AS_STRING((PyStringObject *)key_repr)); - - PyErr_SetObject(UnpicklingError, str); - - Py_DECREF(str); - Py_DECREF(key); - Py_DECREF(key_repr); - + UNLESS(import_str = + (char *)malloc((strlen(module_name) + 15) * sizeof(char))) { + PyErr_NoMemory(); return NULL; } - break; - } + sprintf(import_str, "__import__('%s')", module_name); - if ((err = PyErr_Occurred()) == PyExc_EOFError) - { - return load_eof(self, NULL); - } + UNLESS(eval_dict) + UNLESS(eval_dict = Py_BuildValue("{sO}", "__builtins__", builtins)) + return NULL; - if (err) - return NULL; - - if ((len = PyList_Size(self->stack)) == -1) - return NULL; - - UNLESS(val = PyList_GetItem(self->stack, len - 1)) - return NULL; - Py_INCREF(val); - - if (DEL_LIST_SLICE(self->stack, len - 1, len) == -1) - { - Py_DECREF(val); - return NULL; - } - - return val; - -err: - Py_XDECREF(stack); - - return NULL; -} - - -static struct PyMethodDef Unpickler_methods[] = -{ - {"load", (PyCFunction)Unpickler_load, 0, ""}, - {"load_none", (PyCFunction)load_none, 0, ""}, - {"load_int", (PyCFunction)load_int, 0, ""}, - {"load_long", (PyCFunction)load_long, 0, ""}, - {"load_float", (PyCFunction)load_float, 0, ""}, - {"load_string", (PyCFunction)load_string, 0, ""}, - {"load_tuple", (PyCFunction)load_tuple, 0, ""}, - {"load_list", (PyCFunction)load_list, 0, ""}, - {"load_dict", (PyCFunction)load_dict, 0, ""}, - {"load_inst", (PyCFunction)load_inst, 0, ""}, - {"load_class", (PyCFunction)load_class, 0, ""}, - {"load_persid", (PyCFunction)load_persid, 0, ""}, - {"load_pop", (PyCFunction)load_pop, 0, ""}, - {"load_dup", (PyCFunction)load_dup, 0, ""}, - {"load_get", (PyCFunction)load_get, 0, ""}, - {"load_put", (PyCFunction)load_put, 0, ""}, - {"load_append", (PyCFunction)load_append, 0, ""}, - {"load_setitem", (PyCFunction)load_setitem, 0, ""}, - {"load_build", (PyCFunction)load_build, 0, ""}, - {"load_mark", (PyCFunction)load_mark, 0, ""}, - {"load_eof", (PyCFunction)load_eof, 0, ""}, - {NULL, NULL} /* sentinel */ -}; - - -static Unpicklerobject * -newUnpicklerobject(ARG(PyObject *, f)) - ARGDECL(PyObject *, f) -{ - Unpicklerobject *self; - PyObject *memo = 0; - - UNLESS(memo = PyDict_New()) - goto err; - - UNLESS(self = PyObject_NEW(Unpicklerobject, &Unpicklertype)) goto err; - - if (PyFile_Check(f)) - { - self->fp = PyFile_AsFile(f); - self->read_func = read_file; - self->readline_func = readline_file; - self->read = NULL; - self->readline = NULL; - } - else if (PycStringIO_InputCheck(f)) - { - self->fp = NULL; - self->read_func = read_cStringIO; - self->readline_func = readline_cStringIO; - self->read = NULL; - self->readline = NULL; - } - else - { - PyObject *readline, *read; - - self->fp = NULL; - self->read_func = read_other; - self->readline_func = readline_other; - - UNLESS(readline = PyObject_GetAttrString(f, "readline")) - goto err; - - UNLESS(read = PyObject_GetAttrString(f, "read")) - { - Py_DECREF(readline); - goto err; + if (!(import = + PyRun_String(import_str, eval_input, eval_dict, eval_dict))) { + free(import_str); + return NULL; } - - self->read = read; - self->readline = readline; - } - Py_INCREF(f); - - self->file = f; - self->memo = memo; - self->arg = NULL; - self->stack = NULL; - self->pers_func = NULL; - self->marks = NULL; - self->num_marks = 0; - self->marks_size = 0; + free(import_str); - return self; - -err: - Py_XDECREF(memo); - Py_XDECREF((PyObject *)self); - - return NULL; + return import; } static PyObject * -get_Unpickler(ARG(PyObject *, self), ARG(PyObject *, args)) - ARGDECL(PyObject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *file; +find_class(PyObject *py_module_name, PyObject *py_class_name) { + PyObject *import = 0, *class = 0, *t = 0; + char *module_name, *class_name; + PyObject *res = NULL; - UNLESS(PyArg_Parse(args, "O", &file)) return NULL; - return (PyObject *)newUnpicklerobject(file); -} + static PyObject *eval_dict = 0; + module_name = PyString_AS_STRING((PyStringObject *)py_module_name); + class_name = PyString_AS_STRING((PyStringObject *)py_class_name); -static void -Unpickler_dealloc(ARG(Unpicklerobject *, self)) - ARGDECL(Unpicklerobject *, self) -{ - Py_XDECREF(self->readline); - Py_XDECREF(self->read); - Py_XDECREF(self->file); - Py_XDECREF(self->memo); - Py_XDECREF(self->stack); - Py_XDECREF(self->pers_func); - Py_XDECREF(self->arg); - free(self->marks); - PyMem_DEL(self); -} + UNLESS(t = PyTuple_New(2)) + goto finally; + PyTuple_SET_ITEM((PyTupleObject *)t, 0, py_module_name); + Py_INCREF(py_module_name); + + PyTuple_SET_ITEM((PyTupleObject *)t, 1, py_class_name); + Py_INCREF(py_class_name); -static PyObject * -Unpickler_getattr(ARG(Unpicklerobject *, self), ARG(char *, name)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(char *, name) -{ - if (!strcmp(name, "persistent_load")) - { - if (!self->pers_func) - { - PyErr_SetString(PyExc_NameError, name); - return NULL; + if (class = PyDict_GetItem(class_map, t)) { + res = class; + Py_INCREF(class); + goto finally; } - Py_INCREF(self->pers_func); - return self->pers_func; - } + PyErr_Clear(); - if (!strcmp(name, "memo")) - { - if (!self->memo) - { - PyErr_SetString(PyExc_NameError, name); - return NULL; - } + if (!(import = PyImport_ImportModuleNi(module_name)) || + !(class = PyObject_GetAttr(import, py_class_name))) { + PyErr_Format(PyExc_SystemError, "Failed to import global %s " + "from module %s", "ss", class_name, module_name); + goto finally; + } - Py_INCREF(self->memo); - return self->memo; - } + if (PyDict_SetItem(class_map, t, class) < 0) + goto finally; - if (!strcmp(name, "UnpicklingError")) - { - Py_INCREF(UnpicklingError); - return UnpicklingError; - } + res = class; - return Py_FindMethod(Unpickler_methods, (PyObject *)self, name); +finally: + Py_XDECREF(import); + Py_XDECREF(t); + + return res; } static int -Unpickler_setattr(ARG(Unpicklerobject *, self), ARG(char *, name), ARG(PyObject *, value)) - ARGDECL(Unpicklerobject *, self) - ARGDECL(char *, name) - ARGDECL(PyObject *, value) -{ - if (!strcmp(name, "persistent_load")) - { - Py_XDECREF(self->pers_func); - self->pers_func = value; - Py_INCREF(value); +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) { + if (PyList_Append(self->stack, Py_None) < 0) + return -1; + return 0; +} + + +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; + UNLESS(s=strndup(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; + UNLESS(py_int=PyLong_FromString(s,&endptr,0)) goto finally; + + if ((*endptr != '\n') || (endptr[1] != '\0')) { + PyErr_SetString(PyExc_ValueError, + "could not convert string to int"); + goto finally; + } + } + else { + UNLESS(py_int = PyInt_FromLong(l)) goto finally; + } + + if (PyList_Append(self->stack, py_int) < 0) goto finally; + + res = 0; + +finally: + free(s); + Py_XDECREF(py_int); + + return res; +} + + +static long +calc_binint(char *s, int x) { + unsigned char c; + int i; + long l; + + for (i = 0, l = 0L; i < x; i++) { + c = (unsigned char)s[i]; + l |= (long)c << (i * 8); + } + + return l; +} + + +static int +load_binintx(Unpicklerobject *self, char *s, int x) { + PyObject *py_int = 0; + long l; + + l = calc_binint(s, x); + + UNLESS(py_int = PyInt_FromLong(l)) + return -1; + + if (PyList_Append(self->stack, py_int) < 0) { + Py_DECREF(py_int); + return -1; + } + + Py_DECREF(py_int); + + return 0; +} + + +static int +load_binint(Unpicklerobject *self) { + char *s; + + if ((*self->read_func)(self, &s, 4) < 0) + return -1; + + return load_binintx(self, s, 4); +} + + +static int +load_binint1(Unpicklerobject *self) { + char *s; + + if ((*self->read_func)(self, &s, 1) < 0) + return -1; + + return load_binintx(self, s, 1); +} + + +static int +load_binint2(Unpicklerobject *self) { + char *s; + + if ((*self->read_func)(self, &s, 2) < 0) + return -1; + + return load_binintx(self, s, 2); +} + +static int +load_long(Unpicklerobject *self) { + PyObject *l = 0; + char *end, *s; + int len, res = -1; + + static PyObject *arg = 0; + + if ((len = (*self->readline_func)(self, &s)) < 0) return -1; + UNLESS(s=strndup(s,len)) return -1; + + UNLESS(l = PyLong_FromString(s, &end, 0)) + goto finally; + + if (PyList_Append(self->stack, l) < 0) + goto finally; + + res = 0; + +finally: + free(s); + Py_XDECREF(l); + + return res; +} + + +static int +load_float(Unpicklerobject *self) { + PyObject *py_float = 0; + char *endptr, *s; + int len, res = -1; + double d; + + if ((len = (*self->readline_func)(self, &s)) < 0) return -1; + UNLESS(s=strndup(s,len)) return -1; + + errno = 0; + d = strtod(s, &endptr); + + if (errno || (endptr[0] != '\n') || (endptr[1] != '\0')) { + PyErr_SetString(PyExc_ValueError, + "could not convert string to float"); + goto finally; + } + + UNLESS(py_float = PyFloat_FromDouble(d)) + goto finally; + + if (PyList_Append(self->stack, py_float) < 0) + goto finally; + + res = 0; + +finally: + free(s); + Py_XDECREF(py_float); + + return res; +} + +#ifdef FORMAT_1_3 +static int +load_binfloat(Unpicklerobject *self) { + PyObject *py_float = 0; + int s, e, res = -1; + long fhi, flo; + double x; + char *p; + + if ((*self->read_func)(self, &p, 8) < 0) + return -1; + + /* First byte */ + s = (*p>>7) & 1; + e = (*p & 0x7F) << 4; + p++; + + /* Second byte */ + e |= (*p>>4) & 0xF; + fhi = (*p & 0xF) << 24; + p++; + + /* Third byte */ + fhi |= (*p & 0xFF) << 16; + p++; + + /* Fourth byte */ + fhi |= (*p & 0xFF) << 8; + p++; + + /* Fifth byte */ + fhi |= *p & 0xFF; + p++; + + /* Sixth byte */ + flo = (*p & 0xFF) << 16; + p++; + + /* Seventh byte */ + flo |= (*p & 0xFF) << 8; + p++; + + /* Eighth byte */ + flo |= *p & 0xFF; + + x = (double)fhi + (double)flo / 16777216.0; /* 2**24 */ + x /= 268435456.0; /* 2**28 */ + + /* XXX This sadly ignores Inf/NaN */ + if (e == 0) + e = -1022; + else { + x += 1.0; + e -= 1023; + } + x = ldexp(x, e); + + if (s) + x = -x; + + UNLESS(py_float = PyFloat_FromDouble(x)) + goto finally; + + if (PyList_Append(self->stack, py_float) < 0) + goto finally; + + res = 0; + +finally: + Py_XDECREF(py_float); + + return res; +} +#endif + +static int +load_string(Unpicklerobject *self) { + PyObject *str = 0; + int len, res = -1; + char *s; + + static PyObject *eval_dict = 0; + + if ((len = (*self->readline_func)(self, &s)) < 0) return -1; + UNLESS(s=strndup(s,len)) return -1; + + UNLESS(eval_dict) + UNLESS(eval_dict = Py_BuildValue("{s{}}", "__builtins__")) + goto finally; + + UNLESS(str = PyRun_String(s, eval_input, eval_dict, eval_dict)) + goto finally; + + if (PyList_Append(self->stack, str) < 0) + goto finally; + + res = 0; + +finally: + free(s); + Py_XDECREF(str); + + return res; +} + + +static int +load_binstring(Unpicklerobject *self) { + PyObject *py_string = 0; + long l; + int res = -1; + char *s; + + if ((*self->read_func)(self, &s, 4) < 0) + goto finally; + + l = calc_binint(s, 4); + + if ((*self->read_func)(self, &s, l) < 0) + goto finally; + + UNLESS(py_string = PyString_FromStringAndSize(s, l)) + goto finally; + + if (PyList_Append(self->stack, py_string) < 0) + goto finally; + + res = 0; + +finally: + Py_XDECREF(py_string); + + return res; +} + + +static int +load_short_binstring(Unpicklerobject *self) { + PyObject *py_string = 0; + unsigned char l; + int res = -1; + char *s; + + if ((*self->read_func)(self, &s, 1) < 0) + return -1; + + l = (unsigned char)s[0]; + + if ((*self->read_func)(self, &s, l) < 0) + goto finally; + + UNLESS(py_string = PyString_FromStringAndSize(s, l)) + goto finally; + + if (PyList_Append(self->stack, py_string) < 0) + goto finally; + + res = 0; + +finally: + Py_XDECREF(py_string); + + return res; +} + + +static int +load_tuple(Unpicklerobject *self) { + PyObject *tup = 0, *slice = 0, *list = 0; + int i, j, res = -1; + + if ((i = marker(self)) < 0) + goto finally; + + if ((j = PyList_Size(self->stack)) < 0) + goto finally; + + UNLESS(slice = PyList_GetSlice(self->stack, i, j)) + goto finally; + + UNLESS(tup = PySequence_Tuple(slice)) + goto finally; + + UNLESS(list = PyList_New(1)) + goto finally; + + Py_INCREF(tup); + if (PyList_SetItem(list, 0, tup) < 0) + goto finally; + + if (PyList_SetSlice(self->stack, i, j, list) < 0) + goto finally; + + res = 0; + +finally: + Py_XDECREF(tup); + Py_XDECREF(list); + Py_XDECREF(slice); + + return res; +} + +static int +load_empty_tuple(Unpicklerobject *self) { + PyObject *tup = 0; + int res; + + UNLESS(tup=PyTuple_New(0)) return -1; + res=PyList_Append(self->stack, tup); + Py_DECREF(tup); + return res; +} + +static int +load_empty_list(Unpicklerobject *self) { + PyObject *list = 0; + int res; + + UNLESS(list=PyList_New(0)) return -1; + res=PyList_Append(self->stack, list); + Py_DECREF(list); + return res; +} + +static int +load_empty_dict(Unpicklerobject *self) { + PyObject *dict = 0; + int res; + + UNLESS(dict=PyDict_New()) return -1; + res=PyList_Append(self->stack, dict); + Py_DECREF(dict); + return res; +} + + +static int +load_list(Unpicklerobject *self) { + PyObject *list = 0, *slice = 0; + int i, j, l, res = -1; + + if ((i = marker(self)) < 0) + goto finally; + + if ((j = PyList_Size(self->stack)) < 0) + goto finally; + + UNLESS(slice = PyList_GetSlice(self->stack, i, j)) + goto finally; + + if((l=PyList_Size(slice)) < 0) + goto finally; + + if(l) { + UNLESS(list = PyList_New(1)) + goto finally; + + Py_INCREF(slice); + if (PyList_SetItem(list, 0, slice) < 0) + goto finally; + + if (PyList_SetSlice(self->stack, i, j, list) < 0) + goto finally; + } else { + if(PyList_Append(self->stack,slice) < 0) + goto finally; + } + + res = 0; + +finally: + Py_XDECREF(list); + Py_XDECREF(slice); + + return res; +} + +static int +load_dict(Unpicklerobject *self) { + PyObject *list = 0, *dict = 0, *key = 0, *value = 0; + int i, j, k, res = -1; + + if ((i = marker(self)) < 0) + goto finally; + + if ((j = PyList_Size(self->stack)) < 0) + goto finally; + + UNLESS(dict = PyDict_New()) + goto finally; + + for (k = i; k < j; k += 2) { + UNLESS(key = PyList_GET_ITEM((PyListObject *)self->stack, k)) + goto finally; + + UNLESS(value = PyList_GET_ITEM((PyListObject *)self->stack, k + 1)) + goto finally; + + if (PyDict_SetItem(dict, key, value) < 0) + goto finally; + } + + if(j) { + + UNLESS(list = PyList_New(1)) + goto finally; + + Py_INCREF(dict); + if (PyList_SetItem(list, 0, dict) < 0) + goto finally; + + if (PyList_SetSlice(self->stack, i, j, list) < 0) + goto finally; + } + else + if(PyList_Append(self->stack, dict) < 0) + goto finally; + + res = 0; + +finally: + Py_XDECREF(dict); + Py_XDECREF(list); + + return res; +} + +static PyObject * +Instance_New(PyObject *cls, PyObject *args) +{ + int has_key; + PyObject *safe=0, *r=0; + + if (PyClass_Check(cls)) + if(r=PyInstance_New(cls, args, NULL)) return r; + else goto err; + + + if ((has_key = cPickle_PyMapping_HasKey(safe_constructors, cls)) < 0) + goto err; + + if (!has_key) + if(!(safe = PyObject_GetAttr(cls, __safe_for_unpickling___str)) || + !PyObject_IsTrue(safe)) { + PyErr_Format(UnpicklingError, "%s is not safe for unpickling", "O", cls); + Py_XDECREF(safe); + return NULL; } - return -1; + if(r=PyObject_CallObject(cls, args)) return r; +err: + { + PyObject *tp, *v, *tb; + + PyErr_Fetch(&tp, &v, &tb); + if(r=Py_BuildValue("OOO",v,cls,args)) + { + Py_XDECREF(v); + v=r; + } + PyErr_Restore(tp,v,tb); + } + return NULL; +} + + +static int +load_obj(Unpicklerobject *self) { + PyObject *class = 0, *slice = 0, *tup = 0, *obj = 0; + int i, len, res = -1; + + if ((i = marker(self)) < 0) + goto finally; + + class = PyList_GET_ITEM((PyListObject *)self->stack, i); + Py_INCREF(class); + + if ((len = PyList_Size(self->stack)) < 0) + goto finally; + + UNLESS(slice = PyList_GetSlice(self->stack, i + 1, len)) + goto finally; + + UNLESS(tup = PySequence_Tuple(slice)) + goto finally; + + UNLESS(obj = Instance_New(class, tup)) + goto finally; + + if (DEL_LIST_SLICE(self->stack, i, len) < 0) + goto finally; + + if (PyList_Append(self->stack, obj) < 0) + goto finally; + + res = 0; + +finally: + + Py_XDECREF(class); + Py_XDECREF(slice); + Py_XDECREF(tup); + Py_XDECREF(obj); + + return res; +} + + +static int +load_inst(Unpicklerobject *self) { + PyObject *arg_tup = 0, *arg_slice = 0, *class = 0, *obj = 0, + *module_name = 0, *class_name = 0; + int i, j, len, res = -1; + char *s; + + if ((i = marker(self)) < 0) + goto finally; + + if ((j = PyList_Size(self->stack)) < 0) + goto finally; + + UNLESS(arg_slice = PyList_GetSlice(self->stack, i, j)) + goto finally; + + UNLESS(arg_tup = PySequence_Tuple(arg_slice)) + goto finally; + + if (DEL_LIST_SLICE(self->stack, i, j) < 0) + goto finally; + + if ((len = (*self->readline_func)(self, &s)) < 0) + goto finally; + + UNLESS(module_name = PyString_FromStringAndSize(s, len - 1)) + goto finally; + + if ((len = (*self->readline_func)(self, &s)) < 0) + goto finally; + + UNLESS(class_name = PyString_FromStringAndSize(s, len - 1)) + goto finally; + + UNLESS(class = find_class(module_name, class_name)) + goto finally; + + UNLESS(obj = Instance_New(class, arg_tup)) + goto finally; + + if (PyList_Append(self->stack, obj) < 0) + goto finally; + + res = 0; + +finally: + Py_XDECREF(class); + Py_XDECREF(arg_slice); + Py_XDECREF(arg_tup); + Py_XDECREF(obj); + Py_XDECREF(module_name); + Py_XDECREF(class_name); + + return res; +} + + +static int +load_global(Unpicklerobject *self) { + PyObject *class = 0, *module_name = 0, *class_name = 0; + int res = -1, len; + char *s; + + if ((len = (*self->readline_func)(self, &s)) < 0) + goto finally; + + UNLESS(module_name = PyString_FromStringAndSize(s, len - 1)) + goto finally; + + if ((len = (*self->readline_func)(self, &s)) < 0) + goto finally; + + UNLESS(class_name = PyString_FromStringAndSize(s, len - 1)) + goto finally; + + UNLESS(class = find_class(module_name, class_name)) + goto finally; + + if (PyList_Append(self->stack, class) < 0) + goto finally; + + res = 0; + +finally: + Py_XDECREF(class); + Py_XDECREF(module_name); + Py_XDECREF(class_name); + + return res; +} + + +static int +load_persid(Unpicklerobject *self) { + PyObject *pid = 0, *pers_load_val = 0; + int len, res = -1; + char *s; + + if (self->pers_func) { + if ((len = (*self->readline_func)(self, &s)) < 0) + goto finally; + + UNLESS(pid = PyString_FromStringAndSize(s, len - 1)) + goto finally; + + UNLESS(self->arg) + UNLESS(self->arg = PyTuple_New(1)) + goto finally; + + Py_INCREF(pid); + if (PyTuple_SetItem(self->arg, 0, pid) < 0) + goto finally; + + UNLESS(pers_load_val = + PyObject_CallObject(self->pers_func, self->arg)) + goto finally; + + if (PyList_Append(self->stack, pers_load_val) < 0) + goto finally; + } + + res = 0; + +finally: + Py_XDECREF(pid); + Py_XDECREF(pers_load_val); + + return res; +} + + +static int +load_binpersid(Unpicklerobject *self) { + PyObject *pid = 0, *pers_load_val = 0; + int len, res = -1; + + if (self->pers_func) { + if ((len = PyList_Size(self->stack)) < 0) + goto finally; + + pid = PyList_GET_ITEM((PyListObject *)self->stack, len - 1); + Py_INCREF(pid); + + if (DEL_LIST_SLICE(self->stack, len - 1, len) < 0) + goto finally; + + UNLESS(self->arg) + UNLESS(self->arg = PyTuple_New(1)) + goto finally; + + Py_INCREF(pid); + if (PyTuple_SetItem(self->arg, 0, pid) < 0) + goto finally; + + UNLESS(pers_load_val = + PyObject_CallObject(self->pers_func, self->arg)) + goto finally; + + if (PyList_Append(self->stack, pers_load_val) < 0) + goto finally; + } + + res = 0; + +finally: + Py_XDECREF(pid); + Py_XDECREF(pers_load_val); + + return res; +} + + +static int +load_pop(Unpicklerobject *self) { + int len; + + if ((len = PyList_Size(self->stack)) < 0) + return -1; + + if ((self->num_marks > 0) && + (self->marks[self->num_marks - 1] == len)) + self->num_marks--; + else if (DEL_LIST_SLICE(self->stack, len - 1, len) < 0) + return -1; + + return 0; +} + + +static int +load_pop_mark(Unpicklerobject *self) { + int i, len; + + if ((i = marker(self)) < 0) + return -1; + + if ((len = PyList_Size(self->stack)) < 0) + return -1; + + if (DEL_LIST_SLICE(self->stack, i, len) < 0) + return -1; + + return 0; +} + + +static int +load_dup(Unpicklerobject *self) { + PyObject *last; + int len; + + if ((len = PyList_Size(self->stack)) < 0) + return -1; + + UNLESS(last = PyList_GetItem(self->stack, len - 1)) + return -1; + + if (PyList_Append(self->stack, last) < 0) + return -1; + + return 0; +} + + +static int +load_get(Unpicklerobject *self) { + PyObject *py_str = 0, *value = 0; + int len, res = -1; + char *s; + + if ((len = (*self->readline_func)(self, &s)) < 0) + goto finally; + + UNLESS(py_str = PyString_FromStringAndSize(s, len - 1)) + goto finally; + + UNLESS(value = PyDict_GetItem(self->memo, py_str)) + goto finally; + + if (PyList_Append(self->stack, value) < 0) + goto finally; + + res = 0; + +finally: + Py_XDECREF(py_str); + + return res; +} + + +static int +load_binget(Unpicklerobject *self) { + PyObject *py_key = 0, *value = 0; + unsigned char key; + int res = -1; + char *s; + + if ((*self->read_func)(self, &s, 1) < 0) + goto finally; + + key = (unsigned char)s[0]; + + UNLESS(py_key = PyInt_FromLong((long)key)) + goto finally; + + UNLESS(value = PyDict_GetItem(self->memo, py_key)) + goto finally; + + if (PyList_Append(self->stack, value) < 0) + goto finally; + + res = 0; + +finally: + Py_XDECREF(py_key); + + return res; +} + + +static int +load_long_binget(Unpicklerobject *self) { + PyObject *py_key = 0, *value = 0; + unsigned char c, *s; + long key; + int res = -1; + + if ((*self->read_func)(self, &s, 4) < 0) + goto finally; + + c = (unsigned char)s[0]; + key = (long)c; + c = (unsigned char)s[1]; + key |= (long)c << 8; + c = (unsigned char)s[2]; + key |= (long)c << 16; + c = (unsigned char)s[3]; + key |= (long)c << 24; + + UNLESS(py_key = PyInt_FromLong(key)) + goto finally; + + UNLESS(value = PyDict_GetItem(self->memo, py_key)) + goto finally; + + if (PyList_Append(self->stack, value) < 0) + goto finally; + + res = 0; + +finally: + Py_XDECREF(py_key); + + return res; +} + + +static int +load_put(Unpicklerobject *self) { + PyObject *py_str = 0, *value = 0; + int len, res = -1; + char *s; + + if ((len = (*self->readline_func)(self, &s)) < 0) + goto finally; + + UNLESS(py_str = PyString_FromStringAndSize(s, len - 1)) + goto finally; + + if ((len = PyList_Size(self->stack)) < 0) + goto finally; + + UNLESS(value = PyList_GetItem(self->stack, len - 1)) + goto finally; + + if (PyDict_SetItem(self->memo, py_str, value) < 0) + goto finally; + + res = 0; + +finally: + Py_XDECREF(py_str); + + return res; +} + + +static int +load_binput(Unpicklerobject *self) { + PyObject *py_key = 0, *value = 0; + unsigned char key, *s; + int len, res = -1; + + if ((*self->read_func)(self, &s, 1) < 0) + goto finally; + + key = (unsigned char)s[0]; + + UNLESS(py_key = PyInt_FromLong((long)key)) + goto finally; + + if ((len = PyList_Size(self->stack)) < 0) + goto finally; + + UNLESS(value = PyList_GetItem(self->stack, len - 1)) + goto finally; + + if (PyDict_SetItem(self->memo, py_key, value) < 0) + goto finally; + + res = 0; + +finally: + Py_XDECREF(py_key); + + return res; +} + + +static int +load_long_binput(Unpicklerobject *self) { + PyObject *py_key = 0, *value = 0; + long key; + unsigned char c, *s; + int len, res = -1; + + if ((*self->read_func)(self, &s, 4) < 0) + goto finally; + + c = (unsigned char)s[0]; + key = (long)c; + c = (unsigned char)s[1]; + key |= (long)c << 8; + c = (unsigned char)s[2]; + key |= (long)c << 16; + c = (unsigned char)s[3]; + key |= (long)c << 24; + + UNLESS(py_key = PyInt_FromLong(key)) + goto finally; + + if ((len = PyList_Size(self->stack)) < 0) + goto finally; + + UNLESS(value = PyList_GetItem(self->stack, len - 1)) + goto finally; + + if (PyDict_SetItem(self->memo, py_key, value) < 0) + goto finally; + + res = 0; + +finally: + Py_XDECREF(py_key); + + return res; +} + + +static int +do_append(Unpicklerobject *self, int x) { + PyObject *value = 0, *list = 0, *append_method = 0; + int len, i; + + if ((len = PyList_Size(self->stack)) < 0) + return -1; + + UNLESS(list = PyList_GetItem(self->stack, x - 1)) + goto err; + + if (PyList_Check(list)) { + PyObject *slice = 0; + int list_len; + + UNLESS(slice = PyList_GetSlice(self->stack, x, len)) + return -1; + + list_len = PyList_Size(list); + if (PyList_SetSlice(list, list_len, list_len, slice) < 0) { + Py_DECREF(slice); + return -1; + } + + Py_DECREF(slice); + } + else { + + UNLESS(append_method = PyObject_GetAttr(list, append_str)) + return -1; + + for (i = x; i < len; i++) { + PyObject *junk; + + UNLESS(value = PyList_GetItem(self->stack, i)) + return -1; + + UNLESS(self->arg) + UNLESS(self->arg = PyTuple_New(1)) + goto err; + + Py_INCREF(value); + if (PyTuple_SetItem(self->arg, 0, value) < 0) + goto err; + + UNLESS(junk = PyObject_CallObject(append_method, self->arg)) + goto err; + Py_DECREF(junk); + } + } + + if (DEL_LIST_SLICE(self->stack, x, len) < 0) + goto err; + + Py_XDECREF(append_method); + + return 0; + +err: + Py_XDECREF(append_method); + + return -1; +} + + +static int +load_append(Unpicklerobject *self) { + return do_append(self, PyList_Size(self->stack) - 1); +} + + +static int +load_appends(Unpicklerobject *self) { + return do_append(self, marker(self)); +} + + +static int +do_setitems(Unpicklerobject *self, int x) { + PyObject *value = 0, *key = 0, *dict = 0; + int len, i, res = -1; + + if ((len = PyList_Size(self->stack)) < 0) + goto finally; + + UNLESS(dict = PyList_GetItem(self->stack, x - 1)) + goto finally; + + for (i = x; i < len; i += 2) { + UNLESS(key = PyList_GetItem(self->stack, i)) + goto finally; + + UNLESS(value = PyList_GetItem(self->stack, i + 1)) + goto finally; + + if (PyObject_SetItem(dict, key, value) < 0) + goto finally; + } + + if (DEL_LIST_SLICE(self->stack, x, len) < 0) + goto finally; + + res = 0; + +finally: + + return res; +} + + +static int +load_setitem(Unpicklerobject *self) { + return do_setitems(self, PyList_Size(self->stack) - 2); +} + + +static int +load_setitems(Unpicklerobject *self) { + return do_setitems(self, marker(self)); +} + + +static int +load_build(Unpicklerobject *self) { + PyObject *value = 0, *inst = 0, *instdict = 0, *d_key = 0, *d_value = 0, + *junk = 0, *__setstate__ = 0; + int len, i, res = -1; + + if ((len = PyList_Size(self->stack)) < 0) + goto finally; + + UNLESS(value = PyList_GetItem(self->stack, len - 1)) + goto finally; + Py_INCREF(value); + + if (DEL_LIST_SLICE(self->stack, len - 1, len) < 0) + goto finally; + + UNLESS(inst = PyList_GetItem(self->stack, len - 2)) + goto finally; + + UNLESS(__setstate__ = PyObject_GetAttr(inst, __setstate___str)) + { + PyErr_Clear(); + + UNLESS(instdict = PyObject_GetAttr(inst, __dict___str)) + goto finally; + + i = 0; + while (PyDict_Next(value, &i, &d_key, &d_value)) { + if (PyObject_SetItem(instdict, d_key, d_value) < 0) + goto finally; + } + } + else { + UNLESS(self->arg) + UNLESS(self->arg = PyTuple_New(1)) + goto finally; + + Py_INCREF(value); + if (PyTuple_SetItem(self->arg, 0, value) < 0) + goto finally; + + UNLESS(junk = PyObject_CallObject(__setstate__, self->arg)) + goto finally; + Py_DECREF(junk); + } + + res = 0; + +finally: + Py_XDECREF(value); + Py_XDECREF(instdict); + Py_XDECREF(__setstate__); + + return res; +} + + +static int +load_mark(Unpicklerobject *self) { + int len; + + if ((len = PyList_Size(self->stack)) < 0) + return -1; + + if (!self->marks_size) { + self->marks_size = 20; + UNLESS(self->marks = (int *)malloc(self->marks_size * sizeof(int))) { + PyErr_NoMemory(); + return -1; + } + } + else if ((self->num_marks + 1) >= self->marks_size) { + UNLESS(self->marks = (int *)realloc(self->marks, + (self->marks_size + 20) * sizeof(int))) { + PyErr_NoMemory(); + return -1; + } + + self->marks_size += 20; + } + + self->marks[self->num_marks++] = len; + + return 0; +} + +static int +load_reduce(Unpicklerobject *self) { + PyObject *callable = 0, *arg_tup = 0, *ob = 0; + int len, res = -1; + + if ((len = PyList_Size(self->stack)) < 0) + goto finally; + + UNLESS(arg_tup = PyList_GetItem(self->stack, len - 1)) + goto finally; + + UNLESS(callable = PyList_GetItem(self->stack, len - 2)) + goto finally; + + UNLESS(ob = Instance_New(callable, arg_tup)) + goto finally; + + if (PyList_Append(self->stack, ob) < 0) + goto finally; + + if (DEL_LIST_SLICE(self->stack, len - 2, len) < 0) + goto finally; + + res = 0; + +finally: + Py_XDECREF(ob); + + return res; +} + +static PyObject * +load(Unpicklerobject *self) +{ + PyObject *stack = 0, *err = 0, *exc = 0, *val = 0, *tb = 0; + int len; + char *s; + + UNLESS(stack = PyList_New(0)) + goto err; + + self->stack = stack; + self->num_marks = 0; + + while (1) { + if ((*self->read_func)(self, &s, 1) < 0) + break; + + switch (s[0]) { + case NONE: + if (load_none(self) < 0) + break; + continue; + + case BININT: + if (load_binint(self) < 0) + break; + continue; + + case BININT1: + if (load_binint1(self) < 0) + break; + continue; + + case BININT2: + if (load_binint2(self) < 0) + break; + continue; + + case INT: + if (load_int(self) < 0) + break; + continue; + + case LONG: + if (load_long(self) < 0) + break; + continue; + + case FLOAT: + if (load_float(self) < 0) + break; + continue; + +#ifdef FORMAT_1_3 + case BINFLOAT: + if (load_binfloat(self) < 0) + break; + continue; +#endif + + case BINSTRING: + if (load_binstring(self) < 0) + break; + continue; + + case SHORT_BINSTRING: + if (load_short_binstring(self) < 0) + break; + continue; + + case STRING: + if (load_string(self) < 0) + break; + continue; + + case EMPTY_TUPLE: + if (load_empty_tuple(self) < 0) + break; + continue; + + case TUPLE: + if (load_tuple(self) < 0) + break; + continue; + + case EMPTY_LIST: + if (load_empty_list(self) < 0) + break; + continue; + + case LIST: + if (load_list(self) < 0) + break; + continue; + + case EMPTY_DICT: + if (load_empty_dict(self) < 0) + break; + continue; + + case DICT: + if (load_dict(self) < 0) + break; + continue; + + case OBJ: + if (load_obj(self) < 0) + break; + continue; + + case INST: + if (load_inst(self) < 0) + break; + continue; + + case GLOBAL: + if (load_global(self) < 0) + break; + continue; + + case APPEND: + if (load_append(self) < 0) + break; + continue; + + case APPENDS: + if (load_appends(self) < 0) + break; + continue; + + case BUILD: + if (load_build(self) < 0) + break; + continue; + + case DUP: + if (load_dup(self) < 0) + break; + continue; + + case BINGET: + if (load_binget(self) < 0) + break; + continue; + + case LONG_BINGET: + if (load_long_binget(self) < 0) + break; + continue; + + case GET: + if (load_get(self) < 0) + break; + continue; + + case MARK: + if (load_mark(self) < 0) + break; + continue; + + case BINPUT: + if (load_binput(self) < 0) + break; + continue; + + case LONG_BINPUT: + if (load_long_binput(self) < 0) + break; + continue; + + case PUT: + if (load_put(self) < 0) + break; + continue; + + case POP: + if (load_pop(self) < 0) + break; + continue; + + case POP_MARK: + if (load_pop_mark(self) < 0) + break; + continue; + + case SETITEM: + if (load_setitem(self) < 0) + break; + continue; + + case SETITEMS: + if (load_setitems(self) < 0) + break; + continue; + + case STOP: + break; + + case PERSID: + if (load_persid(self) < 0) + break; + continue; + + case BINPERSID: + if (load_binpersid(self) < 0) + break; + continue; + + case REDUCE: + if (load_reduce(self) < 0) + break; + continue; + + default: + PyErr_Format(UnpicklingError, "invalid load key, '%s'.", + "c", s[0]); + goto err; + } + + break; + } + + if ((err = PyErr_Occurred()) == PyExc_EOFError) { + PyErr_SetNone(PyExc_EOFError); + goto err; + } + + if (err) goto err; + + if ((len = PyList_Size(stack)) < 0) goto err; + + UNLESS(val = PyList_GetItem(stack, len - 1)) goto err; + Py_INCREF(val); + + Py_DECREF(stack); + + self->stack=NULL; + return val; + +err: + self->stack=NULL; + Py_XDECREF(stack); + + return NULL; +} + + +static PyObject * +Unpickler_load(Unpicklerobject *self, PyObject *args) { + UNLESS(PyArg_ParseTuple(args, "")) + return NULL; + + return load(self); +} + + +static struct PyMethodDef Unpickler_methods[] = { + {"load", (PyCFunction)Unpickler_load, 1, ""}, + {NULL, NULL} /* sentinel */ +}; + + +static Unpicklerobject * +newUnpicklerobject(PyObject *f) { + Unpicklerobject *self; + + UNLESS(self = PyObject_NEW(Unpicklerobject, &Unpicklertype)) + return NULL; + + self->file = NULL; + self->arg = NULL; + self->stack = NULL; + self->pers_func = NULL; + self->last_string = NULL; + self->marks = NULL; + self->num_marks = 0; + self->marks_size = 0; + self->buf_size = 0; + self->read = NULL; + self->readline = NULL; + + UNLESS(self->memo = PyDict_New()) { + Py_XDECREF((PyObject *)self); + return NULL; + } + + Py_INCREF(f); + self->file = f; + + /* Set read, readline based on type of f */ + if (PyFile_Check(f)) { + self->fp = PyFile_AsFile(f); + self->read_func = read_file; + self->readline_func = readline_file; + } + else if (PycStringIO_InputCheck(f)) { + self->fp = NULL; + self->read_func = read_cStringIO; + self->readline_func = readline_cStringIO; + } + else { + + self->fp = NULL; + self->read_func = read_other; + self->readline_func = readline_other; + + UNLESS((self->readline = PyObject_GetAttr(f, readline_str)) && + (self->read = PyObject_GetAttr(f, read_str))) + { + PyErr_Clear(); + PyErr_SetString( PyExc_TypeError, "argument must have 'read' and " + "'readline' attributes" ); + Py_XDECREF((PyObject *)self); + return NULL; + } + } + + return self; } static PyObject * -dump(ARG(PyObject *, self), ARG(PyObject *, args)) - ARGDECL(PyObject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *ob, *file, *ret_val; - Picklerobject *pickler; - int bin = 0; +get_Unpickler(PyObject *self, PyObject *args) { + PyObject *file; + + UNLESS(PyArg_ParseTuple(args, "O", &file)) + return NULL; + return (PyObject *)newUnpicklerobject(file); +} - UNLESS(PyArg_ParseTuple(args, "OO|i", &ob, &file, &bin)) - return NULL; - UNLESS(pickler = newPicklerobject(file, bin)) - return NULL; +static void +Unpickler_dealloc(Unpicklerobject *self) { + Py_XDECREF(self->readline); + Py_XDECREF(self->read); + Py_XDECREF(self->file); + Py_XDECREF(self->memo); + Py_XDECREF(self->stack); + Py_XDECREF(self->pers_func); + Py_XDECREF(self->arg); + Py_XDECREF(self->last_string); - UNLESS(ret_val = Pickler_dump(pickler, ob)) - { - Pickler_dealloc(pickler); - return NULL; - } + if (self->marks) { + free(self->marks); + } - Pickler_dealloc(pickler); - - return ret_val; + if (self->buf_size) { + free(self->buf); + } + + PyMem_DEL(self); } static PyObject * -dumps(ARG(PyObject *, self), ARG(PyObject *, args)) - ARGDECL(PyObject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *ob, *file, *pickle_str; - Picklerobject *pickler; - int bin = 0; +Unpickler_getattr(Unpicklerobject *self, char *name) { + if (!strcmp(name, "persistent_load")) { + if (!self->pers_func) { + PyErr_SetString(PyExc_AttributeError, name); + return NULL; + } - UNLESS(PyArg_ParseTuple(args, "O|i", &ob, &bin)) - return NULL; + Py_INCREF(self->pers_func); + return self->pers_func; + } - UNLESS(file = (*PycStringIO_NewOutput)(128)) - return NULL; + if (!strcmp(name, "memo")) { + if (!self->memo) { + PyErr_SetString(PyExc_AttributeError, name); + return NULL; + } - UNLESS(pickler = newPicklerobject(file, bin)) - { - Py_DECREF(file); - return NULL; - } + Py_INCREF(self->memo); + return self->memo; + } - UNLESS(Pickler_dump(pickler, ob)) - { - Pickler_dealloc(pickler); - Py_DECREF(file); - return NULL; - } + if (!strcmp(name, "stack")) { + if (!self->stack) { + PyErr_SetString(PyExc_AttributeError, name); + return NULL; + } - Pickler_dealloc(pickler); + Py_INCREF(self->stack); + return self->stack; + } - UNLESS(pickle_str = (*PycStringIO_cgetvalue)((PyObject *)file)) - { - Py_DECREF(file); - return NULL; - } + if (!strcmp(name, "UnpicklingError")) { + Py_INCREF(UnpicklingError); + return UnpicklingError; + } - Py_DECREF(file); + return Py_FindMethod(Unpickler_methods, (PyObject *)self, name); +} - return pickle_str; + +static int +Unpickler_setattr(Unpicklerobject *self, char *name, PyObject *value) { + if (!strcmp(name, "persistent_load")) { + Py_XDECREF(self->pers_func); + self->pers_func = value; + Py_INCREF(value); + return 0; + } + + PyErr_SetString(PyExc_AttributeError, name); + return -1; +} + + +static PyObject * +cpm_dump(PyObject *self, PyObject *args) { + PyObject *ob, *file, *res = NULL; + Picklerobject *pickler = 0; + int bin = 0; + + UNLESS(PyArg_ParseTuple(args, "OO|i", &ob, &file, &bin)) + goto finally; + + UNLESS(pickler = newPicklerobject(file, bin)) + goto finally; + + if (dump(pickler, ob) < 0) + goto finally; + + Py_INCREF(Py_None); + res = Py_None; + +finally: + Py_XDECREF(pickler); + + return res; +} + + +static PyObject * +cpm_dumps(PyObject *self, PyObject *args) { + PyObject *ob, *file = 0, *res = NULL; + Picklerobject *pickler = 0; + int bin = 0; + + UNLESS(PyArg_ParseTuple(args, "O|i", &ob, &bin)) + goto finally; + + UNLESS(file = PycStringIO->NewOutput(128)) + goto finally; + + UNLESS(pickler = newPicklerobject(file, bin)) + goto finally; + + if (dump(pickler, ob) < 0) + goto finally; + + res = PycStringIO->cgetvalue(file); + +finally: + Py_XDECREF(pickler); + Py_XDECREF(file); + + return res; } static PyObject * -cpm_load(ARG(PyObject *, self), ARG(PyObject *, args)) - ARGDECL(PyObject *, self) - ARGDECL(PyObject *, args) -{ - Unpicklerobject *unpickler; - PyObject *load_result; +cpm_load(PyObject *self, PyObject *args) { + Unpicklerobject *unpickler = 0; + PyObject *ob, *res = NULL; - UNLESS(PyArg_Parse(args, "O", &args)) - return NULL; + UNLESS(PyArg_ParseTuple(args, "O", &ob)) + goto finally; - UNLESS(unpickler = newUnpicklerobject(args)) - return NULL; + UNLESS(unpickler = newUnpicklerobject(ob)) + goto finally; - UNLESS(load_result = Unpickler_load(unpickler, NULL)) - { - Unpickler_dealloc(unpickler); - return NULL; - } + res = load(unpickler); - Py_DECREF(unpickler); +finally: + Py_XDECREF(unpickler); - return load_result; + return res; } static PyObject * -loads(ARG(PyObject *, self), ARG(PyObject *, args)) - ARGDECL(PyObject *, self) - ARGDECL(PyObject *, args) -{ - PyObject *file, *load_result; - Unpicklerobject *unpickler; +cpm_loads(PyObject *self, PyObject *args) { + PyObject *ob, *file = 0, *res = NULL; + Unpicklerobject *unpickler = 0; - UNLESS(PyArg_Parse(args, "O", &args)) - return NULL; + UNLESS(PyArg_ParseTuple(args, "O", &ob)) + goto finally; - UNLESS(file = (*PycStringIO_NewInput)(args)) - return NULL; + UNLESS(file = PycStringIO->NewInput(ob)) + goto finally; - UNLESS(unpickler = newUnpicklerobject(file)) - { - Py_DECREF(file); - return NULL; - } + UNLESS(unpickler = newUnpicklerobject(file)) + goto finally; - UNLESS(load_result = Unpickler_load(unpickler, NULL)) - { - Unpickler_dealloc(unpickler); - Py_DECREF(file); - return NULL; - } + res = load(unpickler); - Py_DECREF(file); - Unpickler_dealloc(unpickler); +finally: + Py_XDECREF(file); + Py_XDECREF(unpickler); - return load_result; + return res; } static char Unpicklertype__doc__[] = ""; -static PyTypeObject Unpicklertype = -{ - PyObject_HEAD_INIT(&PyType_Type) - 0, /*ob_size*/ - "Unpickler", /*tp_name*/ - sizeof(Unpicklerobject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)Unpickler_dealloc, /*tp_dealloc*/ - (printfunc)0, /*tp_print*/ - (getattrfunc)Unpickler_getattr, /*tp_getattr*/ - (setattrfunc)Unpickler_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*/ +static PyTypeObject Unpicklertype_value() { + PyTypeObject Unpicklertype = { + PyObject_HEAD_INIT(&PyType_Type) + 0, /*ob_size*/ + "Unpickler", /*tp_name*/ + sizeof(Unpicklerobject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor)Unpickler_dealloc, /*tp_dealloc*/ + (printfunc)0, /*tp_print*/ + (getattrfunc)Unpickler_getattr, /*tp_getattr*/ + (setattrfunc)Unpickler_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, - Unpicklertype__doc__ /* Documentation string */ -}; + /* Space for future expansion */ + 0L,0L,0L,0L, + Unpicklertype__doc__ /* Documentation string */ + }; + return Unpicklertype; +} - -static struct PyMethodDef cPickle_methods[] = -{ - {"dump", (PyCFunction)dump, 1, ""}, - {"dumps", (PyCFunction)dumps, 1, ""}, - {"load", (PyCFunction)cpm_load, 0, ""}, - {"loads", (PyCFunction)loads, 0, ""}, +static struct PyMethodDef cPickle_methods[] = { + {"dump", (PyCFunction)cpm_dump, 1, ""}, + {"dumps", (PyCFunction)cpm_dumps, 1, ""}, + {"load", (PyCFunction)cpm_load, 1, ""}, + {"loads", (PyCFunction)cpm_loads, 1, ""}, {"Pickler", (PyCFunction)get_Pickler, 1, ""}, - {"Unpickler", (PyCFunction)get_Unpickler, 0, ""}, + {"Unpickler", (PyCFunction)get_Unpickler, 1, ""}, { NULL, NULL } }; -static int -init_stuff() -{ - PyObject *builtins, *apply_func, *string; - - UNLESS(builtins = PyImport_ImportModule("__builtin__")) - return 1; - - UNLESS(apply_func = PyObject_GetAttrString(builtins, "apply")) - return 1; - - BuiltinFunctionType = apply_func->ob_type; - - Py_DECREF(apply_func); - - Py_DECREF(builtins); - - UNLESS(string = PyImport_ImportModule("string")) - return 1; - - UNLESS(atol_func = PyObject_GetAttrString(string, "atol")) - return 1; - - Py_DECREF(string); - - UNLESS(empty_list = PyList_New(0)) - return 1; - - UNLESS(empty_tuple = PyTuple_New(0)) - return 1; - - UNLESS(class_map = PyDict_New()) - return 1; - - UNLESS(PicklingError = PyString_FromString("cPickle.PicklingError")) - return 1; - - UNLESS(UnpicklingError = PyString_FromString("cPickle.UnpicklingError")) - return 1; - - PycString_IMPORT; - return 0; +#define CHECK_FOR_ERRORS(MESS) \ +if(PyErr_Occurred()) { \ + PyObject *__sys_exc_type, *__sys_exc_value, *__sys_exc_traceback; \ + PyErr_Fetch( &__sys_exc_type, &__sys_exc_value, &__sys_exc_traceback); \ + fprintf(stderr, # MESS ":\n\t"); \ + PyObject_Print(__sys_exc_type, stderr,0); \ + fprintf(stderr,", "); \ + PyObject_Print(__sys_exc_value, stderr,0); \ + fprintf(stderr,"\n"); \ + fflush(stderr); \ + Py_FatalError(# MESS); \ } -#define CHECK_FOR_ERRORS(MESS) \ -if(PyErr_Occurred()) { \ - PyObject *__sys_exc_type, *__sys_exc_value, *__sys_exc_traceback; \ - PyErr_Fetch( &__sys_exc_type, &__sys_exc_value, &__sys_exc_traceback); \ - fprintf(stderr, # MESS ":\n\t"); \ - PyObject_Print(__sys_exc_type, stderr,0); \ - fprintf(stderr,", "); \ - PyObject_Print(__sys_exc_value, stderr,0); \ - fprintf(stderr,"\n"); \ - fflush(stderr); \ - Py_FatalError(# MESS); \ +static int +init_stuff(PyObject *module, PyObject *module_dict) { + PyObject *string, *copy_reg; + +#define INIT_STR(S) UNLESS(S ## _str=PyString_FromString(#S)) return -1; + + INIT_STR(__class__); + INIT_STR(__getinitargs__); + INIT_STR(__dict__); + INIT_STR(__getstate__); + INIT_STR(__setstate__); + INIT_STR(__name__); + INIT_STR(__reduce__); + INIT_STR(write); + INIT_STR(__safe_for_unpickling__); + INIT_STR(append); + INIT_STR(read); + INIT_STR(readline); + + UNLESS(builtins = PyImport_ImportModule("__builtin__")) + return -1; + + UNLESS(copy_reg = PyImport_ImportModule("copy_reg")) + return -1; + + UNLESS(dispatch_table = PyObject_GetAttrString(copy_reg, + "dispatch_table")) + return -1; + + UNLESS(safe_constructors = PyObject_GetAttrString(copy_reg, + "safe_constructors")) + return -1; + + Py_DECREF(copy_reg); + + UNLESS(string = PyImport_ImportModule("string")) + return -1; + + UNLESS(atol_func = PyObject_GetAttrString(string, "atol")) + return -1; + + Py_DECREF(string); + + UNLESS(empty_tuple = PyTuple_New(0)) + return -1; + + UNLESS(class_map = PyDict_New()) + return -1; + + UNLESS(PicklingError = PyString_FromString("cPickle.PicklingError")) + return -1; + + if (PyDict_SetItemString(module_dict, "PicklingError", + PicklingError) < 0) + return -1; + + UNLESS(UnpicklingError = PyString_FromString("cPickle.UnpicklingError")) + return -1; + + if (PyDict_SetItemString(module_dict, "UnpicklingError", + UnpicklingError) < 0) + return -1; + + PycString_IMPORT; + + return 0; } /* Initialization function for the module (*must* be called initcPickle) */ void -initcPickle() -{ - PyObject *m, *d; +initcPickle() { + PyObject *m, *d; + char *rev="$Revision$"; + PyObject *format_version; + PyObject *compatible_formats; - /* Create the module and add the functions */ - m = Py_InitModule4("cPickle", cPickle_methods, - cPickle_module_documentation, - (PyObject*)NULL,PYTHON_API_VERSION); - /* Add some symbolic constants to the module */ - d = PyModule_GetDict(m); - ErrorObject = PyString_FromString("cPickle.error"); - PyDict_SetItemString(d, "error", ErrorObject); + /* Create the module and add the functions */ + m = Py_InitModule4("cPickle", cPickle_methods, + cPickle_module_documentation, + (PyObject*)NULL,PYTHON_API_VERSION); - /* XXXX Add constants here */ + Picklertype=Picklertype_value(); + Unpicklertype=Unpicklertype_value(); - if (init_stuff()) - Py_FatalError("can't initialize module cPickle"); + /* Add some symbolic constants to the module */ + d = PyModule_GetDict(m); + PyDict_SetItemString(d,"__version__", + PyString_FromStringAndSize(rev+11,strlen(rev+11)-2)); - CHECK_FOR_ERRORS("can't initialize module cPickle"); +#ifdef FORMAT_1_3 + format_version = PyString_FromString("1.3"); + compatible_formats = Py_BuildValue("[sss]", "1.0", "1.1", "1.2"); +#else + format_version = PyString_FromString("1.2"); + compatible_formats = Py_BuildValue("[ss]", "1.0", "1.1"); +#endif - PyDict_SetItemString(d, "PicklingError", PicklingError); - CHECK_FOR_ERRORS("can't initialize module cPickle: error creating PicklingError"); + PyDict_SetItemString(d, "format_version", format_version); + PyDict_SetItemString(d, "compatible_formats", compatible_formats); - PyDict_SetItemString(d, "UnpicklingError", UnpicklingError); - CHECK_FOR_ERRORS("can't initialize module cPickle: error creating UnpicklingError"); + init_stuff(m, d); + CHECK_FOR_ERRORS("can't initialize module cPickle"); } + +/**************************************************************************** + $Log$ + Revision 2.3 1997/04/09 17:36:32 guido + Jim Fulton's version 2.2. + + Revision 1.36 1997/03/11 22:05:02 chris + write POP rather than POPMARK in non-binary mode + use put2() in save_reduce() and save_inst() only if state is not a dictionary + removed put2() from save_tuple() + + Revision 1.35 1997/03/11 20:03:30 jim + Added log comment at bottom. + + + + ****************************************************************************/