1 // This is the support for QString.
2 //
3 // Copyright (c) 2021 Riverbank Computing Limited <info@riverbankcomputing.com>
4 //
5 // This file is part of PyQt5.
6 //
7 // This file may be used under the terms of the GNU General Public License
8 // version 3.0 as published by the Free Software Foundation and appearing in
9 // the file LICENSE included in the packaging of this file. Please review the
10 // following information to ensure the GNU General Public License version 3.0
11 // requirements will be met: http://www.gnu.org/copyleft/gpl.html.
12 //
13 // If you do not wish to use this file under the terms of the GPL version 3.0
14 // then you may purchase a commercial license. For more information contact
15 // info@riverbankcomputing.com.
16 //
17 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
18 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19
20
21 #include <Python.h>
22 #include <string.h>
23
24 #include <QString>
25 #include <QVector>
26
27 #include "qpycore_api.h"
28
29 #include "sipAPIQtCore.h"
30
31
32 // Work out if we should enable PEP 393 support. This is complicated by the
33 // broken LLVM that XCode v4 installs.
34 #if PY_VERSION_HEX >= 0x03030000
35 #if defined(Q_OS_MAC)
36 #if !defined(__llvm__) || defined(__clang__)
37 // Python v3.3 or later on a Mac using either g++ or Clang, but not LLVM.
38 #define PYQT_PEP_393
39 #endif
40 #else
41 // Python v3.3 or later on a non-Mac.
42 #define PYQT_PEP_393
43 #endif
44 #endif
45
46
47 // Convert a QString to a Python Unicode object.
qpycore_PyObject_FromQString(const QString & qstr)48 PyObject *qpycore_PyObject_FromQString(const QString &qstr)
49 {
50 PyObject *obj;
51
52 #if defined(PYQT_PEP_393)
53 // We have to work out exactly which kind to use. We assume ASCII while we
54 // are checking so that we only go through the string once in the most
55 // common case. Note that we can't use PyUnicode_FromKindAndData() because
56 // it doesn't handle surrogates in UCS2 strings.
57 int qt_len = qstr.length();
58 int kind;
59 void *data;
60
61 if ((obj = sipUnicodeNew(qt_len, 0x007f, &kind, &data)) == NULL)
62 return NULL;
63
64 const QChar *qch = qstr.constData();
65
66 for (int qt_i = 0; qt_i < qt_len; ++qt_i)
67 {
68 ushort uch = qch->unicode();
69
70 if (uch > 0x007f)
71 {
72 // This is useless.
73 Py_DECREF(obj);
74
75 // Work out what kind we really need and what the Python length
76 // should be.
77 uint maxchar = 0x00ff;
78
79 int py_len = qt_len;
80
81 while (qt_i < qt_len)
82 {
83 uch = qch->unicode();
84
85 if (uch > 0x00ff)
86 {
87 if (maxchar == 0x00ff)
88 maxchar = 0x00ffff;
89
90 // See if this is a surrogate pair. Note that we cannot
91 // trust that the QString is terminated by a null QChar.
92 if (qch->isHighSurrogate() && qt_i + 1 < qt_len && (qch + 1)->isLowSurrogate())
93 {
94 maxchar = 0x10ffff;
95 --py_len;
96 ++qch;
97 ++qt_i;
98 }
99 }
100
101 ++qch;
102 ++qt_i;
103 }
104
105 // Create the correctly sized object.
106 if ((obj = sipUnicodeNew(py_len, maxchar, &kind, &data)) == NULL)
107 return NULL;
108
109 qch = qstr.constData();
110
111 int qt_i2 = 0;
112
113 for (int py_i = 0; py_i < py_len; ++py_i)
114 {
115 uint py_ch;
116
117 if (qch->isHighSurrogate() && qt_i2 + 1 < qt_len && (qch + 1)->isLowSurrogate())
118 {
119 py_ch = QChar::surrogateToUcs4(*qch, *(qch + 1));
120 ++qt_i2;
121 ++qch;
122 }
123 else
124 {
125 py_ch = qch->unicode();
126 }
127
128 ++qt_i2;
129 ++qch;
130
131 sipUnicodeWrite(kind, data, py_i, py_ch);
132 }
133
134 break;
135 }
136
137 ++qch;
138
139 sipUnicodeWrite(kind, data, qt_i, uch);
140 }
141 #elif defined(Py_UNICODE_WIDE)
142 QVector<uint> ucs4 = qstr.toUcs4();
143
144 if ((obj = PyUnicode_FromUnicode(NULL, ucs4.size())) == NULL)
145 return NULL;
146
147 memcpy(PyUnicode_AS_UNICODE(obj), ucs4.constData(),
148 ucs4.size() * sizeof (Py_UNICODE));
149 #else
150 if ((obj = PyUnicode_FromUnicode(NULL, qstr.length())) == NULL)
151 return NULL;
152
153 memcpy(PyUnicode_AS_UNICODE(obj), qstr.utf16(),
154 qstr.length() * sizeof (Py_UNICODE));
155 #endif
156
157 return obj;
158 }
159
160
161 // Convert a Python string object to a QString.
qpycore_PyObject_AsQString(PyObject * obj)162 QString qpycore_PyObject_AsQString(PyObject *obj)
163 {
164 #if PY_MAJOR_VERSION < 3
165 if (PyString_Check(obj))
166 {
167 const char *obj_s = PyString_AsString(obj);
168
169 if (!obj_s)
170 return QString();
171
172 return QString::fromUtf8(obj_s);
173 }
174 #endif
175
176 #if defined(PYQT_PEP_393)
177 int char_size;
178 Py_ssize_t len;
179 void *data = sipUnicodeData(obj, &char_size, &len);
180
181 if (char_size == 1)
182 return QString::fromLatin1(reinterpret_cast<char *>(data), len);
183
184 if (char_size == 2)
185 // The (QChar *) cast should be safe.
186 return QString(reinterpret_cast<QChar *>(data), len);
187
188 if (char_size == 4)
189 return QString::fromUcs4(reinterpret_cast<uint *>(data), len);
190
191 return QString();
192 #elif defined(Py_UNICODE_WIDE)
193 return QString::fromUcs4((const uint *)PyUnicode_AS_UNICODE(obj),
194 PyUnicode_GET_SIZE(obj));
195 #else
196 return QString::fromUtf16((const ushort *)PyUnicode_AS_UNICODE(obj),
197 PyUnicode_GET_SIZE(obj));
198 #endif
199 }
200