Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:07:38

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