cpython/Include/internal/pycore_object_stack.h

88 lines
2.1 KiB
C

#ifndef Py_INTERNAL_OBJECT_STACK_H
#define Py_INTERNAL_OBJECT_STACK_H
#include "pycore_freelist.h" // _PyFreeListState
#ifdef __cplusplus
extern "C" {
#endif
#ifndef Py_BUILD_CORE
# error "this header requires Py_BUILD_CORE define"
#endif
// _PyObjectStack is a stack of Python objects implemented as a linked list of
// fixed size buffers.
// Chosen so that _PyObjectStackChunk is a power-of-two size.
#define _Py_OBJECT_STACK_CHUNK_SIZE 254
typedef struct _PyObjectStackChunk {
struct _PyObjectStackChunk *prev;
Py_ssize_t n;
PyObject *objs[_Py_OBJECT_STACK_CHUNK_SIZE];
} _PyObjectStackChunk;
typedef struct _PyObjectStack {
_PyObjectStackChunk *head;
} _PyObjectStack;
extern _PyObjectStackChunk *
_PyObjectStackChunk_New(void);
extern void
_PyObjectStackChunk_Free(_PyObjectStackChunk *);
// Push an item onto the stack. Return -1 on allocation failure, 0 on success.
static inline int
_PyObjectStack_Push(_PyObjectStack *stack, PyObject *obj)
{
_PyObjectStackChunk *buf = stack->head;
if (buf == NULL || buf->n == _Py_OBJECT_STACK_CHUNK_SIZE) {
buf = _PyObjectStackChunk_New();
if (buf == NULL) {
return -1;
}
buf->prev = stack->head;
buf->n = 0;
stack->head = buf;
}
assert(buf->n >= 0 && buf->n < _Py_OBJECT_STACK_CHUNK_SIZE);
buf->objs[buf->n] = obj;
buf->n++;
return 0;
}
// Pop the top item from the stack. Return NULL if the stack is empty.
static inline PyObject *
_PyObjectStack_Pop(_PyObjectStack *stack)
{
_PyObjectStackChunk *buf = stack->head;
if (buf == NULL) {
return NULL;
}
assert(buf->n > 0 && buf->n <= _Py_OBJECT_STACK_CHUNK_SIZE);
buf->n--;
PyObject *obj = buf->objs[buf->n];
if (buf->n == 0) {
stack->head = buf->prev;
_PyObjectStackChunk_Free(buf);
}
return obj;
}
// Merge src into dst, leaving src empty
extern void
_PyObjectStack_Merge(_PyObjectStack *dst, _PyObjectStack *src);
// Remove all items from the stack
extern void
_PyObjectStack_Clear(_PyObjectStack *stack);
#ifdef __cplusplus
}
#endif
#endif // !Py_INTERNAL_OBJECT_STACK_H