diff options
Diffstat (limited to 'sources/pyside6/libpyside/pysideclassdecorator_p.h')
-rw-r--r-- | sources/pyside6/libpyside/pysideclassdecorator_p.h | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/sources/pyside6/libpyside/pysideclassdecorator_p.h b/sources/pyside6/libpyside/pysideclassdecorator_p.h new file mode 100644 index 000000000..6068f6a2e --- /dev/null +++ b/sources/pyside6/libpyside/pysideclassdecorator_p.h @@ -0,0 +1,164 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef CLASSDECORATOR_P_H +#define CLASSDECORATOR_P_H + +#include <pysidemacros.h> + +#include <sbkpython.h> +#include <pep384ext.h> + +#include <QtCore/QByteArray> + +#include <array> +#include <string> + +/// Helpers for class decorators with parameters +namespace PySide::ClassDecorator { + +/// Base class for private objects of class decorators with parameters +class PYSIDE_API DecoratorPrivate +{ +public: + Q_DISABLE_COPY_MOVE(DecoratorPrivate) + + virtual ~DecoratorPrivate(); + + /// Virtual function which is passed the decorated class type + /// \param args Decorated class type argument + /// \return class with reference count increased if the call was successful, + /// else nullptr + virtual PyObject *tp_call(PyObject *self, PyObject *args, PyObject * /* kw */) = 0; + + /// Virtual function which is passed the decorator parameters + /// \param args Decorator arguments + /// \return 0 if the parameters are correct + virtual int tp_init(PyObject *self, PyObject *args, PyObject *kwds) = 0; + virtual const char *name() const = 0; + + /// Helper that returns DecoratorPrivate instance from a PyObject + template <class DerivedPrivate> + static DerivedPrivate *get(PyObject *o) + { return static_cast<DerivedPrivate *>(DecoratorPrivate::getPrivate(o)); } + +protected: + /// Check mode for the arguments of the call operator + enum class CheckMode { None, WrappedType, QObjectType }; + + DecoratorPrivate() noexcept; + static DecoratorPrivate *getPrivate(PyObject *o); + + /// Helper for checking the arguments of the call operator + /// \param args Arguments + /// \param checkMode Type check mode + /// \return The type object extracted from args tuple (borrowed reference) + /// if the argument is a matching type + PyObject *tp_call_check(PyObject *args, + CheckMode checkMode = CheckMode::QObjectType) const; +}; + +/// Base class for private objects of class decorator with a string parameter +class PYSIDE_API StringDecoratorPrivate : public DecoratorPrivate +{ +public: + /// Init function that retrieves the string parameter using convertToString() + int tp_init(PyObject *self, PyObject *args, PyObject *kwds) override; + + QByteArray string() const { return m_string; } + +protected: + /// Helper function that retrieves the string parameter + /// \param self self + /// \param args Arguments + /// \return 0 if the parameter is correct, else -1 (for tp_init()) + int convertToString(PyObject *self, PyObject *args); + +private: + QByteArray m_string; +}; + +/// Base class for private objects of class decorator with a type parameter +class PYSIDE_API TypeDecoratorPrivate : public DecoratorPrivate +{ +public: + /// Init function that retrieves the type parameter using convertToType() + int tp_init(PyObject *self, PyObject *args, PyObject *kwds) override; + + PyTypeObject *type() const { return m_type; } + +protected: + /// Helper function that retrieves the type parameter + /// \param self self + /// \param args Arguments + /// \return 0 if the parameter is correct, else -1 (for tp_init()) + int convertToType(PyObject *self, PyObject *args); + +private: + PyTypeObject *m_type = nullptr; +}; + +} // namespace PySide::ClassDecorator + +extern "C" +{ +LIBSHIBOKEN_API void Sbk_object_dealloc(PyObject *self); + +/// Python type for class decorators with DecoratorPrivate +struct PYSIDE_API PySideClassDecorator +{ + PyObject_HEAD + PySide::ClassDecorator::DecoratorPrivate *d; +}; +}; + +namespace PySide::ClassDecorator { + +/// Helper template providing the methods (slots) for class decorators +template <class DecoratorPrivate> +struct Methods +{ + static PyObject *tp_new(PyTypeObject *subtype) + { + auto *result = PepExt_TypeCallAlloc<PySideClassDecorator>(subtype, 0); + result->d = new DecoratorPrivate; + return reinterpret_cast<PyObject *>(result); + } + + static void tp_free(void *self) + { + auto pySelf = reinterpret_cast<PyObject *>(self); + auto decorator = reinterpret_cast<PySideClassDecorator *>(self); + delete decorator->d; + PepExt_TypeCallFree(Py_TYPE(pySelf)->tp_base, self); + } + + static PyObject *tp_call(PyObject *self, PyObject *args, PyObject *kwds) + { + auto *decorator = reinterpret_cast<PySideClassDecorator *>(self); + return decorator->d->tp_call(self, args, kwds); + } + + static int tp_init(PyObject *self, PyObject *args, PyObject *kwds) + { + auto *decorator = reinterpret_cast<PySideClassDecorator *>(self); + return decorator->d->tp_init(self, args, kwds); + } + + using TypeSlots = std::array<PyType_Slot, 6>; + + static TypeSlots typeSlots() + { + return { {{Py_tp_call, reinterpret_cast<void *>(tp_call)}, + {Py_tp_init, reinterpret_cast<void *>(tp_init)}, + {Py_tp_new, reinterpret_cast<void *>(tp_new)}, + {Py_tp_free, reinterpret_cast<void *>(tp_free)}, + {Py_tp_dealloc, reinterpret_cast<void *>(Sbk_object_dealloc)}, + {0, nullptr}} + }; + } +}; + +} // namespace PySide::ClassDecorator + +#endif // CLASSDECORATOR_P_H |