diff options
author | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2011-07-10 15:24:15 -0500 |
---|---|---|
committer | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2011-07-10 15:24:15 -0500 |
commit | bd0f3345a938b35ce6a12f6150373b0955b8dd12 (patch) | |
tree | 7a520322212d48ebcb9fbe1087e7fca28b76185c /src/codecs/qutfcodec.cpp | |
download | qt3-bd0f3345a938b35ce6a12f6150373b0955b8dd12.tar.gz qt3-bd0f3345a938b35ce6a12f6150373b0955b8dd12.zip |
Add Qt3 development HEAD version
Diffstat (limited to 'src/codecs/qutfcodec.cpp')
-rw-r--r-- | src/codecs/qutfcodec.cpp | 350 |
1 files changed, 350 insertions, 0 deletions
diff --git a/src/codecs/qutfcodec.cpp b/src/codecs/qutfcodec.cpp new file mode 100644 index 0000000..bc1abce --- /dev/null +++ b/src/codecs/qutfcodec.cpp @@ -0,0 +1,350 @@ +/**************************************************************************** +** +** Implementation of QUtf{8,16}Codec class +** +** Created : 981015 +** +** Copyright (C) 1998-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the tools module of the Qt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free Qt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing requirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.QPL +** included in the packaging of this file. Licensees holding valid Qt +** Commercial licenses may use this file in accordance with the Qt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +#include "qutfcodec.h" + +#ifndef QT_NO_TEXTCODEC + +int QUtf8Codec::mibEnum() const +{ + return 106; +} + +QCString QUtf8Codec::fromUnicode(const QString& uc, int& lenInOut) const +{ + int l = uc.length(); + if (lenInOut > 0) + l = QMIN(l, lenInOut); + int rlen = l*3+1; + QCString rstr(rlen); + uchar* cursor = (uchar*)rstr.data(); + const QChar *ch = uc.unicode(); + for (int i=0; i < l; i++) { + uint u = ch->unicode(); + if ( u < 0x80 ) { + *cursor++ = (uchar)u; + } else { + if ( u < 0x0800 ) { + *cursor++ = 0xc0 | ((uchar) (u >> 6)); + } else { + if (u >= 0xd800 && u < 0xdc00 && i < l-1) { + unsigned short low = ch[1].unicode(); + if (low >= 0xdc00 && low < 0xe000) { + ++ch; + ++i; + u = (u - 0xd800)*0x400 + (low - 0xdc00) + 0x10000; + } + } + if (u > 0xffff) { + // see QString::fromUtf8() and QString::utf8() for explanations + if (u > 0x10fe00 && u < 0x10ff00) { + *cursor++ = (u - 0x10fe00); + ++ch; + continue; + } else { + *cursor++ = 0xf0 | ((uchar) (u >> 18)); + *cursor++ = 0x80 | ( ((uchar) (u >> 12)) & 0x3f); + } + } else { + *cursor++ = 0xe0 | ((uchar) (u >> 12)); + } + *cursor++ = 0x80 | ( ((uchar) (u >> 6)) & 0x3f); + } + *cursor++ = 0x80 | ((uchar) (u&0x3f)); + } + ++ch; + } + *cursor = 0; + lenInOut = cursor - (uchar*)rstr.data(); + ((QByteArray&)rstr).resize(lenInOut+1); + return rstr; +} + +QString QUtf8Codec::toUnicode(const char* chars, int len) const +{ + if (len > 3 && (uchar)chars[0] == 0xef && (uchar)chars[1] == 0xbb && (uchar)chars[2] == 0xbf) { + // starts with a byte order mark + chars += 3; + len -= 3; + } + return QString::fromUtf8( chars, len ); +} + + +const char* QUtf8Codec::name() const +{ + return "UTF-8"; +} + +int QUtf8Codec::heuristicContentMatch(const char* chars, int len) const +{ + int score = 0; + for (int i=0; i<len; i++) { + uchar ch = chars[i]; + // No nulls allowed. + if ( !ch ) + return -1; + if ( ch < 128 ) { + // Inconclusive + score++; + } else if ( (ch&0xe0) == 0xc0 ) { + if ( i < len-1 ) { + uchar c2 = chars[++i]; + if ( (c2&0xc0) != 0x80 ) + return -1; + score+=3; + } + } else if ( (ch&0xf0) == 0xe0 ) { + if ( i < len-1 ) { + uchar c2 = chars[++i]; + if ( (c2&0xc0) != 0x80 ) { + return -1; +#if 0 + if ( i < len-1 ) { + uchar c3 = chars[++i]; + if ( (c3&0xc0) != 0x80 ) + return -1; + score+=3; + } +#endif + } + score+=2; + } + } + } + return score; +} + + + + +class QUtf8Decoder : public QTextDecoder { + uint uc; + uint min_uc; + int need; + bool headerDone; +public: + QUtf8Decoder() : need(0), headerDone(FALSE) + { + } + + QString toUnicode(const char* chars, int len) + { + QString result; + result.setLength( len + 1 ); // worst case + QChar *qch = (QChar *)result.unicode(); + uchar ch; + int error = -1; + for (int i=0; i<len; i++) { + ch = chars[i]; + if (need) { + if ( (ch&0xc0) == 0x80 ) { + uc = (uc << 6) | (ch & 0x3f); + need--; + if ( !need ) { + if (uc > 0xffff) { + // surrogate pair + uc -= 0x10000; + unsigned short high = uc/0x400 + 0xd800; + unsigned short low = uc%0x400 + 0xdc00; + *qch++ = QChar(high); + *qch++ = QChar(low); + headerDone = TRUE; + } else if ((uc < min_uc) || (uc >= 0xd800 && uc <= 0xdfff) || (uc >= 0xfffe)) { + *qch++ = QChar::replacement; + } else { + if (headerDone || QChar(uc) != QChar::byteOrderMark) + *qch++ = uc; + headerDone = TRUE; + } + } + } else { + // error + i = error; + *qch++ = QChar::replacement; + need = 0; + } + } else { + if ( ch < 128 ) { + *qch++ = ch; + headerDone = TRUE; + } else if ((ch & 0xe0) == 0xc0) { + uc = ch & 0x1f; + need = 1; + error = i; + min_uc = 0x80; + } else if ((ch & 0xf0) == 0xe0) { + uc = ch & 0x0f; + need = 2; + error = i; + min_uc = 0x800; + } else if ((ch&0xf8) == 0xf0) { + uc = ch & 0x07; + need = 3; + error = i; + min_uc = 0x10000; + } else { + // error + *qch++ = QChar::replacement; + } + } + } + result.truncate( qch - result.unicode() ); + return result; + } +}; + +QTextDecoder* QUtf8Codec::makeDecoder() const +{ + return new QUtf8Decoder; +} + + + + + + +int QUtf16Codec::mibEnum() const +{ + return 1000; +} + +const char* QUtf16Codec::name() const +{ + return "ISO-10646-UCS-2"; +} + +int QUtf16Codec::heuristicContentMatch(const char* chars, int len) const +{ + uchar* uchars = (uchar*)chars; + if ( len >= 2 && (uchars[0] == 0xff && uchars[1] == 0xfe || + uchars[1] == 0xff && uchars[0] == 0xfe) ) + return len; + else + return 0; +} + + + + +class QUtf16Encoder : public QTextEncoder { + bool headerdone; +public: + QUtf16Encoder() : headerdone(FALSE) + { + } + + QCString fromUnicode(const QString& uc, int& lenInOut) + { + if ( headerdone ) { + lenInOut = uc.length()*sizeof(QChar); + QCString d(lenInOut); + memcpy(d.data(),uc.unicode(),lenInOut); + return d; + } else { + headerdone = TRUE; + lenInOut = (1+uc.length())*sizeof(QChar); + QCString d(lenInOut); + memcpy(d.data(),&QChar::byteOrderMark,sizeof(QChar)); + memcpy(d.data()+sizeof(QChar),uc.unicode(),uc.length()*sizeof(QChar)); + return d; + } + } +}; + +class QUtf16Decoder : public QTextDecoder { + uchar buf; + bool half; + bool swap; + bool headerdone; + +public: + QUtf16Decoder() : half(FALSE), swap(FALSE), headerdone(FALSE) + { + } + + QString toUnicode(const char* chars, int len) + { + QString result; + result.setLength( len + 1 ); // worst case + QChar *qch = (QChar *)result.unicode(); + QChar ch; + while ( len-- ) { + if ( half ) { + if ( swap ) { + ch.setRow( *chars++ ); + ch.setCell( buf ); + } else { + ch.setRow( buf ); + ch.setCell( *chars++ ); + } + if ( !headerdone ) { + if ( ch == QChar::byteOrderSwapped ) { + swap = !swap; + } else if ( ch == QChar::byteOrderMark ) { + // Ignore ZWNBSP + } else { + *qch++ = ch; + } + headerdone = TRUE; + } else + *qch++ = ch; + half = FALSE; + } else { + buf = *chars++; + half = TRUE; + } + } + result.truncate( qch - result.unicode() ); + return result; + } +}; + +QTextDecoder* QUtf16Codec::makeDecoder() const +{ + return new QUtf16Decoder; +} + +QTextEncoder* QUtf16Codec::makeEncoder() const +{ + return new QUtf16Encoder; +} + +#endif //QT_NO_TEXTCODEC |