@@ -4409,9 +4409,99 @@ dictviews_or(PyObject* self, PyObject *other)
44094409 return result ;
44104410}
44114411
4412+ static PyObject *
4413+ dictitems_xor (PyObject * self , PyObject * other )
4414+ {
4415+ assert (PyDictItems_Check (self ));
4416+ assert (PyDictItems_Check (other ));
4417+ PyObject * d1 = (PyObject * )((_PyDictViewObject * )self )-> dv_dict ;
4418+ PyObject * d2 = (PyObject * )((_PyDictViewObject * )other )-> dv_dict ;
4419+
4420+ PyObject * temp_dict = PyDict_Copy (d1 );
4421+ if (temp_dict == NULL ) {
4422+ return NULL ;
4423+ }
4424+ PyObject * result_set = PySet_New (NULL );
4425+ if (result_set == NULL ) {
4426+ Py_CLEAR (temp_dict );
4427+ return NULL ;
4428+ }
4429+
4430+ PyObject * key = NULL , * val1 = NULL , * val2 = NULL ;
4431+ Py_ssize_t pos = 0 ;
4432+ Py_hash_t hash ;
4433+
4434+ while (_PyDict_Next (d2 , & pos , & key , & val2 , & hash )) {
4435+ Py_INCREF (key );
4436+ Py_INCREF (val2 );
4437+ val1 = _PyDict_GetItem_KnownHash (temp_dict , key , hash );
4438+
4439+ int to_delete ;
4440+ if (val1 == NULL ) {
4441+ if (PyErr_Occurred ()) {
4442+ goto error ;
4443+ }
4444+ to_delete = 0 ;
4445+ }
4446+ else {
4447+ Py_INCREF (val1 );
4448+ to_delete = PyObject_RichCompareBool (val1 , val2 , Py_EQ );
4449+ if (to_delete < 0 ) {
4450+ goto error ;
4451+ }
4452+ }
4453+
4454+ if (to_delete ) {
4455+ if (_PyDict_DelItem_KnownHash (temp_dict , key , hash ) < 0 ) {
4456+ goto error ;
4457+ }
4458+ }
4459+ else {
4460+ PyObject * pair = PyTuple_Pack (2 , key , val2 );
4461+ if (pair == NULL ) {
4462+ goto error ;
4463+ }
4464+ if (PySet_Add (result_set , pair ) < 0 ) {
4465+ Py_DECREF (pair );
4466+ goto error ;
4467+ }
4468+ Py_DECREF (pair );
4469+ }
4470+ Py_DECREF (key );
4471+ Py_XDECREF (val1 );
4472+ Py_DECREF (val2 );
4473+ }
4474+ key = val1 = val2 = NULL ;
4475+
4476+ _Py_IDENTIFIER (items );
4477+ PyObject * remaining_pairs = _PyObject_CallMethodIdNoArgs (temp_dict ,
4478+ & PyId_items );
4479+ if (remaining_pairs == NULL ) {
4480+ goto error ;
4481+ }
4482+ if (_PySet_Update (result_set , remaining_pairs ) < 0 ) {
4483+ Py_DECREF (remaining_pairs );
4484+ goto error ;
4485+ }
4486+ Py_DECREF (temp_dict );
4487+ Py_DECREF (remaining_pairs );
4488+ return result_set ;
4489+
4490+ error :
4491+ Py_XDECREF (temp_dict );
4492+ Py_XDECREF (result_set );
4493+ Py_XDECREF (key );
4494+ Py_XDECREF (val1 );
4495+ Py_XDECREF (val2 );
4496+ return NULL ;
4497+ }
4498+
44124499static PyObject *
44134500dictviews_xor (PyObject * self , PyObject * other )
44144501{
4502+ if (PyDictItems_Check (self ) && PyDictItems_Check (other )) {
4503+ return dictitems_xor (self , other );
4504+ }
44154505 PyObject * result = dictviews_to_set (self );
44164506 if (result == NULL ) {
44174507 return NULL ;
0 commit comments