Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-11-19 09:50:48

0001 #ifndef Py_INTERNAL_OBJECT_STACK_H
0002 #define Py_INTERNAL_OBJECT_STACK_H
0003 
0004 #include "pycore_freelist.h"        // _PyFreeListState
0005 
0006 #ifdef __cplusplus
0007 extern "C" {
0008 #endif
0009 
0010 #ifndef Py_BUILD_CORE
0011 #  error "this header requires Py_BUILD_CORE define"
0012 #endif
0013 
0014 // _PyObjectStack is a stack of Python objects implemented as a linked list of
0015 // fixed size buffers.
0016 
0017 // Chosen so that _PyObjectStackChunk is a power-of-two size.
0018 #define _Py_OBJECT_STACK_CHUNK_SIZE 254
0019 
0020 typedef struct _PyObjectStackChunk {
0021     struct _PyObjectStackChunk *prev;
0022     Py_ssize_t n;
0023     PyObject *objs[_Py_OBJECT_STACK_CHUNK_SIZE];
0024 } _PyObjectStackChunk;
0025 
0026 typedef struct _PyObjectStack {
0027     _PyObjectStackChunk *head;
0028 } _PyObjectStack;
0029 
0030 
0031 extern _PyObjectStackChunk *
0032 _PyObjectStackChunk_New(void);
0033 
0034 extern void
0035 _PyObjectStackChunk_Free(_PyObjectStackChunk *);
0036 
0037 // Push an item onto the stack. Return -1 on allocation failure, 0 on success.
0038 static inline int
0039 _PyObjectStack_Push(_PyObjectStack *stack, PyObject *obj)
0040 {
0041     _PyObjectStackChunk *buf = stack->head;
0042     if (buf == NULL || buf->n == _Py_OBJECT_STACK_CHUNK_SIZE) {
0043         buf = _PyObjectStackChunk_New();
0044         if (buf == NULL) {
0045             return -1;
0046         }
0047         buf->prev = stack->head;
0048         buf->n = 0;
0049         stack->head = buf;
0050     }
0051 
0052     assert(buf->n >= 0 && buf->n < _Py_OBJECT_STACK_CHUNK_SIZE);
0053     buf->objs[buf->n] = obj;
0054     buf->n++;
0055     return 0;
0056 }
0057 
0058 // Pop the top item from the stack.  Return NULL if the stack is empty.
0059 static inline PyObject *
0060 _PyObjectStack_Pop(_PyObjectStack *stack)
0061 {
0062     _PyObjectStackChunk *buf = stack->head;
0063     if (buf == NULL) {
0064         return NULL;
0065     }
0066     assert(buf->n > 0 && buf->n <= _Py_OBJECT_STACK_CHUNK_SIZE);
0067     buf->n--;
0068     PyObject *obj = buf->objs[buf->n];
0069     if (buf->n == 0) {
0070         stack->head = buf->prev;
0071         _PyObjectStackChunk_Free(buf);
0072     }
0073     return obj;
0074 }
0075 
0076 static inline Py_ssize_t
0077 _PyObjectStack_Size(_PyObjectStack *stack)
0078 {
0079     Py_ssize_t size = 0;
0080     for (_PyObjectStackChunk *buf = stack->head; buf != NULL; buf = buf->prev) {
0081         size += buf->n;
0082     }
0083     return size;
0084 }
0085 
0086 // Merge src into dst, leaving src empty
0087 extern void
0088 _PyObjectStack_Merge(_PyObjectStack *dst, _PyObjectStack *src);
0089 
0090 // Remove all items from the stack
0091 extern void
0092 _PyObjectStack_Clear(_PyObjectStack *stack);
0093 
0094 #ifdef __cplusplus
0095 }
0096 #endif
0097 #endif  // !Py_INTERNAL_OBJECT_STACK_H