Skip to content

Commit 7a2f166

Browse files
committed
modstruct: Fix alignment handling issues.
Also, factor out mp_binary_get_int() function.
1 parent 5aa740c commit 7a2f166

3 files changed

Lines changed: 30 additions & 19 deletions

File tree

py/binary.c

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,28 @@ mp_obj_t mp_binary_get_val_array(char typecode, void *p, int index) {
125125
return MP_OBJ_NEW_SMALL_INT(val);
126126
}
127127

128+
machine_int_t mp_binary_get_int(uint size, bool is_signed, bool big_endian, byte *p) {
129+
int delta;
130+
if (!big_endian) {
131+
delta = -1;
132+
p += size - 1;
133+
} else {
134+
delta = 1;
135+
}
136+
137+
machine_int_t val = 0;
138+
if (is_signed && *p & 0x80) {
139+
val = -1;
140+
}
141+
for (uint i = 0; i < size; i++) {
142+
val <<= 8;
143+
val |= *p;
144+
p += delta;
145+
}
146+
147+
return val;
148+
}
149+
128150
#define is_signed(typecode) (typecode > 'Z')
129151
mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) {
130152
byte *p = *ptr;
@@ -140,26 +162,10 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) {
140162
struct_type = '>';
141163
#endif
142164
}
165+
*ptr = p + size;
143166

144-
int delta;
145-
if (struct_type == '<') {
146-
delta = -1;
147-
p += size - 1;
148-
} else {
149-
delta = 1;
150-
}
151-
152-
machine_int_t val = 0;
153-
if (is_signed(val_type) && *p & 0x80) {
154-
val = -1;
155-
}
156-
for (uint i = 0; i < size; i++) {
157-
val <<= 8;
158-
val |= *p;
159-
p += delta;
160-
}
167+
machine_int_t val = mp_binary_get_int(size, is_signed(val_type), (struct_type == '>'), p);
161168

162-
*ptr += size;
163169
if (val_type == 'O') {
164170
return (mp_obj_t)val;
165171
} else if (val_type == 'S') {
@@ -185,6 +191,7 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **
185191
struct_type = '>';
186192
#endif
187193
}
194+
*ptr = p + size;
188195

189196
#if MP_ENDIANNESS_BIG
190197
#error Not implemented
@@ -215,7 +222,6 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **
215222
in += in_delta;
216223
}
217224

218-
*ptr += size;
219225
}
220226

221227
void mp_binary_set_val_array(char typecode, void *p, int index, mp_obj_t val_in) {

py/binary.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,4 @@ void mp_binary_set_val_array(char typecode, void *p, int index, mp_obj_t val_in)
3434
void mp_binary_set_val_array_from_int(char typecode, void *p, int index, machine_int_t val);
3535
mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr);
3636
void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **ptr);
37+
machine_int_t mp_binary_get_int(uint size, bool is_signed, bool big_endian, byte *p);

tests/basics/struct1.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,7 @@
2121
print(struct.calcsize("97sI"))
2222
print(struct.unpack("<6sH", b"foo\0\0\0\x12\x34"))
2323
print(struct.pack("<6sH", b"foo", 10000))
24+
25+
s = struct.pack("BHBI", 10, 100, 200, 300)
26+
v = struct.unpack("BHBI", s)
27+
print(v == (10, 100, 200, 300))

0 commit comments

Comments
 (0)