gdnative_python/generation/builtins_templates/array.tmpl.pxi
2023-06-02 17:59:23 +02:00

271 lines
11 KiB
Cython

{%- block pxd_header %}
{% endblock -%}
{%- block pyx_header %}
# TODO
{{ force_mark_rendered("pandemonium_array_append_array") }}
{{ force_mark_rendered("pandemonium_array_deep_equal") }}
{{ force_mark_rendered("pandemonium_array_deep_equal_recursion_count") }}
{{ force_mark_rendered("pandemonium_array_duplicate_deep") }}
{{ force_mark_rendered("pandemonium_array_fill") }}
{{ force_mark_rendered("pandemonium_array_find_from") }}
{{ force_mark_rendered("pandemonium_array_new_pool_vector2i_array") }}
{{ force_mark_rendered("pandemonium_array_new_pool_vector3i_array") }}
{{ force_mark_rendered("pandemonium_array_new_pool_vector4_array") }}
{{ force_mark_rendered("pandemonium_array_new_pool_vector4i_array") }}
{{ force_mark_rendered("pandemonium_array_operator_equals") }}
{{ force_mark_rendered("pandemonium_array_pop_at") }}
{{ force_mark_rendered("pandemonium_array_rfind_from") }}
{{ force_mark_rendered("pandemonium_array_slice_step") }}
{{ force_mark_rendered("pandemonium_array_slice_step_deep") }}
{% endblock -%}
{# TODO: conversion from pool arrays is not supported #}
{{ force_mark_rendered("pandemonium_array_new_pool_byte_array") }}
{{ force_mark_rendered("pandemonium_array_new_pool_color_array") }}
{{ force_mark_rendered("pandemonium_array_new_pool_int_array") }}
{{ force_mark_rendered("pandemonium_array_new_pool_real_array") }}
{{ force_mark_rendered("pandemonium_array_new_pool_string_array") }}
{{ force_mark_rendered("pandemonium_array_new_pool_vector2_array") }}
{{ force_mark_rendered("pandemonium_array_new_pool_vector3_array") }}
{# We can't do const in Python #}
{{ force_mark_rendered("pandemonium_array_operator_index_const") }}
@cython.final
cdef class Array:
{% block cdef_attributes %}
cdef pandemonium_array _gd_data
@staticmethod
cdef inline Array new()
@staticmethod
cdef inline Array from_ptr(const pandemonium_array *_ptr)
cdef inline Array operator_getslice(self, pandemonium_int start, pandemonium_int stop, pandemonium_int step)
cdef inline bint operator_equal(self, Array other)
cdef inline Array operator_add(self, Array items)
cdef inline operator_iadd(self, Array items)
{% endblock %}
{% block python_defs %}
def __init__(self, iterable=None):
{{ force_mark_rendered("pandemonium_array_new") }}
{{ force_mark_rendered("pandemonium_array_duplicate") }}
if not iterable:
gdapi10.pandemonium_array_new(&self._gd_data)
elif isinstance(iterable, Array):
self._gd_data = gdapi10.pandemonium_array_duplicate(&(<Array>iterable)._gd_data)
# TODO: handle Pool*Array
else:
gdapi10.pandemonium_array_new(&self._gd_data)
for x in iterable:
self.append(x)
@staticmethod
cdef inline Array new():
# Call to __new__ bypasses __init__ constructor
cdef Array ret = Array.__new__(Array)
gdapi10.pandemonium_array_new(&ret._gd_data)
return ret
@staticmethod
cdef inline Array from_ptr(const pandemonium_array *_ptr):
# Call to __new__ bypasses __init__ constructor
cdef Array ret = Array.__new__(Array)
# `pandemonium_array` is a cheap structure pointing on a refcounted vector
# of variants. Unlike it name could let think, `pandemonium_array_new_copy`
# only increment the refcount of the underlying structure.
{{ force_mark_rendered("pandemonium_array_new_copy") }}
gdapi10.pandemonium_array_new_copy(&ret._gd_data, _ptr)
return ret
def __dealloc__(self):
# /!\ if `__init__` is skipped, `_gd_data` must be initialized by
# hand otherwise we will get a segfault here
{{ force_mark_rendered("pandemonium_array_destroy") }}
gdapi10.pandemonium_array_destroy(&self._gd_data)
def __repr__(self):
return f"<{type(self).__name__}([{', '.join([repr(x) for x in self])}])>"
# Operators
cdef inline Array operator_getslice(self, pandemonium_int start, pandemonium_int stop, pandemonium_int step):
{{ force_mark_rendered("pandemonium_array_slice") }}
cdef Array ret = Array.__new__(Array)
#TODO
#ret._gd_data = gdapi10.pandemonium_array_slice_step(&self._gd_data, start, stop, step, False)
ret._gd_data = gdapi10.pandemonium_array_slice(&self._gd_data, start, stop)
return ret
# TODO: support slice
def __getitem__(self, index):
{{ force_mark_rendered("pandemonium_array_operator_index") }}
cdef pandemonium_int size = self.size()
cdef pandemonium_int start
cdef pandemonium_int stop
cdef pandemonium_int step
if isinstance(index, slice):
step = index.step if index.step is not None else 1
if step == 0:
raise ValueError("slice step cannot be zero")
elif step > 0:
start = index.start if index.start is not None else 0
stop = index.stop if index.stop is not None else size
else:
start = index.start if index.start is not None else size
stop = index.stop if index.stop is not None else -size - 1
return Array.operator_getslice(self, start, stop, step)
if index < 0:
index = index + size
if index < 0 or index >= size:
raise IndexError("list index out of range")
cdef pandemonium_variant *p_ret = gdapi10.pandemonium_array_operator_index(&self._gd_data, index)
return pandemonium_variant_to_pyobj(p_ret)
# TODO: support slice
def __setitem__(self, pandemonium_int index, object value):
cdef pandemonium_int size = self.size()
index = size + index if index < 0 else index
if abs(index) >= size:
raise IndexError("list index out of range")
cdef pandemonium_variant *p_ret = gdapi10.pandemonium_array_operator_index(&self._gd_data, index)
gdapi10.pandemonium_variant_destroy(p_ret)
pyobj_to_pandemonium_variant(value, p_ret)
# TODO: support slice
def __delitem__(self, pandemonium_int index):
cdef pandemonium_int size = self.size()
index = size + index if index < 0 else index
if abs(index) >= size:
raise IndexError("list index out of range")
gdapi10.pandemonium_array_remove(&self._gd_data, index)
def __iter__(self):
# TODO: mid iteration mutation should throw exception ?
cdef int i
for i in range(self.size()):
yield self.get(i)
def __copy__(self):
return self.duplicate(False)
def __deepcopy__(self):
return self.duplicate(True)
cdef inline bint operator_equal(self, Array other):
# TODO `pandemonium_array_operator_equal` is missing in gdapi, submit a PR ?
cdef pandemonium_int size = self.size()
if size != other.size():
return False
cdef int i
for i in range(size):
if not gdapi10.pandemonium_variant_operator_equal(
gdapi10.pandemonium_array_operator_index(&self._gd_data, i),
gdapi10.pandemonium_array_operator_index(&other._gd_data, i)
):
return False
return True
def __eq__(self, other):
try:
return Array.operator_equal(self, <Array?>other)
except TypeError:
return False
def __ne__(self, other):
try:
return not Array.operator_equal(self, <Array?>other)
except TypeError:
return True
cdef inline operator_iadd(self, Array items):
cdef pandemonium_int self_size = self.size()
cdef pandemonium_int items_size = items.size()
gdapi10.pandemonium_array_resize(&self._gd_data, self_size + items_size)
cdef int i
for i in range(items_size):
Array.set(self, self_size + i, items.get(i))
# TODO: support __iadd__ for other types than Array ?
def __iadd__(self, items not None):
try:
Array.operator_iadd(self, items)
except TypeError:
for x in items:
self.append(x)
return self
cdef inline Array operator_add(self, Array items):
cdef pandemonium_int self_size = self.size()
cdef pandemonium_int items_size = items.size()
cdef Array ret = Array.new()
gdapi10.pandemonium_array_resize(&ret._gd_data, self_size + items_size)
cdef int i
for i in range(self_size):
Array.set(ret, i, self.get(i))
for i in range(items_size):
Array.set(ret, self_size + i, items.get(i))
return ret
# TODO: support __add__ for other types than Array ?
def __add__(self, items not None):
try:
return Array.operator_add(self, items)
except TypeError:
ret = Array.duplicate(self, False)
for x in items:
ret.append(x)
return ret
{{ render_method("size", py_name="__len__") | indent }}
{{ render_method("hash", py_name="__hash__") | indent }}
{{ render_method("has", py_name="__contains__") | indent }}
{{ render_method("hash") | indent }}
{{ render_method("size") | indent }}
{{ render_method("duplicate") | indent }}
{{ render_method("get") | indent }}
{{ render_method("set") | indent }}
{{ render_method("append") | indent }}
{{ render_method("clear") | indent }}
{{ render_method("empty") | indent }}
{{ render_method("count") | indent }}
{{ render_method("erase") | indent }}
{{ render_method("front") | indent }}
{{ render_method("back") | indent }}
{{ render_method("find") | indent }}
{{ render_method("find_last") | indent }}
{{ render_method("insert") | indent }}
{{ render_method("invert") | indent }}
{{ render_method("pop_back") | indent }}
{{ render_method("pop_front") | indent }}
{{ render_method("push_back") | indent }}
{{ render_method("push_front") | indent }}
{{ render_method("remove") | indent }}
{{ render_method("resize") | indent }}
{{ render_method("rfind") | indent }}
{{ render_method("sort") | indent }}
{#- TODO: opaque object as param is not supported #}
{{- force_mark_rendered("pandemonium_array_sort_custom") }}
{#- {{ render_method("sort_custom") | indent }} #}
{{ render_method("bsearch") | indent }}
{#- TODO: opaque object as param is not supported #}
{{- force_mark_rendered("pandemonium_array_bsearch_custom") }}
{#- {{ render_method("bsearch_custom") | indent }} #}
{{ render_method("max") | indent }}
{{ render_method("min") | indent }}
{{ render_method("shuffle") | indent }}
{% endblock %}
{%- block python_consts %}
{% endblock %}