1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QSTRINGCONVERTER_BASE_H
5#define QSTRINGCONVERTER_BASE_H
6
7#if 0
8// QStringConverter(Base) class are handled in qstringconverter
9#pragma qt_sync_stop_processing
10#endif
11
12#include <optional>
13
14#include <QtCore/qglobal.h> // QT_{BEGIN,END}_NAMESPACE
15#include <QtCore/qflags.h> // Q_DECLARE_FLAGS
16
17#include <cstring>
18
19QT_BEGIN_NAMESPACE
20
21class QByteArrayView;
22class QChar;
23class QByteArrayView;
24class QStringView;
25
26class QStringConverterBase
27{
28public:
29 enum class Flag {
30 Default = 0,
31 Stateless = 0x1,
32 ConvertInvalidToNull = 0x2,
33 WriteBom = 0x4,
34 ConvertInitialBom = 0x8,
35 UsesIcu = 0x10,
36 };
37 Q_DECLARE_FLAGS(Flags, Flag)
38
39 struct State {
40 constexpr State(Flags f = Flag::Default) noexcept
41 : flags(f), state_data{0, 0, 0, 0} {}
42 ~State() { clear(); }
43
44 State(State &&other) noexcept
45 : flags(other.flags),
46 remainingChars(other.remainingChars),
47 invalidChars(other.invalidChars),
48 state_data{other.state_data[0], other.state_data[1],
49 other.state_data[2], other.state_data[3]},
50 clearFn(other.clearFn)
51 { other.clearFn = nullptr; }
52 State &operator=(State &&other) noexcept
53 {
54 clear();
55 flags = other.flags;
56 remainingChars = other.remainingChars;
57 invalidChars = other.invalidChars;
58 std::memmove(dest: state_data, src: other.state_data, n: sizeof state_data); // self-assignment-safe
59 clearFn = other.clearFn;
60 other.clearFn = nullptr;
61 return *this;
62 }
63 Q_CORE_EXPORT void clear() noexcept;
64 Q_CORE_EXPORT void reset() noexcept;
65
66 Flags flags;
67 int internalState = 0;
68 qsizetype remainingChars = 0;
69 qsizetype invalidChars = 0;
70
71 union {
72 uint state_data[4];
73 void *d[2];
74 };
75 using ClearDataFn = void (*)(State *) noexcept;
76 ClearDataFn clearFn = nullptr;
77 private:
78 Q_DISABLE_COPY(State)
79 };
80protected:
81 ~QStringConverterBase() = default;
82};
83Q_DECLARE_OPERATORS_FOR_FLAGS(QStringConverterBase::Flags)
84
85class QStringConverter : public QStringConverterBase
86{
87public:
88
89 enum Encoding {
90 Utf8,
91 Utf16,
92 Utf16LE,
93 Utf16BE,
94 Utf32,
95 Utf32LE,
96 Utf32BE,
97 Latin1,
98 System,
99 LastEncoding = System
100 };
101#ifdef Q_QDOC
102 // document the flags here
103 enum class Flag {
104 Default = 0,
105 Stateless = 0x1,
106 ConvertInvalidToNull = 0x2,
107 WriteBom = 0x4,
108 ConvertInitialBom = 0x8,
109 UsesIcu = 0x10,
110 };
111 Q_DECLARE_FLAGS(Flags, Flag)
112#endif
113
114protected:
115
116 struct Interface
117 {
118 using DecoderFn = QChar * (*)(QChar *out, QByteArrayView in, State *state);
119 using LengthFn = qsizetype (*)(qsizetype inLength);
120 using EncoderFn = char * (*)(char *out, QStringView in, State *state);
121 const char *name = nullptr;
122 DecoderFn toUtf16 = nullptr;
123 LengthFn toUtf16Len = nullptr;
124 EncoderFn fromUtf16 = nullptr;
125 LengthFn fromUtf16Len = nullptr;
126 };
127
128 constexpr QStringConverter() noexcept
129 : iface(nullptr)
130 {}
131 constexpr explicit QStringConverter(Encoding encoding, Flags f)
132 : iface(&encodingInterfaces[qsizetype(encoding)]), state(f)
133 {}
134 constexpr explicit QStringConverter(const Interface *i) noexcept
135 : iface(i)
136 {}
137 Q_CORE_EXPORT explicit QStringConverter(const char *name, Flags f);
138
139
140 ~QStringConverter() = default;
141
142public:
143 QStringConverter(QStringConverter &&) = default;
144 QStringConverter &operator=(QStringConverter &&) = default;
145
146 bool isValid() const noexcept { return iface != nullptr; }
147
148 void resetState() noexcept
149 {
150 state.reset();
151 }
152 bool hasError() const noexcept { return state.invalidChars != 0; }
153
154 Q_CORE_EXPORT const char *name() const noexcept;
155
156 Q_CORE_EXPORT static std::optional<Encoding> encodingForName(const char *name) noexcept;
157 Q_CORE_EXPORT static const char *nameForEncoding(Encoding e);
158 Q_CORE_EXPORT static std::optional<Encoding>
159 encodingForData(QByteArrayView data, char16_t expectedFirstCharacter = 0) noexcept;
160 Q_CORE_EXPORT static std::optional<Encoding> encodingForHtml(QByteArrayView data);
161
162protected:
163 const Interface *iface;
164 State state;
165private:
166 Q_CORE_EXPORT static const Interface encodingInterfaces[Encoding::LastEncoding + 1];
167};
168
169QT_END_NAMESPACE
170
171#endif
172

source code of qtbase/src/corelib/text/qstringconverter_base.h