Skip to content

Commit 2b080cf

Browse files
committed
py/modstruct: Support repetition counters for all types, not just string.
This makes format specifiers ~ fully compatible with CPython. Adds 24 bytes for stmhal port (because previosuly we had to catch and report it's unsupported to user).
1 parent f705cb5 commit 2b080cf

File tree

1 file changed

+37
-37
lines changed

1 file changed

+37
-37
lines changed

py/modstruct.c

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,15 @@ STATIC mp_uint_t get_fmt_num(const char **p) {
8585
STATIC uint calcsize_items(const char *fmt) {
8686
uint cnt = 0;
8787
while (*fmt) {
88-
// TODO supports size spec only for "s"
89-
if (!unichar_isdigit(*fmt++)) {
90-
cnt++;
88+
int num = 1;
89+
if (unichar_isdigit(*fmt)) {
90+
num = get_fmt_num(&fmt);
91+
if (*fmt == 's') {
92+
num = 1;
93+
}
9194
}
95+
cnt += num;
96+
fmt++;
9297
}
9398
return cnt;
9499
}
@@ -103,24 +108,25 @@ STATIC mp_obj_t struct_calcsize(mp_obj_t fmt_in) {
103108
if (unichar_isdigit(*fmt)) {
104109
cnt = get_fmt_num(&fmt);
105110
}
106-
if (cnt > 1) {
107-
// TODO: count spec support only for string len
108-
if (*fmt != 's') {
109-
mp_not_implemented("count>1");
110-
}
111-
}
112111

113-
mp_uint_t sz;
112+
mp_uint_t sz = 0;
114113
if (*fmt == 's') {
115114
sz = cnt;
116-
} else {
117-
sz = (mp_uint_t)mp_binary_get_size(fmt_type, *fmt, &align);
115+
cnt = 1;
116+
}
117+
118+
while (cnt--) {
119+
// If we already have size for 's' case, don't set it again
120+
if (sz == 0) {
121+
sz = (mp_uint_t)mp_binary_get_size(fmt_type, *fmt, &align);
122+
}
123+
// TODO
124+
assert(sz != (mp_uint_t)-1);
125+
// Apply alignment
126+
size = (size + align - 1) & ~(align - 1);
127+
size += sz;
128+
sz = 0;
118129
}
119-
// TODO
120-
assert(sz != (mp_uint_t)-1);
121-
// Apply alignment
122-
size = (size + align - 1) & ~(align - 1);
123-
size += sz;
124130
}
125131
return MP_OBJ_NEW_SMALL_INT(size);
126132
}
@@ -136,26 +142,24 @@ STATIC mp_obj_t struct_unpack(mp_obj_t fmt_in, mp_obj_t data_in) {
136142
mp_get_buffer_raise(data_in, &bufinfo, MP_BUFFER_READ);
137143
byte *p = bufinfo.buf;
138144

139-
for (uint i = 0; i < size; i++) {
145+
for (uint i = 0; i < size;) {
140146
mp_uint_t sz = 1;
141147
if (unichar_isdigit(*fmt)) {
142148
sz = get_fmt_num(&fmt);
143149
}
144-
if (sz > 1) {
145-
// TODO: size spec support only for string len
146-
if (*fmt != 's') {
147-
mp_not_implemented("count>1");
148-
}
149-
}
150+
150151
mp_obj_t item;
151152
if (*fmt == 's') {
152153
item = mp_obj_new_bytes(p, sz);
153154
p += sz;
154-
fmt++;
155+
res->items[i++] = item;
155156
} else {
156-
item = mp_binary_get_val(fmt_type, *fmt++, &p);
157+
while (sz--) {
158+
item = mp_binary_get_val(fmt_type, *fmt, &p);
159+
res->items[i++] = item;
160+
}
157161
}
158-
res->items[i] = item;
162+
fmt++;
159163
}
160164
return res;
161165
}
@@ -171,32 +175,28 @@ STATIC mp_obj_t struct_pack(mp_uint_t n_args, const mp_obj_t *args) {
171175
byte *p = (byte*)vstr.buf;
172176
memset(p, 0, size);
173177

174-
for (mp_uint_t i = 1; i < n_args; i++) {
178+
for (mp_uint_t i = 1; i < n_args;) {
175179
mp_uint_t sz = 1;
176180
if (unichar_isdigit(*fmt)) {
177181
sz = get_fmt_num(&fmt);
178182
}
179-
if (sz > 1) {
180-
// TODO: size spec support only for string len
181-
if (*fmt != 's') {
182-
mp_not_implemented("count>1");
183-
}
184-
}
185183

186184
if (*fmt == 's') {
187185
mp_buffer_info_t bufinfo;
188-
mp_get_buffer_raise(args[i], &bufinfo, MP_BUFFER_READ);
186+
mp_get_buffer_raise(args[i++], &bufinfo, MP_BUFFER_READ);
189187
mp_uint_t to_copy = sz;
190188
if (bufinfo.len < to_copy) {
191189
to_copy = bufinfo.len;
192190
}
193191
memcpy(p, bufinfo.buf, to_copy);
194192
memset(p + to_copy, 0, sz - to_copy);
195193
p += sz;
196-
fmt++;
197194
} else {
198-
mp_binary_set_val(fmt_type, *fmt++, args[i], &p);
195+
while (sz--) {
196+
mp_binary_set_val(fmt_type, *fmt, args[i++], &p);
197+
}
199198
}
199+
fmt++;
200200
}
201201

202202
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);

0 commit comments

Comments
 (0)