Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/QtCore/qstringconverter.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

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