diff options
author | Lars Knoll <lars.knoll@qt.io> | 2020-04-16 12:56:58 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2020-05-10 11:31:50 +0200 |
commit | babcabfbc899d5a72b282f8cf0b510840e91ba0e (patch) | |
tree | d4e89b175401d8daa0ca83675ab6b2f24de109e7 /src/corelib/codecs | |
parent | a77b19a911c4d6c47c185a8e59ebbcec8b14bcca (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.cpp | 9 | ||||
-rw-r--r-- | src/corelib/codecs/qicucodec.cpp | 13 | ||||
-rw-r--r-- | src/corelib/codecs/qtextcodec.cpp | 17 | ||||
-rw-r--r-- | src/corelib/codecs/qtextcodec.h | 19 | ||||
-rw-r--r-- | src/corelib/codecs/qtextcodec_p.h | 15 |
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: |