1
1
# vim: set ts=4 sw=4 tw=79 fileencoding=utf-8:
2
2
# Copyright (c) 2011, Timo Schmid <[email protected] >
3
3
# All rights reserved.
4
- #
4
+ #
5
5
# Redistribution and use in source and binary forms, with or without
6
6
# modification, are permitted provided that the following conditions
7
7
# are met:
8
8
#
9
- # * Redistributions of source code must retain the above copyright
9
+ # * Redistributions of source code must retain the above copyright
10
10
# notice, this list of conditions and the following disclaimer.
11
11
# * Redistributions in binary form must reproduce the above copyright
12
12
# notice, this list of conditions and the following disclaimer in the
26
26
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
27
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
28
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ from __future__ import unicode_literals
30
+
31
+ from builtins import str , bytes
29
32
30
33
import struct
31
34
import logging
32
35
import sys
33
36
34
37
log = logging .getLogger (__name__ )
35
38
39
+
36
40
class MultiByteInt31 (object ):
37
41
38
42
def __init__ (self , * args ):
39
43
self .value = args [0 ] if len (args ) else None
40
-
44
+
41
45
def to_bytes (self ):
42
46
"""
43
47
>>> MultiByteInt31(268435456).to_bytes()
44
- '\\ x80\\ x80\\ x80\\ x80\\ x01'
48
+ b '\\ x80\\ x80\\ x80\\ x80\\ x01'
45
49
>>> MultiByteInt31(0x7f).to_bytes()
46
- '\\ x7f'
50
+ b '\\ x7f'
47
51
>>> MultiByteInt31(0x3fff).to_bytes()
48
- '\\ xff\\ x7f'
52
+ b '\\ xff\\ x7f'
49
53
>>> MultiByteInt31(0x1fffff).to_bytes()
50
- '\\ xff\\ xff\\ x7f'
54
+ b '\\ xff\\ xff\\ x7f'
51
55
>>> MultiByteInt31(0xfffffff).to_bytes()
52
- '\\ xff\\ xff\\ xff\\ x7f'
56
+ b '\\ xff\\ xff\\ xff\\ x7f'
53
57
>>> MultiByteInt31(0x3fffffff).to_bytes()
54
- '\\ xff\\ xff\\ xff\\ xff\\ x03'
58
+ b '\\ xff\\ xff\\ xff\\ xff\\ x03'
55
59
"""
56
60
value_a = self .value & 0x7F
57
- value_b = (self .value >> 7 ) & 0x7F
61
+ value_b = (self .value >> 7 ) & 0x7F
58
62
value_c = (self .value >> 14 ) & 0x7F
59
63
value_d = (self .value >> 21 ) & 0x7F
60
64
value_e = (self .value >> 28 ) & 0x03
61
65
if value_e != 0 :
62
- return struct .pack ('<BBBBB' ,
63
- value_a | 0x80 ,
64
- value_b | 0x80 ,
65
- value_c | 0x80 ,
66
- value_d | 0x80 ,
67
- value_e )
66
+ ret = struct .pack (b '<BBBBB' ,
67
+ value_a | 0x80 ,
68
+ value_b | 0x80 ,
69
+ value_c | 0x80 ,
70
+ value_d | 0x80 ,
71
+ value_e )
68
72
elif value_d != 0 :
69
- return struct .pack ('<BBBB' ,
70
- value_a | 0x80 ,
71
- value_b | 0x80 ,
72
- value_c | 0x80 ,
73
- value_d )
73
+ ret = struct .pack (b '<BBBB' ,
74
+ value_a | 0x80 ,
75
+ value_b | 0x80 ,
76
+ value_c | 0x80 ,
77
+ value_d )
74
78
elif value_c != 0 :
75
- return struct .pack ('<BBB' ,
76
- value_a | 0x80 ,
77
- value_b | 0x80 ,
78
- value_c )
79
+ ret = struct .pack (b '<BBB' ,
80
+ value_a | 0x80 ,
81
+ value_b | 0x80 ,
82
+ value_c )
79
83
elif value_b != 0 :
80
- return struct .pack ('<BB' ,
81
- value_a | 0x80 ,
82
- value_b )
84
+ ret = struct .pack (b '<BB' ,
85
+ value_a | 0x80 ,
86
+ value_b )
83
87
else :
84
- return struct .pack ('<B' ,
85
- value_a )
88
+ ret = struct .pack (b'<B' ,
89
+ value_a )
90
+ return bytes (ret )
86
91
87
92
def __str__ (self ):
88
93
return str (self .value )
89
94
90
95
@classmethod
91
96
def parse (cls , fp ):
92
97
v = 0
93
- #tmp = ''
98
+ # tmp = ''
94
99
for pos in range (4 ):
95
100
b = fp .read (1 )
96
- #tmp += b
97
- value = struct .unpack ('<B' , b )[0 ]
101
+ # tmp += b
102
+ value = struct .unpack (b '<B' , b )[0 ]
98
103
v |= (value & 0x7F ) << 7 * pos
99
104
if not value & 0x80 :
100
105
break
101
- #print ('%s => 0x%X' % (repr(tmp), v))
102
-
106
+ # print ('%s => 0x%X' % (repr(tmp), v))
107
+
103
108
return cls (v )
104
109
110
+
105
111
class Utf8String (object ):
106
112
107
113
def __init__ (self , * args ):
108
114
self .value = args [0 ] if len (args ) else None
109
- if sys .version_info >= (3 ,0 , 0 ):
115
+ if sys .version_info >= (3 , 0 , 0 ):
110
116
if not isinstance (self .value , str ):
111
117
self .value = self .value .decode ('utf-8' )
112
118
else :
@@ -115,62 +121,60 @@ def __init__(self, *args):
115
121
116
122
def to_bytes (self ):
117
123
"""
118
- >>> Utf8String(u "abc").to_bytes()
119
- '\\ x03\x61 \x62 \x63 '
120
- >>> Utf8String(u "\xfc ber").to_bytes()
121
- '\\ x05\\ xc3\\ xbcber'
122
- >>> Utf8String("\\ xc3\\ xbcber".decode('utf-8')).to_bytes()
123
- '\\ x05\\ xc3\\ xbcber'
124
+ >>> Utf8String("abc").to_bytes()
125
+ b '\\ x03\x61 \x62 \x63 '
126
+ >>> Utf8String("\xfc ber").to_bytes()
127
+ b '\\ x05\\ xc3\\ xbcber'
128
+ >>> Utf8String(b "\\ xc3\\ xbcber".decode('utf-8')).to_bytes()
129
+ b '\\ x05\\ xc3\\ xbcber'
124
130
"""
125
- data = self .value .encode ('utf-8' )
131
+ data = self .value .encode ('utf-8' )
126
132
strlen = len (data )
127
133
128
- return MultiByteInt31 (strlen ).to_bytes () + data
134
+ return bytes ( MultiByteInt31 (strlen ).to_bytes () + data )
129
135
130
136
def __str__ (self ):
131
- return self .value .encode ('utf-8' )
132
-
133
- def __unicode__ (self ):
134
- return self .value
137
+ return str (self .value )
135
138
136
139
@classmethod
137
140
def parse (cls , fp ):
138
141
"""
139
- >>> from StringIO import StringIO as io
140
- >>> fp = io( "\\ x05\\ xc3\\ xbcber")
142
+ >>> from io import BytesIO
143
+ >>> fp = BytesIO(b "\\ x05\\ xc3\\ xbcber")
141
144
>>> s = Utf8String.parse(fp)
142
145
>>> s.to_bytes()
143
- '\\ x05\\ xc3\\ xbcber'
144
- >>> print str(s)
146
+ b '\\ x05\\ xc3\\ xbcber'
147
+ >>> print( str(s) )
145
148
über
146
149
"""
147
- lngth = struct .unpack ('<B' , fp .read (1 ))[0 ]
148
-
150
+ lngth = struct .unpack (b '<B' , fp .read (1 ))[0 ]
151
+
149
152
return cls (fp .read (lngth ).decode ('utf-8' ))
150
153
154
+
151
155
class Decimal (object ):
152
156
def __init__ (self , sign , high , low , scale ):
153
157
154
158
if not 0 <= scale <= 28 :
155
159
raise ValueError ('scale %d isn\' t between 0 and 28' % scale )
156
160
self .sign = sign
157
161
self .high = high
158
- self .low = low
162
+ self .low = low
159
163
self .scale = scale
160
164
161
165
def to_bytes (self ):
162
166
"""
163
167
>>> Decimal(False, 0, 5123456, 6).to_bytes()
164
- '\\ x00\\ x00\\ x06\\ x00\\ x00\\ x00\\ x00\\ x00\\ x80-N\\ x00\\ x00\\ x00\\ x00\\ x00'
168
+ b '\\ x00\\ x00\\ x06\\ x00\\ x00\\ x00\\ x00\\ x00\\ x80-N\\ x00\\ x00\\ x00\\ x00\\ x00'
165
169
"""
166
170
log .warn ('Possible false interpretation' )
167
- bytes = struct .pack ('<H' , 0 )
168
- bytes += struct .pack ('<B' , self .scale )
169
- bytes += struct .pack ('<B' , 0x80 if self .sign else 0x00 )
170
- bytes += struct .pack ('<I' , self .high )
171
- bytes += struct .pack ('<Q' , self .low )
171
+ bt = struct .pack (b '<H' , 0 )
172
+ bt += struct .pack (b '<B' , self .scale )
173
+ bt += struct .pack (b '<B' , 0x80 if self .sign else 0x00 )
174
+ bt += struct .pack (b '<I' , self .high )
175
+ bt += struct .pack (b '<Q' , self .low )
172
176
173
- return bytes
177
+ return bytes ( bt )
174
178
175
179
def __str__ (self ):
176
180
"""
@@ -187,25 +191,25 @@ def __str__(self):
187
191
value = str (self .high * 2 ** 64 + self .low )
188
192
if self .scale > 0 :
189
193
value = value [:- self .scale ] + '.' + value [- self .scale :]
190
-
194
+
191
195
if self .sign :
192
196
value = '-%s' % value
193
197
return value
194
198
195
199
@classmethod
196
200
def parse (cls , fp ):
197
201
"""
198
- >>> from StringIO import StringIO as io
199
- >>> buf = io( '\\ x00\\ x00\\ x06\\ x00\\ x00\\ x00\\ x00\\ x00\\ x80-N\\ x00\\ x00\\ x00\\ x00\\ x00')
202
+ >>> from io import BytesIO
203
+ >>> buf = BytesIO(b '\\ x00\\ x00\\ x06\\ x00\\ x00\\ x00\\ x00\\ x00\\ x80-N\\ x00\\ x00\\ x00\\ x00\\ x00')
200
204
>>> str(Decimal.parse(buf))
201
205
'5.123456'
202
206
"""
203
207
log .warn ('Possible false interpretation' )
204
208
fp .read (2 )
205
- scale = struct .unpack ('<B' , fp .read (1 ))[0 ]
206
- sign = struct .unpack ('<B' , fp .read (1 ))[0 ] & 0x80
207
- high = struct .unpack ('<I' , fp .read (4 ))[0 ]
208
- low = struct .unpack ('<Q' , fp .read (8 ))[0 ]
209
+ scale = struct .unpack (b '<B' , fp .read (1 ))[0 ]
210
+ sign = struct .unpack (b '<B' , fp .read (1 ))[0 ] & 0x80
211
+ high = struct .unpack (b '<I' , fp .read (4 ))[0 ]
212
+ low = struct .unpack (b '<Q' , fp .read (8 ))[0 ]
209
213
210
214
return cls (sign , high , low , scale )
211
215
0 commit comments