@@ -137,7 +137,8 @@ enum opcode {
137137 /* Protocol 5 */
138138 BYTEARRAY8 = '\x96' ,
139139 NEXT_BUFFER = '\x97' ,
140- READONLY_BUFFER = '\x98'
140+ READONLY_BUFFER = '\x98' ,
141+ FROZENDICT = '\x99' ,
141142};
142143
143144enum {
@@ -596,6 +597,34 @@ Pdata_poplist(Pdata *self, Py_ssize_t start)
596597 return list ;
597598}
598599
600+ static PyObject *
601+ Pdata_poplist2 (PickleState * state , Pdata * self , Py_ssize_t start )
602+ {
603+ if (start < self -> fence ) {
604+ Pdata_stack_underflow (state , self );
605+ return NULL ;
606+ }
607+
608+ Py_ssize_t len = (Py_SIZE (self ) - start ) >> 1 ;
609+
610+ PyObject * list = PyList_New (len );
611+ if (list == NULL ) {
612+ return NULL ;
613+ }
614+
615+ for (Py_ssize_t i = start , j = 0 ; j < len ; i += 2 , j ++ ) {
616+ PyObject * subtuple = PyTuple_Pack (2 , self -> data [i ], self -> data [i + 1 ]);
617+ if (subtuple == NULL ) {
618+ Py_DECREF (list );
619+ return NULL ;
620+ }
621+ PyList_SET_ITEM (list , j , subtuple );
622+ }
623+
624+ Py_SET_SIZE (self , start );
625+ return list ;
626+ }
627+
599628typedef struct {
600629 PyObject * me_key ;
601630 Py_ssize_t me_value ;
@@ -3594,6 +3623,63 @@ save_dict(PickleState *state, PicklerObject *self, PyObject *obj)
35943623 return status ;
35953624}
35963625
3626+ static int
3627+ save_frozendict (PickleState * state , PicklerObject * self , PyObject * obj )
3628+ {
3629+ if (self -> fast && !fast_save_enter (self , obj )) {
3630+ return -1 ;
3631+ }
3632+
3633+ if (self -> proto < 4 ) {
3634+ PyObject * items = PyDict_Items (obj );
3635+ if (items == NULL ) {
3636+ return -1 ;
3637+ }
3638+
3639+ PyObject * reduce_value ;
3640+ reduce_value = Py_BuildValue ("(O(O))" , (PyObject * )& PyFrozenDict_Type ,
3641+ items );
3642+ Py_DECREF (items );
3643+ if (reduce_value == NULL ) {
3644+ return -1 ;
3645+ }
3646+
3647+ /* save_reduce() will memoize the object automatically */
3648+ int status = save_reduce (state , self , reduce_value , obj );
3649+ Py_DECREF (reduce_value );
3650+ return status ;
3651+ }
3652+
3653+ const char mark_op = MARK ;
3654+ if (_Pickler_Write (self , & mark_op , 1 ) < 0 ) {
3655+ return -1 ;
3656+ }
3657+
3658+ PyObject * key = NULL , * value = NULL ;
3659+ Py_ssize_t pos = 0 ;
3660+ while (PyDict_Next (obj , & pos , & key , & value )) {
3661+ int res = save (state , self , key , 0 );
3662+ if (res < 0 ) {
3663+ return -1 ;
3664+ }
3665+
3666+ res = save (state , self , value , 0 );
3667+ if (res < 0 ) {
3668+ return -1 ;
3669+ }
3670+ }
3671+
3672+ const char frozendict_op = FROZENDICT ;
3673+ if (_Pickler_Write (self , & frozendict_op , 1 ) < 0 ) {
3674+ return -1 ;
3675+ }
3676+
3677+ if (memo_put (state , self , obj ) < 0 ) {
3678+ return -1 ;
3679+ }
3680+ return 0 ;
3681+ }
3682+
35973683static int
35983684save_set (PickleState * state , PicklerObject * self , PyObject * obj )
35993685{
@@ -4569,6 +4655,10 @@ save(PickleState *st, PicklerObject *self, PyObject *obj, int pers_save)
45694655 status = save_dict (st , self , obj );
45704656 goto done ;
45714657 }
4658+ else if (type == & PyFrozenDict_Type ) {
4659+ status = save_frozendict (st , self , obj );
4660+ goto done ;
4661+ }
45724662 else if (type == & PySet_Type ) {
45734663 status = save_set (st , self , obj );
45744664 goto done ;
@@ -6030,6 +6120,30 @@ load_dict(PickleState *st, UnpicklerObject *self)
60306120 return 0 ;
60316121}
60326122
6123+
6124+ static int
6125+ load_frozendict (PickleState * st , UnpicklerObject * self )
6126+ {
6127+ Py_ssize_t i = marker (st , self );
6128+ if (i < 0 ) {
6129+ return -1 ;
6130+ }
6131+
6132+ PyObject * items = Pdata_poplist2 (st , self -> stack , i );
6133+ if (items == NULL ) {
6134+ return -1 ;
6135+ }
6136+
6137+ PyObject * frozendict = PyFrozenDict_New (items );
6138+ Py_DECREF (items );
6139+ if (frozendict == NULL ) {
6140+ return -1 ;
6141+ }
6142+
6143+ PDATA_PUSH (self -> stack , frozendict , -1 );
6144+ return 0 ;
6145+ }
6146+
60336147static int
60346148load_frozenset (PickleState * state , UnpicklerObject * self )
60356149{
@@ -7130,6 +7244,7 @@ load(PickleState *st, UnpicklerObject *self)
71307244 OP (LIST , load_list )
71317245 OP (EMPTY_DICT , load_empty_dict )
71327246 OP (DICT , load_dict )
7247+ OP (FROZENDICT , load_frozendict )
71337248 OP (EMPTY_SET , load_empty_set )
71347249 OP (ADDITEMS , load_additems )
71357250 OP (FROZENSET , load_frozenset )
0 commit comments