summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--py/binary.c39
-rw-r--r--py/binary.h3
-rw-r--r--py/modstruct.c18
-rw-r--r--py/qstrdefs.h12
-rw-r--r--tests/basics/struct1.py10
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))