| #ifndef _Py_PYCORE_SLOTS_H | |
| #define _Py_PYCORE_SLOTS_H | |
| #ifndef Py_BUILD_CORE | |
| # error "this header requires Py_BUILD_CORE define" | |
| #endif | |
| #include <stdbool.h> | |
| /* Slot data type */ | |
| typedef enum _PySlot_DTYPE { | |
| _PySlot_DTYPE_VOID, | |
| _PySlot_DTYPE_FUNC, | |
| _PySlot_DTYPE_PTR, | |
| _PySlot_DTYPE_SIZE, | |
| _PySlot_DTYPE_INT64, | |
| _PySlot_DTYPE_UINT64, | |
| }_PySlot_DTYPE; | |
| /* Slot kind, used to identify: | |
| * - the thing the slot initializes (type/module/special) | |
| * - the struct type (PySlot/PyType_Slot/PyModuleDef_Slot) | |
| */ | |
| typedef enum _PySlot_KIND { | |
| _PySlot_KIND_TYPE, | |
| _PySlot_KIND_MOD, | |
| _PySlot_KIND_COMPAT, | |
| _PySlot_KIND_SLOT, | |
| } _PySlot_KIND; | |
| typedef enum _PySlot_PROBLEM_HANDLING { | |
| _PySlot_PROBLEM_ALLOW, | |
| _PySlot_PROBLEM_DEPRECATED, | |
| _PySlot_PROBLEM_REJECT, | |
| } _PySlot_PROBLEM_HANDLING; | |
| PyAPI_DATA(const char *const) _PySlot_names[]; | |
| #define _PySlot_MAX_NESTING 5 | |
| /* State for one nesting level of a slots iterator */ | |
| typedef struct _PySlotIterator_state { | |
| union { | |
| // tagged by slot_struct_kind: | |
| const PySlot *slot; // with _PySlot_KIND_SLOT | |
| const PyType_Slot *tp_slot; // with _PySlot_KIND_TYPE | |
| const PyModuleDef_Slot *mod_slot; // with _PySlot_KIND_MOD | |
| const void *any_slot; | |
| }; | |
| _PySlot_KIND slot_struct_kind; | |
| } _PySlotIterator_state; | |
| #define _PySlot_SEEN_ENTRY_BITS (8 * sizeof(unsigned int)) | |
| /* State for a slots iterator */ | |
| typedef struct { | |
| _PySlotIterator_state *state; | |
| _PySlotIterator_state states[_PySlot_MAX_NESTING]; | |
| unsigned int seen[_Py_slot_COUNT / _PySlot_SEEN_ENTRY_BITS + 1]; | |
| _PySlot_KIND kind; | |
| uint8_t recursion_level; | |
| bool is_at_end :1; | |
| bool is_first_run :1; | |
| // Name of the object (type/module) being defined, NULL if unknown. | |
| // Must be set by the callers as soon as it's known. | |
| const char *name; | |
| /* Output information: */ | |
| // The slot. Always a copy; may be modified by caller of the iterator. | |
| PySlot current; | |
| } _PySlotIterator; | |
| /* Initialize an iterator using a PySlot array */ | |
| PyAPI_FUNC(void) | |
| _PySlotIterator_Init(_PySlotIterator *it, const PySlot *slots, | |
| _PySlot_KIND result_kind); | |
| /* Initialize an iterator using a legacy slot array */ | |
| PyAPI_FUNC(void) | |
| _PySlotIterator_InitLegacy(_PySlotIterator *it, const void *slots, | |
| _PySlot_KIND kind); | |
| /* Reset a *successfully exhausted* iterator to the beginning. | |
| * The *slots* must be the same as for the previous | |
| * `_PySlotIterator_InitWithKind` call. | |
| * (Unlike creating a new iterator, we can skip some validation after Rewind.) | |
| */ | |
| PyAPI_FUNC(void) _PySlotIterator_Rewind(_PySlotIterator *it, const void *slots); | |
| /* Iteration function. | |
| * | |
| * Return false at the end (when successfully exhausted). | |
| * Otherwise (even on error), fill output information in `it` and return true. | |
| * | |
| * On error, set an exception and set `it->current.sl_id` to `Py_slot_invalid`. | |
| */ | |
| PyAPI_FUNC(bool) _PySlotIterator_Next(_PySlotIterator *it); | |
| /* Return 1 if given slot was "seen" by an earlier _PySlotIterator_Next call. | |
| * (This state is not reset by rewinding.) | |
| */ | |
| PyAPI_FUNC(bool) _PySlotIterator_SawSlot(_PySlotIterator *, int); | |
| static inline const char * | |
| _PySlot_GetName(uint16_t id) | |
| { | |
| if (id >= _Py_slot_COUNT) { | |
| return "<unknown_slot>"; | |
| } | |
| if (id == Py_slot_invalid) { | |
| return "Py_slot_invalid"; | |
| } | |
| return _PySlot_names[id]; | |
| } | |
| static inline void | |
| _PySlot_err_bad_slot(char *kind, uint16_t id) | |
| { | |
| if (id < _Py_slot_COUNT) { | |
| PyErr_Format(PyExc_SystemError, "invalid %s slot %d (%s)", | |
| kind, (unsigned int)id, _PySlot_names[id]); | |
| } | |
| else if (id == Py_slot_invalid) { | |
| PyErr_Format(PyExc_SystemError, "invalid slot (Py_slot_invalid, %u)", | |
| (unsigned int)id); | |
| } | |
| else { | |
| PyErr_Format(PyExc_SystemError, "unknown %s slot ID %u", | |
| kind, (unsigned int)id); | |
| } | |
| } | |
| #include "internal/pycore_slots_generated.h" | |
| #endif // _Py_PYCORE_SLOTS_H |