diff options
Diffstat (limited to 'src/corelib/text/qstringconverter_base.h')
-rw-r--r-- | src/corelib/text/qstringconverter_base.h | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/src/corelib/text/qstringconverter_base.h b/src/corelib/text/qstringconverter_base.h new file mode 100644 index 0000000000..d6b6fcb484 --- /dev/null +++ b/src/corelib/text/qstringconverter_base.h @@ -0,0 +1,176 @@ +// 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 + +#ifndef QSTRINGCONVERTER_BASE_H +#define QSTRINGCONVERTER_BASE_H + +#if 0 +// 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 <cstring> + +QT_BEGIN_NAMESPACE + +class QByteArrayView; +class QChar; +class QByteArrayView; +class QStringView; + +class QStringConverterBase +{ +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) + }; +protected: + ~QStringConverterBase() = default; +}; +Q_DECLARE_OPERATORS_FOR_FLAGS(QStringConverterBase::Flags) + +class QStringConverter : public QStringConverterBase +{ +public: + + enum Encoding { + Utf8, +#ifndef QT_BOOTSTRAPPED + Utf16, + Utf16LE, + Utf16BE, + Utf32, + Utf32LE, + Utf32BE, +#endif + Latin1, + System, + LastEncoding = System + }; +#ifdef Q_QDOC + // document the flags here + enum class Flag { + Default = 0, + Stateless = 0x1, + ConvertInvalidToNull = 0x2, + WriteBom = 0x4, + ConvertInitialBom = 0x8, + UsesIcu = 0x10, + }; + Q_DECLARE_FLAGS(Flags, Flag) +#endif + +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) + {} + Q_CORE_EXPORT explicit QStringConverter(const char *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; + + Q_CORE_EXPORT static std::optional<Encoding> encodingForName(const char *name) noexcept; + Q_CORE_EXPORT static const char *nameForEncoding(Encoding e); + 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(); + +protected: + const Interface *iface; + State state; +private: + Q_CORE_EXPORT static const Interface encodingInterfaces[Encoding::LastEncoding + 1]; +}; + +QT_END_NAMESPACE + +#endif |