summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2014-10-06 15:05:35 +0000
committerDamien George <damien.p.george@gmail.com>2014-10-06 15:05:35 +0000
commit9336ee320a85527942d9ca2ddb95221d90582da0 (patch)
tree6e91cda3d03cc9d0e64da443cacf93293e9d5f40
parentfcdb2398156bb208c2bf54dd184835038f2398f5 (diff)
downloadmicropython-9336ee320a85527942d9ca2ddb95221d90582da0.tar.gz
micropython-9336ee320a85527942d9ca2ddb95221d90582da0.zip
py: Make mp_binary_set_val work on big endian machine.
-rw-r--r--extmod/moductypes.c2
-rw-r--r--py/binary.c58
-rw-r--r--py/binary.h4
-rw-r--r--py/modstruct.c4
4 files changed, 33 insertions, 35 deletions
diff --git a/extmod/moductypes.c b/extmod/moductypes.c
index 3e35ed682a..bc18247656 100644
--- a/extmod/moductypes.c
+++ b/extmod/moductypes.c
@@ -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);
} else {
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
}
diff --git a/py/binary.c b/py/binary.c
index 1201ec34fa..fed69f9d1b 100644
--- a/py/binary.c
+++ b/py/binary.c
@@ -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
// most 8 (for q and Q), so we will always be able to parse the given data
// 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;
if (!big_endian) {
delta = -1;
- p += size - 1;
+ src += size - 1;
} else {
delta = 1;
}
long long val = 0;
- if (is_signed && *p & 0x80) {
+ if (is_signed && *src & 0x80) {
val = -1;
}
for (uint i = 0; i < size; i++) {
val <<= 8;
- val |= *p;
- p += delta;
+ val |= *src;
+ src += delta;
}
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) {
- int in_delta, out_delta;
- if (big_endian) {
- in_delta = -1;
- out_delta = 1;
- val_ptr += val_sz - 1;
+void mp_binary_set_int(mp_uint_t val_sz, bool big_endian, byte *dest, mp_uint_t val) {
+ if (MP_ENDIANNESS_LITTLE && !big_endian) {
+ memcpy(dest, &val, val_sz);
+ } else if (MP_ENDIANNESS_BIG && big_endian) {
+ // only copy the least-significant val_sz bytes
+ memcpy(dest, (byte*)&val + sizeof(mp_uint_t) - val_sz, val_sz);
} else {
- in_delta = out_delta = 1;
- }
-
- for (uint i = val_sz; i > 0; i--) {
- *p = *val_ptr;
- p += out_delta;
- val_ptr += in_delta;
+ const byte *src;
+ if (MP_ENDIANNESS_LITTLE) {
+ src = (const byte*)&val + val_sz;
+ } else {
+ src = (const byte*)&val + sizeof(mp_uint_t);
+ }
+ 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 == '@') {
// Make pointer aligned
p = (byte*)(((mp_uint_t)p + align - 1) & ~((mp_uint_t)align - 1));
- #if MP_ENDIANNESS_LITTLE
- struct_type = '<';
- #else
- struct_type = '>';
- #endif
+ if (MP_ENDIANNESS_LITTLE) {
+ struct_type = '<';
+ } else {
+ struct_type = '>';
+ }
}
*ptr = p + size;
-#if MP_ENDIANNESS_BIG
-#error Not implemented
-#endif
- mp_int_t val;
- byte *in = (byte*)&val;
+ mp_uint_t val;
switch (val_type) {
case 'O':
- in = (byte*)&val_in;
+ val = (mp_uint_t)val_in;
break;
default:
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) {
diff --git a/py/binary.h b/py/binary.h
index 2a63ba9928..dc9d3f6808 100644
--- a/py/binary.h
+++ b/py/binary.h
@@ -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);
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);
-long long mp_binary_get_int(mp_uint_t size, bool is_signed, bool big_endian, byte *p);
-void mp_binary_set_int(mp_uint_t val_sz, bool big_endian, byte *p, byte *val_ptr);
+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 *dest, mp_uint_t val);
diff --git a/py/modstruct.c b/py/modstruct.c
index 8122a96685..8c0cafda07 100644
--- a/py/modstruct.c
+++ b/py/modstruct.c
@@ -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);
-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."
const char *fmt = mp_obj_str_get_str(args[0]);
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);
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;
if (unichar_isdigit(*fmt)) {
sz = get_fmt_num(&fmt);