3434#include "objtuple.h"
3535#include "objstr.h"
3636#include "binary.h"
37+ #include "parsenum.h"
3738
3839#if MICROPY_ENABLE_MOD_STRUCT
3940
@@ -56,9 +57,26 @@ STATIC char get_fmt_type(const char **fmt) {
5657 return t ;
5758}
5859
60+ STATIC machine_uint_t get_fmt_num (const char * * p ) {
61+ const char * num = * p ;
62+ uint len = 1 ;
63+ while (unichar_isdigit (* ++ num )) {
64+ len ++ ;
65+ }
66+ machine_uint_t val = (machine_uint_t )MP_OBJ_SMALL_INT_VALUE (mp_parse_num_integer (* p , len , 10 ));
67+ * p = num ;
68+ return val ;
69+ }
70+
5971STATIC uint calcsize_items (const char * fmt ) {
60- // TODO
61- return strlen (fmt );
72+ uint cnt = 0 ;
73+ while (* fmt ) {
74+ // TODO supports size spec only for "s"
75+ if (!unichar_isdigit (* fmt ++ )) {
76+ cnt ++ ;
77+ }
78+ }
79+ return cnt ;
6280}
6381
6482STATIC mp_obj_t struct_calcsize (mp_obj_t fmt_in ) {
@@ -67,9 +85,23 @@ STATIC mp_obj_t struct_calcsize(mp_obj_t fmt_in) {
6785 machine_uint_t size ;
6886 for (size = 0 ; * fmt ; fmt ++ ) {
6987 uint align ;
70- int sz = mp_binary_get_size (fmt_type , * fmt , & align );
88+ machine_uint_t cnt = 1 ;
89+ if (unichar_isdigit (* fmt )) {
90+ cnt = get_fmt_num (& fmt );
91+ }
92+ if (cnt > 1 ) {
93+ // TODO: count spec support only for string len
94+ assert (* fmt == 's' );
95+ }
96+
97+ machine_uint_t sz ;
98+ if (* fmt == 's' ) {
99+ sz = cnt ;
100+ } else {
101+ sz = (machine_uint_t )mp_binary_get_size (fmt_type , * fmt , & align );
102+ }
71103 // TODO
72- assert (sz != -1 );
104+ assert (sz != ( machine_uint_t ) - 1 );
73105 // Apply alignment
74106 size = (size + align - 1 ) & ~(align - 1 );
75107 size += sz ;
@@ -89,7 +121,22 @@ STATIC mp_obj_t struct_unpack(mp_obj_t fmt_in, mp_obj_t data_in) {
89121 byte * p = bufinfo .buf ;
90122
91123 for (uint i = 0 ; i < size ; i ++ ) {
92- mp_obj_t item = mp_binary_get_val (fmt_type , * fmt ++ , & p );
124+ machine_uint_t sz = 1 ;
125+ if (unichar_isdigit (* fmt )) {
126+ sz = get_fmt_num (& fmt );
127+ }
128+ if (sz > 1 ) {
129+ // TODO: size spec support only for string len
130+ assert (* fmt == 's' );
131+ }
132+ mp_obj_t item ;
133+ if (* fmt == 's' ) {
134+ item = mp_obj_new_bytes (p , sz );
135+ p += sz ;
136+ fmt ++ ;
137+ } else {
138+ item = mp_binary_get_val (fmt_type , * fmt ++ , & p );
139+ }
93140 res -> items [i ] = item ;
94141 }
95142 return res ;
@@ -106,7 +153,29 @@ STATIC mp_obj_t struct_pack(uint n_args, mp_obj_t *args) {
106153 memset (p , 0 , size );
107154
108155 for (uint i = 1 ; i < n_args ; i ++ ) {
109- mp_binary_set_val (fmt_type , * fmt ++ , args [i ], & p );
156+ machine_uint_t sz = 1 ;
157+ if (unichar_isdigit (* fmt )) {
158+ sz = get_fmt_num (& fmt );
159+ }
160+ if (sz > 1 ) {
161+ // TODO: size spec support only for string len
162+ assert (* fmt == 's' );
163+ }
164+
165+ if (* fmt == 's' ) {
166+ mp_buffer_info_t bufinfo ;
167+ mp_get_buffer_raise (args [i ], & bufinfo , MP_BUFFER_READ );
168+ machine_uint_t to_copy = sz ;
169+ if (bufinfo .len < to_copy ) {
170+ to_copy = bufinfo .len ;
171+ }
172+ memcpy (p , bufinfo .buf , to_copy );
173+ memset (p + to_copy , 0 , sz - to_copy );
174+ p += sz ;
175+ fmt ++ ;
176+ } else {
177+ mp_binary_set_val (fmt_type , * fmt ++ , args [i ], & p );
178+ }
110179 }
111180 return res ;
112181}
0 commit comments