cpickle.c

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

C
2,601
字号
}


static int
dump(Picklerobject *self, PyObject *args) {
    static char stop = STOP;

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

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

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

    return 0;
}

static PyObject *
Pickle_clear_memo(Picklerobject *self, PyObject *args) {
    if (!PyArg_ParseTuple(args,":clear_memo")) 
	return NULL;
    if (self->memo) 
	PyDict_Clear(self->memo);
    Py_INCREF(Py_None);
    return Py_None;
}

static PyObject *
Pickle_getvalue(Picklerobject *self, PyObject *args) {
  int l, i, rsize, ssize, clear=1, lm;
  long ik;
  PyObject *k, *r;
  char *s, *p, *have_get;
  Pdata *data;

  /* Can be called by Python code or C code */
  if (args && !PyArg_ParseTuple(args, "|i:getvalue", &clear)) 
      return NULL;

  /* Check to make sure we are based on a list */
  if (! Pdata_Check(self->file)) {
      PyErr_SetString(PicklingError,
                      "Attempt to getvalue() a non-list-based pickler");
      return NULL;
  }

  /* flush write buffer */
  if (write_other(self, NULL, 0) < 0) return NULL;

  data=(Pdata*)self->file;
  l=data->length;

  /* set up an array to hold get/put status */
  if ((lm=PyDict_Size(self->memo)) < 0) return NULL;
  lm++;
  if (! (have_get=malloc((lm)*sizeof(char)))) return PyErr_NoMemory();
  memset(have_get,0,lm);

  /* Scan for gets. */
  for (rsize=0, i=l; --i >= 0; ) {
      k=data->data[i];

      if (PyString_Check(k)) {
        rsize += PyString_GET_SIZE(k);
      }

      else if (PyInt_Check(k)) { /* put */
        ik=PyInt_AS_LONG((PyIntObject*)k);
        if (ik >= lm || ik==0) {
          PyErr_SetString(PicklingError,
                          "Invalid get data");
          return NULL;
        }
        if (have_get[ik]) { /* with matching get */
          if (ik < 256) rsize += 2;
          else rsize+=5;
        }
      }

      else if (! (PyTuple_Check(k) &&
                  PyTuple_GET_SIZE(k) == 2 &&
                  PyInt_Check((k=PyTuple_GET_ITEM(k,0))))
               ) {
        PyErr_SetString(PicklingError,
                        "Unexpected data in internal list");
        return NULL;
      }

      else { /* put */
        ik=PyInt_AS_LONG((PyIntObject*)k);
        if (ik >= lm || ik==0) {
          PyErr_SetString(PicklingError,
                          "Invalid get data");
          return NULL;
        }
        have_get[ik]=1;
        if (ik < 256) rsize += 2;
        else rsize+=5;
      }

    }

  /* Now generate the result */
  UNLESS (r=PyString_FromStringAndSize(NULL,rsize)) goto err;
  s=PyString_AS_STRING((PyStringObject*)r);

  for (i=0; i<l; i++) {
      k=data->data[i];

      if (PyString_Check(k)) {
        ssize=PyString_GET_SIZE(k);
        if (ssize) {
            p=PyString_AS_STRING((PyStringObject*)k);
            while (--ssize >= 0) *s++=*p++;
          }
      }

      else if (PyTuple_Check(k)) { /* get */
        ik=PyInt_AS_LONG((PyIntObject*)PyTuple_GET_ITEM(k,0));
        if (ik < 256) {
          *s++ = BINGET;
          *s++ = (int)(ik & 0xff);
        }
        else {
          *s++ = LONG_BINGET;
          *s++ = (int)(ik & 0xff);
          *s++ = (int)((ik >> 8)  & 0xff);
          *s++ = (int)((ik >> 16) & 0xff);
          *s++ = (int)((ik >> 24) & 0xff);
        }
      }

      else { /* put */
        ik=PyInt_AS_LONG((PyIntObject*)k);

        if (have_get[ik]) { /* with matching get */
          if (ik < 256) {
            *s++ = BINPUT;
            *s++ = (int)(ik & 0xff);
          }
          else {
            *s++ = LONG_BINPUT;
            *s++ = (int)(ik & 0xff);
            *s++ = (int)((ik >> 8)  & 0xff);
            *s++ = (int)((ik >> 16) & 0xff);
            *s++ = (int)((ik >> 24) & 0xff);
          }
        }
      }

    }

  if (clear) {
    PyDict_Clear(self->memo);
    Pdata_clear(data,0);
  }

  free(have_get);
  return r;
err:
  free(have_get);
  return NULL;
}

static PyObject *
Pickler_dump(Picklerobject *self, PyObject *args) {
    PyObject *ob;
    int get=0;

    UNLESS (PyArg_ParseTuple(args, "O|i:dump", &ob, &get))
        return NULL;

    if (dump(self, ob) < 0)
        return NULL;

    if (get) return Pickle_getvalue(self, NULL);

    /* XXX Why does dump() return self? */
    Py_INCREF(self);
    return (PyObject*)self;
}


