~ubuntu-branches/ubuntu/wily/qtbase-opensource-src/wily

« back to all changes in this revision

Viewing changes to src/corelib/codecs/qjiscodec.cpp

  • Committer: Package Import Robot
  • Author(s): Timo Jyrinki
  • Date: 2013-02-05 12:46:17 UTC
  • Revision ID: package-import@ubuntu.com-20130205124617-c8jouts182j002fx
Tags: upstream-5.0.1+dfsg
ImportĀ upstreamĀ versionĀ 5.0.1+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
 
4
** Contact: http://www.qt-project.org/legal
 
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 Digia.  For licensing terms and
 
14
** conditions see http://qt.digia.com/licensing.  For further information
 
15
** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
 
20
** Foundation and appearing in the file LICENSE.LGPL included in the
 
21
** packaging of this file.  Please review the following information to
 
22
** ensure the GNU Lesser General Public License version 2.1 requirements
 
23
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 
24
**
 
25
** In addition, as a special exception, Digia gives you certain additional
 
26
** rights.  These rights are described in the Digia Qt LGPL Exception
 
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 
28
**
 
29
** GNU General Public License Usage
 
30
** Alternatively, this file may be used under the terms of the GNU
 
31
** General Public License version 3.0 as published by the Free Software
 
32
** Foundation and appearing in the file LICENSE.GPL included in the
 
33
** packaging of this file.  Please review the following information to
 
34
** ensure the GNU General Public License version 3.0 requirements will be
 
35
** met: http://www.gnu.org/copyleft/gpl.html.
 
36
**
 
37
**
 
38
** $QT_END_LICENSE$
 
39
**
 
40
****************************************************************************/
 
41
 
 
42
// Most of the code here was originally written by Serika Kurusugawa,
 
43
// a.k.a. Junji Takagi, and is included in Qt with the author's permission
 
44
// and the grateful thanks of the Qt team.
 
45
 
 
46
/*! \class QJisCodec
 
47
    \inmodule QtCore
 
48
    \reentrant
 
49
    \internal
 
50
*/
 
51
 
 
52
#include "qjiscodec_p.h"
 
53
#include "qlist.h"
 
54
 
 
55
QT_BEGIN_NAMESPACE
 
56
 
 
57
#ifndef QT_NO_BIG_CODECS
 
58
enum {
 
59
    Esc = 0x1b,
 
60
    So = 0x0e,         // Shift Out
 
61
    Si = 0x0f,         // Shift In
 
62
 
 
63
    ReverseSolidus = 0x5c,
 
64
    YenSign = 0x5c,
 
65
    Tilde = 0x7e,
 
66
    Overline = 0x7e
 
67
};
 
68
 
 
69
#define        IsKana(c)        (((c) >= 0xa1) && ((c) <= 0xdf))
 
70
#define        IsJisChar(c)        (((c) >= 0x21) && ((c) <= 0x7e))
 
71
 
 
72
#define        QValidChar(u)        ((u) ? QChar((ushort)(u)) : QChar(QChar::ReplacementCharacter))
 
73
 
 
74
enum Iso2022State{ Ascii, MinState = Ascii,
 
75
                   JISX0201_Latin, JISX0201_Kana,
 
76
                   JISX0208_1978, JISX0208_1983,
 
77
                   JISX0212, MaxState = JISX0212,
 
78
                   UnknownState };
 
79
 
 
80
static const char Esc_CHARS[] = "()*+-./";
 
81
 
 
82
static const char Esc_Ascii[]                 = {Esc, '(', 'B', 0 };
 
83
static const char Esc_JISX0201_Latin[]        = {Esc, '(', 'J', 0 };
 
84
static const char Esc_JISX0201_Kana[]        = {Esc, '(', 'I', 0 };
 
85
static const char Esc_JISX0208_1978[]        = {Esc, '$', '@', 0 };
 
86
static const char Esc_JISX0208_1983[]        = {Esc, '$', 'B', 0 };
 
87
static const char Esc_JISX0212[]        = {Esc, '$', '(', 'D', 0 };
 
88
static const char * const Esc_SEQ[] = { Esc_Ascii,
 
89
                                        Esc_JISX0201_Latin,
 
90
                                        Esc_JISX0201_Kana,
 
91
                                        Esc_JISX0208_1978,
 
92
                                        Esc_JISX0208_1983,
 
93
                                        Esc_JISX0212 };
 
94
 
 
95
/*!
 
96
    \internal
 
97
*/
 
98
QJisCodec::QJisCodec() : conv(QJpUnicodeConv::newConverter(QJpUnicodeConv::Default))
 
99
{
 
100
}
 
101
 
 
102
 
 
103
/*!
 
104
    \internal
 
105
*/
 
106
QJisCodec::~QJisCodec()
 
107
{
 
108
    delete (QJpUnicodeConv*)conv;
 
109
    conv = 0;
 
110
}
 
