OSDN Git Service

implement QTextCodec::codecForText() via ICU
authorIvailo Monev <xakepa10@laimg.moc>
Mon, 16 Dec 2019 14:05:02 +0000 (14:05 +0000)
committerIvailo Monev <xakepa10@laimg.moc>
Mon, 16 Dec 2019 14:05:02 +0000 (14:05 +0000)
Signed-off-by: Ivailo Monev <xakepa10@laimg.moc>
src/core/codecs/qicucodec.cpp
src/core/codecs/qicucodec_p.h
src/core/codecs/qtextcodec.cpp
src/core/codecs/qtextcodec.h

index ba087f3..ae41f42 100644 (file)
@@ -33,6 +33,8 @@
 #include "qcorecommon_p.h"
 #include "qdebug.h"
 
+#include <unicode/ucsdet.h>
+
 QT_BEGIN_NAMESPACE
 
 // generated via genmib.py
@@ -1143,6 +1145,42 @@ QTextCodec *QIcuCodec::codecForUtf(const QByteArray &text, QTextCodec *defaultCo
 
     return defaultCodec;
 }
+QTextCodec *QIcuCodec::codecForData(const QByteArray &text, QTextCodec *defaultCodec)
+{
+    UErrorCode error = U_ZERO_ERROR;
+    UCharsetDetector *detector = ucsdet_open(&error);
+    if (Q_UNLIKELY(U_FAILURE(error))) {
+        qWarning("QIcuCodec::codecForData: ucsdet_open() failed %s", u_errorName(error));
+        return defaultCodec;
+    }
+
+    error = U_ZERO_ERROR;
+    ucsdet_setText(detector, text.constData(), text.size(), &error);
+    if (Q_UNLIKELY(U_FAILURE(error))) {
+        qWarning("QIcuCodec::codecForData: ucsdet_setText() failed %s", u_errorName(error));
+        ucsdet_close(detector);
+        return defaultCodec;
+    }
+
+    error = U_ZERO_ERROR;
+    const UCharsetMatch *match = ucsdet_detect(detector, &error);
+    if (Q_UNLIKELY(U_FAILURE(error))) {
+        qWarning("QIcuCodec::codecForData: ucsdet_detect() failed %s", u_errorName(error));
+        ucsdet_close(detector);
+        return defaultCodec;
+    }
+
+    error = U_ZERO_ERROR;
+    const char *name = ucsdet_getName(match, &error);
+    if (Q_UNLIKELY(U_FAILURE(error))) {
+        qWarning("QIcuCodec::codecForData: ucsdet_getName() failed %s", u_errorName(error));
+        ucsdet_close(detector);
+        return defaultCodec;
+    }
+
+    ucsdet_close(detector);
+    return QTextCodec::codecForName(name);
+}
 #endif
 
 UConverter *QIcuCodec::getConverter(QTextCodec::ConverterState *state) const
index b073159..61af750 100644 (file)
@@ -69,6 +69,7 @@ public:
     static QList<QByteArray> allCodecs();
     static QList<int> allMibs();
     static QTextCodec* codecForUtf(const QByteArray &text, QTextCodec *defaultCodec);
+    static QTextCodec* codecForData(const QByteArray &text, QTextCodec *defaultCodec);
 #endif
 
 private:
index 78179a9..749e081 100644 (file)
@@ -1070,7 +1070,7 @@ QString QTextDecoder::toUnicode(const QByteArray &ba)
     cannot be detected from the content provided, \a defaultCodec is
     returned.
 
-    \sa codecForUtfText()
+    \sa codecForText(), codecForUtfText()
 */
 QTextCodec *QTextCodec::codecForHtml(const QByteArray &ba, QTextCodec *defaultCodec)
 {
@@ -1087,15 +1087,12 @@ QTextCodec *QTextCodec::codecForHtml(const QByteArray &ba, QTextCodec *defaultCo
                     int pos2 = header.indexOf('\"', pos+1);
                     QByteArray cs = header.mid(pos, pos2-pos);
                     //            qDebug("found charset: %s", cs.data());
-                    c = QTextCodec::codecForName(cs);
+                    return QTextCodec::codecForName(cs);
                 }
             }
         }
     }
-    if (!c)
-        c = defaultCodec;
-
-    return c;
+    return QTextCodec::codecForText(ba, defaultCodec);;
 }
 
 /*!
@@ -1106,6 +1103,8 @@ QTextCodec *QTextCodec::codecForHtml(const QByteArray &ba, QTextCodec *defaultCo
     and the content-type meta header and returns a QTextCodec instance
     that is capable of decoding the html to unicode. If the codec cannot
     be detected, this overload returns a Latin-1 QTextCodec.
+
+    \sa codecForText(), codecForUtfText()
 */
 QTextCodec *QTextCodec::codecForHtml(const QByteArray &ba)
 {
@@ -1121,7 +1120,7 @@ QTextCodec *QTextCodec::codecForHtml(const QByteArray &ba)
     cannot be detected from the content provided, \a defaultCodec is
     returned.
 
-    \sa codecForHtml()
+    \sa codecForText(), codecForHtml()
 */
 QTextCodec *QTextCodec::codecForUtfText(const QByteArray &ba, QTextCodec *defaultCodec)
 {
@@ -1136,7 +1135,7 @@ QTextCodec *QTextCodec::codecForUtfText(const QByteArray &ba, QTextCodec *defaul
     that is capable of decoding the text to unicode. If the codec
     cannot be detected, this overload returns a Latin-1 QTextCodec.
 
-    \sa codecForHtml()
+    \sa codecForText(), codecForHtml()
 */
 QTextCodec *QTextCodec::codecForUtfText(const QByteArray &ba)
 {
@@ -1144,6 +1143,38 @@ QTextCodec *QTextCodec::codecForUtfText(const QByteArray &ba)
 }
 
 
+/*!
+    \since 4.9
+
+    Tries to detect the encoding of the provided snippet \a ba and
+    returns a QTextCodec instance that is capable of decoding the text
+    to unicode. If the codec cannot be detected from the content
+    provided, \a defaultCodec is returned. The results can not be
+    guaranteed to always be correct.
+
+    \sa codecForUtfText(), codecForHtml()
+*/
+QTextCodec *QTextCodec::codecForText(const QByteArray &ba, QTextCodec *defaultCodec)
+{
+    return QIcuCodec::codecForData(ba, defaultCodec);
+}
+
+/*!
+    \overload
+
+    Tries to detect the encoding of the provided snippet \a ba by
+    returns a QTextCodec instance that is capable of decoding the
+    text to unicode. If the codec cannot be detected, this overload
+    returns a Latin-1 QTextCodec. The results can not be guaranteed
+    to always be correct.
+
+    \sa codecForUtfText(), codecForHtml()
+*/
+QTextCodec *QTextCodec::codecForText(const QByteArray &ba)
+{
+    return codecForText(ba, QTextCodec::codecForMib(/*Latin 1*/ 4));
+}
+
 /*! \internal
     \since 4.3
     Determines whether the decoder encountered a failure while decoding the input. If
index fd0b41e..a58fd00 100644 (file)
@@ -77,6 +77,9 @@ public:
     static QTextCodec *codecForUtfText(const QByteArray &ba);
     static QTextCodec *codecForUtfText(const QByteArray &ba, QTextCodec *defaultCodec);
 
+    static QTextCodec *codecForText(const QByteArray &ba);
+    static QTextCodec *codecForText(const QByteArray &ba, QTextCodec *defaultCodec);
+
     bool canEncode(QChar) const;
     bool canEncode(const QString&) const;