[pypy-svn] r46939 - in pypy/dist/pypy/module/struct: . test
arigo at codespeak.net
arigo at codespeak.net
Thu Sep 27 11:54:15 CEST 2007
Author: arigo
Date: Thu Sep 27 11:54:15 2007
New Revision: 46939
Modified:
pypy/dist/pypy/module/struct/formatiterator.py
pypy/dist/pypy/module/struct/nativefmttable.py
pypy/dist/pypy/module/struct/test/test_struct.py
Log:
Native floats and doubles in the struct module.
Modified: pypy/dist/pypy/module/struct/formatiterator.py
==============================================================================
--- pypy/dist/pypy/module/struct/formatiterator.py (original)
+++ pypy/dist/pypy/module/struct/formatiterator.py Thu Sep 27 11:54:15 2007
@@ -142,6 +142,10 @@
w_obj = self.accept_obj_arg()
return self.space.str_w(w_obj)
+ def accept_float_arg(self):
+ w_obj = self.accept_obj_arg()
+ return self.space.float_w(w_obj)
+
class UnpackFormatIterator(FormatIterator):
Modified: pypy/dist/pypy/module/struct/nativefmttable.py
==============================================================================
--- pypy/dist/pypy/module/struct/nativefmttable.py (original)
+++ pypy/dist/pypy/module/struct/nativefmttable.py Thu Sep 27 11:54:15 2007
@@ -2,6 +2,7 @@
from pypy.module.struct import standardfmttable as std
from pypy.rpython.tool import rffi_platform
from pypy.rpython.lltypesystem import lltype, rffi
+from pypy.rlib.rarithmetic import r_singlefloat
native_is_bigendian = struct.pack("=i", 1) == struct.pack(">i", 1)
@@ -13,49 +14,113 @@
}
# ____________________________________________________________
+
+def pack_double(fmtiter):
+ doubleval = fmtiter.accept_float_arg()
+ buf = lltype.malloc(rffi.DOUBLEP.TO, 1, flavor='raw')
+ try:
+ buf[0] = doubleval
+ p = rffi.cast(rffi.CCHARP, buf)
+ for i in range(sizeof_double):
+ fmtiter.result.append(p[i])
+ finally:
+ lltype.free(buf, flavor='raw')
+
+def unpack_double(fmtiter):
+ input = fmtiter.read(sizeof_double)
+ buf = lltype.malloc(rffi.DOUBLEP.TO, 1, flavor='raw')
+ try:
+ p = rffi.cast(rffi.CCHARP, buf)
+ for i in range(sizeof_double):
+ p[i] = input[i]
+ doubleval = buf[0]
+ finally:
+ lltype.free(buf, flavor='raw')
+ fmtiter.appendobj(doubleval)
+
+def pack_float(fmtiter):
+ doubleval = fmtiter.accept_float_arg()
+ floatval = r_singlefloat(doubleval)
+ buf = lltype.malloc(rffi.FLOATP.TO, 1, flavor='raw')
+ try:
+ buf[0] = floatval
+ p = rffi.cast(rffi.CCHARP, buf)
+ for i in range(sizeof_float):
+ fmtiter.result.append(p[i])
+ finally:
+ lltype.free(buf, flavor='raw')
+
+def unpack_float(fmtiter):
+ input = fmtiter.read(sizeof_float)
+ buf = lltype.malloc(rffi.FLOATP.TO, 1, flavor='raw')
+ try:
+ p = rffi.cast(rffi.CCHARP, buf)
+ for i in range(sizeof_float):
+ p[i] = input[i]
+ floatval = buf[0]
+ finally:
+ lltype.free(buf, flavor='raw')
+ doubleval = float(floatval)
+ fmtiter.appendobj(doubleval)
+
+# ____________________________________________________________
#
# Use rffi_platform to get the native sizes and alignments from the C compiler
-INSPECT = {'b': 'signed char',
- 'h': 'signed short',
- 'i': 'signed int',
- 'l': 'signed long',
- 'q': 'signed long long',
- 'B': 'unsigned char',
- 'H': 'unsigned short',
- 'I': 'unsigned int',
- 'L': 'unsigned long',
- 'Q': 'unsigned long long',
- 'P': 'char *',
- 'f': 'float',
- 'd': 'double',
- }
-
-class CConfig:
- _header_ = ""
-
-for fmtchar, ctype in INSPECT.items():
- CConfig._header_ += """
- struct about_%s {
- char pad;
- %s field;
- };
- """ % (fmtchar, ctype)
- setattr(CConfig, fmtchar, rffi_platform.Struct(
- "struct about_%s" % (fmtchar,),
- [('field', lltype.FixedSizeArray(rffi.CHAR, 1))]))
-
-cConfig = rffi_platform.configure(CConfig)
-
-for fmtchar, ctype in INSPECT.items():
- S = cConfig[fmtchar]
- alignment = rffi.offsetof(S, 'c_field')
- size = rffi.sizeof(S.c_field)
- signed = 'a' <= fmtchar <= 'z'
-
- native_fmttable[fmtchar] = {
- 'size': size,
- 'alignment': alignment,
- 'pack': std.make_int_packer(size, signed), # XXX 'f', 'd'
- 'unpack': std.make_int_unpacker(size, signed),
- }
+def setup():
+ INSPECT = {'b': 'signed char',
+ 'h': 'signed short',
+ 'i': 'signed int',
+ 'l': 'signed long',
+ 'q': 'signed long long',
+ 'B': 'unsigned char',
+ 'H': 'unsigned short',
+ 'I': 'unsigned int',
+ 'L': 'unsigned long',
+ 'Q': 'unsigned long long',
+ 'P': 'char *',
+ 'f': 'float',
+ 'd': 'double',
+ }
+
+ class CConfig:
+ _header_ = ""
+
+ for fmtchar, ctype in INSPECT.items():
+ CConfig._header_ += """
+ struct about_%s {
+ char pad;
+ %s field;
+ };
+ """ % (fmtchar, ctype)
+ setattr(CConfig, fmtchar, rffi_platform.Struct(
+ "struct about_%s" % (fmtchar,),
+ [('field', lltype.FixedSizeArray(rffi.CHAR, 1))]))
+
+ cConfig = rffi_platform.configure(CConfig)
+
+ for fmtchar, ctype in INSPECT.items():
+ S = cConfig[fmtchar]
+ alignment = rffi.offsetof(S, 'c_field')
+ size = rffi.sizeof(S.c_field)
+ signed = 'a' <= fmtchar <= 'z'
+
+ if fmtchar == 'f':
+ pack = pack_float
+ unpack = unpack_float
+ elif fmtchar == 'd':
+ pack = pack_double
+ unpack = unpack_double
+ else:
+ pack = std.make_int_packer(size, signed)
+ unpack = std.make_int_unpacker(size, signed)
+
+ native_fmttable[fmtchar] = {'size': size,
+ 'alignment': alignment,
+ 'pack': pack,
+ 'unpack': unpack}
+
+setup()
+
+sizeof_double = native_fmttable['d']['size']
+sizeof_float = native_fmttable['f']['size']
Modified: pypy/dist/pypy/module/struct/test/test_struct.py
==============================================================================
--- pypy/dist/pypy/module/struct/test/test_struct.py (original)
+++ pypy/dist/pypy/module/struct/test/test_struct.py Thu Sep 27 11:54:15 2007
@@ -221,6 +221,37 @@
assert unpack("5x", "hello") == ()
+ def test_native_floats(self):
+ """
+ Check the 'd' and 'f' format characters on native packing.
+ """
+ calcsize = self.struct.calcsize
+ pack = self.struct.pack
+ unpack = self.struct.unpack
+ data = pack("d", 12.34)
+ assert len(data) == calcsize("d")
+ assert unpack("d", data) == (12.34,) # no precision lost
+ data = pack("f", 12.34)
+ assert len(data) == calcsize("f")
+ res, = unpack("f", data)
+ assert res != 12.34 # precision lost
+ assert abs(res - 12.34) < 1E-6
+
+
+ def test_standard_floats(self):
+ """
+ Check the 'd' and 'f' format characters on standard packing.
+ """
+ skip("in-progress")
+ pack = self.struct.pack
+ unpack = self.struct.unpack
+ assert pack("!d", 12.5) == '@)\x00\x00\x00\x00\x00\x00'
+ assert pack("<d", 12.5) == '\x00\x00\x00\x00\x00\x00)@'
+ assert unpack("!d", '@)\x00\x00\x00\x00\x00\x00') == (12.5,)
+ assert unpack("<d", '\x00\x00\x00\x00\x00\x00)@') == (12.5,)
+ XXX # "f"
+
+
def test_struct_error(self):
"""
Check the various ways to get a struct.error. Note that CPython
More information about the Pypy-commit
mailing list