111
 
 
112
QByteArray QJisCodec::convertFromUnicode(const QChar *uc, int len, ConverterState *cs) const
 
113
{
 
114
    char replacement = '?';
 
115
    if (cs) {
 
116
        if (cs->flags & ConvertInvalidToNull)
 
117
            replacement = 0;
 
118
    }
 
119
    int invalid = 0;
 
120
 
 
121
    QByteArray result;
 
122
    Iso2022State state = Ascii;
 
123
    Iso2022State prev = Ascii;
 
124
    for (int i = 0; i < len; i++) {
 
125
        QChar ch = uc[i];
 
126
        uint j;
 
127
        if (ch.row() == 0x00 && ch.cell() < 0x80) {
 
128
            // Ascii
 
129
            if (state != JISX0201_Latin ||
 
130
                ch.cell() == ReverseSolidus || ch.cell() == Tilde) {
 
131
                state = Ascii;
 
132
            }
 
133
            j = ch.cell();
 
134
        } else if ((j = conv->unicodeToJisx0201(ch.row(), ch.cell())) != 0) {
 
135
            if (j < 0x80) {
 
136
                // JIS X 0201 Latin
 
137
                if (state != Ascii ||
 
138
                    ch.cell() == YenSign || ch.cell() == Overline) {
 
139
                    state = JISX0201_Latin;
 
140
                }
 
141
            } else {
 
142
                // JIS X 0201 Kana
 
143
                state = JISX0201_Kana;
 
144
                j &= 0x7f;
 
145
            }
 
146
        } else if ((j = conv->unicodeToJisx0208(ch.row(), ch.cell())) != 0) {
 
147
            // JIS X 0208
 
148
            state = JISX0208_1983;
 
149
        } else if ((j = conv->unicodeToJisx0212(ch.row(), ch.cell())) != 0) {
 
150
            // JIS X 0212
 
151
            state = JISX0212;
 
152
        } else {
 
153
            // Invalid
 
154
            state = UnknownState;
 
155
            j = replacement;
 
156
            ++invalid;
 
157
        }
 
158
        if (state != prev) {
 
159
            if (state == UnknownState) {
 
160
                result += Esc_Ascii;
 
161
            } else {
 
162
                result += Esc_SEQ[state - MinState];
 
163
            }
 
164
            prev = state;
 
165
        }
 
166
        if (j < 0x0100) {
 
167
            result += j & 0xff;
 
168
        } else {
 
169
            result += (j >> 8) & 0xff;
 
170
            result += j & 0xff;
 
171
        }
 
172
    }
 
173
    if (prev != Ascii) {
 
174
        result += Esc_Ascii;
 
175
    }
 
176
 
 
177
    if (cs) {
 
178
        cs->invalidChars += invalid;
 
179
    }
 
180
    return result;
 
181
}
 
182
 
 
183
QString QJisCodec::convertToUnicode(const char* chars, int len, ConverterState *cs) const
 
