1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 // Most of the code here was originally written by Serika Kurusugawa
41 // a.k.a. Junji Takagi, and is included in Qt with the author's permission,
42 // and the grateful thanks of the Qt team.
43 
44 /*! \class QSjisCodec
45     \inmodule QtCore
46     \reentrant
47     \internal
48 */
49 
50 #include "qsjiscodec_p.h"
51 #include "qlist.h"
52 
53 QT_BEGIN_NAMESPACE
54 
55 enum {
56     Esc = 0x1b
57 };
58 
59 #define        IsKana(c)        (((c) >= 0xa1) && ((c) <= 0xdf))
60 #define        IsSjisChar1(c)        ((((c) >= 0x81) && ((c) <= 0x9f)) ||        \
61                          (((c) >= 0xe0) && ((c) <= 0xfc)))
62 #define        IsSjisChar2(c)        (((c) >= 0x40) && ((c) != 0x7f) && ((c) <= 0xfc))
63 #define        IsUserDefinedChar1(c)        (((c) >= 0xf0) && ((c) <= 0xfc))
64 
65 #define        QValidChar(u)        ((u) ? QChar((ushort)(u)) : QChar(QChar::ReplacementCharacter))
66 
67 /*!
68   Creates a Shift-JIS codec. Note that this is done automatically by
69   the QApplication, you do not need construct your own.
70 */
QSjisCodec()71 QSjisCodec::QSjisCodec() : conv(QJpUnicodeConv::newConverter(QJpUnicodeConv::Default))
72 {
73 }
74 
75 
76 /*!
77   Destroys the Shift-JIS codec.
78 */
~QSjisCodec()79 QSjisCodec::~QSjisCodec()
80 {
81     delete (const QJpUnicodeConv*)conv;
82     conv = 0;
83 }
84 
85 
convertFromUnicode(const QChar * uc,int len,ConverterState * state) const86 QByteArray QSjisCodec::convertFromUnicode(const QChar *uc, int len, ConverterState *state) const
87 {
88     char replacement = '?';
89     if (state) {
90         if (state->flags & ConvertInvalidToNull)
91             replacement = 0;
92     }
93     int invalid = 0;
94 
95     int rlen = 2*len + 1;
96     QByteArray rstr;
97     rstr.resize(rlen);
98     uchar* cursor = (uchar*)rstr.data();
99     for (int i = 0; i < len; i++) {
100         QChar ch = uc[i];
101         uint j;
102         if (ch.row() == 0x00 && ch.cell() < 0x80) {
103             // ASCII
104             *cursor++ = ch.cell();
105         } else if ((j = conv->unicodeToJisx0201(ch.row(), ch.cell())) != 0) {
106             // JIS X 0201 Latin or JIS X 0201 Kana
107             *cursor++ = j;
108         } else if ((j = conv->unicodeToSjis(ch.row(), ch.cell())) != 0) {
109             // JIS X 0208
110             *cursor++ = (j >> 8);
111             *cursor++ = (j & 0xff);
112         } else if ((j = conv->unicodeToSjisibmvdc(ch.row(), ch.cell())) != 0) {
113             // JIS X 0208 IBM VDC
114             *cursor++ = (j >> 8);
115             *cursor++ = (j & 0xff);
116         } else if ((j = conv->unicodeToCp932(ch.row(), ch.cell())) != 0) {
117             // CP932 (for lead bytes 87, ee & ed)
118             *cursor++ = (j >> 8);
119             *cursor++ = (j & 0xff);
120         } else if ((j = conv->unicodeToJisx0212(ch.row(), ch.cell())) != 0) {
121             // JIS X 0212 (can't be encoded in ShiftJIS !)
122             *cursor++ = 0x81;        // white square
123             *cursor++ = 0xa0;        // white square
124         } else {
125             // Error
126             *cursor++ = replacement;
127             ++invalid;
128         }
129     }
130     rstr.resize(cursor - (const uchar*)rstr.constData());
131 
132     if (state) {
133         state->invalidChars += invalid;
134     }
135     return rstr;
136 }
137 
convertToUnicode(const char * chars,int len,ConverterState * state) const138 QString QSjisCodec::convertToUnicode(const char* chars, int len, ConverterState *state) const
139 {
140     uchar buf[1] = {0};
141     int nbuf = 0;
142     QChar replacement = QChar::ReplacementCharacter;
143     if (state) {
144         if (state->flags & ConvertInvalidToNull)
145             replacement = QChar::Null;
146         nbuf = state->remainingChars;
147         buf[0] = state->state_data[0];
148     }
149     int invalid = 0;
150     uint u= 0;
151     QString result;
152     for (int i=0; i<len; i++) {
153         uchar ch = chars[i];
154         switch (nbuf) {
155         case 0:
156             if (ch < 0x80) {
157                 result += QValidChar(ch);
158             } else if (IsKana(ch)) {
159                 // JIS X 0201 Latin or JIS X 0201 Kana
160                 u = conv->jisx0201ToUnicode(ch);
161                 result += QValidChar(u);
162             } else if (IsSjisChar1(ch)) {
163                 // JIS X 0208
164                 buf[0] = ch;
165                 nbuf = 1;
166             } else {
167                 // Invalid
168                 result += replacement;
169                 ++invalid;
170             }
171             break;
172         case 1:
173             // JIS X 0208
174             if (IsSjisChar2(ch)) {
175                 if ((u = conv->sjisibmvdcToUnicode(buf[0], ch))) {
176                     result += QValidChar(u);
177                 } else if ((u = conv->cp932ToUnicode(buf[0], ch))) {
178                     result += QValidChar(u);
179                 }
180                 else if (IsUserDefinedChar1(buf[0])) {
181                     result += QChar::ReplacementCharacter;
182                 } else {
183                     u = conv->sjisToUnicode(buf[0], ch);
184                     result += QValidChar(u);
185                 }
186             } else {
187                 // Invalid
188                 result += replacement;
189                 ++invalid;
190             }
191             nbuf = 0;
192             break;
193         }
194     }
195 
196     if (state) {
197         state->remainingChars = nbuf;
198         state->state_data[0] = buf[0];
199         state->invalidChars += invalid;
200     }
201     return result;
202 }
203 
204 
_mibEnum()205 int QSjisCodec::_mibEnum()
206 {
207     return 17;
208 }
209 
_name()210 QByteArray QSjisCodec::_name()
211 {
212     return "Shift_JIS";
213 }
214 
215 /*!
216     Returns the codec's mime name.
217 */
_aliases()218 QList<QByteArray> QSjisCodec::_aliases()
219 {
220     QList<QByteArray> list;
221     list << "SJIS" // Qt 3 compat
222          << "MS_Kanji";
223     return list;
224 }
225 
226 QT_END_NAMESPACE
227