[pypy-svn] r15320 - pypy/dist/pypy/lib
ale at codespeak.net
ale at codespeak.net
Fri Jul 29 09:09:58 CEST 2005
Author: ale
Date: Fri Jul 29 09:09:56 2005
New Revision: 15320
Modified:
pypy/dist/pypy/lib/struct.py
Log:
removed a check for size of signed short. It seems that test_binhex relies on struct to truncate the value.
Modified: pypy/dist/pypy/lib/struct.py
==============================================================================
--- pypy/dist/pypy/lib/struct.py (original)
+++ pypy/dist/pypy/lib/struct.py Fri Jul 29 09:09:56 2005
@@ -1,37 +1,37 @@
-"""Functions to convert between Python values and C structs.
-Python strings are used to hold the data representing the C struct
+"""Functions to convert between Python values and C structs.
+Python strings are used to hold the data representing the C struct
and also as format strings to describe the layout of data in the C struct.
-The optional first format char indicates byte order, size and alignment:
- @: native order, size & alignment (default)
- =: native order, std. size & alignment
- <: little-endian, std. size & alignment
- >: big-endian, std. size & alignment
- !: same as >
-
-The remaining chars indicate types of args and must match exactly;
-these can be preceded by a decimal repeat count:
- x: pad byte (no data);
- c:char;
- b:signed byte;
- B:unsigned byte;
- h:short;
- H:unsigned short;
- i:int;
- I:unsigned int;
- l:long;
- L:unsigned long;
- f:float;
- d:double.
-Special cases (preceding decimal count indicates length):
- s:string (array of char); p: pascal string (with count byte).
-Special case (only available in native format):
- P:an integer type that is wide enough to hold a pointer.
-Special case (not in native mode unless 'long long' in platform C):
- q:long long;
- Q:unsigned long long
-Whitespace between formats is ignored.
-
+The optional first format char indicates byte order, size and alignment:
+ @: native order, size & alignment (default)
+ =: native order, std. size & alignment
+ <: little-endian, std. size & alignment
+ >: big-endian, std. size & alignment
+ !: same as >
+
+The remaining chars indicate types of args and must match exactly;
+these can be preceded by a decimal repeat count:
+ x: pad byte (no data);
+ c:char;
+ b:signed byte;
+ B:unsigned byte;
+ h:short;
+ H:unsigned short;
+ i:int;
+ I:unsigned int;
+ l:long;
+ L:unsigned long;
+ f:float;
+ d:double.
+Special cases (preceding decimal count indicates length):
+ s:string (array of char); p: pascal string (with count byte).
+Special case (only available in native format):
+ P:an integer type that is wide enough to hold a pointer.
+Special case (not in native mode unless 'long long' in platform C):
+ q:long long;
+ Q:unsigned long long
+Whitespace between formats is ignored.
+
The variable struct.error is an exception raised on errors."""
import math, sys
@@ -51,11 +51,11 @@
def unpack_signed_int(data,index,size,le):
number = unpack_int(data,index,size,le)
- max = 2**(size*8)
+ max = 2**(size*8)
if number > 2**(size*8 - 1) - 1:
number = int(-1*(max - number))
return number
-
+
def unpack_float(data,index,size,le):
bytes = [ord(b) for b in data[index:index+size]]
if len(bytes) != size:
@@ -72,42 +72,37 @@
bias = 1023
exp = 11
prec = 52
-# print bytes,size,index,len(data),data
mantissa = long(bytes[size-2] & (2**(15-exp)-1))
-# print mantissa
for b in bytes[size-3::-1]:
mantissa = mantissa << 8 | b
-# print mantissa
mantissa = 1 + (1.0*mantissa)/(2**(prec))
mantissa /= 2
-# print mantissa
e = (bytes[-1] & 0x7f) << (exp - 7)
e += (bytes[size-2] >> (15 - exp)) & (2**(exp - 7) -1)
e -= bias
e += 1
sign = bytes[-1] & 0x80
number = math.ldexp(mantissa,e)
-# print number,index,mantissa,e,bytes#,data
if sign : number *= -1
return number
def unpack_char(data,index,size,le):
return data[index:index+size]
-
+
def pack_int(number,size,le):
x=number
res=[]
for i in range(size):
res.append(chr(x&0xff))
- x >>= 8
+ x >>= 8
if le == 'big':
res.reverse()
- return ''.join(res)
-
+ return ''.join(res)
+
def pack_signed_int(number,size,le):
if not isinstance(number, (int,long)):
raise StructError,"argument for i,I,l,L,q,Q,h,H must be integer"
- if number > 2**(8*size-1)-1 or number < -1*2**(8*size-1):
+ if number < -1*2**(8*size-1): #number > 2**(8*size-1)-1 or
raise OverflowError,"Number:%i too large to convert" % number
return pack_int(number,size,le)
@@ -119,22 +114,21 @@
if number > 2**(8*size)-1:
raise OverflowError,"Number:%i too large to convert" % number
return pack_int(number,size,le)
-
+
def pack_char(char,size,le):
-# print char
return str(char)
def sane_float(man,e):
# TODO: XXX Implement checks for floats
return True
-
+
def pack_float(number, size, le):
-
+
if number < 0:
sign = 1
number *= -1
elif number == 0.0:
- return "\x00" * size
+ return "\x00" * size
else:
sign = 0
if size == 4:
@@ -145,7 +139,7 @@
bias = 1023
exp = 11
prec = 52
-
+
man, e = math.frexp(number)
if 0.5 <= man and man < 1.0:
man *= 2
@@ -153,12 +147,12 @@
if sane_float(man,e):
man -= 1
e += bias
- mantissa = int(2**prec *(man) +0.5)
+ mantissa = int(2**prec *(man) +0.5)
res=[]
if mantissa >> prec :
mantissa = 0
e += 1
-
+
for i in range(size-2):
res += [ mantissa & 0xff]
mantissa >>= 8
@@ -168,7 +162,7 @@
res.reverse()
return ''.join([chr(x) for x in res])
# TODO: What todo with insane floats/doubles. handle in sanefloat?
-
+
big_endian_format = {
'x':{ 'size' : 1, 'alignment' : 0, 'pack' : None, 'unpack' : None},
'b':{ 'size' : 1, 'alignment' : 0, 'pack' : pack_signed_int, 'unpack' : unpack_signed_int},
@@ -188,12 +182,12 @@
'd':{ 'size' : 8, 'alignment' : 0, 'pack' : pack_float, 'unpack' : unpack_float},
}
default = big_endian_format
-formatmode={ '<' : (default, 'little'),
- '>' : (default, 'big'),
+formatmode={ '<' : (default, 'little'),
+ '>' : (default, 'big'),
'!' : (default, 'big'),
'=' : (default, sys.byteorder),
'@' : (default, sys.byteorder)
- }
+ }
def getmode(fmt):
try:
@@ -214,12 +208,12 @@
i += 1
cur = fmt[i]
return num,i
-
+
def calcsize(fmt):
- """calcsize(fmt) -> int
- Return size of C struct described by format string fmt.
+ """calcsize(fmt) -> int
+ Return size of C struct described by format string fmt.
See struct.__doc__ for more on format strings."""
-
+
formatdef,endianness,i = getmode(fmt)
num = 0
result = 0
@@ -237,10 +231,10 @@
num = 0
i += 1
return result
-
+
def pack(fmt,*args):
- """pack(fmt, v1, v2, ...) -> string
- Return string containing values v1, v2, ... packed according to fmt.
+ """pack(fmt, v1, v2, ...) -> string
+ Return string containing values v1, v2, ... packed according to fmt.
See struct.__doc__ for more on format strings."""
formatdef,endianness,i = getmode(fmt)
args = list(args)
@@ -258,7 +252,7 @@
num = 1
else:
num_s = num
-
+
if cur == 'x':
result += ['\0'*num]
elif cur == 's':
@@ -271,7 +265,7 @@
elif cur == 'p':
if isinstance(args[0], str):
padding = num - len(args[0]) - 1
-
+
if padding > 0:
result += [chr(len(args[0])) + args[0][:num-1] + '\0'*padding]
else:
@@ -282,7 +276,7 @@
args.pop(0)
else:
raise StructError,"arg for string format not a string"
-
+
else:
if len(args) == 0:
raise StructError,"insufficient arguments to pack"
@@ -294,14 +288,13 @@
if len(args) != 0:
raise StructError,"too many arguments for pack format"
return ''.join(result)
-
+
def unpack(fmt,data):
"""unpack(fmt, string) -> (v1, v2, ...)
Unpack the string, containing packed C structure data, according
to fmt. Requires len(string)==calcsize(fmt).
See struct.__doc__ for more on format strings."""
formatdef,endianness,i = getmode(fmt)
-# print fmt,data
j = 0
num = 0
result = []
@@ -315,7 +308,7 @@
format = formatdef[cur]
except KeyError:
raise StructError,"%s is not a valid format"%cur
-
+
if not num :
num = 1
if cur == 'x':
@@ -332,7 +325,7 @@
result.append(data[j+1:j+n+1])
j += num
i += 1
- else:
+ else:
for n in range(num):
result += [format['unpack'](data,j,format['size'],endianness)]
j += format['size']
@@ -344,4 +337,4 @@
print pack_float(1.23,4,'little')
import struct
print (struct.pack('f',1.23), pack('f',1.23))
- print unpack('f',pack('f',1.23))
+ print unpack('f',pack('f',1.23))
More information about the Pypy-commit
mailing list