py: Make mp_binary_set_val work on big endian machine.

This commit is contained in:
Damien George 2014-10-06 15:05:35 +00:00
parent fcdb239815
commit 9336ee320a
4 changed files with 33 additions and 35 deletions

View File

@ -401,7 +401,7 @@ STATIC mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set
set_aligned_basic(val_type & 6, self->addr + offset, val); set_aligned_basic(val_type & 6, self->addr + offset, val);
} else { } else {
mp_binary_set_int(GET_SCALAR_SIZE(val_type & 7), self->flags == LAYOUT_BIG_ENDIAN, mp_binary_set_int(GET_SCALAR_SIZE(val_type & 7), self->flags == LAYOUT_BIG_ENDIAN,
self->addr + offset, (byte*)&val); self->addr + offset, val);
} }
return set_val; // just !MP_OBJ_NULL return set_val; // just !MP_OBJ_NULL
} }

View File

@ -140,23 +140,23 @@ mp_obj_t mp_binary_get_val_array(char typecode, void *p, mp_uint_t index) {
// The long long type is guaranteed to hold at least 64 bits, and size is at // The long long type is guaranteed to hold at least 64 bits, and size is at
// most 8 (for q and Q), so we will always be able to parse the given data // most 8 (for q and Q), so we will always be able to parse the given data
// and fit it into a long long. // and fit it into a long long.
long long mp_binary_get_int(mp_uint_t size, bool is_signed, bool big_endian, byte *p) { long long mp_binary_get_int(mp_uint_t size, bool is_signed, bool big_endian, const byte *src) {
int delta; int delta;
if (!big_endian) { if (!big_endian) {
delta = -1; delta = -1;
p += size - 1; src += size - 1;
} else { } else {
delta = 1; delta = 1;
} }
long long val = 0; long long val = 0;
if (is_signed && *p & 0x80) { if (is_signed && *src & 0x80) {
val = -1; val = -1;
} }
for (uint i = 0; i < size; i++) { for (uint i = 0; i < size; i++) {
val <<= 8; val <<= 8;
val |= *p; val |= *src;
p += delta; src += delta;
} }
return val; return val;
@ -201,20 +201,22 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) {
} }
} }
void mp_binary_set_int(mp_uint_t val_sz, bool big_endian, byte *p, byte *val_ptr) { void mp_binary_set_int(mp_uint_t val_sz, bool big_endian, byte *dest, mp_uint_t val) {
int in_delta, out_delta; if (MP_ENDIANNESS_LITTLE && !big_endian) {
if (big_endian) { memcpy(dest, &val, val_sz);
in_delta = -1; } else if (MP_ENDIANNESS_BIG && big_endian) {
out_delta = 1; // only copy the least-significant val_sz bytes
val_ptr += val_sz - 1; memcpy(dest, (byte*)&val + sizeof(mp_uint_t) - val_sz, val_sz);
} else { } else {
in_delta = out_delta = 1; const byte *src;
} if (MP_ENDIANNESS_LITTLE) {
src = (const byte*)&val + val_sz;
for (uint i = val_sz; i > 0; i--) { } else {
*p = *val_ptr; src = (const byte*)&val + sizeof(mp_uint_t);
p += out_delta; }
val_ptr += in_delta; while (val_sz--) {
*dest++ = *--src;
}
} }
} }
@ -226,28 +228,24 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **
if (struct_type == '@') { if (struct_type == '@') {
// Make pointer aligned // Make pointer aligned
p = (byte*)(((mp_uint_t)p + align - 1) & ~((mp_uint_t)align - 1)); p = (byte*)(((mp_uint_t)p + align - 1) & ~((mp_uint_t)align - 1));
#if MP_ENDIANNESS_LITTLE if (MP_ENDIANNESS_LITTLE) {
struct_type = '<'; struct_type = '<';
#else } else {
struct_type = '>'; struct_type = '>';
#endif }
} }
*ptr = p + size; *ptr = p + size;
#if MP_ENDIANNESS_BIG mp_uint_t val;
#error Not implemented
#endif
mp_int_t val;
byte *in = (byte*)&val;
switch (val_type) { switch (val_type) {
case 'O': case 'O':
in = (byte*)&val_in; val = (mp_uint_t)val_in;
break; break;
default: default:
val = mp_obj_get_int(val_in); val = mp_obj_get_int(val_in);
} }
mp_binary_set_int(MIN(size, sizeof(val)), struct_type == '>', p, in); mp_binary_set_int(MIN(size, sizeof(val)), struct_type == '>', p, val);
} }
void mp_binary_set_val_array(char typecode, void *p, mp_uint_t index, mp_obj_t val_in) { void mp_binary_set_val_array(char typecode, void *p, mp_uint_t index, mp_obj_t val_in) {

View File

@ -34,5 +34,5 @@ void mp_binary_set_val_array(char typecode, void *p, mp_uint_t index, mp_obj_t v
void mp_binary_set_val_array_from_int(char typecode, void *p, mp_uint_t index, mp_int_t val); void mp_binary_set_val_array_from_int(char typecode, void *p, mp_uint_t index, mp_int_t val);
mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr); mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr);
void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **ptr); void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **ptr);
long long mp_binary_get_int(mp_uint_t size, bool is_signed, bool big_endian, byte *p); long long mp_binary_get_int(mp_uint_t size, bool is_signed, bool big_endian, const byte *src);
void mp_binary_set_int(mp_uint_t val_sz, bool big_endian, byte *p, byte *val_ptr); void mp_binary_set_int(mp_uint_t val_sz, bool big_endian, byte *dest, mp_uint_t val);

View File

@ -160,7 +160,7 @@ STATIC mp_obj_t struct_unpack(mp_obj_t fmt_in, mp_obj_t data_in) {
} }
MP_DEFINE_CONST_FUN_OBJ_2(struct_unpack_obj, struct_unpack); MP_DEFINE_CONST_FUN_OBJ_2(struct_unpack_obj, struct_unpack);
STATIC mp_obj_t struct_pack(uint n_args, mp_obj_t *args) { STATIC mp_obj_t struct_pack(mp_uint_t n_args, const mp_obj_t *args) {
// TODO: "The arguments must match the values required by the format exactly." // TODO: "The arguments must match the values required by the format exactly."
const char *fmt = mp_obj_str_get_str(args[0]); const char *fmt = mp_obj_str_get_str(args[0]);
char fmt_type = get_fmt_type(&fmt); char fmt_type = get_fmt_type(&fmt);
@ -169,7 +169,7 @@ STATIC mp_obj_t struct_pack(uint n_args, mp_obj_t *args) {
mp_obj_t res = mp_obj_str_builder_start(&mp_type_bytes, size, &p); mp_obj_t res = mp_obj_str_builder_start(&mp_type_bytes, size, &p);
memset(p, 0, size); memset(p, 0, size);
for (uint i = 1; i < n_args; i++) { for (mp_uint_t i = 1; i < n_args; i++) {
mp_uint_t sz = 1; mp_uint_t sz = 1;
if (unichar_isdigit(*fmt)) { if (unichar_isdigit(*fmt)) {
sz = get_fmt_num(&fmt); sz = get_fmt_num(&fmt);