Skip to content

Commit

Permalink
Add ObjectArrayList, ObjectArrayListIter
Browse files Browse the repository at this point in the history
  • Loading branch information
xia-mc committed Nov 18, 2024
1 parent 416b359 commit eadd108
Show file tree
Hide file tree
Showing 23 changed files with 3,498 additions and 56 deletions.
18 changes: 18 additions & 0 deletions .idea/PyFastUtil.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.26)
project(PyFastUtil CXX)
project(PyFastUtil CXX C)

set(CMAKE_CXX_STANDARD 23)

Expand Down
1 change: 1 addition & 0 deletions pyfastutil/ints.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ class IntArrayListIter(Iterator[int]):
"""
pass


@final
class BigIntArrayList(list[int]):
"""
Expand Down
7 changes: 7 additions & 0 deletions pyfastutil/objects.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# noinspection PyUnresolvedReferences
from .__pyfastutil import ObjectArrayList as __ObjectArrayList
# noinspection PyUnresolvedReferences
from .__pyfastutil import ObjectArrayListIter as __ObjectArrayListIter

ObjectArrayList = __ObjectArrayList.ObjectArrayList
ObjectArrayListIter = __ObjectArrayListIter.ObjectArrayListIter
138 changes: 138 additions & 0 deletions pyfastutil/objects.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
from typing import overload, Iterable, SupportsIndex, final, Iterator


@final
class ObjectArrayList(list):
"""
A specialized version of Python's `list` that can store any type of object, optimized for performance by using a C implementation.
This class behaves similarly to the standard Python `list`, but it is designed for use cases where performance is critical.
It can store objects of any type, including integers, strings, custom objects, and more, making it as flexible as Python's
built-in `list` type.
The `ObjectArrayList` is optimized for performance, especially for large datasets, by utilizing underlying C-based optimizations.
It supports all standard list operations such as indexing, slicing, appending, and iteration.
Parameters:
- `exceptSize` (optional): The expected size of the list. This is used for preallocating memory to avoid frequent resizing
when adding elements.
- `iterable` (optional): An iterable of objects to initialize the list with.
Example:
>>> obj_list = ObjectArrayList([1, "hello", 3.14])
>>> obj_list.append({"key": "value"})
>>> print(obj_list)
[1, "hello", 3.14, {"key": "value"}]
>>> obj_list = ObjectArrayList(10) # Preallocate space for 10 elements
>>> obj_list.append(42)
>>> print(obj_list)
[42]
Note:
- Unlike `IntArrayList`, `ObjectArrayList` can store objects of any type, making it a more flexible data structure.
"""

@overload
def __init__(self, exceptSize: int) -> None:
"""
Initializes an empty `ObjectArrayList` with a preallocated size.
Parameters:
exceptSize (int): The expected size of the list. This preallocates memory for the list to avoid frequent resizing
as elements are added.
"""
pass

@overload
def __init__(self, iterable: Iterable[object], exceptSize: int) -> None:
"""
Initializes an `ObjectArrayList` from an iterable of objects with a preallocated size.
Parameters:
iterable (Iterable[object]): An iterable of objects to initialize the list with.
exceptSize (int): The expected size of the list. This preallocates memory for the list to avoid frequent resizing.
"""
pass

@overload
def __init__(self) -> None:
"""
Initializes an empty `ObjectArrayList` with no preallocated size.
"""
pass

@overload
def __init__(self, iterable: Iterable[object]) -> None:
"""
Initializes an `ObjectArrayList` from an iterable of objects.
Parameters:
iterable (Iterable[object]): An iterable of objects to initialize the list with.
"""
pass

def resize(self, __size: int) -> None:
"""
Resizes the `ObjectArrayList` to the specified size.
If the new size is larger than the current size, the list will be extended with `None` values. If the new size is
smaller, excess elements will be removed.
Parameters:
__size (int): The new size of the list.
Example:
>>> obj_list = ObjectArrayList([1, "hello", 3.14])
>>> obj_list.resize(5)
>>> print(obj_list)
[1, "hello", 3.14, None, None]
>>> obj_list.resize(2)
>>> print(obj_list)
[1, "hello"]
"""
pass


@final
class ObjectArrayListIter(Iterator):
"""
Iterator for `ObjectArrayList`.
This class provides an iterator over an `ObjectArrayList`, allowing you to iterate over the elements
of the list one by one.
Note:
This class cannot be directly instantiated by users. It is designed to be used internally by
`ObjectArrayList` and can only be obtained by calling the `__iter__` method on an `ObjectArrayList` object.
Example:
>>> obj_list = ObjectArrayList([1, "hello", 3.14])
>>> iter_obj = iter(obj_list) # This returns an ObjectArrayListIter instance
>>> next(iter_obj)
1
>>> next(iter_obj)
"hello"
>>> next(iter_obj)
3.14
>>> next(iter_obj) # Raises StopIteration
Raises:
TypeError: If attempted to be instantiated directly.
"""

