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

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