Revision control

++ // Copyright (C) 2022 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
++ // Qt-Security score:critical reason:data-parser
++
++ #ifndef QSTRINGCONVERTER_BASE_H
++ #define QSTRINGCONVERTER_BASE_H
++
++ #if 0
++ // IWYU pragma: private, include "qstringconverter.h"
++ // QStringConverter(Base) class are handled in qstringconverter
++ #pragma qt_sync_stop_processing
++ #endif
++
++ #include <optional>
++
++ #include <QtCore/qglobal.h> // QT_{BEGIN,END}_NAMESPACE
++ #include <QtCore/qflags.h> // Q_DECLARE_FLAGS
++ #include <QtCore/qcontainerfwd.h>
++ #include <QtCore/qstringfwd.h>
++
++ #include <cstring>
++
++ QT_BEGIN_NAMESPACE
++
++ class QByteArrayView;
++ class QChar;
++ class QByteArrayView;
++ class QStringView;
++
++ #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(Q_QDOC) && !defined(QT_BOOTSTRAPPED)
++ class QStringConverterBase
++ #else
++ class QStringConverter
++ #endif
++ {
++ public:
++ enum class Flag {
++ Default = 0,
++ Stateless = 0x1,
++ ConvertInvalidToNull = 0x2,
++ WriteBom = 0x4,
++ ConvertInitialBom = 0x8,
++ UsesIcu = 0x10,
++ };
++ Q_DECLARE_FLAGS(Flags, Flag)
++
++ struct State {
++ constexpr State(Flags f = Flag::Default) noexcept
++ : flags(f), state_data{0, 0, 0, 0} {}
++ ~State() { clear(); }
++
++ State(State &&other) noexcept
++ : flags(other.flags),
++ remainingChars(other.remainingChars),
++ invalidChars(other.invalidChars),
++ state_data{other.state_data[0], other.state_data[1],
++ other.state_data[2], other.state_data[3]},
++ clearFn(other.clearFn)
++ { other.clearFn = nullptr; }
++ State &operator=(State &&other) noexcept
++ {
++ clear();
++ flags = other.flags;
++ remainingChars = other.remainingChars;
++ invalidChars = other.invalidChars;
++ std::memmove(state_data, other.state_data, sizeof state_data); // self-assignment-safe
++ clearFn = other.clearFn;
++ other.clearFn = nullptr;
++ return *this;
++ }
++ Q_CORE_EXPORT void clear() noexcept;
++ Q_CORE_EXPORT void reset() noexcept;
++
++ Flags flags;
++ int internalState = 0;
++ qsizetype remainingChars = 0;
++ qsizetype invalidChars = 0;
++
++ union {
++ uint state_data[4];
++ void *d[2];
++ };
++ using ClearDataFn = void (*)(State *) noexcept;
++ ClearDataFn clearFn = nullptr;
++ private:
++ Q_DISABLE_COPY(State)
++ };
++
++ #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(Q_QDOC) && !defined(QT_BOOTSTRAPPED)
++ protected:
++ QStringConverterBase() = default;
++ ~QStringConverterBase() = default;
++ QStringConverterBase(QStringConverterBase &&) = default;
++ QStringConverterBase &operator=(QStringConverterBase &&) = default;
++ };
++
++ class QStringConverter : public QStringConverterBase
++ {
++ public:
++ #endif // Qt 6 compat for QStringConverterBase
++
++ enum Encoding {
++ Utf8,
++ #ifndef QT_BOOTSTRAPPED
++ Utf16,
++ Utf16LE,
++ Utf16BE,
++ Utf32,
++ Utf32LE,
++ Utf32BE,
++ #endif
++ Latin1,
++ System,
++ LastEncoding = System
++ };
++
++ protected:
++
++ struct Interface
++ {
++ using DecoderFn = QChar * (*)(QChar *out, QByteArrayView in, State *state);
++ using LengthFn = qsizetype (*)(qsizetype inLength);
++ using EncoderFn = char * (*)(char *out, QStringView in, State *state);
++ const char *name = nullptr;
++ DecoderFn toUtf16 = nullptr;
++ LengthFn toUtf16Len = nullptr;
++ EncoderFn fromUtf16 = nullptr;
++ LengthFn fromUtf16Len = nullptr;
++ };
++
++ constexpr QStringConverter() noexcept
++ : iface(nullptr)
++ {}
++ constexpr explicit QStringConverter(Encoding encoding, Flags f)
++ : iface(&encodingInterfaces[qsizetype(encoding)]), state(f)
++ {}
++ constexpr explicit QStringConverter(const Interface *i) noexcept
++ : iface(i)
++ {}
++ #if QT_CORE_REMOVED_SINCE(6, 8)
++ Q_CORE_EXPORT explicit QStringConverter(const char *name, Flags f);
++ #endif
++ Q_CORE_EXPORT explicit QStringConverter(QAnyStringView name, Flags f);
++
++
++ ~QStringConverter() = default;
++
++ public:
++ QStringConverter(QStringConverter &&) = default;
++ QStringConverter &operator=(QStringConverter &&) = default;
++
++ bool isValid() const noexcept { return iface != nullptr; }
++
++ void resetState() noexcept
++ {
++ state.reset();
++ }
++ bool hasError() const noexcept { return state.invalidChars != 0; }
++
++ Q_CORE_EXPORT const char *name() const noexcept;
++
++ #if QT_CORE_REMOVED_SINCE(6, 8)
++ Q_CORE_EXPORT static std::optional<Encoding> encodingForName(const char *name) noexcept;
++ #endif
++ Q_CORE_EXPORT static std::optional<Encoding> encodingForName(QAnyStringView name) noexcept;
++ Q_DECL_PURE_FUNCTION Q_CORE_EXPORT static const char *nameForEncoding(Encoding e) noexcept;
++ Q_CORE_EXPORT static std::optional<Encoding>
++ encodingForData(QByteArrayView data, char16_t expectedFirstCharacter = 0) noexcept;
++ Q_CORE_EXPORT static std::optional<Encoding> encodingForHtml(QByteArrayView data);
++
++ Q_CORE_EXPORT static QStringList availableCodecs();
++
++
++ enum class FinalizeResultError : quint8 {
++ NoError,
++ InvalidCharacters,
++ NotEnoughSpace,
++ };
++ template <typename Char>
++ struct FinalizeResultChar
++ {
++ using Error = FinalizeResultError;
++
++ Char *next;
++ qint16 invalidChars;
++ Error error;
++ };
++
++ protected:
++ const Interface *iface;
++ State state;
++ private:
++ Q_CORE_EXPORT static const Interface encodingInterfaces[Encoding::LastEncoding + 1];
++ };
++
++ Q_DECLARE_OPERATORS_FOR_FLAGS(QStringConverter::Flags)
++
++ QT_END_NAMESPACE
++
++ #endif