Skip to content

Commit 6204460

Browse files
committed
modstruct: Initial implementation of struct.pack().
1 parent 504e233 commit 6204460

5 files changed

Lines changed: 75 additions & 7 deletions

File tree

py/binary.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,45 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) {
138138
}
139139
}
140140

141+
void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **ptr) {
142+
byte *p = *ptr;
143+
uint align;
144+
145+
int size = mp_binary_get_size(struct_type, val_type, &align);
146+
if (struct_type == '@') {
147+
// Make pointer aligned
148+
p = (byte*)(((machine_uint_t)p + align - 1) & ~(align - 1));
149+
#if MP_ENDIANNESS_LITTLE
150+
struct_type = '<';
151+
#else
152+
struct_type = '>';
153+
#endif
154+
}
155+
156+
#if MP_ENDIANNESS_BIG
157+
#error Not implemented
158+
#endif
159+
machine_int_t val = mp_obj_int_get_checked(val_in);
160+
byte *in = (byte*)&val;
161+
int in_delta, out_delta;
162+
uint val_sz = MIN(size, sizeof(val));
163+
if (struct_type == '>') {
164+
in_delta = -1;
165+
out_delta = 1;
166+
in += val_sz - 1;
167+
} else {
168+
in_delta = out_delta = 1;
169+
}
170+
171+
for (uint i = val_sz; i > 0; i--) {
172+
*p = *in;
173+
p += out_delta;
174+
in += in_delta;
175+
}
176+
177+
*ptr += size;
178+
}
179+
141180
void mp_binary_set_val_array(char typecode, void *p, int index, mp_obj_t val_in) {
142181
switch (typecode) {
143182
#if MICROPY_ENABLE_FLOAT

py/binary.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
int mp_binary_get_size(char struct_type, char val_type, uint *palign);
66
mp_obj_t mp_binary_get_val_array(char typecode, void *p, int index);
7-
mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr);
87
void mp_binary_set_val_array(char typecode, void *p, int index, mp_obj_t val_in);
98
void mp_binary_set_val_array_from_int(char typecode, void *p, int index, machine_int_t val);
9+
mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr);
10+
void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **ptr);

py/modstruct.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "obj.h"
77
#include "builtin.h"
88
#include "objtuple.h"
9+
#include "objstr.h"
910
#include "binary.h"
1011

1112
#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) {
6970
}
7071
MP_DEFINE_CONST_FUN_OBJ_2(struct_unpack_obj, struct_unpack);
7172

73+
STATIC mp_obj_t struct_pack(uint n_args, mp_obj_t *args) {
74+
// TODO: "The arguments must match the values required by the format exactly."
75+
const char *fmt = mp_obj_str_get_str(args[0]);
76+
char fmt_type = get_fmt_type(&fmt);
77+
int size = MP_OBJ_SMALL_INT_VALUE(struct_calcsize(args[0]));
78+
byte *p;
79+
mp_obj_t res = mp_obj_str_builder_start(&mp_type_bytes, size, &p);
80+
memset(p, 0, size);
81+
82+
for (uint i = 1; i < n_args; i++) {
83+
mp_binary_set_val(fmt_type, *fmt++, args[i], &p);
84+
}
85+
return res;
86+
}
87+
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(struct_pack_obj, 1, -1, struct_pack);
88+
7289
STATIC const mp_map_elem_t mp_module_struct_globals_table[] = {
7390
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_struct) },
7491
{ MP_OBJ_NEW_QSTR(MP_QSTR_calcsize), (mp_obj_t)&struct_calcsize_obj },
92+
{ MP_OBJ_NEW_QSTR(MP_QSTR_pack), (mp_obj_t)&struct_pack_obj },
7593
{ MP_OBJ_NEW_QSTR(MP_QSTR_unpack), (mp_obj_t)&struct_unpack_obj },
7694
};
7795

py/qstrdefs.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -139,16 +139,10 @@ Q(staticmethod)
139139
Q(sum)
140140
Q(super)
141141
Q(str)
142-
#if MICROPY_ENABLE_MOD_STRUCT
143-
Q(struct)
144-
#endif
145142
Q(sys)
146143
Q(to_bytes)
147144
Q(tuple)
148145
Q(type)
149-
#if MICROPY_ENABLE_MOD_STRUCT
150-
Q(unpack)
151-
#endif
152146
Q(value)
153147
Q(zip)
154148

@@ -299,6 +293,12 @@ Q(version)
299293
Q(version_info)
300294
#endif
301295

296+
#if MICROPY_ENABLE_MOD_STRUCT
297+
Q(struct)
298+
Q(pack)
299+
Q(unpack)
300+
#endif
301+
302302
#if MICROPY_ENABLE_PROPERTY
303303
Q(property)
304304
Q(getter)

tests/basics/struct1.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,13 @@
66

77
# 32-bit little-endian specific
88
#print(struct.unpack("bI", b"\x80\xaa\x55\xaa\0\0\x01\0"))
9+
10+
print(struct.pack("<i", 1))
11+
print(struct.pack(">i", 1))
12+
print(struct.pack("<h", 1))
13+
print(struct.pack(">h", 1))
14+
print(struct.pack("<b", 1))
15+
print(struct.pack(">b", 1))
16+
17+
print(struct.pack("<bI", -128, 256))
18+
print(struct.pack(">bI", -128, 256))

0 commit comments

Comments
 (0)