Kaydet (Commit) df88846e authored tarafından Michael W. Hudson's avatar Michael W. Hudson

This is my patch:

[ 1180995 ] binary formats for marshalling floats

Adds 2 new type codes for marshal (binary floats and binary complexes), a
new marshal version (2), updates MAGIC and fiddles the de-serializing of
code objects to be less likely to clobber the real reason for failing if
it fails.
üst 268e61cf
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
extern "C" { extern "C" {
#endif #endif
#define Py_MARSHAL_VERSION 1 #define Py_MARSHAL_VERSION 2
PyAPI_FUNC(void) PyMarshal_WriteLongToFile(long, FILE *, int); PyAPI_FUNC(void) PyMarshal_WriteLongToFile(long, FILE *, int);
PyAPI_FUNC(void) PyMarshal_WriteObjectToFile(PyObject *, FILE *, int); PyAPI_FUNC(void) PyMarshal_WriteObjectToFile(PyObject *, FILE *, int);
......
...@@ -73,20 +73,34 @@ class FloatTestCase(unittest.TestCase): ...@@ -73,20 +73,34 @@ class FloatTestCase(unittest.TestCase):
n /= 123.4567 n /= 123.4567
f = 0.0 f = 0.0
s = marshal.dumps(f) s = marshal.dumps(f, 2)
got = marshal.loads(s) got = marshal.loads(s)
self.assertEqual(f, got) self.assertEqual(f, got)
# and with version <= 1 (floats marshalled differently then)
s = marshal.dumps(f, 1)
got = marshal.loads(s)
self.assertEqual(f, got)
n = sys.maxint * 3.7e-250 n = sys.maxint * 3.7e-250
while n < small: while n < small:
for expected in (-n, n): for expected in (-n, n):
f = float(expected) f = float(expected)
s = marshal.dumps(f) s = marshal.dumps(f)
got = marshal.loads(s) got = marshal.loads(s)
self.assertEqual(f, got) self.assertEqual(f, got)
s = marshal.dumps(f, 1)
got = marshal.loads(s)
self.assertEqual(f, got)
marshal.dump(f, file(test_support.TESTFN, "wb")) marshal.dump(f, file(test_support.TESTFN, "wb"))
got = marshal.load(file(test_support.TESTFN, "rb")) got = marshal.load(file(test_support.TESTFN, "rb"))
self.assertEqual(f, got) self.assertEqual(f, got)
marshal.dump(f, file(test_support.TESTFN, "wb"), 1)
got = marshal.load(file(test_support.TESTFN, "rb"))
self.assertEqual(f, got)
n *= 123.4567 n *= 123.4567
os.unlink(test_support.TESTFN) os.unlink(test_support.TESTFN)
......
...@@ -12,6 +12,9 @@ What's New in Python 2.5 alpha 1? ...@@ -12,6 +12,9 @@ What's New in Python 2.5 alpha 1?
Core and builtins Core and builtins
----------------- -----------------
- SF patch #1180995: marshal now uses a binary format by default when
serializing floats.
- SF patch #1181301: on platforms that appear to use IEEE 754 floats, - SF patch #1181301: on platforms that appear to use IEEE 754 floats,
the routines that promise to produce IEEE 754 binary representations the routines that promise to produce IEEE 754 binary representations
of floats now simply copy bytes around. of floats now simply copy bytes around.
......
...@@ -50,8 +50,9 @@ extern time_t PyOS_GetLastModificationTime(char *, FILE *); ...@@ -50,8 +50,9 @@ extern time_t PyOS_GetLastModificationTime(char *, FILE *);
Python 2.4a0: 62041 Python 2.4a0: 62041
Python 2.4a3: 62051 Python 2.4a3: 62051
Python 2.4b1: 62061 Python 2.4b1: 62061
Python 2.5a0: 62071
*/ */
#define MAGIC (62061 | ((long)'\r'<<16) | ((long)'\n'<<24)) #define MAGIC (62071 | ((long)'\r'<<16) | ((long)'\n'<<24))
/* Magic word as global; note that _PyImport_Init() can change the /* Magic word as global; note that _PyImport_Init() can change the
value of this global to accommodate for alterations of how the value of this global to accommodate for alterations of how the
......
...@@ -15,28 +15,30 @@ ...@@ -15,28 +15,30 @@
*/ */
#define MAX_MARSHAL_STACK_DEPTH 5000 #define MAX_MARSHAL_STACK_DEPTH 5000
#define TYPE_NULL '0' #define TYPE_NULL '0'
#define TYPE_NONE 'N' #define TYPE_NONE 'N'
#define TYPE_FALSE 'F' #define TYPE_FALSE 'F'
#define TYPE_TRUE 'T' #define TYPE_TRUE 'T'
#define TYPE_STOPITER 'S' #define TYPE_STOPITER 'S'
#define TYPE_ELLIPSIS '.' #define TYPE_ELLIPSIS '.'
#define TYPE_INT 'i' #define TYPE_INT 'i'
#define TYPE_INT64 'I' #define TYPE_INT64 'I'
#define TYPE_FLOAT 'f' #define TYPE_FLOAT 'f'
#define TYPE_COMPLEX 'x' #define TYPE_BINARY_FLOAT 'g'
#define TYPE_LONG 'l' #define TYPE_COMPLEX 'x'
#define TYPE_STRING 's' #define TYPE_BINARY_COMPLEX 'y'
#define TYPE_INTERNED 't' #define TYPE_LONG 'l'
#define TYPE_STRINGREF 'R' #define TYPE_STRING 's'
#define TYPE_TUPLE '(' #define TYPE_INTERNED 't'
#define TYPE_LIST '[' #define TYPE_STRINGREF 'R'
#define TYPE_DICT '{' #define TYPE_TUPLE '('
#define TYPE_CODE 'c' #define TYPE_LIST '['
#define TYPE_UNICODE 'u' #define TYPE_DICT '{'
#define TYPE_UNKNOWN '?' #define TYPE_CODE 'c'
#define TYPE_SET '<' #define TYPE_UNICODE 'u'
#define TYPE_FROZENSET '>' #define TYPE_UNKNOWN '?'
#define TYPE_SET '<'
#define TYPE_FROZENSET '>'
typedef struct { typedef struct {
FILE *fp; FILE *fp;
...@@ -47,6 +49,7 @@ typedef struct { ...@@ -47,6 +49,7 @@ typedef struct {
char *ptr; char *ptr;
char *end; char *end;
PyObject *strings; /* dict on marshal, list on unmarshal */ PyObject *strings; /* dict on marshal, list on unmarshal */
int version;
} WFILE; } WFILE;
#define w_byte(c, p) if (((p)->fp)) putc((c), (p)->fp); \ #define w_byte(c, p) if (((p)->fp)) putc((c), (p)->fp); \
...@@ -165,32 +168,62 @@ w_object(PyObject *v, WFILE *p) ...@@ -165,32 +168,62 @@ w_object(PyObject *v, WFILE *p)
w_short(ob->ob_digit[i], p); w_short(ob->ob_digit[i], p);
} }
else if (PyFloat_Check(v)) { else if (PyFloat_Check(v)) {
char buf[256]; /* Plenty to format any double */ if (p->version > 1) {
PyFloat_AsReprString(buf, (PyFloatObject *)v); char buf[8];
n = strlen(buf); if (_PyFloat_Pack8(PyFloat_AsDouble(v),
w_byte(TYPE_FLOAT, p); buf, 1) < 0) {
w_byte(n, p); p->error = 1;
w_string(buf, n, p); return;
}
w_byte(TYPE_BINARY_FLOAT, p);
w_string(buf, 8, p);
}
else {
char buf[256]; /* Plenty to format any double */
PyFloat_AsReprString(buf, (PyFloatObject *)v);
n = strlen(buf);
w_byte(TYPE_FLOAT, p);
w_byte(n, p);
w_string(buf, n, p);
}
} }
#ifndef WITHOUT_COMPLEX #ifndef WITHOUT_COMPLEX
else if (PyComplex_Check(v)) { else if (PyComplex_Check(v)) {
char buf[256]; /* Plenty to format any double */ if (p->version > 1) {
PyFloatObject *temp; char buf[8];
w_byte(TYPE_COMPLEX, p); if (_PyFloat_Pack8(PyComplex_RealAsDouble(v),
temp = (PyFloatObject*)PyFloat_FromDouble( buf, 1) < 0) {
PyComplex_RealAsDouble(v)); p->error = 1;
PyFloat_AsReprString(buf, temp); return;
Py_DECREF(temp); }
n = strlen(buf); w_byte(TYPE_BINARY_COMPLEX, p);
w_byte(n, p); w_string(buf, 8, p);
w_string(buf, n, p); if (_PyFloat_Pack8(PyComplex_ImagAsDouble(v),
temp = (PyFloatObject*)PyFloat_FromDouble( buf, 1) < 0) {
PyComplex_ImagAsDouble(v)); p->error = 1;
PyFloat_AsReprString(buf, temp); return;
Py_DECREF(temp); }
n = strlen(buf); w_string(buf, 8, p);
w_byte(n, p); }
w_string(buf, n, p); else {
char buf[256]; /* Plenty to format any double */
PyFloatObject *temp;
w_byte(TYPE_COMPLEX, p);
temp = (PyFloatObject*)PyFloat_FromDouble(
PyComplex_RealAsDouble(v));
PyFloat_AsReprString(buf, temp);
Py_DECREF(temp);
n = strlen(buf);
w_byte(n, p);
w_string(buf, n, p);
temp = (PyFloatObject*)PyFloat_FromDouble(
PyComplex_ImagAsDouble(v));
PyFloat_AsReprString(buf, temp);
Py_DECREF(temp);
n = strlen(buf);
w_byte(n, p);
w_string(buf, n, p);
}
} }
#endif #endif
else if (PyString_Check(v)) { else if (PyString_Check(v)) {
...@@ -335,6 +368,7 @@ PyMarshal_WriteLongToFile(long x, FILE *fp, int version) ...@@ -335,6 +368,7 @@ PyMarshal_WriteLongToFile(long x, FILE *fp, int version)
wf.error = 0; wf.error = 0;
wf.depth = 0; wf.depth = 0;
wf.strings = NULL; wf.strings = NULL;
wf.version = version;
w_long(x, &wf); w_long(x, &wf);
} }
...@@ -346,6 +380,7 @@ PyMarshal_WriteObjectToFile(PyObject *x, FILE *fp, int version) ...@@ -346,6 +380,7 @@ PyMarshal_WriteObjectToFile(PyObject *x, FILE *fp, int version)
wf.error = 0; wf.error = 0;
wf.depth = 0; wf.depth = 0;
wf.strings = (version > 0) ? PyDict_New() : NULL; wf.strings = (version > 0) ? PyDict_New() : NULL;
wf.version = version;
w_object(x, &wf); w_object(x, &wf);
Py_XDECREF(wf.strings); Py_XDECREF(wf.strings);
} }
...@@ -519,6 +554,22 @@ r_object(RFILE *p) ...@@ -519,6 +554,22 @@ r_object(RFILE *p)
return PyFloat_FromDouble(dx); return PyFloat_FromDouble(dx);
} }
case TYPE_BINARY_FLOAT:
{
char buf[8];
double x;
if (r_string(buf, 8, p) != 8) {
PyErr_SetString(PyExc_EOFError,
"EOF read where object expected");
return NULL;
}
x = _PyFloat_Unpack8(buf, 1);
if (x == -1.0 && PyErr_Occurred()) {
return NULL;
}
return PyFloat_FromDouble(x);
}
#ifndef WITHOUT_COMPLEX #ifndef WITHOUT_COMPLEX
case TYPE_COMPLEX: case TYPE_COMPLEX:
{ {
...@@ -546,6 +597,31 @@ r_object(RFILE *p) ...@@ -546,6 +597,31 @@ r_object(RFILE *p)
PyFPE_END_PROTECT(c) PyFPE_END_PROTECT(c)
return PyComplex_FromCComplex(c); return PyComplex_FromCComplex(c);
} }
case TYPE_BINARY_COMPLEX:
{
char buf[8];
Py_complex c;
if (r_string(buf, 8, p) != 8) {
PyErr_SetString(PyExc_EOFError,
"EOF read where object expected");
return NULL;
}
c.real = _PyFloat_Unpack8(buf, 1);
if (c.real == -1.0 && PyErr_Occurred()) {
return NULL;
}
if (r_string(buf, 8, p) != 8) {
PyErr_SetString(PyExc_EOFError,
"EOF read where object expected");
return NULL;
}
c.imag = _PyFloat_Unpack8(buf, 1);
if (c.imag == -1.0 && PyErr_Occurred()) {
return NULL;
}
return PyComplex_FromCComplex(c);
}
#endif #endif
case TYPE_INTERNED: case TYPE_INTERNED:
...@@ -707,30 +783,63 @@ r_object(RFILE *p) ...@@ -707,30 +783,63 @@ r_object(RFILE *p)
return NULL; return NULL;
} }
else { else {
int argcount = r_long(p); int argcount;
int nlocals = r_long(p); int nlocals;
int stacksize = r_long(p); int stacksize;
int flags = r_long(p); int flags;
PyObject *code = r_object(p); PyObject *code = NULL;
PyObject *consts = r_object(p); PyObject *consts = NULL;
PyObject *names = r_object(p); PyObject *names = NULL;
PyObject *varnames = r_object(p); PyObject *varnames = NULL;
PyObject *freevars = r_object(p); PyObject *freevars = NULL;
PyObject *cellvars = r_object(p); PyObject *cellvars = NULL;
PyObject *filename = r_object(p); PyObject *filename = NULL;
PyObject *name = r_object(p); PyObject *name = NULL;
int firstlineno = r_long(p); int firstlineno;
PyObject *lnotab = r_object(p); PyObject *lnotab = NULL;
if (!PyErr_Occurred()) { v = NULL;
v = (PyObject *) PyCode_New(
argcount = r_long(p);
nlocals = r_long(p);
stacksize = r_long(p);
flags = r_long(p);
code = r_object(p);
if (code == NULL)
goto code_error;
consts = r_object(p);
if (consts == NULL)
goto code_error;
names = r_object(p);
if (names == NULL)
goto code_error;
varnames = r_object(p);
if (varnames == NULL)
goto code_error;
freevars = r_object(p);
if (freevars == NULL)
goto code_error;
cellvars = r_object(p);
if (cellvars == NULL)
goto code_error;
filename = r_object(p);
if (filename == NULL)
goto code_error;
name = r_object(p);
if (name == NULL)
goto code_error;
firstlineno = r_long(p);
lnotab = r_object(p);
if (lnotab == NULL)
goto code_error;
v = (PyObject *) PyCode_New(
argcount, nlocals, stacksize, flags, argcount, nlocals, stacksize, flags,
code, consts, names, varnames, code, consts, names, varnames,
freevars, cellvars, filename, name, freevars, cellvars, filename, name,
firstlineno, lnotab); firstlineno, lnotab);
}
else code_error:
v = NULL;
Py_XDECREF(code); Py_XDECREF(code);
Py_XDECREF(consts); Py_XDECREF(consts);
Py_XDECREF(names); Py_XDECREF(names);
...@@ -882,6 +991,7 @@ PyMarshal_WriteObjectToString(PyObject *x, int version) ...@@ -882,6 +991,7 @@ PyMarshal_WriteObjectToString(PyObject *x, int version)
wf.end = wf.ptr + PyString_Size(wf.str); wf.end = wf.ptr + PyString_Size(wf.str);
wf.error = 0; wf.error = 0;
wf.depth = 0; wf.depth = 0;
wf.version = version;
wf.strings = (version > 0) ? PyDict_New() : NULL; wf.strings = (version > 0) ? PyDict_New() : NULL;
w_object(x, &wf); w_object(x, &wf);
Py_XDECREF(wf.strings); Py_XDECREF(wf.strings);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment