[Zope-Checkins] CVS: Zope2 - cPickle.c:1.72.98.1

Jim Fulton jim@digicool.com
Tue, 10 Apr 2001 12:49:33 -0400 (EDT)


Update of /cvs-repository/Zope2/lib/Components/cPickle
In directory korak:/tmp/cvs-serv7735

Modified Files:
      Tag: zope-2_3-branch
	cPickle.c 
Log Message:
Merged Tim's fixes to cross-platform handling of binary integers.



--- Updated File cPickle.c in package Zope2 --
--- cPickle.c	2000/05/09 18:05:09	1.72
+++ cPickle.c	2001/04/10 16:49:32	1.72.98.1
@@ -69,6 +69,20 @@
 
 #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        '.'
@@ -905,18 +919,20 @@
 
     if (!self->bin
 #if SIZEOF_LONG > 4
-        || (l >> 32)
+        || l >  0x7fffffffL
+        || l < -0x80000000L
 #endif
-            ) {
-                /* Save extra-long ints in non-binary mode, so that
-                   we can use python long parsing code to restore,
-                   if necessary. */
+       ) {
+        /* Text-mode pickle, or long too big to fit in the 4-byte
+         * signed BININT format:  store as a string.
+         */
         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 {
+        /* Binary pickle and l fits in a signed 4-byte int. */
         c_str[1] = (int)( l        & 0xff);
         c_str[2] = (int)((l >> 8)  & 0xff);
         c_str[3] = (int)((l >> 16) & 0xff);
@@ -2401,7 +2417,14 @@
         c = (unsigned char)s[i];
         l |= (long)c << (i * 8);
     }
-
+#if SIZEOF_LONG > 4
+    /* Unlike BININT1 and BININT2, BININT (more accurately BININT4)
+     * is signed, so on a box with longs bigger than 4 bytes we need
+     * to extend a BININT's sign bit to the full width.
+     */
+    if (x == 4 && l & (1L << 31))
+        l |= (~0L) << 32;
+#endif
     return l;
 }