diff options
Diffstat (limited to 'structutils.py')
-rw-r--r-- | structutils.py | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/structutils.py b/structutils.py new file mode 100644 index 0000000..26b0188 --- /dev/null +++ b/structutils.py | |||
@@ -0,0 +1,108 @@ | |||
1 | # vim: set filencoding=utf8 | ||
2 | """ | ||
3 | Utilities for Manipulating Byte Streams | ||
4 | |||
5 | @author: Mike Crute (mcrute@gmail.com) | ||
6 | @organization: SoftGroup Interactive, Inc. | ||
7 | @date: May 05, 2010 | ||
8 | """ | ||
9 | |||
10 | import struct | ||
11 | |||
12 | |||
13 | INT_FORMAT = struct.Struct('>I') | ||
14 | |||
15 | |||
16 | def pack_string(string): | ||
17 | """ | ||
18 | Pack a string into a network style byte array. | ||
19 | """ | ||
20 | return pack_int(len(string)) + string | ||
21 | |||
22 | |||
23 | def pack_int(integer): | ||
24 | """ | ||
25 | Pack an integer into a byte array. | ||
26 | """ | ||
27 | return INT_FORMAT.pack(integer) | ||
28 | |||
29 | |||
30 | def pack_mp_int(mp_int): | ||
31 | """ | ||
32 | Pack a multiple-percision integer into a byte array. | ||
33 | """ | ||
34 | return pack_string(int_to_bytes(mp_int)) | ||
35 | |||
36 | |||
37 | def unpack_string(buf): | ||
38 | """ | ||
39 | Unpack a string from a byte array buffer returning | ||
40 | the string and the remainder of the buffer. | ||
41 | """ | ||
42 | length, = INT_FORMAT.unpack(buf[:4]) | ||
43 | string = buf[4:4+length] | ||
44 | remainder = buf[4+length:] | ||
45 | return string, remainder | ||
46 | |||
47 | |||
48 | def unpack_mp_int(buf): | ||
49 | """ | ||
50 | Unpack a multiple-percision integer from a byte array | ||
51 | buffer returning the string and the remainder of the | ||
52 | buffer. | ||
53 | """ | ||
54 | length, = INT_FORMAT.unpack(buf[:4]) | ||
55 | remainder = buf[4+length:] | ||
56 | |||
57 | return bytes_to_int(buf[4:4+length]), remainder | ||
58 | |||
59 | |||
60 | def unpack_int(buf): | ||
61 | """ | ||
62 | Unpack an integer from a byte array buffer returning the | ||
63 | string and the remainder of the buffer. | ||
64 | """ | ||
65 | integer, = INT_FORMAT.unpack(buf[:4]) | ||
66 | remainder = buf[4:] | ||
67 | return integer, remainder | ||
68 | |||
69 | |||
70 | def get_packed_mp_ints(buf, count=1): | ||
71 | """ | ||
72 | Get a number of multiple-percision integers from a byte | ||
73 | array buffer but leaves them as network style mpints. | ||
74 | """ | ||
75 | ints = [] | ||
76 | for _ in range(count): | ||
77 | length, = INT_FORMAT.unpack(buf[:4]) | ||
78 | ints.append(buf[:4+length] | ||
79 | buf = buf[4+length:] | ||
80 | |||
81 | return ints | ||
82 | |||
83 | |||
84 | def int_to_bytes(integer): | ||
85 | """ | ||
86 | Convert an integer or a long integer to an array of | ||
87 | bytes. | ||
88 | """ | ||
89 | bytes = [] | ||
90 | |||
91 | while integer > 0: | ||
92 | integer, chunk = divmod(integer, 256) | ||
93 | bytes.insert(0, chr(chunk)) | ||
94 | |||
95 | return ''.join(bytes) | ||
96 | |||
97 | |||
98 | def bytes_to_int(buf): | ||
99 | """ | ||
100 | Convert an array of bytes into an integer or long | ||
101 | integer. | ||
102 | """ | ||
103 | integer = 0 | ||
104 | for byte in buf: | ||
105 | integer <<= 8 | ||
106 | integer += ord(byte) | ||
107 | |||
108 | return integer | ||