184
{
 
185
    uchar buf[4] = {0, 0, 0, 0};
 
186
    int nbuf = 0;
 
187
    Iso2022State state = Ascii, prev = Ascii;
 
188
    bool esc = false;
 
189
    QChar replacement = QChar::ReplacementCharacter;
 
190
    if (cs) {
 
191
        if (cs->flags & ConvertInvalidToNull)
 
192
            replacement = QChar::Null;
 
193
        nbuf = cs->remainingChars;
 
194
        buf[0] = (cs->state_data[0] >> 24) & 0xff;
 
195
        buf[1] = (cs->state_data[0] >> 16) & 0xff;
 
196
        buf[2] = (cs->state_data[0] >>  8) & 0xff;
 
197
        buf[3] = (cs->state_data[0] >>  0) & 0xff;
 
198
        state = (Iso2022State)((cs->state_data[1] >>  0) & 0xff);
 
199
        prev = (Iso2022State)((cs->state_data[1] >>  8) & 0xff);
 
200
        esc = cs->state_data[2];
 
201
    }
 
202
    int invalid = 0;
 
203
 
 
204
    QString result;
 
205
    for (int i=0; i<len; i++) {
 
206
        uchar ch = chars[i];
 
207
        if (esc) {
 
208
            // Escape sequence
 
209
            state = UnknownState;
 
210
            switch (nbuf) {
 
211
            case 0:
 
212
                if (ch == '$' || strchr(Esc_CHARS, ch)) {
 
213
                    buf[nbuf++] = ch;
 
214
                } else {
 
215
                    nbuf = 0;
 
216
                    esc = false;
 
217
                }
 
218
                break;
 
219
            case 1:
 
220
                if (buf[0] == '$') {
 
221
                    if (strchr(Esc_CHARS, ch)) {
 
222
                        buf[nbuf++] = ch;
 
223
                    } else {
 
224
                        switch (ch) {
 
225
                        case '@':
 
226
                            state = JISX0208_1978;        // Esc $ @
 
227
                            break;
 
228
                        case 'B':
 
229
                            state = JISX0208_1983;        // Esc $ B
 
230
                            break;
 
231
                        }
 
232
                        nbuf = 0;
 
233
                        esc = false;
 
234
                    }
 
235
                } else {
 
236
                    if (buf[0] == '(') {
 
237
                        switch (ch) {
 
238
                        case 'B':
 
239
                            state = Ascii;        // Esc (B
 
240
                            break;
 
241
                        case 'I':
 
242
                            state = JISX0201_Kana;        // Esc (I
 
243
                            break;
 
244
                        case 'J':
 
245
                            state = JISX0201_Latin;        // Esc (J
 
246
                            break;
 
247
                        }
 
248
                    }
 
249
                    nbuf = 0;
 
250
                    esc = false;
 
251
                }
 
252
                break;
 
253
            case 2:
 
254
                if (buf[1] == '(') {
 
255
                    switch (ch) {
 
256
                    case 'D':
 
257
                        state = JISX0212;        // Esc $ (D
 
258
                        break;
 
259
                    }
 
260
                }
 
261
                nbuf = 0;
 
262
                esc = false;
 
263
                break;
 
264
            }
 
265
        } else {
 
266
            if (ch == Esc) {
 
267
                // Escape sequence
 
268
                nbuf = 0;
 
269
                esc = true;
 
270
            } else if (ch == So) {
 
271
                // Shift out
 
272
                prev = state;
 
273
                state = JISX0201_Kana;
 
274
                nbuf = 0;
 
275
            } else if (ch == Si) {
 
276
                // Shift in
 
277
                if (prev == Ascii || prev == JISX0201_Latin) {
 
278
                    state = prev;
 
279
                } else {
 
280
                    state = Ascii;
 
281
                }
 
282
                nbuf = 0;
 
283
            } else {
 
284
                uint u;
 
285
                switch (nbuf) {
 
286
                case 0:
 
287
                    switch (state) {
 
288
                    case Ascii:
 
289
                        if (ch < 0x80) {
 
290
                            result += QLatin1Char(ch);
 
291
                            break;
 
292
                        }
 
293
                        /* fall through */
 
294
                    case JISX0201_Latin:
 
295
                        u = conv->jisx0201ToUnicode(ch);
 
296
                        result += QValidChar(u);
 
297
                        break;
 
298
                    case JISX0201_Kana:
 
299
                        u = conv->jisx0201ToUnicode(ch | 0x80);
 
300
                        result += QValidChar(u);
 
301
                        break;
 
302
                    case JISX0208_1978:
 
303
                    case JISX0208_1983:
 
304
                    case JISX0212:
 
305
                        buf[nbuf++] = ch;
 
306
                        break;
 
307
                    default:
 
308
                        result += QChar::ReplacementCharacter;
 
309
                        break;
 
310
                    }
 
311
                    break;
 
312
                case 1:
 
313
                    switch (state) {
 
314
                    case JISX0208_1978:
 
315
                    case JISX0208_1983:
 
316
                        u = conv->jisx0208ToUnicode(buf[0] & 0x7f, ch & 0x7f);
 
317
                        result += QValidChar(u);
 
318
                        break;
 
319
                    case JISX0212:
 
320
                        u = conv->jisx0212ToUnicode(buf[0] & 0x7f, ch & 0x7f);
 
321
                        result += QValidChar(u);
 
322
                        break;
 
323
                    default:
 
324
                        result += replacement;
 
325
                        ++invalid;
 
326
                        break;
 
327
                    }
 
328
                    nbuf = 0;
 
329
                    break;
 
330
                }
 
331
            }
 
332
        }
 
333
    }
 
334
 
 
335
    if (cs) {
 
336
        cs->remainingChars = nbuf;
 
337
        cs->invalidChars += invalid;
 
338
        cs->state_data[0] = (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + buf[3];
 
339
        cs->state_data[1] = (prev << 8) + state;
 
340
        cs->state_data[2] = esc;
 
341
    }
 
342
 
 
343
    return result;
 
344
}
 
345
 
 
346
 
 
347
 
 
348
/*!
 
349
    \internal
 
350
*/
 
351
int QJisCodec::_mibEnum()
 
352
{
 
353
    return 39;
 
354
}
 
355
 
 
356
/*!
 
357
    \internal
 
358
*/
 
359
QByteArray QJisCodec::_name()
 
360
{
 
361
    return "ISO-2022-JP";
 
362
}
 
363
 
 
364
/*!
 
365
    Returns the codec's mime name.
 
366
*/
 
367
QList<QByteArray> QJisCodec::_aliases()
 
368
{
 
369
    QList<QByteArray> list;
 
370
    list << "JIS7"; // Qt 3 compat
 
371
    return list;
 
372
}
 
373
 
 
374
#endif // QT_NO_BIG_CODECS
 
375
 
 
376
QT_END_NAMESPACE