1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#if 0
5// keep existing syncqt header working after the move of the class
6// into qstringconverter_base
7#pragma qt_class(QStringConverter)
8#pragma qt_class(QStringConverterBase)
9#endif
10
11#ifndef QSTRINGCONVERTER_H
12#define QSTRINGCONVERTER_H
13
14#include <QtCore/qstringconverter_base.h>
15#include <QtCore/qstring.h>
16#include <QtCore/qstringbuilder.h>
17
18QT_BEGIN_NAMESPACE
19
20class QStringEncoder : public QStringConverter
21{
22protected:
23 constexpr explicit QStringEncoder(const Interface *i) noexcept
24 : QStringConverter(i)
25 {}
26public:
27 constexpr QStringEncoder() noexcept
28 : QStringConverter()
29 {}
30 constexpr explicit QStringEncoder(Encoding encoding, Flags flags = Flag::Default)
31 : QStringConverter(encoding, flags)
32 {}
33 explicit QStringEncoder(const char *name, Flags flags = Flag::Default)
34 : QStringConverter(name, flags)
35 {}
36
37#if defined(Q_QDOC)
38 QByteArray operator()(const QString &in);
39 QByteArray operator()(QStringView in);
40 QByteArray encode(const QString &in);
41 QByteArray encode(QStringView in);
42#else
43 template<typename T>
44 struct DecodedData
45 {
46 QStringEncoder *encoder;
47 T data;
48 operator QByteArray() const { return encoder->encodeAsByteArray(in: data); }
49 };
50 Q_WEAK_OVERLOAD
51 DecodedData<const QString &> operator()(const QString &str)
52 { return DecodedData<const QString &>{.encoder: this, .data: str}; }
53 DecodedData<QStringView> operator()(QStringView in)
54 { return DecodedData<QStringView>{.encoder: this, .data: in}; }
55 Q_WEAK_OVERLOAD
56 DecodedData<const QString &> encode(const QString &str)
57 { return DecodedData<const QString &>{.encoder: this, .data: str}; }
58 DecodedData<QStringView> encode(QStringView in)
59 { return DecodedData<QStringView>{.encoder: this, .data: in}; }
60#endif
61
62 qsizetype requiredSpace(qsizetype inputLength) const
63 { return iface ? iface->fromUtf16Len(inputLength) : 0; }
64 char *appendToBuffer(char *out, QStringView in)
65 {
66 if (!iface) {
67 state.invalidChars = 1;
68 return out;
69 }
70 return iface->fromUtf16(out, in, &state);
71 }
72private:
73 QByteArray encodeAsByteArray(QStringView in)
74 {
75 if (!iface) {
76 // ensure that hasError returns true
77 state.invalidChars = 1;
78 return {};
79 }
80 QByteArray result(iface->fromUtf16Len(in.size()), Qt::Uninitialized);
81 char *out = result.data();
82 out = iface->fromUtf16(out, in, &state);
83 result.truncate(pos: out - result.constData());
84 return result;
85 }
86
87};
88
89class QStringDecoder : public QStringConverter
90{
91protected:
92 constexpr explicit QStringDecoder(const Interface *i) noexcept
93 : QStringConverter(i)
94 {}
95public:
96 constexpr explicit QStringDecoder(Encoding encoding, Flags flags = Flag::Default)
97 : QStringConverter(encoding, flags)
98 {}
99 constexpr QStringDecoder() noexcept
100 : QStringConverter()
101 {}
102 explicit QStringDecoder(const char *name, Flags f = Flag::Default)
103 : QStringConverter(name, f)
104 {}
105
106#if defined(Q_QDOC)
107 QString operator()(const QByteArray &ba);
108 QString operator()(QByteArrayView ba);
109 QString decode(const QByteArray &ba);
110 QString decode(QByteArrayView ba);
111#else
112 template<typename T>
113 struct EncodedData
114 {
115 QStringDecoder *decoder;
116 T data;
117 operator QString() const { return decoder->decodeAsString(in: data); }
118 };
119 Q_WEAK_OVERLOAD
120 EncodedData<const QByteArray &> operator()(const QByteArray &ba)
121 { return EncodedData<const QByteArray &>{.decoder: this, .data: ba}; }
122 EncodedData<QByteArrayView> operator()(QByteArrayView ba)
123 { return EncodedData<QByteArrayView>{.decoder: this, .data: ba}; }
124 Q_WEAK_OVERLOAD
125 EncodedData<const QByteArray &> decode(const QByteArray &ba)
126 { return EncodedData<const QByteArray &>{.decoder: this, .data: ba}; }
127 EncodedData<QByteArrayView> decode(QByteArrayView ba)
128 { return EncodedData<QByteArrayView>{.decoder: this, .data: ba}; }
129#endif
130
131 qsizetype requiredSpace(qsizetype inputLength) const
132 { return iface ? iface->toUtf16Len(inputLength) : 0; }
133 QChar *appendToBuffer(QChar *out, QByteArrayView ba)
134 {
135 if (!iface) {
136 state.invalidChars = 1;
137 return out;
138 }
139 return iface->toUtf16(out, ba, &state);
140 }
141 char16_t *appendToBuffer(char16_t *out, QByteArrayView ba)
142 { return reinterpret_cast<char16_t *>(appendToBuffer(out: reinterpret_cast<QChar *>(out), ba)); }
143
144 Q_CORE_EXPORT static QStringDecoder decoderForHtml(QByteArrayView data);
145
146private:
147 QString decodeAsString(QByteArrayView in)
148 {
149 if (!iface) {
150 // ensure that hasError returns true
151 state.invalidChars = 1;
152 return {};
153 }
154 QString result(iface->toUtf16Len(in.size()), Qt::Uninitialized);
155 const QChar *out = iface->toUtf16(result.data(), in, &state);
156 result.truncate(pos: out - result.constData());
157 return result;
158 }
159};
160
161
162#if defined(QT_USE_FAST_OPERATOR_PLUS) || defined(QT_USE_QSTRINGBUILDER)
163template <typename T>
164struct QConcatenable<QStringDecoder::EncodedData<T>>
165 : private QAbstractConcatenable
166{
167 typedef QChar type;
168 typedef QString ConvertTo;
169 enum { ExactSize = false };
170 static qsizetype size(const QStringDecoder::EncodedData<T> &s) { return s.decoder->requiredSpace(s.data.size()); }
171 static inline void appendTo(const QStringDecoder::EncodedData<T> &s, QChar *&out)
172 {
173 out = s.decoder->appendToBuffer(out, s.data);
174 }
175};
176
177template <typename T>
178struct QConcatenable<QStringEncoder::DecodedData<T>>
179 : private QAbstractConcatenable
180{
181 typedef char type;
182 typedef QByteArray ConvertTo;
183 enum { ExactSize = false };
184 static qsizetype size(const QStringEncoder::DecodedData<T> &s) { return s.encoder->requiredSpace(s.data.size()); }
185 static inline void appendTo(const QStringEncoder::DecodedData<T> &s, char *&out)
186 {
187 out = s.encoder->appendToBuffer(out, s.data);
188 }
189};
190
191template <typename T>
192QString &operator+=(QString &a, const QStringDecoder::EncodedData<T> &b)
193{
194 qsizetype len = a.size() + QConcatenable<QStringDecoder::EncodedData<T>>::size(b);
195 a.reserve(asize: len);
196 QChar *it = a.data() + a.size();
197 QConcatenable<QStringDecoder::EncodedData<T>>::appendTo(b, it);
198 a.resize(size: qsizetype(it - a.constData())); //may be smaller than len
199 return a;
200}
201
202template <typename T>
203QByteArray &operator+=(QByteArray &a, const QStringEncoder::DecodedData<T> &b)
204{
205 qsizetype len = a.size() + QConcatenable<QStringEncoder::DecodedData<T>>::size(b);
206 a.reserve(asize: len);
207 char *it = a.data() + a.size();
208 QConcatenable<QStringEncoder::DecodedData<T>>::appendTo(b, it);
209 a.resize(size: qsizetype(it - a.constData())); //may be smaller than len
210 return a;
211}
212#endif
213
214QT_END_NAMESPACE
215
216#endif
217

source code of qtbase/src/corelib/text/qstringconverter.h