summaryrefslogtreecommitdiffstats
path: root/src/corelib/codecs
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2020-04-16 12:56:58 +0200
committerLars Knoll <lars.knoll@qt.io>2020-05-10 11:31:50 +0200
commitbabcabfbc899d5a72b282f8cf0b510840e91ba0e (patch)
treed4e89b175401d8daa0ca83675ab6b2f24de109e7 /src/corelib/codecs
parenta77b19a911c4d6c47c185a8e59ebbcec8b14bcca (diff)
Clean up state handling for ICU and iconv based codecs
Get rid of the hack for the FreeFunction and instead add a proper function pointer to clear the data to the ConverterState struct. Change-Id: I104aae1a4381c69f1a254713ec76e1aeaa862cdc Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/corelib/codecs')
-rw-r--r--src/corelib/codecs/qiconvcodec.cpp9
-rw-r--r--src/corelib/codecs/qicucodec.cpp13
-rw-r--r--src/corelib/codecs/qtextcodec.cpp17
-rw-r--r--src/corelib/codecs/qtextcodec.h19
-rw-r--r--src/corelib/codecs/qtextcodec_p.h15
5 files changed, 35 insertions, 38 deletions
diff --git a/src/corelib/codecs/qiconvcodec.cpp b/src/corelib/codecs/qiconvcodec.cpp
index 9c39727946..0fa18eadba 100644
--- a/src/corelib/codecs/qiconvcodec.cpp
+++ b/src/corelib/codecs/qiconvcodec.cpp
@@ -121,7 +121,7 @@ void QIconvCodec::IconvState::saveChars(const char *c, int count)
static void qIconvCodecStateFree(QTextCodec::ConverterState *state)
{
- delete reinterpret_cast<QIconvCodec::IconvState *>(state->d);
+ delete reinterpret_cast<QIconvCodec::IconvState *>(state->d[0]);
}
Q_GLOBAL_STATIC(QThreadStorage<QIconvCodec::IconvState *>, toUnicodeState)
@@ -139,15 +139,14 @@ QString QIconvCodec::convertToUnicode(const char* chars, int len, ConverterState
if (convState) {
// stateful conversion
- pstate = reinterpret_cast<IconvState **>(&convState->d);
- if (convState->d) {
+ pstate = reinterpret_cast<IconvState **>(&convState->d[0]);
+ if (convState->d[0]) {
// restore state
remainingCount = convState->remainingChars;
remainingBuffer = (*pstate)->buffer;
} else {
// first time
- convState->flags |= FreeFunction;
- QTextCodecUnalignedPointer::encode(convState->state_data, qIconvCodecStateFree);
+ convState->clearFn = qIconvCodecStateFree;
}
} else {
QThreadStorage<QIconvCodec::IconvState *> *ts = toUnicodeState();
diff --git a/src/corelib/codecs/qicucodec.cpp b/src/corelib/codecs/qicucodec.cpp
index 8a6dfc756f..295cbfe97f 100644
--- a/src/corelib/codecs/qicucodec.cpp
+++ b/src/corelib/codecs/qicucodec.cpp
@@ -60,7 +60,7 @@ typedef QList<QByteArray>::ConstIterator ByteArrayListConstIt;
static void qIcuCodecStateFree(QTextCodec::ConverterState *state)
{
- ucnv_close(static_cast<UConverter *>(state->d));
+ ucnv_close(static_cast<UConverter *>(state->d[0]));
}
bool qTextCodecNameMatch(const char *n, const char *h)
@@ -569,18 +569,17 @@ UConverter *QIcuCodec::getConverter(QTextCodec::ConverterState *state) const
{
UConverter *conv = nullptr;
if (state) {
- if (!state->d) {
+ if (!state->d[0]) {
// first time
- state->flags |= QTextCodec::FreeFunction;
- QTextCodecUnalignedPointer::encode(state->state_data, qIcuCodecStateFree);
+ state->clearFn = qIcuCodecStateFree;
UErrorCode error = U_ZERO_ERROR;
- state->d = ucnv_open(m_name, &error);
- ucnv_setSubstChars(static_cast<UConverter *>(state->d),
+ state->d[0] = ucnv_open(m_name, &error);
+ ucnv_setSubstChars(static_cast<UConverter *>(state->d[0]),
state->flags & QTextCodec::ConvertInvalidToNull ? "\0" : "?", 1, &error);
if (U_FAILURE(error))
qDebug("getConverter(state) ucnv_open failed %s %s", m_name, u_errorName(error));
}
- conv = static_cast<UConverter *>(state->d);
+ conv = static_cast<UConverter *>(state->d[0]);
}
if (!conv) {
// stateless conversion
diff --git a/src/corelib/codecs/qtextcodec.cpp b/src/corelib/codecs/qtextcodec.cpp
index 72c7844561..c221e51ecc 100644
--- a/src/corelib/codecs/qtextcodec.cpp
+++ b/src/corelib/codecs/qtextcodec.cpp
@@ -343,10 +343,19 @@ static void setup() {}
*/
QTextCodec::ConverterState::~ConverterState()
{
- if (flags & FreeFunction)
- (QTextCodecUnalignedPointer::decode(state_data))(this);
- else if (d)
- free(d);
+ clear();
+}
+
+void QTextCodec::ConverterState::clear()
+{
+ if (clearFn)
+ clearFn(this);
+ remainingChars = 0;
+ invalidChars = 0;
+ state_data[0] = 0;
+ state_data[1] = 0;
+ state_data[2] = 0;
+ state_data[3] = 0;
}
/*!
diff --git a/src/corelib/codecs/qtextcodec.h b/src/corelib/codecs/qtextcodec.h
index 885518d17f..5b502d2a98 100644
--- a/src/corelib/codecs/qtextcodec.h
+++ b/src/corelib/codecs/qtextcodec.h
@@ -92,20 +92,25 @@ public:
enum ConversionFlag {
DefaultConversion,
ConvertInvalidToNull = 0x80000000,
- IgnoreHeader = 0x1,
- FreeFunction = 0x2
+ IgnoreHeader = 0x1
};
Q_DECLARE_FLAGS(ConversionFlags, ConversionFlag)
struct Q_CORE_EXPORT ConverterState {
ConverterState(ConversionFlags f = DefaultConversion)
- : flags(f), remainingChars(0), invalidChars(0), d(nullptr) { state_data[0] = state_data[1] = state_data[2] = 0; }
+ : flags(f), state_data{0, 0, 0, 0} {}
~ConverterState();
ConversionFlags flags;
- int remainingChars;
- int invalidChars;
- uint state_data[3];
- void *d;
+ int remainingChars = 0;
+ int invalidChars = 0;
+
+ union {
+ uint state_data[4];
+ void *d[2];
+ };
+ void clear();
+ using ClearDataFn = void (*)(ConverterState *);
+ ClearDataFn clearFn = nullptr;
private:
Q_DISABLE_COPY(ConverterState)
};
diff --git a/src/corelib/codecs/qtextcodec_p.h b/src/corelib/codecs/qtextcodec_p.h
index 7fcf6df984..ef5758619d 100644
--- a/src/corelib/codecs/qtextcodec_p.h
+++ b/src/corelib/codecs/qtextcodec_p.h
@@ -66,21 +66,6 @@ QT_BEGIN_NAMESPACE
typedef void (*QTextCodecStateFreeFunction)(QTextCodec::ConverterState*);
-struct QTextCodecUnalignedPointer
-{
- static inline QTextCodecStateFreeFunction decode(const uint *src)
- {
- quintptr data;
- memcpy(&data, src, sizeof(data));
- return reinterpret_cast<QTextCodecStateFreeFunction>(data);
- }
- static inline void encode(uint *dst, QTextCodecStateFreeFunction fn)
- {
- quintptr data = reinterpret_cast<quintptr>(fn);
- memcpy(dst, &data, sizeof(data));
- }
-};
-
bool qTextCodecNameMatch(const char *a, const char *b);
#else // without textcodec: