Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 34k
gh-125543: Add an internal C API for dynamic arrays#125554
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Uh oh!
There was an error while loading. Please reload this page.
Closed
Changes from all commits
Commits
Show all changes
22 commits Select commit Hold shift + click to select a range
111fb4b Setup build.
ZeroIntensity 6e305d1 Simple implementation.
ZeroIntensity 210d4d2 Add to header file.
ZeroIntensity 2c77397 Add convenience macros.
ZeroIntensity d90329a Add docstrings and some sanity checks.
ZeroIntensity 3173c08 Add some simple tests.
ZeroIntensity 6a8f026 Clean up tests.
ZeroIntensity 84a922a Add a test for deallocators.
ZeroIntensity caf037c Boy oh boy do I hate the Windows build system.
ZeroIntensity 14e46a4 Correction: I hate all build systems.
ZeroIntensity be1de70 Add set and remove operations.
ZeroIntensity db5adbf Add tests for set and remove.
ZeroIntensity aad50d8 Update docstrings.
ZeroIntensity 0ecc65f Add pop.
ZeroIntensity 6a46733 Add tests for pop.
ZeroIntensity 4d732dc Add insert.
ZeroIntensity 95c7753 Add insertion.
ZeroIntensity 51664b8 Add more heap tests and fix insertion.
ZeroIntensity b2be58f Don't use GCC extension.
ZeroIntensity a24fec2 > instead of >=
Eclips4 23902f9 Fix behavior upon allocation failure.
ZeroIntensity 86f78c6 Remove useless comment.
ZeroIntensity File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Jump to file
Failed to load files.
Loading
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,233 @@ | ||
| #ifndef Py_INTERNAL_DYNARRAY_H | ||
| #define Py_INTERNAL_DYNARRAY_H | ||
| #ifdef __cplusplus | ||
| extern "C"{ | ||
| #endif | ||
| #include "Python.h" // Py_ssize_t | ||
| #ifndef Py_BUILD_CORE | ||
| # error "this header requires Py_BUILD_CORE define" | ||
| #endif | ||
| #define _PyDynArray_DEFAULT_SIZE 16 | ||
| /* | ||
| * Deallocator for items on a _PyDynArray structure. A NULL pointer | ||
| * will never be given to the deallocator. | ||
| */ | ||
| typedef void (*_PyDynArray_Deallocator)(void *); | ||
| /* | ||
| * Internal only dynamic array for CPython. | ||
| */ | ||
| typedef struct{ | ||
| /* | ||
| * The actual items in the dynamic array. | ||
| * Don't access this field publicly to get | ||
| * items--use _PyDynArray_GET_ITEM() instead. | ||
| */ | ||
| void **items; | ||
| /* | ||
| * The length of the actual items array allocation. | ||
| */ | ||
| Py_ssize_t capacity; | ||
| /* | ||
| * The number of items in the array. | ||
| * Don't use this field publicly--use _PyDynArray_LENGTH() | ||
| */ | ||
| Py_ssize_t length; | ||
| /* | ||
| * The deallocator, set by one of the initializer functions. | ||
| * This may be NULL. | ||
| */ | ||
| _PyDynArray_Deallocator deallocator; | ||
| } _PyDynArray; | ||
| static inline void | ||
| _PyDynArray_ASSERT_VALID(_PyDynArray *array) | ||
| { | ||
| assert(array != NULL); | ||
| assert(array->items != NULL); | ||
| } | ||
| static inline void | ||
| _PyDynArray_ASSERT_INDEX(_PyDynArray *array, Py_ssize_t index) | ||
| { | ||
| // Ensure the index is valid | ||
| assert(index >= 0); | ||
| assert(index < array->length); | ||
| } | ||
| /* | ||
| * Initialize a dynamic array with an initial size and deallocator. | ||
| * | ||
| * If the deallocator is NULL, then nothing happens to items upon | ||
| * removal and upon array clearing. | ||
| * | ||
| * Returns -1 upon failure, 0 otherwise. | ||
| */ | ||
| PyAPI_FUNC(int) | ||
| _PyDynArray_InitWithSize(_PyDynArray *array, | ||
| _PyDynArray_Deallocator deallocator, | ||
| Py_ssize_t initial); | ||
| /* | ||
| * Append to the array. | ||
| * | ||
| * Returns -1 upon failure, 0 otherwise. | ||
| * If this fails, the deallocator is not ran on the item. | ||
| */ | ||
| PyAPI_FUNC(int) _PyDynArray_Append(_PyDynArray *array, void *item); | ||
| /* | ||
| * Insert an item at the target index. The index | ||
| * must currently be a valid index in the array. | ||
| * | ||
| * Returns -1 upon failure, 0 otherwise. | ||
| * If this fails, the deallocator is not ran on the item. | ||
| */ | ||
| PyAPI_FUNC(int) | ||
| _PyDynArray_Insert(_PyDynArray *array, Py_ssize_t index, void *item); | ||
| /* | ||
| * Clear all the fields on the array. | ||
| * | ||
| * Note that this does *not* free the actual dynamic array | ||
| * structure--use _PyDynArray_Free() for that. | ||
| * | ||
| * It's safe to call _PyDynArray_Init() or InitWithSize() again | ||
| * on the array after calling this. | ||
| */ | ||
| PyAPI_FUNC(void) _PyDynArray_Clear(_PyDynArray *array); | ||
| /* | ||
| * Set a value at index in the array. | ||
| * | ||
| * If an item already exists at the target index, the deallocator | ||
| * is called on it, if the array has one set. | ||
| * | ||
| * This cannot fail. | ||
| */ | ||
| PyAPI_FUNC(void) | ||
| _PyDynArray_Set(_PyDynArray *array, Py_ssize_t index, void *item); | ||
| /* | ||
| * Remove the item at the index, and call the deallocator on it (if the array | ||
| * has one set). | ||
| * | ||
| * This cannot fail. | ||
| */ | ||
| PyAPI_FUNC(void) | ||
| _PyDynArray_Remove(_PyDynArray *array, Py_ssize_t index); | ||
| /* | ||
| * Remove the item at the index *without* deallocating it, and | ||
| * return the item. | ||
| * | ||
| * This cannot fail. | ||
| */ | ||
| PyAPI_FUNC(void *) | ||
| _PyDynArray_Pop(_PyDynArray *array, Py_ssize_t index); | ||
| /* | ||
| * Clear all the fields on a dynamic array, and then | ||
| * free the dynamic array structure itself. | ||
| * | ||
| * The array must have been created by _PyDynArray_New() | ||
| */ | ||
| static inline void | ||
| _PyDynArray_Free(_PyDynArray *array) | ||
| { | ||
| _PyDynArray_ASSERT_VALID(array); | ||
| _PyDynArray_Clear(array); | ||
| PyMem_RawFree(array); | ||
| } | ||
| /* | ||
| * Equivalent to _PyDynArray_InitWithSize() with a default size of 16. | ||
| * | ||
| * Returns -1 upon failure, 0 otherwise. | ||
| */ | ||
| static inline int | ||
| _PyDynArray_Init(_PyDynArray *array, _PyDynArray_Deallocator deallocator) | ||
| { | ||
| return _PyDynArray_InitWithSize(array, deallocator, _PyDynArray_DEFAULT_SIZE); | ||
| } | ||
| /* | ||
| * Allocate and create a new dynamic array on the heap. | ||
| * | ||
| * The returned pointer should be freed with _PyDynArray_Free() | ||
| * If this function fails, it returns NULL. | ||
| */ | ||
| static inline _PyDynArray * | ||
| _PyDynArray_NewWithSize(_PyDynArray_Deallocator deallocator, Py_ssize_t initial) | ||
| { | ||
| _PyDynArray *array = PyMem_RawMalloc(sizeof(_PyDynArray)); | ||
| if (array == NULL) | ||
| { | ||
| return NULL; | ||
| } | ||
| if (_PyDynArray_InitWithSize(array, deallocator, initial) < 0) | ||
| { | ||
| PyMem_RawFree(array); | ||
| return NULL; | ||
| } | ||
| _PyDynArray_ASSERT_VALID(array); // Sanity check | ||
| return array; | ||
| } | ||
| /* | ||
| * Equivalent to _PyDynArray_NewWithSize() with a size of 16. | ||
| * | ||
| * The returned array must be freed with _PyDynArray_Free(). | ||
| * Returns NULL on failure. | ||
| */ | ||
| static inline _PyDynArray * | ||
| _PyDynArray_New(_PyDynArray_Deallocator deallocator) | ||
| { | ||
| return _PyDynArray_NewWithSize(deallocator, _PyDynArray_DEFAULT_SIZE); | ||
| } | ||
| /* | ||
| * Get an item from the array. This cannot fail. | ||
| * | ||
| * If the index is not valid, this is undefined behavior. | ||
| */ | ||
| static inline void * | ||
| _PyDynArray_GET_ITEM(_PyDynArray *array, Py_ssize_t index) | ||
| { | ||
| _PyDynArray_ASSERT_VALID(array); | ||
| _PyDynArray_ASSERT_INDEX(array, index); | ||
| return array->items[index]; | ||
| } | ||
| /* | ||
| * Get the length of the array. This cannot fail. | ||
| */ | ||
| static inline Py_ssize_t | ||
| _PyDynArray_LENGTH(_PyDynArray *array) | ||
| { | ||
| _PyDynArray_ASSERT_VALID(array); | ||
| return array->length; | ||
| } | ||
| /* | ||
| * Pop the item at the end the array. | ||
| * This function cannot fail. | ||
| */ | ||
| static inline void * | ||
| _PyDynArray_PopTop(_PyDynArray *array) | ||
| { | ||
| return _PyDynArray_Pop(array, _PyDynArray_LENGTH(array) - 1); | ||
| } | ||
| #ifdef __cplusplus | ||
| } | ||
| #endif | ||
| #endif /* !Py_INTERNAL_DYNARRAY_H */ | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Oops, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.