@@ -37,7 +37,7 @@ Now let's partition this bit representation of the hash into blocks of
3737 0b00_00000_10010_11101_00101_01011_10000 = 19830128
3838 (6) (5) (4) (3) (2) (1)
3939
40- Each block of 5 bits represents a number betwen 0 and 31. So if we have
40+ Each block of 5 bits represents a number between 0 and 31. So if we have
4141a tree that consists of nodes, each of which is an array of 32 pointers,
4242those 5-bit blocks will encode a position on a single tree level.
4343
@@ -885,7 +885,7 @@ map_node_bitmap_assoc(MapNode_Bitmap *self,
885885 pairs.
886886
887887 Small map objects (<30 keys) usually don't have any
888- Array nodes at all. Betwen ~30 and ~400 keys map
888+ Array nodes at all. Between ~30 and ~400 keys map
889889 objects usually have one Array node, and usually it's
890890 a root node.
891891 */
@@ -2460,7 +2460,7 @@ map_without(MapObject *o, PyObject *key)
24602460 return NULL ;
24612461 }
24622462
2463- MapNode * new_root ;
2463+ MapNode * new_root = NULL ;
24642464
24652465 map_without_t res = map_node_without (
24662466 (MapNode * )(o -> h_root ),
@@ -3715,31 +3715,74 @@ map_update(uint64_t mutid, MapObject *o, PyObject *src)
37153715 return new ;
37163716}
37173717
3718+ static int
3719+ mapmut_check_finalized (MapMutationObject * o )
3720+ {
3721+ if (o -> m_mutid == 0 ) {
3722+ PyErr_Format (
3723+ PyExc_ValueError ,
3724+ "mutation %R has been finalized" ,
3725+ o , NULL );
3726+ return -1 ;
3727+ }
37183728
3719- static PyObject *
3720- mapmut_py_set (MapMutationObject * o , PyObject * args )
3729+ return 0 ;
3730+ }
3731+
3732+ static int
3733+ mapmut_delete (MapMutationObject * o , PyObject * key , int32_t key_hash )
37213734{
3722- PyObject * key ;
3723- PyObject * val ;
3735+ MapNode * new_root = NULL ;
37243736
3725- if (!PyArg_UnpackTuple (args , "set" , 2 , 2 , & key , & val )) {
3726- return NULL ;
3727- }
3737+ assert (key_hash != -1 );
3738+ map_without_t res = map_node_without (
3739+ (MapNode * )(o -> m_root ),
3740+ 0 , key_hash , key ,
3741+ & new_root ,
3742+ o -> m_mutid );
37283743
3729- int32_t key_hash ;
3730- int added_leaf = 0 ;
3744+ switch (res ) {
3745+ case W_ERROR :
3746+ return -1 ;
37313747
3732- key_hash = map_hash (key );
3733- if (key_hash == -1 ) {
3734- return NULL ;
3748+ case W_EMPTY :
3749+ new_root = map_node_bitmap_new (0 , o -> m_mutid );
3750+ if (new_root == NULL ) {
3751+ return -1 ;
3752+ }
3753+ Py_SETREF (o -> m_root , new_root );
3754+ o -> m_count = 0 ;
3755+ return 0 ;
3756+
3757+ case W_NOT_FOUND :
3758+ PyErr_SetObject (PyExc_KeyError , key );
3759+ return -1 ;
3760+
3761+ case W_NEWNODE : {
3762+ assert (new_root != NULL );
3763+ Py_SETREF (o -> m_root , new_root );
3764+ o -> m_count -- ;
3765+ return 0 ;
3766+ }
3767+
3768+ default :
3769+ abort ();
37353770 }
3771+ }
3772+
3773+ static int
3774+ mapmut_set (MapMutationObject * o , PyObject * key , int32_t key_hash ,
3775+ PyObject * val )
3776+ {
3777+ int added_leaf = 0 ;
37363778
3779+ assert (key_hash != -1 );
37373780 MapNode * new_root = map_node_assoc (
37383781 (MapNode * )(o -> m_root ),
37393782 0 , key_hash , key , val , & added_leaf ,
37403783 o -> m_mutid );
37413784 if (new_root == NULL ) {
3742- return NULL ;
3785+ return -1 ;
37433786 }
37443787
37453788 if (added_leaf ) {
@@ -3748,62 +3791,39 @@ mapmut_py_set(MapMutationObject *o, PyObject *args)
37483791
37493792 if (new_root == o -> m_root ) {
37503793 Py_DECREF (new_root );
3751- goto done ;
3794+ return 0 ;
37523795 }
37533796
37543797 Py_SETREF (o -> m_root , new_root );
3755-
3756- done :
3757- Py_RETURN_NONE ;
3798+ return 0 ;
37583799}
37593800
3760-
37613801static PyObject *
3762- mapmut_py_delete (MapMutationObject * o , PyObject * key )
3802+ mapmut_py_set (MapMutationObject * o , PyObject * args )
37633803{
3764- int32_t key_hash = map_hash (key );
3765- if (key_hash == -1 ) {
3804+ PyObject * key ;
3805+ PyObject * val ;
3806+
3807+ if (!PyArg_UnpackTuple (args , "set" , 2 , 2 , & key , & val )) {
37663808 return NULL ;
37673809 }
37683810
3769- MapNode * new_root ;
3770-
3771- map_without_t res = map_node_without (
3772- (MapNode * )(o -> m_root ),
3773- 0 , key_hash , key ,
3774- & new_root ,
3775- o -> m_mutid );
3811+ if (mapmut_check_finalized (o )) {
3812+ return NULL ;
3813+ }
37763814
3777- switch (res ) {
3778- case W_ERROR :
3779- return NULL ;
3780- case W_EMPTY :
3781- new_root = map_node_bitmap_new (0 , o -> m_mutid );
3782- if (new_root == NULL ) {
3783- return NULL ;
3784- }
3785- Py_SETREF (o -> m_root , new_root );
3786- o -> m_count = 0 ;
3787- goto done ;
3815+ int32_t key_hash = map_hash (key );
3816+ if (key_hash == -1 ) {
3817+ return NULL ;
3818+ }
37883819
3789- case W_NOT_FOUND :
3790- PyErr_SetObject (PyExc_KeyError , key );
3791- return NULL ;
3792- case W_NEWNODE : {
3793- assert (new_root != NULL );
3794- Py_SETREF (o -> m_root , new_root );
3795- o -> m_count -- ;
3796- goto done ;
3797- }
3798- default :
3799- abort ();
3820+ if (mapmut_set (o , key , key_hash , val )) {
3821+ return NULL ;
38003822 }
38013823
3802- done :
38033824 Py_RETURN_NONE ;
38043825}
38053826
3806-
38073827static PyObject *
38083828mapmut_tp_richcompare (PyObject * v , PyObject * w , int op )
38093829{
@@ -3848,11 +3868,88 @@ mapmut_py_finalize(MapMutationObject *self, PyObject *args)
38483868 return (PyObject * )o ;
38493869}
38503870
3871+ static int
3872+ mapmut_tp_ass_sub (MapMutationObject * self , PyObject * key , PyObject * val )
3873+ {
3874+ if (mapmut_check_finalized (self )) {
3875+ return -1 ;
3876+ }
3877+
3878+ int32_t key_hash = map_hash (key );
3879+ if (key_hash == -1 ) {
3880+ return -1 ;
3881+ }
3882+
3883+ if (val == NULL ) {
3884+ return mapmut_delete (self , key , key_hash );
3885+ }
3886+ else {
3887+ return mapmut_set (self , key , key_hash , val );
3888+ }
3889+ }
3890+
3891+ static PyObject *
3892+ mapmut_py_pop (MapMutationObject * self , PyObject * args )
3893+ {
3894+ PyObject * key , * deflt = NULL , * val = NULL ;
3895+
3896+ if (!PyArg_UnpackTuple (args , "pop" , 1 , 2 , & key , & deflt )) {
3897+ return NULL ;
3898+ }
3899+
3900+ if (mapmut_check_finalized (self )) {
3901+ return NULL ;
3902+ }
3903+
3904+ if (!self -> m_count ) {
3905+ goto not_found ;
3906+ }
3907+
3908+ int32_t key_hash = map_hash (key );
3909+ if (key_hash == -1 ) {
3910+ return NULL ;
3911+ }
3912+
3913+ map_find_t find_res = map_node_find (self -> m_root , 0 , key_hash , key , & val );
3914+
3915+ switch (find_res ) {
3916+ case F_ERROR :
3917+ return NULL ;
3918+
3919+ case F_NOT_FOUND :
3920+ goto not_found ;
3921+
3922+ case F_FOUND :
3923+ break ;
3924+
3925+ default :
3926+ abort ();
3927+ }
3928+
3929+ Py_INCREF (val );
3930+
3931+ if (mapmut_delete (self , key , key_hash )) {
3932+ Py_DECREF (val );
3933+ return NULL ;
3934+ }
3935+
3936+ return val ;
3937+
3938+ not_found :
3939+ if (deflt ) {
3940+ Py_INCREF (deflt );
3941+ return deflt ;
3942+ }
3943+
3944+ PyErr_SetObject (PyExc_KeyError , key );
3945+ return NULL ;
3946+ }
3947+
38513948
38523949static PyMethodDef MapMutation_methods [] = {
38533950 {"set" , (PyCFunction )mapmut_py_set , METH_VARARGS , NULL },
38543951 {"get" , (PyCFunction )map_py_get , METH_VARARGS , NULL },
3855- {"delete " , (PyCFunction )mapmut_py_delete , METH_O , NULL },
3952+ {"pop " , (PyCFunction )mapmut_py_pop , METH_VARARGS , NULL },
38563953 {"finalize" , (PyCFunction )mapmut_py_finalize , METH_NOARGS , NULL },
38573954 {NULL , NULL }
38583955};
@@ -3871,8 +3968,9 @@ static PySequenceMethods MapMutation_as_sequence = {
38713968};
38723969
38733970static PyMappingMethods MapMutation_as_mapping = {
3874- (lenfunc )map_tp_len , /* mp_length */
3875- (binaryfunc )map_tp_subscript , /* mp_subscript */
3971+ (lenfunc )map_tp_len , /* mp_length */
3972+ (binaryfunc )map_tp_subscript , /* mp_subscript */
3973+ (objobjargproc )mapmut_tp_ass_sub , /* mp_subscript */
38763974};
38773975
38783976PyTypeObject _MapMutation_Type = {
0 commit comments