Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 09:26:48

0001 // Copyright (C) 2020 The Qt Company Ltd.
0002 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0003 // Qt-Security score:critical reason:data-parser
0004 
0005 #if 0
0006 // keep existing syncqt header working after the move of the class
0007 // into qstringconverter_base
0008 #pragma qt_class(QStringConverter)
0009 #pragma qt_class(QStringConverterBase)
0010 #endif
0011 
0012 #ifndef QSTRINGCONVERTER_H
0013 #define QSTRINGCONVERTER_H
0014 
0015 #include <QtCore/qstringconverter_base.h>
0016 #include <QtCore/qstring.h>
0017 #include <QtCore/qstringbuilder.h>
0018 
0019 QT_BEGIN_NAMESPACE
0020 
0021 class QStringEncoder : public QStringConverter
0022 {
0023 protected:
0024     constexpr explicit QStringEncoder(const Interface *i) noexcept
0025         : QStringConverter(i)
0026     {}
0027 public:
0028     constexpr QStringEncoder() noexcept
0029         : QStringConverter()
0030     {}
0031     constexpr explicit QStringEncoder(Encoding encoding, Flags flags = Flag::Default)
0032         : QStringConverter(encoding, flags)
0033     {}
0034     explicit QStringEncoder(QAnyStringView name, Flags flags = Flag::Default)
0035         : QStringConverter(name, flags)
0036     {}
0037 
0038     template<typename T>
0039     struct DecodedData
0040     {
0041         QStringEncoder *encoder;
0042         T data;
0043         operator QByteArray() const { return encoder->encodeAsByteArray(data); }
0044     };
0045     Q_WEAK_OVERLOAD
0046     DecodedData<const QString &> operator()(const QString &str)
0047     { return DecodedData<const QString &>{this, str}; }
0048     DecodedData<QStringView> operator()(QStringView in)
0049     { return DecodedData<QStringView>{this, in}; }
0050     Q_WEAK_OVERLOAD
0051     DecodedData<const QString &> encode(const QString &str)
0052     { return DecodedData<const QString &>{this, str}; }
0053     DecodedData<QStringView> encode(QStringView in)
0054     { return DecodedData<QStringView>{this, in}; }
0055 
0056     qsizetype requiredSpace(qsizetype inputLength) const
0057     { return iface ? iface->fromUtf16Len(inputLength) : 0; }
0058     char *appendToBuffer(char *out, QStringView in)
0059     {
0060         if (!iface) {
0061             state.invalidChars = 1;
0062             return out;
0063         }
0064         return iface->fromUtf16(out, in, &state);
0065     }
0066 private:
0067     QByteArray encodeAsByteArray(QStringView in)
0068     {
0069         if (!iface) {
0070             // ensure that hasError returns true
0071             state.invalidChars = 1;
0072             return {};
0073         }
0074         QByteArray result(iface->fromUtf16Len(in.size()), Qt::Uninitialized);
0075         char *out = result.data();
0076         out = iface->fromUtf16(out, in, &state);
0077         result.truncate(out - result.constData());
0078         return result;
0079     }
0080 
0081 };
0082 
0083 class QStringDecoder : public QStringConverter
0084 {
0085 protected:
0086     constexpr explicit QStringDecoder(const Interface *i) noexcept
0087         : QStringConverter(i)
0088     {}
0089 public:
0090     constexpr explicit QStringDecoder(Encoding encoding, Flags flags = Flag::Default)
0091         : QStringConverter(encoding, flags)
0092     {}
0093     constexpr QStringDecoder() noexcept
0094         : QStringConverter()
0095     {}
0096     explicit QStringDecoder(QAnyStringView name, Flags f = Flag::Default)
0097         : QStringConverter(name, f)
0098     {}
0099 
0100     template<typename T>
0101     struct EncodedData
0102     {
0103         QStringDecoder *decoder;
0104         T data;
0105         operator QString() const { return decoder->decodeAsString(data); }
0106     };
0107     Q_WEAK_OVERLOAD
0108     EncodedData<const QByteArray &> operator()(const QByteArray &ba)
0109     { return EncodedData<const QByteArray &>{this, ba}; }
0110     EncodedData<QByteArrayView> operator()(QByteArrayView ba)
0111     { return EncodedData<QByteArrayView>{this, ba}; }
0112     Q_WEAK_OVERLOAD
0113     EncodedData<const QByteArray &> decode(const QByteArray &ba)
0114     { return EncodedData<const QByteArray &>{this, ba}; }
0115     EncodedData<QByteArrayView> decode(QByteArrayView ba)
0116     { return EncodedData<QByteArrayView>{this, ba}; }
0117 
0118     qsizetype requiredSpace(qsizetype inputLength) const
0119     { return iface ? iface->toUtf16Len(inputLength) : 0; }
0120     QChar *appendToBuffer(QChar *out, QByteArrayView ba)
0121     {
0122         if (!iface) {
0123             state.invalidChars = 1;
0124             return out;
0125         }
0126         return iface->toUtf16(out, ba, &state);
0127     }
0128     char16_t *appendToBuffer(char16_t *out, QByteArrayView ba)
0129     { return reinterpret_cast<char16_t *>(appendToBuffer(reinterpret_cast<QChar *>(out), ba)); }
0130 
0131     Q_CORE_EXPORT static QStringDecoder decoderForHtml(QByteArrayView data);
0132 
0133 private:
0134     QString decodeAsString(QByteArrayView in)
0135     {
0136         if (!iface) {
0137             // ensure that hasError returns true
0138             state.invalidChars = 1;
0139             return {};
0140         }
0141         QString result(iface->toUtf16Len(in.size()), Qt::Uninitialized);
0142         const QChar *out = iface->toUtf16(result.data(), in, &state);
0143         result.truncate(out - result.constData());
0144         return result;
0145     }
0146 };
0147 
0148 
0149 #if defined(QT_USE_FAST_OPERATOR_PLUS) || defined(QT_USE_QSTRINGBUILDER)
0150 template <typename T>
0151 struct QConcatenable<QStringDecoder::EncodedData<T>>
0152         : private QAbstractConcatenable
0153 {
0154     typedef QChar type;
0155     typedef QString ConvertTo;
0156     enum { ExactSize = false };
0157     static qsizetype size(const QStringDecoder::EncodedData<T> &s) { return s.decoder->requiredSpace(s.data.size()); }
0158     static inline void appendTo(const QStringDecoder::EncodedData<T> &s, QChar *&out)
0159     {
0160         out = s.decoder->appendToBuffer(out, s.data);
0161     }
0162 };
0163 
0164 template <typename T>
0165 struct QConcatenable<QStringEncoder::DecodedData<T>>
0166         : private QAbstractConcatenable
0167 {
0168     typedef char type;
0169     typedef QByteArray ConvertTo;
0170     enum { ExactSize = false };
0171     static qsizetype size(const QStringEncoder::DecodedData<T> &s) { return s.encoder->requiredSpace(s.data.size()); }
0172     static inline void appendTo(const QStringEncoder::DecodedData<T> &s, char *&out)
0173     {
0174         out = s.encoder->appendToBuffer(out, s.data);
0175     }
0176 };
0177 
0178 template <typename T>
0179 QString &operator+=(QString &a, const QStringDecoder::EncodedData<T> &b)
0180 {
0181     qsizetype len = a.size() + QConcatenable<QStringDecoder::EncodedData<T>>::size(b);
0182     a.reserve(len);
0183     QChar *it = a.data() + a.size();
0184     QConcatenable<QStringDecoder::EncodedData<T>>::appendTo(b, it);
0185     a.resize(qsizetype(it - a.constData())); //may be smaller than len
0186     return a;
0187 }
0188 
0189 template <typename T>
0190 QByteArray &operator+=(QByteArray &a, const QStringEncoder::DecodedData<T> &b)
0191 {
0192     qsizetype len = a.size() + QConcatenable<QStringEncoder::DecodedData<T>>::size(b);
0193     a.reserve(len);
0194     char *it = a.data() + a.size();
0195     QConcatenable<QStringEncoder::DecodedData<T>>::appendTo(b, it);
0196     a.resize(qsizetype(it - a.constData())); //may be smaller than len
0197     return a;
0198 }
0199 #endif
0200 
0201 template <typename InputIterator>
0202 void QString::assign_helper_char8(InputIterator first, InputIterator last)
0203 {
0204     static_assert(!QString::is_contiguous_iterator_v<InputIterator>,
0205         "Internal error: Should have been handed over to the QAnyStringView overload."
0206     );
0207 
0208     using ValueType = typename std::iterator_traits<InputIterator>::value_type;
0209     constexpr bool IsFwdIt = std::is_convertible_v<
0210         typename std::iterator_traits<InputIterator>::iterator_category,
0211         std::forward_iterator_tag
0212     >;
0213 
0214     resize(0);
0215     // In case of not being shared, there is the possibility of having free space at begin
0216     // even after the resize to zero.
0217     if (const auto offset = d.freeSpaceAtBegin())
0218         d.setBegin(d.begin() - offset);
0219 
0220     if constexpr (IsFwdIt)
0221         reserve(static_cast<qsizetype>(std::distance(first, last)));
0222 
0223     auto toUtf16 = QStringDecoder(QStringDecoder::Utf8);
0224     auto availableCapacity = d.constAllocatedCapacity();
0225     auto *dst = d.data();
0226     auto *dend = d.data() + availableCapacity;
0227 
0228     while (true) {
0229         if (first == last) {                                    // ran out of input elements
0230             Q_ASSERT(!std::less<>{}(dend, dst));
0231             d.size = dst - d.begin();
0232             return;
0233         }
0234         const ValueType next = *first; // decays proxies, if any
0235         const auto chunk = QUtf8StringView(&next, 1);
0236         // UTF-8 characters can have a maximum size of 4 bytes and may result in a surrogate
0237         // pair of UTF-16 code units. In the input-iterator case, we don't know the size
0238         // and would need to always reserve space for 2 code units. To keep our promise
0239         // of 'not allocating if it fits', we have to pre-check this condition.
0240         //          We know that it fits in the forward-iterator case.
0241         if constexpr (!IsFwdIt) {
0242             constexpr qsizetype Pair = 2;
0243             char16_t buf[Pair];
0244             const qptrdiff n = toUtf16.appendToBuffer(buf, chunk) - buf;
0245             if (dend - dst < n) {                               // ran out of allocated memory
0246                 const auto offset = dst - d.begin();
0247                 reallocData(d.constAllocatedCapacity() + Pair, QArrayData::Grow);
0248                 // update the pointers since we've re-allocated
0249                 availableCapacity = d.constAllocatedCapacity();
0250                 dst = d.data() + offset;
0251                 dend = d.data() + availableCapacity;
0252             }
0253             dst = std::copy_n(buf, n, dst);
0254         } else {                                                // take the fast path
0255             dst = toUtf16.appendToBuffer(dst, chunk);
0256         }
0257         ++first;
0258     }
0259 }
0260 
0261 QT_END_NAMESPACE
0262 
0263 #endif