def __next__(self) -> object:
"""
Return the next element in the iteration.
This method retrieves the next element from the `ObjectArrayList` that this iterator is associated with.
If all elements have been iterated over, it raises a `StopIteration` exception.
Returns:
object: The next object in the `ObjectArrayList`.
Raises:
StopIteration: If there are no more elements to iterate over.
"""
pass
5 changes: 3 additions & 2 deletions pyfastutil/src/Compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@
#define __forceinline inline
#endif


#ifdef __cplusplus
namespace compat {

/**
* Helper function to get the macOS version
*/
static __forceinline bool isMacos1015OrNewer() {
[[maybe_unused]] static __forceinline bool isMacos1015OrNewer() {
#ifdef __APPLE__
struct utsname sys_info;
if (uname(&sys_info) != 0) {
Expand All @@ -46,6 +46,7 @@ namespace compat {
}

}
#endif

#pragma clang diagnostic pop

Expand Down
4 changes: 4 additions & 0 deletions pyfastutil/src/PyFastUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include "ints/IntArrayListIter.h"
#include "ints/BigIntArrayList.h"
#include "ints/BigIntArrayListIter.h"
#include "objects/ObjectArrayList.h"
#include "objects/ObjectArrayListIter.h"
#include "unsafe/Unsafe.h"

static struct PyModuleDef pyfastutilModule = {
Expand All @@ -32,6 +34,8 @@ PyMODINIT_FUNC PyInit___pyfastutil() {
PyModule_AddObject(parent, "IntArrayListIter", PyInit_IntArrayListIter());
PyModule_AddObject(parent, "BigIntArrayList", PyInit_BigIntArrayList());
PyModule_AddObject(parent, "BigIntArrayListIter", PyInit_BigIntArrayListIter());
PyModule_AddObject(parent, "ObjectArrayList", PyInit_ObjectArrayList());
PyModule_AddObject(parent, "ObjectArrayListIter", PyInit_ObjectArrayListIter());

PyModule_AddObject(parent, "Unsafe", PyInit_Unsafe());

Expand Down
34 changes: 17 additions & 17 deletions pyfastutil/src/ints/BigIntArrayList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -831,7 +831,7 @@ static int BigIntArrayList_contains(PyObject *pySelf, PyObject *key) {
}

try {
if (std::find(self->vector.begin(), self->vector.end(), static_cast<int>(value)) != self->vector.end()) {
if (std::find(self->vector.begin(), self->vector.end(), value) != self->vector.end()) {
return 1; // true
} else {
return 0; // false
Expand Down Expand Up @@ -1104,22 +1104,22 @@ static PyObject *BigIntArrayList_str(PyObject *pySelf) {
}

static PyMethodDef BigIntArrayList_methods[] = {
{"from_range", (PyCFunction) BigIntArrayList_from_range, METH_VARARGS | METH_STATIC},
{"resize", (PyCFunction) BigIntArrayList_resize, METH_O},
{"tolist", (PyCFunction) BigIntArrayList_to_list, METH_NOARGS},
{"copy", (PyCFunction) BigIntArrayList_copy, METH_NOARGS},
{"append", (PyCFunction) BigIntArrayList_append, METH_O},
{"extend", (PyCFunction) BigIntArrayList_extend, METH_FASTCALL},
{"pop", (PyCFunction) BigIntArrayList_pop, METH_FASTCALL},
{"index", (PyCFunction) BigIntArrayList_index, METH_VARARGS},
{"count", (PyCFunction) BigIntArrayList_count, METH_O},
{"insert", (PyCFunction) BigIntArrayList_insert, METH_VARARGS},
{"remove", (PyCFunction) BigIntArrayList_remove, METH_O},
{"sort", (PyCFunction) BigIntArrayList_sort, METH_VARARGS | METH_KEYWORDS},
{"reverse", (PyCFunction) BigIntArrayList_reverse, METH_NOARGS},
{"clear", (PyCFunction) BigIntArrayList_clear, METH_NOARGS},
{"__rmul__", (PyCFunction) BigIntArrayList_rmul, METH_O},
{"__reversed__", (PyCFunction) BigIntArrayList_reversed, METH_NOARGS},
{"from_range", (PyCFunction) BigIntArrayList_from_range, METH_VARARGS | METH_STATIC},
{"resize", (PyCFunction) BigIntArrayList_resize, METH_O},
{"tolist", (PyCFunction) BigIntArrayList_to_list, METH_NOARGS},
{"copy", (PyCFunction) BigIntArrayList_copy, METH_NOARGS},
{"append", (PyCFunction) BigIntArrayList_append, METH_O},
{"extend", (PyCFunction) BigIntArrayList_extend, METH_FASTCALL},
{"pop", (PyCFunction) BigIntArrayList_pop, METH_FASTCALL},
{"index", (PyCFunction) BigIntArrayList_index, METH_VARARGS},
{"count", (PyCFunction) BigIntArrayList_count, METH_O},
{"insert", (PyCFunction) BigIntArrayList_insert, METH_VARARGS},
{"remove", (PyCFunction) BigIntArrayList_remove, METH_O},
{"sort", (PyCFunction) BigIntArrayList_sort, METH_VARARGS | METH_KEYWORDS},
{"reverse", (PyCFunction) BigIntArrayList_reverse, METH_NOARGS},
{"clear", (PyCFunction) BigIntArrayList_clear, METH_NOARGS},
{"__rmul__", (PyCFunction) BigIntArrayList_rmul, METH_O},
{"__reversed__", (PyCFunction) BigIntArrayList_reversed, METH_NOARGS},
{"__class_getitem__", (PyCFunction) BigIntArrayList_class_getitem, METH_O | METH_CLASS},
{nullptr}
};
Expand Down
32 changes: 16 additions & 16 deletions pyfastutil/src/ints/IntArrayList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1104,22 +1104,22 @@ static PyObject *IntArrayList_str(PyObject *pySelf) {
}

static PyMethodDef IntArrayList_methods[] = {
{"from_range", (PyCFunction) IntArrayList_from_range, METH_VARARGS | METH_STATIC},
{"resize", (PyCFunction) IntArrayList_resize, METH_O},
{"tolist", (PyCFunction) IntArrayList_to_list, METH_NOARGS},
{"copy", (PyCFunction) IntArrayList_copy, METH_NOARGS},
{"append", (PyCFunction) IntArrayList_append, METH_O},
{"extend", (PyCFunction) IntArrayList_extend, METH_FASTCALL},
{"pop", (PyCFunction) IntArrayList_pop, METH_FASTCALL},
{"index", (PyCFunction) IntArrayList_index, METH_VARARGS},
{"count", (PyCFunction) IntArrayList_count, METH_O},
{"insert", (PyCFunction) IntArrayList_insert, METH_VARARGS},
{"remove", (PyCFunction) IntArrayList_remove, METH_O},
{"sort", (PyCFunction) IntArrayList_sort, METH_VARARGS | METH_KEYWORDS},
{"reverse", (PyCFunction) IntArrayList_reverse, METH_NOARGS},
{"clear", (PyCFunction) IntArrayList_clear, METH_NOARGS},
{"__rmul__", (PyCFunction) IntArrayList_rmul, METH_O},
{"__reversed__", (PyCFunction) IntArrayList_reversed, METH_NOARGS},
{"from_range", (PyCFunction) IntArrayList_from_range, METH_VARARGS | METH_STATIC},
{"resize", (PyCFunction) IntArrayList_resize, METH_O},
{"tolist", (PyCFunction) IntArrayList_to_list, METH_NOARGS},
{"copy", (PyCFunction) IntArrayList_copy, METH_NOARGS},
{"append", (PyCFunction) IntArrayList_append, METH_O},
{"extend", (PyCFunction) IntArrayList_extend, METH_FASTCALL},
{"pop", (PyCFunction) IntArrayList_pop, METH_FASTCALL},
{"index", (PyCFunction) IntArrayList_index, METH_VARARGS},
{"count", (PyCFunction) IntArrayList_count, METH_O},
{"insert", (PyCFunction) IntArrayList_insert, METH_VARARGS},
{"remove", (PyCFunction) IntArrayList_remove, METH_O},
{"sort", (PyCFunction) IntArrayList_sort, METH_VARARGS | METH_KEYWORDS},
{"reverse", (PyCFunction) IntArrayList_reverse, METH_NOARGS},
{"clear", (PyCFunction) IntArrayList_clear, METH_NOARGS},
{"__rmul__", (PyCFunction) IntArrayList_rmul, METH_O},
{"__reversed__", (PyCFunction) IntArrayList_reversed, METH_NOARGS},
{"__class_getitem__", (PyCFunction) IntArrayList_class_getitem, METH_O | METH_CLASS},
{nullptr}
};
Expand Down
Loading

0 comments on commit eadd108

Please sign in to comment.