5151//|
5252//| Supported size/byte order prefixes: *@*, *<*, *>*, *!*.
5353//|
54- //| Supported format codes: *b*, *B*, *h*, *H*, *i*, *I*, *l*, *L*, *q*, *Q*,
54+ //| Supported format codes: *b*, *B*, *x*, * h*, *H*, *i*, *I*, *l*, *L*, *q*, *Q*,
5555//| *s*, *P*, *f*, *d* (the latter 2 depending on the floating-point support).
5656//|
5757
@@ -74,7 +74,6 @@ MP_DEFINE_CONST_FUN_OBJ_1(struct_calcsize_obj, struct_calcsize);
7474//|
7575
7676STATIC mp_obj_t struct_pack (size_t n_args , const mp_obj_t * args ) {
77- // TODO: "The arguments must match the values required by the format exactly."
7877 mp_int_t size = MP_OBJ_SMALL_INT_VALUE (struct_calcsize (args [0 ]));
7978 vstr_t vstr ;
8079 vstr_init_len (& vstr , size );
@@ -115,49 +114,67 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(struct_pack_into_obj, 3, MP_OBJ_FUN_ARGS_MAX
115114//| .. function:: unpack(fmt, data)
116115//|
117116//| Unpack from the data according to the format string fmt. The return value
118- //| is a tuple of the unpacked values.
117+ //| is a tuple of the unpacked values. The buffer size must match the size
118+ //| required by the format.
119119//|
120120
121- //| .. function:: unpack_from(fmt, data, offset)
121+ STATIC mp_obj_t struct_unpack (size_t n_args , const mp_obj_t * args ) {
122+ mp_buffer_info_t bufinfo ;
123+ mp_get_buffer_raise (args [1 ], & bufinfo , MP_BUFFER_READ );
124+ byte * p = bufinfo .buf ;
125+ byte * end_p = & p [bufinfo .len ];
126+
127+ // true means check the size must be exactly right.
128+ return MP_OBJ_FROM_PTR (shared_modules_struct_unpack_from (args [0 ] , p , end_p , true));
129+ }
130+ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (struct_unpack_obj , 2 , 3 , struct_unpack );
131+
132+ //| .. function:: unpack_from(fmt, data, offset=0)
122133//|
123134//| Unpack from the data starting at offset according to the format string fmt.
124135//| offset may be negative to count from the end of buffer. The return value is
125- //| a tuple of the unpacked values.
136+ //| a tuple of the unpacked values. The buffer size must be at least as big
137+ //| as the size required by the form.
126138//|
127139
128- STATIC mp_obj_t struct_unpack_from (size_t n_args , const mp_obj_t * args ) {
129- // unpack requires that the buffer be exactly the right size.
130- // unpack_from requires that the buffer be "big enough".
131- // Since we implement unpack and unpack_from using the same function
132- // we relax the "exact" requirement, and only implement "big enough".
140+ STATIC mp_obj_t struct_unpack_from (size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
141+ enum { ARG_format , ARG_buffer , ARG_offset };
142+ static const mp_arg_t allowed_args [] = {
143+ { MP_QSTR_format , MP_ARG_REQUIRED | MP_ARG_OBJ },
144+ { MP_QSTR_buffer , MP_ARG_REQUIRED | MP_ARG_OBJ },
145+ { MP_QSTR_offset , MP_ARG_INT , {.u_int = 0 } },
146+ };
147+
148+ mp_arg_val_t args [MP_ARRAY_SIZE (allowed_args )];
149+ mp_arg_parse_all (n_args , pos_args , kw_args , MP_ARRAY_SIZE (allowed_args ), allowed_args , args );
150+
133151 mp_buffer_info_t bufinfo ;
134- mp_get_buffer_raise (args [1 ] , & bufinfo , MP_BUFFER_READ );
152+ mp_get_buffer_raise (args [ARG_buffer ]. u_obj , & bufinfo , MP_BUFFER_READ );
135153 byte * p = bufinfo .buf ;
136154 byte * end_p = & p [bufinfo .len ];
137155
138- if (n_args > 2 ) {
139- mp_int_t offset = mp_obj_get_int (args [2 ]);
140- // offset arg provided
156+ mp_int_t offset = args [ARG_offset ].u_int ;
157+ if (offset < 0 ) {
158+ // negative offsets are relative to the end of the buffer
159+ offset = bufinfo .len + offset ;
141160 if (offset < 0 ) {
142- // negative offsets are relative to the end of the buffer
143- offset = bufinfo .len + offset ;
144- if (offset < 0 ) {
145- mp_raise_RuntimeError (translate ("buffer too small" ));
146- }
161+ mp_raise_RuntimeError (translate ("buffer too small" ));
147162 }
148- p += offset ;
149163 }
164+ p += offset ;
150165
151- return MP_OBJ_FROM_PTR (shared_modules_struct_unpack_from (args [0 ] , p , end_p ));
166+ // false means the size doesn't have to be exact. struct.unpack_from() only requires
167+ // that be buffer be big enough.
168+ return MP_OBJ_FROM_PTR (shared_modules_struct_unpack_from (args [ARG_format ].u_obj , p , end_p , false));
152169}
153- MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (struct_unpack_from_obj , 2 , 3 , struct_unpack_from );
170+ MP_DEFINE_CONST_FUN_OBJ_KW (struct_unpack_from_obj , 0 , struct_unpack_from );
154171
155172STATIC const mp_rom_map_elem_t mp_module_struct_globals_table [] = {
156173 { MP_ROM_QSTR (MP_QSTR___name__ ), MP_ROM_QSTR (MP_QSTR_struct ) },
157174 { MP_ROM_QSTR (MP_QSTR_calcsize ), MP_ROM_PTR (& struct_calcsize_obj ) },
158175 { MP_ROM_QSTR (MP_QSTR_pack ), MP_ROM_PTR (& struct_pack_obj ) },
159176 { MP_ROM_QSTR (MP_QSTR_pack_into ), MP_ROM_PTR (& struct_pack_into_obj ) },
160- { MP_ROM_QSTR (MP_QSTR_unpack ), MP_ROM_PTR (& struct_unpack_from_obj ) },
177+ { MP_ROM_QSTR (MP_QSTR_unpack ), MP_ROM_PTR (& struct_unpack_obj ) },
161178 { MP_ROM_QSTR (MP_QSTR_unpack_from ), MP_ROM_PTR (& struct_unpack_from_obj ) },
162179};
163180
0 commit comments