3838
3939typedef struct _mp_obj_namedtuple_type_t {
4040 mp_obj_type_t base ;
41- const char * fields ;
41+ mp_uint_t n_fields ;
42+ mp_obj_t fields [];
4243} mp_obj_namedtuple_type_t ;
4344
4445typedef struct _mp_obj_namedtuple_t {
4546 mp_obj_tuple_t tuple ;
4647} mp_obj_namedtuple_t ;
4748
48- static inline bool is_end_tok (char c ) {
49- return c == ' ' || c == ',' ;
50- }
51-
52- static inline const char * skip_to_next (const char * p ) {
53- while (!is_end_tok (* p )) {
54- if (* p == 0 ) {
55- return NULL ;
56- }
57- p ++ ;
58- }
59- while (is_end_tok (* p )) {
60- if (* p == 0 ) {
61- return NULL ;
62- }
63- p ++ ;
64- }
65- return p ;
66- }
67-
68- STATIC uint namedtuple_count_fields (const char * namedef ) {
69- uint cnt = 0 ;
70- while (* namedef != 0 ) {
71- cnt ++ ;
72- while (!is_end_tok (* namedef ) && * namedef != 0 ) {
73- namedef ++ ;
74- }
75- while (is_end_tok (* namedef ) && * namedef != 0 ) {
76- namedef ++ ;
49+ STATIC mp_uint_t namedtuple_find_field (mp_obj_namedtuple_type_t * type , qstr name ) {
50+ for (mp_uint_t i = 0 ; i < type -> n_fields ; i ++ ) {
51+ if (MP_OBJ_QSTR_VALUE (type -> fields [i ]) == name ) {
52+ return i ;
7753 }
7854 }
79- return cnt ;
80- }
81-
82- STATIC int namedtuple_find_field (const char * name , const char * namedef ) {
83- int id = 0 ;
84- size_t len = strlen (name );
85- while (namedef ) {
86- if (memcmp (name , namedef , len ) == 0 ) {
87- namedef += len ;
88- if (* namedef == 0 || is_end_tok (* namedef )) {
89- return id ;
90- }
91- }
92- namedef = skip_to_next (namedef );
93- id ++ ;
94- }
95-
9655 return -1 ;
9756}
9857
9958STATIC void namedtuple_print (void (* print )(void * env , const char * fmt , ...), void * env , mp_obj_t o_in , mp_print_kind_t kind ) {
10059 mp_obj_namedtuple_t * o = o_in ;
10160 print (env , "%s(" , qstr_str (o -> tuple .base .type -> name ));
102- const char * fields = ((mp_obj_namedtuple_type_t * )o -> tuple .base .type )-> fields ;
103-
61+ const mp_obj_t * fields = ((mp_obj_namedtuple_type_t * )o -> tuple .base .type )-> fields ;
10462 for (mp_uint_t i = 0 ; i < o -> tuple .len ; i ++ ) {
10563 if (i > 0 ) {
10664 print (env , ", " );
10765 }
108- const char * next = fields ;
109-
110- while (!is_end_tok (* next ) && * next != 0 ) {
111- next ++ ;
112- }
113- print (env , "%.*s=" , next - fields , fields );
66+ print (env , "%s=" , qstr_str (MP_OBJ_QSTR_VALUE (fields [i ])));
11467 mp_obj_print_helper (print , env , o -> tuple .items [i ], PRINT_REPR );
115- while (is_end_tok (* next ) && * next != 0 ) {
116- next ++ ;
117- }
118- fields = next ;
11968 }
12069 print (env , ")" );
12170}
12271
12372STATIC void namedtuple_load_attr (mp_obj_t self_in , qstr attr , mp_obj_t * dest ) {
12473 mp_obj_namedtuple_t * self = self_in ;
125- const char * fields = ((mp_obj_namedtuple_type_t * )self -> tuple .base .type )-> fields ;
126- int id = namedtuple_find_field (qstr_str (attr ), fields );
127- if (id < 0 ) {
74+ int id = namedtuple_find_field ((mp_obj_namedtuple_type_t * )self -> tuple .base .type , attr );
75+ if (id == -1 ) {
12876 return ;
12977 }
13078 dest [0 ] = self -> tuple .items [id ];
@@ -136,8 +84,8 @@ STATIC bool namedtuple_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) {
13684
13785STATIC mp_obj_t namedtuple_make_new (mp_obj_t type_in , mp_uint_t n_args , mp_uint_t n_kw , const mp_obj_t * args ) {
13886 mp_obj_namedtuple_type_t * type = type_in ;
139- uint num_fields = namedtuple_count_fields ( type -> fields ) ;
140- if (n_args != num_fields ) {
87+ mp_uint_t num_fields = type -> n_fields ;
88+ if (n_args + n_kw != num_fields ) {
14189 // Counts include implicit "self"
14290 nlr_raise (mp_obj_new_exception_msg_varg (& mp_type_TypeError ,
14391 "__new__() takes %d positional arguments but %d were given" ,
@@ -150,8 +98,8 @@ STATIC mp_obj_t namedtuple_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_
15098
15199STATIC const mp_obj_tuple_t namedtuple_base_tuple = {{& mp_type_tuple }, 1 , {(mp_obj_t )& mp_type_tuple }};
152100
153- STATIC mp_obj_t mp_obj_new_namedtuple_type (qstr name , const char * fields ) {
154- mp_obj_namedtuple_type_t * o = m_new0 (mp_obj_namedtuple_type_t , 1 );
101+ STATIC mp_obj_t mp_obj_new_namedtuple_type (qstr name , mp_uint_t n_fields , mp_obj_t * fields ) {
102+ mp_obj_namedtuple_type_t * o = m_new_obj_var (mp_obj_namedtuple_type_t , mp_obj_t , n_fields );
155103 o -> base .base .type = & mp_type_type ;
156104 o -> base .name = name ;
157105 o -> base .print = namedtuple_print ;
@@ -163,14 +111,17 @@ STATIC mp_obj_t mp_obj_new_namedtuple_type(qstr name, const char *fields) {
163111 o -> base .subscr = mp_obj_tuple_subscr ;
164112 o -> base .getiter = mp_obj_tuple_getiter ;
165113 o -> base .bases_tuple = (mp_obj_t )& namedtuple_base_tuple ;
166- o -> fields = fields ;
114+ o -> n_fields = n_fields ;
115+ memcpy (o -> fields , fields , sizeof (mp_obj_t ) * n_fields );
167116 return o ;
168117}
169118
170119STATIC mp_obj_t new_namedtuple_type (mp_obj_t name_in , mp_obj_t fields_in ) {
171120 qstr name = MP_OBJ_QSTR_VALUE (name_in );
172- const char * fields = mp_obj_str_get_str (fields_in );
173- return mp_obj_new_namedtuple_type (name , fields );
121+ mp_uint_t n_fields ;
122+ mp_obj_t * fields ;
123+ mp_obj_list_get (fields_in , & n_fields , & fields );
124+ return mp_obj_new_namedtuple_type (name , n_fields , fields );
174125}
175126MP_DEFINE_CONST_FUN_OBJ_2 (mp_namedtuple_obj , new_namedtuple_type );
176127
0 commit comments