| #define _RESOLVE_MODINIT_FUNC_NAME(NAME) \ | |
| PyInit_ ## NAME | |
| #define RESOLVE_MODINIT_FUNC_NAME(NAME) \ | |
| _RESOLVE_MODINIT_FUNC_NAME(NAME) | |
| #define GETDATA(FUNC) ((_PyXIData_getdata_t){.basic=FUNC}) | |
| static int | |
| ensure_xid_class(PyTypeObject *cls, _PyXIData_getdata_t getdata) | |
| { | |
| PyThreadState *tstate = PyThreadState_Get(); | |
| return _PyXIData_RegisterClass(tstate, cls, getdata); | |
| } | |
| #ifdef REGISTERS_HEAP_TYPES | |
| static int | |
| clear_xid_class(PyTypeObject *cls) | |
| { | |
| PyThreadState *tstate = PyThreadState_Get(); | |
| return _PyXIData_UnregisterClass(tstate, cls); | |
| } | |
| #endif | |
| static inline int64_t | |
| _get_interpid(_PyXIData_t *data) | |
| { | |
| int64_t interpid; | |
| if (data != NULL) { | |
| interpid = _PyXIData_INTERPID(data); | |
| assert(!PyErr_Occurred()); | |
| } | |
| else { | |
| interpid = PyInterpreterState_GetID(PyInterpreterState_Get()); | |
| } | |
| return interpid; | |
| } | |
| #ifdef HAS_FALLBACK | |
| static int | |
| resolve_fallback(int arg, xidata_fallback_t dflt, | |
| xidata_fallback_t *p_fallback) | |
| { | |
| if (arg < 0) { | |
| *p_fallback = dflt; | |
| return 0; | |
| } | |
| xidata_fallback_t fallback; | |
| if (arg == _PyXIDATA_XIDATA_ONLY) { | |
| fallback =_PyXIDATA_XIDATA_ONLY; | |
| } | |
| else if (arg == _PyXIDATA_FULL_FALLBACK) { | |
| fallback = _PyXIDATA_FULL_FALLBACK; | |
| } | |
| else { | |
| PyErr_Format(PyExc_ValueError, "unsupported fallback %d", arg); | |
| return -1; | |
| } | |
| *p_fallback = fallback; | |
| return 0; | |
| } | |
| #endif | |
| /* unbound items ************************************************************/ | |
| #ifdef HAS_UNBOUND_ITEMS | |
| typedef int unboundop_t; | |
| #define UNBOUND_REMOVE 1 | |
| #define UNBOUND_ERROR 2 | |
| #define UNBOUND_REPLACE 3 | |
| // It would also be possible to add UNBOUND_REPLACE where the replacement | |
| // value is user-provided. There would be some limitations there, though. | |
| // Another possibility would be something like UNBOUND_COPY, where the | |
| // object is released but the underlying data is copied (with the "raw" | |
| // allocator) and used when the item is popped off the queue. | |
| #ifndef NDEBUG | |
| static int | |
| check_unbound(int unboundop) | |
| { | |
| switch (unboundop) { | |
| case UNBOUND_REMOVE: | |
| case UNBOUND_ERROR: | |
| case UNBOUND_REPLACE: | |
| return 1; | |
| default: | |
| return 0; | |
| } | |
| } | |
| #endif | |
| static int | |
| resolve_unboundop(int arg, unboundop_t dflt, unboundop_t *p_unboundop) | |
| { | |
| if (arg < 0) { | |
| *p_unboundop = dflt; | |
| return 0; | |
| } | |
| unboundop_t op; | |
| if (arg == UNBOUND_REMOVE) { | |
| op = UNBOUND_REMOVE; | |
| } | |
| else if (arg == UNBOUND_ERROR) { | |
| op = UNBOUND_ERROR; | |
| } | |
| else if (arg == UNBOUND_REPLACE) { | |
| op = UNBOUND_REPLACE; | |
| } | |
| else { | |
| PyErr_Format(PyExc_ValueError, "unsupported unboundop %d", arg); | |
| return -1; | |
| } | |
| *p_unboundop = op; | |
| return 0; | |
| } | |
| #endif |