@@ -17,12 +17,12 @@ static int numfree[ApgRecord_MAXSAVESIZE];
1717
1818
1919PyObject *
20- ApgRecord_New (PyObject * mapping , Py_ssize_t size )
20+ ApgRecord_New (PyObject * desc , Py_ssize_t size )
2121{
2222 ApgRecordObject * o ;
2323 Py_ssize_t i ;
2424
25- if (size < 1 || mapping == NULL ) {
25+ if (size < 1 || desc == NULL || ! ApgRecordDesc_CheckExact ( desc ) ) {
2626 PyErr_BadInternalCall ();
2727 return NULL ;
2828 }
@@ -48,8 +48,8 @@ ApgRecord_New(PyObject *mapping, Py_ssize_t size)
4848 o -> ob_item [i ] = NULL ;
4949 }
5050
51- Py_INCREF (mapping );
52- o -> mapping = mapping ;
51+ Py_INCREF (desc );
52+ o -> desc = ( ApgRecordDescObject * ) desc ;
5353 o -> self_hash = -1 ;
5454 PyObject_GC_Track (o );
5555 return (PyObject * ) o ;
@@ -66,7 +66,7 @@ record_dealloc(ApgRecordObject *o)
6666
6767 o -> self_hash = -1 ;
6868
69- Py_CLEAR (o -> mapping );
69+ Py_CLEAR (o -> desc );
7070
7171 Py_TRASHCAN_SAFE_BEGIN (o )
7272 if (len > 0 ) {
@@ -96,7 +96,7 @@ record_traverse(ApgRecordObject *o, visitproc visit, void *arg)
9696{
9797 Py_ssize_t i ;
9898
99- Py_VISIT (o -> mapping );
99+ Py_VISIT (o -> desc );
100100
101101 for (i = Py_SIZE (o ); -- i >= 0 ;) {
102102 if (o -> ob_item [i ] != NULL ) {
@@ -300,7 +300,7 @@ record_subscript(ApgRecordObject* o, PyObject* item)
300300 }
301301 else {
302302 PyObject * mapped ;
303- mapped = PyObject_GetItem (o -> mapping , item );
303+ mapped = PyObject_GetItem (o -> desc -> mapping , item );
304304 if (mapped != NULL ) {
305305 Py_ssize_t i ;
306306 PyObject * result ;
@@ -348,7 +348,7 @@ record_repr(ApgRecordObject *v)
348348 n = Py_SIZE (v );
349349 assert (n > 0 );
350350
351- keys_iter = PyObject_GetIter (v -> mapping );
351+ keys_iter = PyObject_GetIter (v -> desc -> keys );
352352 if (keys_iter == NULL ) {
353353 return NULL ;
354354 }
@@ -453,7 +453,7 @@ record_keys(PyObject *o, PyObject *args)
453453 return NULL ;
454454 }
455455
456- return PyObject_GetIter (((ApgRecordObject * )o )-> mapping );
456+ return PyObject_GetIter (((ApgRecordObject * )o )-> desc -> mapping );
457457}
458458
459459
@@ -477,7 +477,7 @@ record_contains(ApgRecordObject *o, PyObject *arg)
477477 return -1 ;
478478 }
479479
480- return PySequence_Contains (o -> mapping , arg );
480+ return PySequence_Contains (o -> desc -> mapping , arg );
481481}
482482
483483
@@ -828,7 +828,7 @@ record_new_items_iter(PyObject *seq)
828828 return NULL ;
829829 }
830830
831- map_iter = PyObject_GetIter (((ApgRecordObject * )seq )-> mapping );
831+ map_iter = PyObject_GetIter (((ApgRecordObject * )seq )-> desc -> mapping );
832832 if (map_iter == NULL ) {
833833 return NULL ;
834834 }
@@ -853,6 +853,10 @@ int ApgRecord_InitTypes(void)
853853 return -1 ;
854854 }
855855
856+ if (PyType_Ready (& ApgRecordDesc_Type ) < 0 ) {
857+ return -1 ;
858+ }
859+
856860 if (PyType_Ready (& ApgRecordIter_Type ) < 0 ) {
857861 return -1 ;
858862 }
@@ -863,3 +867,85 @@ int ApgRecord_InitTypes(void)
863867
864868 return 0 ;
865869}
870+
871+
872+ /* ----------------- */
873+
874+
875+ static void
876+ record_desc_dealloc (ApgRecordDescObject * o )
877+ {
878+ PyObject_GC_UnTrack (o );
879+ Py_CLEAR (o -> mapping );
880+ Py_CLEAR (o -> keys );
881+ PyObject_GC_Del (o );
882+ }
883+
884+
885+ static int
886+ record_desc_traverse (ApgRecordDescObject * o , visitproc visit , void * arg )
887+ {
888+ Py_VISIT (o -> mapping );
889+ Py_VISIT (o -> keys );
890+ return 0 ;
891+ }
892+
893+
894+ PyTypeObject ApgRecordDesc_Type = {
895+ PyVarObject_HEAD_INIT (NULL , 0 )
896+ "RecordDescriptor" , /* tp_name */
897+ sizeof (ApgRecordDescObject ), /* tp_basicsize */
898+ 0 , /* tp_itemsize */
899+ /* methods */
900+ (destructor )record_desc_dealloc , /* tp_dealloc */
901+ 0 , /* tp_print */
902+ 0 , /* tp_getattr */
903+ 0 , /* tp_setattr */
904+ 0 , /* tp_reserved */
905+ 0 , /* tp_repr */
906+ 0 , /* tp_as_number */
907+ 0 , /* tp_as_sequence */
908+ 0 , /* tp_as_mapping */
909+ 0 , /* tp_hash */
910+ 0 , /* tp_call */
911+ 0 , /* tp_str */
912+ PyObject_GenericGetAttr , /* tp_getattro */
913+ 0 , /* tp_setattro */
914+ 0 , /* tp_as_buffer */
915+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC , /* tp_flags */
916+ 0 , /* tp_doc */
917+ (traverseproc )record_desc_traverse , /* tp_traverse */
918+ 0 , /* tp_clear */
919+ 0 , /* tp_richcompare */
920+ 0 , /* tp_weaklistoffset */
921+ PyObject_SelfIter , /* tp_iter */
922+ 0 , /* tp_iternext */
923+ 0 , /* tp_methods */
924+ 0 ,
925+ };
926+
927+
928+ PyObject *
929+ ApgRecordDesc_New (PyObject * mapping , PyObject * keys )
930+ {
931+ ApgRecordDescObject * o ;
932+
933+ if (!mapping || !keys || !PyTuple_CheckExact (keys )) {
934+ PyErr_BadInternalCall ();
935+ return NULL ;
936+ }
937+
938+ o = PyObject_GC_New (ApgRecordDescObject , & ApgRecordDesc_Type );
939+ if (o == NULL ) {
940+ return NULL ;
941+ }
942+
943+ Py_INCREF (mapping );
944+ o -> mapping = mapping ;
945+
946+ Py_INCREF (keys );
947+ o -> keys = keys ;
948+
949+ PyObject_GC_Track (o );
950+ return (PyObject * ) o ;
951+ }
0 commit comments