static struct PyMethodDef Pickler_methods[] = {
  {"dump",          (PyCFunction)Pickler_dump,  1,
   "dump(object) --"
   "Write an object in pickle format to the object's pickle stream\n"
  },
  {"clear_memo",  (PyCFunction)Pickle_clear_memo,  1,
   "clear_memo() -- Clear the picklers memo"},
  {"getvalue",  (PyCFunction)Pickle_getvalue,  1,
   "getvalue() -- Finish picking a list-based pickle"},
  {NULL,                NULL}           /* sentinel */
};


static Picklerobject *
newPicklerobject(PyObject *file, int bin) {
    Picklerobject *self;

    UNLESS (self = PyObject_New(Picklerobject, &Picklertype))
        return NULL;

    self->fp = NULL;
    self->write = NULL;
    self->memo = NULL;
    self->arg = NULL;
    self->pers_func = NULL;
    self->inst_pers_func = NULL;
    self->write_buf = NULL;
    self->bin = bin;
    self->fast = 0;
    self->nesting = 0;
    self->fast_container = 0;
    self->fast_memo = NULL;
    self->buf_size = 0;
    self->dispatch_table = NULL;

    if (file)
      Py_INCREF(file);
    else
      file=Pdata_New();

    UNLESS (self->file = file)
      goto err;

    UNLESS (self->memo = PyDict_New())
       goto err;

    if (PyFile_Check(file)) {
        self->fp = PyFile_AsFile(file);
	if (self->fp == NULL) {
	    PyErr_SetString(PyExc_ValueError, "I/O operation on closed file");
	    goto err;
	}
        self->write_func = write_file;
    }
    else if (PycStringIO_OutputCheck(file)) {
        self->write_func = write_cStringIO;
    }
    else if (file == Py_None) {
        self->write_func = write_none;
    }
    else {
        self->write_func = write_other;

        if (! Pdata_Check(file)) {
          UNLESS (self->write = PyObject_GetAttr(file, write_str)) {
            PyErr_Clear();
            PyErr_SetString(PyExc_TypeError, "argument must have 'write' "
                            "attribute");
            goto err;
          }
        }

        UNLESS (self->write_buf =
            (char *)malloc(WRITE_BUF_SIZE * sizeof(char))) {
            PyErr_NoMemory();
            goto err;
        }
    }

    if (PyEval_GetRestricted()) {
        /* Restricted execution, get private tables */
        PyObject *m;

        UNLESS (m=PyImport_Import(copy_reg_str)) goto err;
        self->dispatch_table=PyObject_GetAttr(m, dispatch_table_str);
        Py_DECREF(m);
        UNLESS (self->dispatch_table) goto err;
    }
    else {
        self->dispatch_table=dispatch_table;
        Py_INCREF(dispatch_table);
    }

    return self;

err:
    Py_DECREF((PyObject *)self);
    return NULL;
}


static PyObject *
get_Pickler(PyObject *self, PyObject *args) {
    PyObject *file = NULL;
    int bin = 1;

    if (!PyArg_ParseTuple(args, "|i:Pickler", &bin)) {
        PyErr_Clear();
        bin = 0;
        if (!PyArg_ParseTuple(args, "O|i:Pickler", &file, &bin))
	    return NULL;
    }
    return (PyObject *)newPicklerobject(file, bin);
}


static void
Pickler_dealloc(Picklerobject *self) {
    Py_XDECREF(self->write);
    Py_XDECREF(self->memo);
    Py_XDECREF(self->fast_memo);
    Py_XDECREF(self->arg);
    Py_XDECREF(self->file);
    Py_XDECREF(self->pers_func);
    Py_XDECREF(self->inst_pers_func);
    Py_XDECREF(self->dispatch_table);

    if (self->write_buf) {
        free(self->write_buf);
    }

    PyObject_Del(self);
}

static PyObject *
Pickler_get_pers_func(Picklerobject *p)
{
    if (p->pers_func == NULL)
	PyErr_SetString(PyExc_AttributeError, "persistent_id");
    else
	Py_INCREF(p->pers_func);
    return p->pers_func;
}

static int
Pickler_set_pers_func(Picklerobject *p, PyObject *v)
{
    if (v == NULL) {
        PyErr_SetString(PyExc_TypeError,
			"attribute deletion is not supported");
        return -1;
    }
    Py_XDECREF(p->pers_func);
    Py_INCREF(v);
    p->pers_func = v;
    return 0;
}

static int
Pickler_set_inst_pers_func(Picklerobject *p, PyObject *v)
{
    if (v == NULL) {
        PyErr_SetString(PyExc_TypeError,
			"attribute deletion is not supported");
        return -1;
    }
    Py_XDECREF(p->inst_pers_func);
    Py_INCREF(v);
    p->inst_pers_func = v;
    return 0;
}

