Use the new struct module's ability to pack and unpack standardized

data formats.  The _xdr module is no longer used, since struct
supports the required IEEE floats and doubles.

(I have one doubt about not using _xdr.  The struct module doesn't
handle Inf, NaN and gradual underflow correctly.  If the _xdr module
does these things better, it may still have a (small) competitive
advantage.  On the other hand, since not all platforms support IEEE
floating point, it's not clear that it would be a good idea to ever
transfer Inf or NaNs.  Gradual underflow can be fixed in the struct
module.
This commit is contained in:
Guido van Rossum 1997-01-02 22:52:15 +00:00
parent 07ef655222
commit 6083f0e9ce
1 changed files with 32 additions and 77 deletions

View File

@ -2,24 +2,9 @@
See: RFC 1014 See: RFC 1014
This module will conditionally use the _xdrmodule.so module to get
support for those representations we can't do much with from Python.
""" """
import struct import struct
from types import LongType
# use C layer XDR libraries for some data types if available
try:
import _xdr
except ImportError:
_xdr = None
# this test is done to see if machine representation is the same as
# network representation. if so, we can use module struct for packing
# some data types
_USE_MACHINE_REP = (struct.pack('l', 1) == '\0\0\0\1')
# exceptions # exceptions
class Error: class Error:
@ -60,14 +45,7 @@ class Packer:
get_buf = get_buffer get_buf = get_buffer
def pack_uint(self, x): def pack_uint(self, x):
self.__buf = self.__buf + \ self.__buf = self.__buf + struct.pack('>L', x)
(chr(int(x>>24 & 0xff)) + chr(int(x>>16 & 0xff)) + \
chr(int(x>>8 & 0xff)) + chr(int(x & 0xff)))
if _USE_MACHINE_REP:
def pack_uint(self, x):
if type(x) == LongType:
x = int((x + 0x80000000L) % 0x100000000L - 0x80000000L)
self.__buf = self.__buf + struct.pack('l', x)
pack_int = pack_uint pack_int = pack_uint
pack_enum = pack_int pack_enum = pack_int
@ -83,19 +61,14 @@ class Packer:
pack_hyper = pack_uhyper pack_hyper = pack_uhyper
def pack_float(self, x): def pack_float(self, x):
raise ConversionError('Not supported') try: self.__buf = self.__buf + struct.pack('>f', x)
except struct.error, msg:
raise ConversionError(msg)
def pack_double(self, x): def pack_double(self, x):
raise ConversionError('Not supported') try: self.__buf = self.__buf + struct.pack('>d', x)
# get these from the C layer if available except struct.error, msg:
if _xdr: raise ConversionError(msg)
def pack_float(self, x):
try: self.__buf = self.__buf + _xdr.pack_float(x)
except _xdr.error, msg:
raise ConversionError(msg)
def pack_double(self, x):
try: self.__buf = self.__buf + _xdr.pack_double(x)
except _xdr.error, msg:
raise ConversionError(msg)
def pack_fstring(self, n, s): def pack_fstring(self, n, s):
if n < 0: if n < 0:
@ -163,27 +136,19 @@ class Unpacker:
data = self.__buf[i:j] data = self.__buf[i:j]
if len(data) < 4: if len(data) < 4:
raise EOFError raise EOFError
x = long(ord(data[0]))<<24 | ord(data[1])<<16 | \ x = struct.unpack('>L', data)[0]
ord(data[2])<<8 | ord(data[3]) try:
# Return a Python long only if the value is not representable return int(x)
# as a nonnegative Python int except OverflowError:
if x < 0x80000000L: return x
x = int(x)
return x
if _USE_MACHINE_REP:
def unpack_uint(self):
i = self.__pos
self.__pos = j = i+4
data = self.__buf[i:j]
if len(data) < 4:
raise EOFError
return struct.unpack('l', data)[0]
def unpack_int(self): def unpack_int(self):
x = self.unpack_uint() i = self.__pos
if x >= 0x80000000L: self.__pos = j = i+4
x = x - 0x100000000L data = self.__buf[i:j]
return int(x) if len(data) < 4:
raise EOFError
return struct.unpack('>l', data)[0]
unpack_enum = unpack_int unpack_enum = unpack_int
unpack_bool = unpack_int unpack_bool = unpack_int
@ -200,30 +165,20 @@ class Unpacker:
return x return x
def unpack_float(self): def unpack_float(self):
raise ConversionError('Not supported') i = self.__pos
def unpack_double(self): self.__pos = j = i+4
raise ConversionError('Not supported') data = self.__buf[i:j]
# get these from the C layer if available if len(data) < 4:
if _xdr: raise EOFError
def unpack_float(self): return struct.unpack('>f', data)[0]
i = self.__pos
self.__pos = j = i+4
data = self.__buf[i:j]
if len(data) < 4:
raise EOFError
try: return _xdr.unpack_float(data)
except _xdr.error, msg:
raise ConversionError(msg)
def unpack_double(self): def unpack_double(self):
i = self.__pos i = self.__pos
self.__pos = j = i+8 self.__pos = j = i+8
data = self.__buf[i:j] data = self.__buf[i:j]
if len(data) < 8: if len(data) < 8:
raise EOFError raise EOFError
try: return _xdr.unpack_double(data) return struct.unpack('>d', data)[0]
except _xdr.error, msg:
raise ConversionError(msg)
def unpack_fstring(self, n): def unpack_fstring(self, n):
if n < 0: if n < 0: