From 9bb79adbcc76b58c9b76cb4f671cdde9bb8f1ae3 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 6 Jan 2022 09:30:45 +0100 Subject: Add reserve()/capacity() to contiguous opaque containers Generate bindings for reserve()/capacity() if the container supports it. [ChangeLog][shiboken6] Bindings for reserve()/capacity() were added to contiguous opaque containers. Task-number: PYSIDE-1605 Change-Id: I82dd2efc4a1831600aa2fae9427e5d13a67cdd11 Reviewed-by: Cristian Maureira-Fredes (cherry picked from commit 683314b3491dea17f0205baa2976e71595ccb05d) Reviewed-by: Qt Cherry-pick Bot --- examples/widgets/painting/plot/plot.py | 1 + sources/shiboken6/doc/typesystem_containers.rst | 12 ++++++ .../generator/shiboken/cppgenerator_container.cpp | 2 + sources/shiboken6/libshiboken/sbkcontainer.h | 49 ++++++++++++++++++++++ 4 files changed, 64 insertions(+) diff --git a/examples/widgets/painting/plot/plot.py b/examples/widgets/painting/plot/plot.py index 156a6408d..a125c3253 100644 --- a/examples/widgets/painting/plot/plot.py +++ b/examples/widgets/painting/plot/plot.py @@ -63,6 +63,7 @@ class PlotWidget(QWidget): self._timer.timeout.connect(self.shift) self._points = QPointList() + self._points.reserve(WIDTH) self._x = 0 self._delta_x = 0.05 self._half_height = HEIGHT / 2 diff --git a/sources/shiboken6/doc/typesystem_containers.rst b/sources/shiboken6/doc/typesystem_containers.rst index ac22df558..c3a60a707 100644 --- a/sources/shiboken6/doc/typesystem_containers.rst +++ b/sources/shiboken6/doc/typesystem_containers.rst @@ -47,3 +47,15 @@ the STL and the Qt naming convention (which resembles Python's) are supported: +-------------------------------------------+-----------------------------------+ | ``pop_front()``, ``removeFirst()`` | Removes the first element. | +-------------------------------------------+-----------------------------------+ + | ``reserve(size)`` | For containers that support it | + | | (``std::vector``, ``QList``), | + | | allocate memory for at least | + | | ``size`` elements, preventing | + | | reallocations. | + +-------------------------------------------+-----------------------------------+ + | ``capacity()`` | For containers that support it | + | | (``std::vector``, ``QList``), | + | | return the number of elements | + | | that can be stored without | + | | reallocation. | + +-------------------------------------------+-----------------------------------+ diff --git a/sources/shiboken6/generator/shiboken/cppgenerator_container.cpp b/sources/shiboken6/generator/shiboken/cppgenerator_container.cpp index 1fa7fc463..7d20d2f16 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator_container.cpp +++ b/sources/shiboken6/generator/shiboken/cppgenerator_container.cpp @@ -175,6 +175,8 @@ CppGenerator::OpaqueContainerData writeNoArgsMethod(s, privateObjType, "pop_front"); writeMethod(s, privateObjType, "pop_front", "removeFirst"); // Qt convention } + writeMethod(s, privateObjType, "reserve"); + writeNoArgsMethod(s, privateObjType, "capacity"); s << "{nullptr, nullptr, 0, nullptr} // Sentinel\n" << outdent << "};\n\n"; diff --git a/sources/shiboken6/libshiboken/sbkcontainer.h b/sources/shiboken6/libshiboken/sbkcontainer.h index 97062a198..65bb8646e 100644 --- a/sources/shiboken6/libshiboken/sbkcontainer.h +++ b/sources/shiboken6/libshiboken/sbkcontainer.h @@ -67,6 +67,21 @@ struct ShibokenContainerValueConverter static std::optional convertValueToCpp(PyObject pyArg); }; +// SFINAE test for the presence of reserve() in a sequence container (std::vector/QList) +template +class ShibokenContainerHasReserve +{ +private: + using YesType = char[1]; + using NoType = char[2]; + + template static YesType& test( decltype(&C::reserve) ) ; + template static NoType& test(...); + +public: + enum { value = sizeof(test(nullptr)) == sizeof(YesType) }; +}; + template class ShibokenSequenceContainerPrivate // Helper for sequence type containers { @@ -212,6 +227,40 @@ public: Py_RETURN_NONE; } + // Support for containers with reserve/capacity + static PyObject *reserve(PyObject *self, PyObject *pyArg) + { + auto *d = get(self); + if (PyLong_Check(pyArg) == 0) { + PyErr_SetString(PyExc_TypeError, "wrong type passed to reserve()."); + return nullptr; + } + if (d->m_const) { + PyErr_SetString(PyExc_TypeError, msgModifyConstContainer); + return nullptr; + } + + if constexpr (ShibokenContainerHasReserve::value) { + const Py_ssize_t size = PyLong_AsSsize_t(pyArg); + d->m_list->reserve(size); + } else { + PyErr_SetString(PyExc_TypeError, "Container does not support reserve()."); + return nullptr; + } + + Py_RETURN_NONE; + } + + static PyObject *capacity(PyObject *self) + { + Py_ssize_t result = -1; + if constexpr (ShibokenContainerHasReserve::value) { + const auto *d = get(self); + result = d->m_list->capacity(); + } + return PyLong_FromSsize_t(result); + } + static ShibokenSequenceContainerPrivate *get(PyObject *self) { auto *data = reinterpret_cast(self); -- cgit v1.2.3