static PyObject *
Pickler_get_memo(Picklerobject *p)
{
    if (p->memo == NULL)
	PyErr_SetString(PyExc_AttributeError, "memo");
    else
	Py_INCREF(p->memo);
    return p->memo;
}

static int
Pickler_set_memo(Picklerobject *p, PyObject *v)
{
    if (v == NULL) {
        PyErr_SetString(PyExc_TypeError,
			"attribute deletion is not supported");
        return -1;
    }
    if (!PyDict_Check(v)) {
	PyErr_SetString(PyExc_TypeError, "memo must be a dictionary");
	return -1;
    }
    Py_XDECREF(p->memo);
    Py_INCREF(v);
    p->memo = v;
    return 0;
}

static PyObject *
Pickler_get_error(Picklerobject *p)
{
    /* why is this an attribute on the Pickler? */
    Py_INCREF(PicklingError);
    return PicklingError;
}

static PyMemberDef Pickler_members[] = {
    {"binary", T_INT, offsetof(Picklerobject, bin)},
    {"fast", T_INT, offsetof(Picklerobject, fast)},
    {NULL}
};

static PyGetSetDef Pickler_getsets[] = {
    {"persistent_id", (getter)Pickler_get_pers_func, 
                     (setter)Pickler_set_pers_func},
    {"inst_persistent_id", NULL, (setter)Pickler_set_inst_pers_func},
    {"memo", (getter)Pickler_get_memo, (setter)Pickler_set_memo},
    {"PicklingError", (getter)Pickler_get_error, NULL},
    {NULL}
};

static char Picklertype__doc__[] =
"Objects that know how to pickle objects\n";

static PyTypeObject Picklertype = {
    PyObject_HEAD_INIT(NULL)
    0,                            /*ob_size*/
    "cPickle.Pickler",            /*tp_name*/
    sizeof(Picklerobject),              /*tp_basicsize*/
    0,
    (destructor)Pickler_dealloc,	/* tp_dealloc */
    0,					/* tp_print */
    0,			 		/* tp_getattr */
    0,			 		/* tp_setattr */
    0,					/* tp_compare */
    0,		 			/* tp_repr */
    0,					/* tp_as_number */
    0,					/* tp_as_sequence */
    0,					/* tp_as_mapping */
    0,					/* tp_hash */
    0,					/* tp_call */
    0,					/* tp_str */
    0,	/* set below */			/* tp_getattro */
    0,	/* set below */			/* tp_setattro */
    0,					/* tp_as_buffer */
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
    Picklertype__doc__,			/* tp_doc */
    0,					/* tp_traverse */
    0,					/* tp_clear */
    0,					/* tp_richcompare */
    0,					/* tp_weaklistoffset */
    0,					/* tp_iter */
    0,					/* tp_iternext */
    Pickler_methods,			/* tp_methods */
    Pickler_members,			/* tp_members */
    Pickler_getsets,			/* tp_getset */
};

static PyObject *
find_class(PyObject *py_module_name, PyObject *py_global_name, PyObject *fc) {
    PyObject *global = 0, *module;

    if (fc) {
      if (fc==Py_None) {
	PyErr_SetString(UnpicklingError,
			"Global and instance pickles are not supported.");
	return NULL;
      }
      return PyObject_CallFunction(fc, "OO", py_module_name, py_global_name);
    }

    module = PySys_GetObject("modules");
    if (module == NULL)
      return NULL;

    module = PyDict_GetItem(module, py_module_name);
    if (module == NULL) {
      module = PyImport_Import(py_module_name);
      if (!module)
          return NULL;
      global = PyObject_GetAttr(module, py_global_name);
      Py_DECREF(module);
    }
    else
      global = PyObject_GetAttr(module, py_global_name);
    return global;
}

static int
marker(Unpicklerobject *self) {
    if (self->num_marks < 1) {
        PyErr_SetString(UnpicklingError, "could not find MARK");
        return -1;
    }

    return self->marks[--self->num_marks];
}


static int
load_none(Unpicklerobject *self) {
    PDATA_APPEND(self->stack, Py_None, -1);
    return 0;
}

static int
bad_readline(void) {
    PyErr_SetString(UnpicklingError, "pickle data was truncated");
    return -1;
}

static int
load_int(Unpicklerobject *self) {
    PyObject *py_int = 0;
    char *endptr, *s;
    int len, res = -1;
    long l;

    if ((len = (*self->readline_func)(self, &s)) < 0) return -1;
    if (len < 2) return bad_readline();
    UNLESS (s=pystrndup(s,len)) return -1;

    errno = 0;
    l = strtol(s, &endptr, 0);

    if (errno || (*endptr != '\n') || (endptr[1] != '\0')) {
        /* Hm, maybe we've got something long.  Let's try reading
           it as a Python long object. */
        errno = 0;
        py_int = PyLong_FromString(s, NULL, 0);

⌨️ 快捷键说明

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