aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken6/libshiboken/sbkstring.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken6/libshiboken/sbkstring.cpp')
-rw-r--r--sources/shiboken6/libshiboken/sbkstring.cpp248
1 files changed, 248 insertions, 0 deletions
diff --git a/sources/shiboken6/libshiboken/sbkstring.cpp b/sources/shiboken6/libshiboken/sbkstring.cpp
new file mode 100644
index 000000000..1471cd7fe
--- /dev/null
+++ b/sources/shiboken6/libshiboken/sbkstring.cpp
@@ -0,0 +1,248 @@
+// Copyright (C) 2019 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
+
+#include "sbkstring.h"
+#include "sbkstaticstrings_p.h"
+#include "autodecref.h"
+
+namespace Shiboken::String
+{
+
+// PYSIDE-795: Redirecting PySequence to Iterable
+bool checkIterable(PyObject *obj)
+{
+ return PyObject_HasAttr(obj, Shiboken::PyMagicName::iter());
+}
+
+static PyObject *initPathLike()
+{
+ PyObject *PathLike{};
+ auto osmodule = PyImport_ImportModule("os");
+ if (osmodule == nullptr
+ || (PathLike = PyObject_GetAttrString(osmodule, "PathLike")) == nullptr) {
+ PyErr_Print();
+ Py_FatalError("cannot import os.PathLike");
+ }
+ return PathLike;
+}
+
+// PYSIDE-1499: Migrate to pathlib.Path and support __fspath__ in PySide
+bool checkPath(PyObject *path)
+{
+ // Let normal strings through, unchanged.
+ if (PyUnicode_Check(path) || PyBytes_Check(path))
+ return true;
+ // Without the Limited API, we could look up an `__fspath__` class attribute.
+ // But we use `isinstance(os.PathLike)`, instead.
+ static PyObject *PathLike = initPathLike();
+ return PyObject_IsInstance(path, PathLike);
+}
+
+bool checkType(PyTypeObject *type)
+{
+ return type == &PyUnicode_Type;
+}
+
+bool check(PyObject *obj)
+{
+ return obj == Py_None || PyUnicode_Check(obj);
+}
+
+bool checkChar(PyObject *pyobj)
+{
+ return check(pyobj) && (len(pyobj) == 1);
+}
+
+bool isConvertible(PyObject *obj)
+{
+ return check(obj);
+}
+
+PyObject *fromCString(const char *value)
+{
+ return PyUnicode_FromString(value);
+}
+
+PyObject *fromCString(const char *value, int len)
+{
+ return PyUnicode_FromStringAndSize(value, len);
+}
+
+const char *toCString(PyObject *str)
+{
+ if (str == Py_None)
+ return nullptr;
+ if (PyUnicode_Check(str))
+ return _PepUnicode_AsString(str);
+ if (PyBytes_Check(str))
+ return PyBytes_AS_STRING(str);
+ return nullptr;
+}
+
+const char *toCString(PyObject *str, Py_ssize_t *len)
+{
+ if (str == Py_None) {
+ *len = 0;
+ return nullptr;
+ }
+ if (PyUnicode_Check(str)) {
+ // We need to encode the unicode string into utf8 to know the size of returned char *.
+ Shiboken::AutoDecRef uniStr(PyUnicode_AsUTF8String(str));
+ *len = PyBytes_GET_SIZE(uniStr.object());
+ // Return unicode from str instead of uniStr, because the lifetime of the returned pointer
+ // depends on the lifetime of str.
+ return _PepUnicode_AsString(str);
+ }
+ if (PyBytes_Check(str)) {
+ *len = PyBytes_GET_SIZE(str);
+ return PyBytes_AS_STRING(str);
+ }
+ return nullptr;
+}
+
+bool concat(PyObject **val1, PyObject *val2)
+{
+ if (PyUnicode_Check(*val1) && PyUnicode_Check(val2)) {
+ PyObject *result = PyUnicode_Concat(*val1, val2);
+ Py_DECREF(*val1);
+ *val1 = result;
+ return true;
+ }
+
+ if (PyBytes_Check(*val1) && PyBytes_Check(val2)) {
+ PyBytes_Concat(val1, val2);
+ return true;
+ }
+
+ return false;
+}
+
+PyObject *fromFormat(const char *format, ...)
+{
+ va_list argp;
+ va_start(argp, format);
+ PyObject *result = nullptr;
+ result = PyUnicode_FromFormatV(format, argp);
+ va_end(argp);
+ return result;
+}
+
+PyObject *fromStringAndSize(const char *str, Py_ssize_t size)
+{
+ return PyUnicode_FromStringAndSize(str, size);
+}
+
+int compare(PyObject *val1, const char *val2)
+{
+ if (PyUnicode_Check(val1))
+ return PyUnicode_CompareWithASCIIString(val1, val2);
+ return 0;
+
+}
+
+Py_ssize_t len(PyObject *str)
+{
+ if (str == Py_None)
+ return 0;
+
+ if (PyUnicode_Check(str))
+ return PepUnicode_GetLength(str);
+
+ if (PyBytes_Check(str))
+ return PyBytes_GET_SIZE(str);
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////
+//
+// Implementation of efficient Python strings
+// ------------------------------------------
+//
+// Instead of repetitively executing
+//
+// PyObject *attr = PyObject_GetAttrString(obj, "__name__");
+//
+// a helper of the form
+//
+// PyObject *name()
+// {
+// static PyObject *const s = Shiboken::String::createStaticString("__name__");
+// return result;
+// }
+//
+// can now be implemented, which registers the string into a static set avoiding
+// repetitive string creation. The resulting code looks like:
+//
+// PyObject *attr = PyObject_GetAttr(obj, name());
+//
+
+PyObject *createStaticString(const char *str)
+{
+ return PyUnicode_InternFromString(str);
+}
+
+///////////////////////////////////////////////////////////////////////
+//
+// PYSIDE-1019: Helper function for snake_case vs. camelCase names
+// ---------------------------------------------------------------
+//
+// When renaming dict entries, `BindingManager::getOverride` must
+// use adapted names.
+//
+// This might become more complex when we need to register
+// exceptions from this rule.
+//
+
+PyObject *getSnakeCaseName(const char *name, bool lower)
+{
+ /*
+ * Convert `camelCase` to `snake_case`.
+ * Gives up when there are two consecutive upper chars.
+ *
+ * Also functions beginning with `gl` followed by upper case stay
+ * unchanged since that are the special OpenGL functions.
+ */
+ if (!lower
+ || strlen(name) < 3
+ || (name[0] == 'g' && name[1] == 'l' && isupper(name[2])))
+ return createStaticString(name);
+
+ char new_name[200 + 1] = {};
+ const char *p = name;
+ char *q = new_name;
+ for (; *p && q - new_name < 200; ++p, ++q) {
+ if (isupper(*p)) {
+ if (p != name && isupper(*(p - 1)))
+ return createStaticString(name);
+ *q = '_';
+ ++q;
+ *q = tolower(*p);
+ }
+ else {
+ *q = *p;
+ }
+ }
+ return createStaticString(new_name);
+}
+
+PyObject *getSnakeCaseName(PyObject *name, bool lower)
+{
+ // This is all static strings, not refcounted.
+ if (lower)
+ return getSnakeCaseName(toCString(name), lower);
+ return name;
+}
+
+// Return a generic representation of a PyObject as does PyObject_Repr().
+// Note: PyObject_Repr() may not be called on self from __repr__() as this
+// causes a recursion.
+PyObject *repr(PyObject *o)
+{
+ if (o == nullptr)
+ return PyUnicode_FromString("<NULL>");
+ if (o == Py_None)
+ return PyUnicode_FromString("None");
+ return PyUnicode_FromFormat("<%s object at %p>", Py_TYPE(o)->tp_name, o);
+}
+
+} // namespace Shiboken::String