Skip to content

Commit 9336ee3

Browse files
committed
py: Make mp_binary_set_val work on big endian machine.
1 parent fcdb239 commit 9336ee3

File tree

4 files changed

+33
-35
lines changed

4 files changed

+33
-35
lines changed

extmod/moductypes.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ STATIC mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set
401401
set_aligned_basic(val_type & 6, self->addr + offset, val);
402402
} else {
403403
mp_binary_set_int(GET_SCALAR_SIZE(val_type & 7), self->flags == LAYOUT_BIG_ENDIAN,
404-
self->addr + offset, (byte*)&val);
404+
self->addr + offset, val);
405405
}
406406
return set_val; // just !MP_OBJ_NULL
407407
}

py/binary.c

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -140,23 +140,23 @@ mp_obj_t mp_binary_get_val_array(char typecode, void *p, mp_uint_t index) {
140140
// The long long type is guaranteed to hold at least 64 bits, and size is at
141141
// most 8 (for q and Q), so we will always be able to parse the given data
142142
// and fit it into a long long.
143-
long long mp_binary_get_int(mp_uint_t size, bool is_signed, bool big_endian, byte *p) {
143+
long long mp_binary_get_int(mp_uint_t size, bool is_signed, bool big_endian, const byte *src) {
144144
int delta;
145145
if (!big_endian) {
146146
delta = -1;
147-
p += size - 1;
147+
src += size - 1;
148148
} else {
149149
delta = 1;
150150
}
151151

152152
long long val = 0;
153-
if (is_signed && *p & 0x80) {
153+
if (is_signed && *src & 0x80) {
154154
val = -1;
155155
}
156156
for (uint i = 0; i < size; i++) {
157157
val <<= 8;
158-
val |= *p;
159-
p += delta;
158+
val |= *src;
159+
src += delta;
160160
}
161161

162162
return val;
@@ -201,20 +201,22 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) {
201201
}
202202
}
203203

204-
void mp_binary_set_int(mp_uint_t val_sz, bool big_endian, byte *p, byte *val_ptr) {
205-
int in_delta, out_delta;
206-
if (big_endian) {
207-
in_delta = -1;
208-
out_delta = 1;
209-
val_ptr += val_sz - 1;
204+
void mp_binary_set_int(mp_uint_t val_sz, bool big_endian, byte *dest, mp_uint_t val) {
205+
if (MP_ENDIANNESS_LITTLE && !big_endian) {
206+
memcpy(dest, &val, val_sz);
207+
} else if (MP_ENDIANNESS_BIG && big_endian) {
208+
// only copy the least-significant val_sz bytes
209+
memcpy(dest, (byte*)&val + sizeof(mp_uint_t) - val_sz, val_sz);
210210
} else {
211-
in_delta = out_delta = 1;
212-
}
213-
214-
for (uint i = val_sz; i > 0; i--) {
215-
*p = *val_ptr;
216-
p += out_delta;
217-
val_ptr += in_delta;
211+
const byte *src;
212+
if (MP_ENDIANNESS_LITTLE) {
213+
src = (const byte*)&val + val_sz;
214+
} else {
215+
src = (const byte*)&val + sizeof(mp_uint_t);
216+
}
217+
while (val_sz--) {
218+
*dest++ = *--src;
219+
}
218220
}
219221
}
220222

@@ -226,28 +228,24 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **
226228
if (struct_type == '@') {
227229
// Make pointer aligned
228230
p = (byte*)(((mp_uint_t)p + align - 1) & ~((mp_uint_t)align - 1));
229-
#if MP_ENDIANNESS_LITTLE
230-
struct_type = '<';
231-
#else
232-
struct_type = '>';
233-
#endif
231+
if (MP_ENDIANNESS_LITTLE) {
232+
struct_type = '<';
233+
} else {
234+
struct_type = '>';
235+
}
234236
}
235237
*ptr = p + size;
236238

237-
#if MP_ENDIANNESS_BIG
238-
#error Not implemented
239-
#endif
240-
mp_int_t val;
241-
byte *in = (byte*)&val;
239+
mp_uint_t val;
242240
switch (val_type) {
243241
case 'O':
244-
in = (byte*)&val_in;
242+
val = (mp_uint_t)val_in;
245243
break;
246244
default:
247245
val = mp_obj_get_int(val_in);
248246
}
249247

250-
mp_binary_set_int(MIN(size, sizeof(val)), struct_type == '>', p, in);
248+
mp_binary_set_int(MIN(size, sizeof(val)), struct_type == '>', p, val);
251249
}
252250

253251
void mp_binary_set_val_array(char typecode, void *p, mp_uint_t index, mp_obj_t val_in) {

py/binary.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,5 @@ void mp_binary_set_val_array(char typecode, void *p, mp_uint_t index, mp_obj_t v
3434
void mp_binary_set_val_array_from_int(char typecode, void *p, mp_uint_t index, mp_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-
long long mp_binary_get_int(mp_uint_t size, bool is_signed, bool big_endian, byte *p);
38-
void mp_binary_set_int(mp_uint_t val_sz, bool big_endian, byte *p, byte *val_ptr);
37+
long long mp_binary_get_int(mp_uint_t size, bool is_signed, bool big_endian, const byte *src);
38+
void mp_binary_set_int(mp_uint_t val_sz, bool big_endian, byte *dest, mp_uint_t val);

py/modstruct.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ STATIC mp_obj_t struct_unpack(mp_obj_t fmt_in, mp_obj_t data_in) {
160160
}
161161
MP_DEFINE_CONST_FUN_OBJ_2(struct_unpack_obj, struct_unpack);
162162

163-
STATIC mp_obj_t struct_pack(uint n_args, mp_obj_t *args) {
163+
STATIC mp_obj_t struct_pack(mp_uint_t n_args, const mp_obj_t *args) {
164164
// TODO: "The arguments must match the values required by the format exactly."
165165
const char *fmt = mp_obj_str_get_str(args[0]);
166166
char fmt_type = get_fmt_type(&fmt);
@@ -169,7 +169,7 @@ STATIC mp_obj_t struct_pack(uint n_args, mp_obj_t *args) {
169169
mp_obj_t res = mp_obj_str_builder_start(&mp_type_bytes, size, &p);
170170
memset(p, 0, size);
171171

172-
for (uint i = 1; i < n_args; i++) {
172+
for (mp_uint_t i = 1; i < n_args; i++) {
173173
mp_uint_t sz = 1;
174174
if (unichar_isdigit(*fmt)) {
175175
sz = get_fmt_num(&fmt);

0 commit comments

Comments
 (0)