📄 cpickle.c
字号:
/*
* cPickle.c,v 1.71 1999/07/11 13:30:34 jim Exp
*
* Copyright (c) 1996-1998, Digital Creations, Fredericksburg, VA, USA.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* o Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the disclaimer that follows.
*
* o Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions, and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* o Neither the name of Digital Creations nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
* IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
* CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
#
# If you have questions regarding this software, contact:
#
# Digital Creations, L.C.
# 910 Princess Ann Street
# Fredericksburge, Virginia 22401
#
# info@digicool.com
#
# (540) 371-6909
*/
static char cPickle_module_documentation[] =
"C implementation and optimization of the Python pickle module\n"
"\n"
"cPickle.c,v 1.71 1999/07/11 13:30:34 jim Exp\n"
;
#include "Python.h"
#include "cStringIO.h"
#include "structmember.h"
#ifndef Py_eval_input
#include <graminit.h>
#define Py_eval_input eval_input
#endif /* Py_eval_input */
#include <errno.h>
#define UNLESS(E) if (!(E))
#define DEL_LIST_SLICE(list, from, to) (PyList_SetSlice(list, from, to, NULL))
#define WRITE_BUF_SIZE 256
/* --------------------------------------------------------------------------
NOTES on format codes.
XXX much more is needed here
Integer types
BININT1 8-bit unsigned integer; followed by 1 byte.
BININT2 16-bit unsigned integer; followed by 2 bytes, little-endian.
BININT 32-bit signed integer; followed by 4 bytes, little-endian.
INT Integer; natural decimal string conversion, then newline.
CAUTION: INT-reading code can't assume that what follows
fits in a Python int, because the size of Python ints varies
across platforms.
LONG Long (unbounded) integer; repr(i), then newline.
-------------------------------------------------------------------------- */
#define MARK '('
#define STOP '.'
#define POP '0'
#define POP_MARK '1'
#define DUP '2'
#define FLOAT 'F'
#define BINFLOAT 'G'
#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 UNICODE 'V'
#define BINUNICODE 'X'
#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'
static char MARKv = MARK;
static PyObject *PickleError;
static PyObject *PicklingError;
static PyObject *UnpickleableError;
static PyObject *UnpicklingError;
static PyObject *BadPickleGet;
static PyObject *dispatch_table;
static PyObject *safe_constructors;
static PyObject *empty_tuple;
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, *__main___str, *__basicnew___str,
*copy_reg_str, *dispatch_table_str, *safe_constructors_str;
/*************************************************************************
Internal Data type for pickle data. */
typedef struct {
PyObject_HEAD
int length, size;
PyObject **data;
} Pdata;
static void
Pdata_dealloc(Pdata *self) {
int i;
PyObject **p;
for (i=self->length, p=self->data; --i >= 0; p++) Py_DECREF(*p);
if (self->data) free(self->data);
PyObject_Del(self);
}
static PyTypeObject PdataType = {
PyObject_HEAD_INIT(NULL) 0, "cPickle.Pdata", sizeof(Pdata), 0,
(destructor)Pdata_dealloc,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0L,0L,0L,0L, ""
};
#define Pdata_Check(O) ((O)->ob_type == &PdataType)
static PyObject *
Pdata_New(void) {
Pdata *self;
UNLESS (self = PyObject_New(Pdata, &PdataType)) return NULL;
self->size=8;
self->length=0;
self->data=malloc(self->size * sizeof(PyObject*));
if (self->data) return (PyObject*)self;
Py_DECREF(self);
return PyErr_NoMemory();
}
static int
stackUnderflow(void) {
PyErr_SetString(UnpicklingError, "unpickling stack underflow");
return -1;
}
static int
Pdata_clear(Pdata *self, int clearto) {
int i;
PyObject **p;
if (clearto < 0) return stackUnderflow();
if (clearto >= self->length) return 0;
for (i=self->length, p=self->data+clearto; --i >= clearto; p++)
Py_DECREF(*p);
self->length=clearto;
return 0;
}
static int
Pdata_grow(Pdata *self) {
if (! self->size) {
PyErr_NoMemory();
return -1;
}
self->size *= 2;
self->data = realloc(self->data, self->size*sizeof(PyObject*));
if (! self->data) {
self->size = 0;
PyErr_NoMemory();
return -1;
}
return 0;
}
#define PDATA_POP(D,V) { \
if ((D)->length) V=D->data[--((D)->length)]; \
else { \
PyErr_SetString(UnpicklingError, "bad pickle data"); \
V=NULL; \
} \
}
static PyObject *
Pdata_popTuple(Pdata *self, int start) {
PyObject *r;
int i, j, l;
l=self->length-start;
UNLESS (r=PyTuple_New(l)) return NULL;
for (i=start, j=0 ; j < l; i++, j++)
PyTuple_SET_ITEM(r, j, self->data[i]);
self->length=start;
return r;
}
static PyObject *
Pdata_popList(Pdata *self, int start) {
PyObject *r;
int i, j, l;
l=self->length-start;
UNLESS (r=PyList_New(l)) return NULL;
for (i=start, j=0 ; j < l; i++, j++)
PyList_SET_ITEM(r, j, self->data[i]);
self->length=start;
return r;
}
#define PDATA_APPEND_(D,O,ER) { \
if (Pdata_Append(((Pdata*)(D)), O) < 0) return ER; \
}
#define PDATA_APPEND(D,O,ER) { \
if (((Pdata*)(D))->length == ((Pdata*)(D))->size && \
Pdata_grow((Pdata*)(D)) < 0) \
return ER; \
Py_INCREF(O); \
((Pdata*)(D))->data[((Pdata*)(D))->length++]=O; \
}
#define PDATA_PUSH(D,O,ER) { \
if (((Pdata*)(D))->length == ((Pdata*)(D))->size && \
Pdata_grow((Pdata*)(D)) < 0) { \
Py_DECREF(O); \
return ER; \
} \
((Pdata*)(D))->data[((Pdata*)(D))->length++]=O; \
}
/*************************************************************************/
#define ARG_TUP(self, o) { \
if (self->arg || (self->arg=PyTuple_New(1))) { \
Py_XDECREF(PyTuple_GET_ITEM(self->arg,0)); \
PyTuple_SET_ITEM(self->arg,0,o); \
} \
else { \
Py_DECREF(o); \
} \
}
#define FREE_ARG_TUP(self) { \
if (self->arg->ob_refcnt > 1) { \
Py_DECREF(self->arg); \
self->arg=NULL; \
} \
}
typedef struct Picklerobject {
PyObject_HEAD
FILE *fp;
PyObject *write;
PyObject *file;
PyObject *memo;
PyObject *arg;
PyObject *pers_func;
PyObject *inst_pers_func;
int bin;
int fast; /* Fast mode doesn't save in memo, don't use if circ ref */
int nesting;
int (*write_func)(struct Picklerobject *, char *, int);
char *write_buf;
int buf_size;
PyObject *dispatch_table;
int fast_container; /* count nested container dumps */
PyObject *fast_memo;
} Picklerobject;
#ifndef PY_CPICKLE_FAST_LIMIT
#define PY_CPICKLE_FAST_LIMIT 50
#endif
staticforward PyTypeObject Picklertype;
typedef struct Unpicklerobject {
PyObject_HEAD
FILE *fp;
PyObject *file;
PyObject *readline;
PyObject *read;
PyObject *memo;
PyObject *arg;
Pdata *stack;
PyObject *mark;
PyObject *pers_func;
PyObject *last_string;
int *marks;
int num_marks;
int marks_size;
int (*read_func)(struct Unpicklerobject *, char **, int);
int (*readline_func)(struct Unpicklerobject *, char **);
int buf_size;
char *buf;
PyObject *safe_constructors;
PyObject *find_class;
} Unpicklerobject;
staticforward PyTypeObject Unpicklertype;
/* Forward decls that need the above structs */
static int save(Picklerobject *, PyObject *, int);
static int put2(Picklerobject *, PyObject *);
int
cPickle_PyMapping_HasKey(PyObject *o, PyObject *key) {
PyObject *v;
if ((v = PyObject_GetItem(o,key))) {
Py_DECREF(v);
return 1;
}
PyErr_Clear();
return 0;
}
static
PyObject *
cPickle_ErrFormat(PyObject *ErrType, char *stringformat, char *format, ...)
{
va_list va;
PyObject *args=0, *retval=0;
va_start(va, format);
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) {
if (args) {
PyObject *v;
v=PyString_Format(retval, args);
Py_DECREF(retval);
Py_DECREF(args);
if (! v) return NULL;
retval=v;
}
}
else
if (args) retval=args;
else {
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) {
size_t nbyteswritten;
if (s == NULL) {
return 0;
}
Py_BEGIN_ALLOW_THREADS
nbyteswritten = fwrite(s, sizeof(char), n, self->fp);
Py_END_ALLOW_THREADS
if (nbyteswritten != (size_t)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_none(Picklerobject *self, char *s, int n) {
if (s == NULL) return 0;
return n;
}
static int
write_other(Picklerobject *self, char *s, int n) {
PyObject *py_str = 0, *junk = 0;
if (s == NULL) {
UNLESS (self->buf_size) return 0;
UNLESS (py_str =
PyString_FromStringAndSize(self->write_buf, self->buf_size))
return -1;
}
else {
if (self->buf_size && (n + self->buf_size) > WRITE_BUF_SIZE) {
if (write_other(self, NULL, 0) < 0)
return -1;
}
if (n > WRITE_BUF_SIZE) {
UNLESS (py_str =
PyString_FromStringAndSize(s, n))
return -1;
}
else {
memcpy(self->write_buf + self->buf_size, s, n);
self->buf_size += n;
return n;
}
}
if (self->write) {
/* object with write method */
ARG_TUP(self, py_str);
if (self->arg) {
junk = PyObject_Call(self->write, self->arg, NULL);
FREE_ARG_TUP(self);
}
if (junk) Py_DECREF(junk);
else return -1;
}
else
PDATA_PUSH(self->file, py_str, -1);
self->buf_size = 0;
return n;
}
static int
read_file(Unpicklerobject *self, char **s, int n) {
size_t nbytesread;
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;
}
Py_BEGIN_ALLOW_THREADS
nbytesread = fread(self->buf, sizeof(char), n, self->fp);
Py_END_ALLOW_THREADS
if (nbytesread != (size_t)n) {
if (feof(self->fp)) {
PyErr_SetNone(PyExc_EOFError);
return -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -