[Python-checkins] python/dist/src/Modules cPickle.c,2.121,2.122

tim_one@users.sourceforge.net tim_one@users.sourceforge.net
Mon, 03 Feb 2003 21:06:20 -0800


Update of /cvsroot/python/python/dist/src/Modules
In directory sc8-pr-cvs1:/tmp/cvs-serv29814/Modules

Modified Files:
	cPickle.c 
Log Message:
cPickle can load pickles using proto 2 EXT[124] now, but can't yet
generate these opcodes.


Index: cPickle.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/cPickle.c,v
retrieving revision 2.121
retrieving revision 2.122
diff -C2 -d -r2.121 -r2.122
*** cPickle.c	4 Feb 2003 01:54:49 -0000	2.121
--- cPickle.c	4 Feb 2003 05:06:17 -0000	2.122
***************
*** 3734,3737 ****
--- 3734,3805 ----
  }
  
+ /* Push an object from the extension registry (EXT[124]).  nbytes is
+  * the number of bytes following the opcode, holding the index (code) value.
+  */
+ static int
+ load_extension(Unpicklerobject *self, int nbytes)
+ {
+ 	char *codebytes;	/* the nbytes bytes after the opcode */
+ 	long code;		/* calc_binint returns long */
+ 	PyObject *py_code;	/* code as a Python int */
+ 	PyObject *obj;		/* the object to push */
+ 	PyObject *pair;		/* (module_name, class_name) */
+ 	PyObject *module_name, *class_name;
+ 
+ 	assert(nbytes == 1 || nbytes == 2 || nbytes == 4);
+ 	if (self->read_func(self, &codebytes, nbytes) < 0) return -1;
+ 	code = calc_binint(codebytes,  nbytes);
+ 	if (code <= 0) {		/* note that 0 is forbidden */
+ 		/* Corrupt or hostile pickle. */
+ 		PyErr_SetString(UnpicklingError, "EXT specifies code <= 0");
+ 		return -1;
+ 	}
+ 
+ 	/* Look for the code in the cache. */
+ 	py_code = PyInt_FromLong(code);
+ 	if (py_code == NULL) return -1;
+ 	obj = PyDict_GetItem(extension_cache, py_code);
+ 	if (obj != NULL) {
+ 		/* Bingo. */
+ 		Py_DECREF(py_code);
+ 		PDATA_APPEND(self->stack, obj, -1);
+ 		return 0;
+ 	}
+ 
+ 	/* Look up the (module_name, class_name) pair. */
+ 	pair = PyDict_GetItem(inverted_registry, py_code);
+ 	if (pair == NULL) {
+ 		Py_DECREF(py_code);
+ 		PyErr_Format(PyExc_ValueError, "unregistered extension "
+ 			     "code %ld", code);
+ 		return -1;
+ 	}
+ 	/* Since the extension registry is manipulable via Python code,
+ 	 * confirm that obj is really a 2-tuple of strings.
+ 	 */
+ 	if (!PyTuple_Check(pair) || PyTuple_Size(pair) != 2 ||
+ 	    !PyString_Check(module_name = PyTuple_GET_ITEM(pair, 0)) ||
+ 	    !PyString_Check(class_name = PyTuple_GET_ITEM(pair, 1))) {
+ 		Py_DECREF(py_code);
+ 		PyErr_Format(PyExc_ValueError, "_inverted_registry[%ld] "
+ 			     "isn't a 2-tuple of strings", code);
+ 		return -1;
+ 	}
+ 	/* Load the object. */
+ 	obj = find_class(module_name, class_name, self->find_class);
+ 	if (obj == NULL) {
+ 		Py_DECREF(py_code);
+ 		return -1;
+ 	}
+ 	/* Cache code -> obj. */
+ 	code = PyDict_SetItem(extension_cache, py_code, obj);
+ 	Py_DECREF(py_code);
+ 	if (code < 0) {
+ 		Py_DECREF(obj);
+ 		return -1;
+ 	}
+ 	PDATA_PUSH(self->stack, obj, -1);
+ 	return 0;
+ }
  
  static int
***************
*** 4215,4218 ****
--- 4283,4300 ----
  			continue;
  
+ 		case EXT1:
+ 			if (load_extension(self, 1) < 0)
+ 				break;
+ 			continue;
+ 
+ 		case EXT2:
+ 			if (load_extension(self, 2) < 0)
+ 				break;
+ 			continue;
+ 
+ 		case EXT4:
+ 			if (load_extension(self, 4) < 0)
+ 				break;
+ 			continue;
  		case MARK:
  			if (load_mark(self) < 0)
***************
*** 4371,4374 ****
--- 4453,4467 ----
  }
  
+ static int
+ noload_extension(Unpicklerobject *self, int nbytes)
+ {
+ 	char *codebytes;
+ 
+ 	assert(nbytes == 1 || nbytes == 2 || nbytes == 4);
+ 	if (self->read_func(self, &codebytes, nbytes) < 0) return -1;
+ 	PDATA_APPEND(self->stack, Py_None, -1);
+ 	return 0;
+ }
+ 
  
  static PyObject *
***************
*** 4555,4558 ****
--- 4648,4666 ----
  		case GET:
  			if (load_get(self) < 0)
+ 				break;
+ 			continue;
+ 
+ 		case EXT1:
+ 			if (noload_extension(self, 1) < 0)
+ 				break;
+ 			continue;
+ 
+ 		case EXT2:
+ 			if (noload_extension(self, 2) < 0)
+ 				break;
+ 			continue;
+ 
+ 		case EXT4:
+ 			if (noload_extension(self, 4) < 0)
  				break;
  			continue;