diff options
-rw-r--r-- | py/binary.c | 39 | ||||
-rw-r--r-- | py/binary.h | 3 | ||||
-rw-r--r-- | py/modstruct.c | 18 | ||||
-rw-r--r-- | py/qstrdefs.h | 12 | ||||
-rw-r--r-- | tests/basics/struct1.py | 10 |
5 files changed, 75 insertions, 7 deletions
diff --git a/py/binary.c b/py/binary.c index 702a9cceb3..ee95d56e44 100644 --- a/py/binary.c +++ b/py/binary.c @@ -138,6 +138,45 @@ 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) { + byte *p = *ptr; + uint align; + + int size = mp_binary_get_size(struct_type, val_type, &align); + if (struct_type == '@') { + // Make pointer aligned + p = (byte*)(((machine_uint_t)p + align - 1) & ~(align - 1)); + #if MP_ENDIANNESS_LITTLE + struct_type = '<'; + #else + struct_type = '>'; + #endif + } + +#if MP_ENDIANNESS_BIG +#error Not implemented +#endif + machine_int_t val = mp_obj_int_get_checked(val_in); + byte *in = (byte*)&val; + int in_delta, out_delta; + uint val_sz = MIN(size, sizeof(val)); + if (struct_type == '>') { + in_delta = -1; + out_delta = 1; + in += val_sz - 1; + } else { + in_delta = out_delta = 1; + } + + for (uint i = val_sz; i > 0; i--) { + *p = *in; + p += out_delta; + in += in_delta; + } + + *ptr += size; +} + void mp_binary_set_val_array(char typecode, void *p, int index, mp_obj_t val_in) { switch (typecode) { #if MICROPY_ENABLE_FLOAT diff --git a/py/binary.h b/py/binary.h index 54ff2dc56b..46fb5b36b9 100644 --- a/py/binary.h +++ b/py/binary.h @@ -4,6 +4,7 @@ int mp_binary_get_size(char struct_type, char val_type, uint *palign); mp_obj_t mp_binary_get_val_array(char typecode, void *p, int index); -mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr); void mp_binary_set_val_array(char typecode, void *p, int index, mp_obj_t val_in); void mp_binary_set_val_array_from_int(char typecode, void *p, int index, machine_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); diff --git a/py/modstruct.c b/py/modstruct.c index 0be194feec..81afd94d16 100644 --- a/py/modstruct.c +++ b/py/modstruct.c @@ -6,6 +6,7 @@ #include "obj.h" #include "builtin.h" #include "objtuple.h" +#include "objstr.h" #include "binary.h" #if MICROPY_ENABLE_MOD_STRUCT @@ -69,9 +70,26 @@ 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) { + // 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); + int size = MP_OBJ_SMALL_INT_VALUE(struct_calcsize(args[0])); + byte *p; + 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++) { + mp_binary_set_val(fmt_type, *fmt++, args[i], &p); + } + return res; +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(struct_pack_obj, 1, -1, struct_pack); + STATIC const mp_map_elem_t mp_module_struct_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_struct) }, { MP_OBJ_NEW_QSTR(MP_QSTR_calcsize), (mp_obj_t)&struct_calcsize_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_pack), (mp_obj_t)&struct_pack_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_unpack), (mp_obj_t)&struct_unpack_obj }, }; diff --git a/py/qstrdefs.h b/py/qstrdefs.h index a4df86fda7..86a5f2632c 100644 --- a/py/qstrdefs.h +++ b/py/qstrdefs.h @@ -139,16 +139,10 @@ Q(staticmethod) Q(sum) Q(super) Q(str) -#if MICROPY_ENABLE_MOD_STRUCT -Q(struct) -#endif Q(sys) Q(to_bytes) Q(tuple) Q(type) -#if MICROPY_ENABLE_MOD_STRUCT -Q(unpack) -#endif Q(value) Q(zip) @@ -299,6 +293,12 @@ Q(version) Q(version_info) #endif +#if MICROPY_ENABLE_MOD_STRUCT +Q(struct) +Q(pack) +Q(unpack) +#endif + #if MICROPY_ENABLE_PROPERTY Q(property) Q(getter) diff --git a/tests/basics/struct1.py b/tests/basics/struct1.py index a32979bff9..3a05c85f0b 100644 --- a/tests/basics/struct1.py +++ b/tests/basics/struct1.py @@ -6,3 +6,13 @@ print(struct.unpack(">bI", b"\x80\0\0\x01\0")) # 32-bit little-endian specific #print(struct.unpack("bI", b"\x80\xaa\x55\xaa\0\0\x01\0")) + +print(struct.pack("<i", 1)) +print(struct.pack(">i", 1)) +print(struct.pack("<h", 1)) +print(struct.pack(">h", 1)) +print(struct.pack("<b", 1)) +print(struct.pack(">b", 1)) + +print(struct.pack("<bI", -128, 256)) +print(struct.pack(">bI", -128, 256)) |