[Python-checkins] r51506 - in python/branches/int_unification: Lib/pickle.py Modules/cPickle.c

martin.v.loewis python-checkins at python.org
Wed Aug 23 17:00:21 CEST 2006


Author: martin.v.loewis
Date: Wed Aug 23 17:00:19 2006
New Revision: 51506

Modified:
   python/branches/int_unification/Lib/pickle.py
   python/branches/int_unification/Modules/cPickle.c
Log:
Adjust pickle implementation to int/long unification.
Use INT codes for small integers on binary protocols,
and LONG codes otherwise.


Modified: python/branches/int_unification/Lib/pickle.py
==============================================================================
--- python/branches/int_unification/Lib/pickle.py	(original)
+++ python/branches/int_unification/Lib/pickle.py	Wed Aug 23 17:00:19 2006
@@ -456,9 +456,29 @@
                 return
         # Text pickle, or int too big to fit in signed 4-byte format.
         self.write(INT + repr(obj) + '\n')
-    dispatch[IntType] = save_int
+    # XXX save_int is merged into save_long
+    # dispatch[IntType] = save_int
 
     def save_long(self, obj, pack=struct.pack):
+        if self.bin:
+            # If the int is small enough to fit in a signed 4-byte 2's-comp
+            # format, we can store it more efficiently than the general
+            # case.
+            # First one- and two-byte unsigned ints:
+            if obj >= 0:
+                if obj <= 0xff:
+                    self.write(BININT1 + chr(obj))
+                    return
+                if obj <= 0xffff:
+                    self.write("%c%c%c" % (BININT2, obj&0xff, obj>>8))
+                    return
+            # Next check for 4-byte signed ints:
+            high_bits = obj >> 31  # note that Python shift sign-extends
+            if high_bits == 0 or high_bits == -1:
+                # All high bits are copies of bit 2**31, so the value
+                # fits in a 4-byte signed int.
+                self.write(BININT + pack("<i", obj))
+                return
         if self.proto >= 2:
             bytes = encode_long(obj)
             n = len(bytes)

Modified: python/branches/int_unification/Modules/cPickle.c
==============================================================================
--- python/branches/int_unification/Modules/cPickle.c	(original)
+++ python/branches/int_unification/Modules/cPickle.c	Wed Aug 23 17:00:19 2006
@@ -711,7 +711,9 @@
 		PyErr_SetString(PicklingError, "no int where int expected in memo");
 		return -1;
 	}
-	c_value = PyInt_AS_LONG((PyIntObject*)value);
+	c_value = PyInt_AsLong(value);
+	if (c_value == -1 && PyErr_Occurred())
+		return -1;
 
 	if (!self->bin) {
 		s[0] = GET;
@@ -958,7 +960,7 @@
 {
 	static const char *buf[2] = {FALSE, TRUE};
 	static char len[2] = {sizeof(FALSE)-1, sizeof(TRUE)-1};
-	long l = PyInt_AS_LONG((PyIntObject *)args);
+	long l = args == Py_True;
 
 	if (self->proto >= 2) {
 		char opcode = l ? NEWTRUE : NEWFALSE;
@@ -971,10 +973,9 @@
 }
 
 static int
-save_int(Picklerobject *self, PyObject *args)
+save_int(Picklerobject *self, long l)
 {
 	char c_str[32];
-	long l = PyInt_AS_LONG((PyIntObject *)args);
 	int len = 0;
 
 	if (!self->bin
@@ -1027,9 +1028,16 @@
 	int size;
 	int res = -1;
 	PyObject *repr = NULL;
-
+	int val = PyInt_AsLong(args);
 	static char l = LONG;
 
+	if (val == -1 && PyErr_Occurred()) {
+		/* out of range for int pickling */
+		PyErr_Clear();
+	}
+	else
+		return save_int(self, val);
+
 	if (self->proto >= 2) {
 		/* Linear-time pickling. */
 		size_t nbits;
@@ -2179,13 +2187,6 @@
 			goto finally;
 		}
 		break;
-        case 'i':
-		if (type == &PyInt_Type) {
-			res = save_int(self, args);
-			goto finally;
-		}
-		break;
-
         case 'l':
 		if (type == &PyLong_Type) {
 			res = save_long(self, args);
@@ -2482,7 +2483,9 @@
 			rsize += PyString_GET_SIZE(k);
 
 		else if (PyInt_Check(k)) { /* put */
-			ik = PyInt_AS_LONG((PyIntObject*)k);
+			ik = PyInt_AsLong(k);
+			if (ik == -1 && PyErr_Occurred())
+				goto err;
 			if (ik >= lm || ik == 0) {
 				PyErr_SetString(PicklingError,
 						"Invalid get data");
@@ -2502,7 +2505,9 @@
 		}
 
 		else { /* put */
-			ik = PyInt_AS_LONG((PyIntObject *)k);
+			ik = PyInt_AsLong(k);
+			if (ik == -1 && PyErr_Occurred())
+				goto err;
 			if (ik >= lm || ik == 0) {
 				PyErr_SetString(PicklingError,
 						"Invalid get data");
@@ -2531,8 +2536,9 @@
 		}
 
 		else if (PyTuple_Check(k)) { /* get */
-			ik = PyInt_AS_LONG((PyIntObject *)
-					    PyTuple_GET_ITEM(k, 0));
+			ik = PyLong_AsLong(PyTuple_GET_ITEM(k, 0));
+			if (ik == -1 && PyErr_Occurred())
+				goto err;
 			if (ik < 256) {
 				*s++ = BINGET;
 				*s++ = (int)(ik & 0xff);
@@ -2547,7 +2553,9 @@
 		}
 
 		else { /* put */
-			ik = PyInt_AS_LONG((PyIntObject*)k);
+			ik = PyLong_AsLong(k);
+			if (ik == -1 && PyErr_Occurred())
+				goto err;
 
 			if (have_get[ik]) { /* with matching get */
 				if (ik < 256) {


More information about the Python-checkins mailing list