]> git.tdb.fi Git - libs/core.git/blob - source/iso2022jp.cpp
Added reset function for StringCodec::Decoder
[libs/core.git] / source / iso2022jp.cpp
1 #include "ascii.h"
2 #include "iso2022jp.h"
3 #include "jisx0201.h"
4 #include "jisx0208.h"
5
6 using namespace std;
7
8 namespace Msp {
9
10 void Iso2022Jp::Encoder::encode_char(wchar_t c)
11 {
12         if(c>=0 && c<=0x7F && c!=0x5C && c!=0x7E)
13         {
14                 if(mode!=ASCII && mode!=JISX0201)
15                         switch_mode(ASCII);
16                 append(c);
17         }
18         else if(c==0x5C || c==0x7E)
19         {
20                 if(mode!=ASCII)
21                         switch_mode(ASCII);
22                 append(c);
23         }
24         else if(c==0xA5 || c==0x203E)
25         {
26                 if(mode!=JISX0201)
27                         switch_mode(JISX0201);
28                 if(c==0xA5)
29                         append(0x5C);
30                 else if(c==0x203E)
31                         append(0x7E);
32         }
33         else
34         {
35                 unsigned short jis=ucs_to_jisx0208(c);
36                 if(!jis)
37                         throw CodecError("Can't express character in ISO-2022-JP");
38                 if(mode!=JISX0208)
39                         switch_mode(JISX0208);
40
41                 char buf[2]={jis>>8, jis};
42                 append(buf, 2);
43         }
44 }
45
46 void Iso2022Jp::Encoder::sync()
47 {
48         if(mode!=ASCII)
49                 switch_mode(ASCII);
50 }
51
52 void Iso2022Jp::Encoder::switch_mode(Mode m)
53 {
54         mode=m;
55         switch(mode)
56         {
57         case ASCII:    append("\033(B", 3); break;
58         case JISX0201: append("\033(J", 3); break;
59         case JISX0208: append("\033$B", 3); break;
60         }
61 }
62
63 Iso2022Jp::Decoder::Decoder():
64         mode(ASCII),
65         dec(new Ascii::Decoder),
66         escape(0)
67 { }
68
69 void Iso2022Jp::Decoder::decode_char(const string &str, string::const_iterator &i)
70 {
71         while(i!=str.end())
72         {
73                 if(escape)
74                 {
75                         escape=escape<<8 | static_cast<unsigned char>(*i);
76                         if(*i>='@' && *i<='Z')
77                         {
78                                 switch(escape)
79                                 {
80                                 case 0x1B2842: switch_mode(ASCII); break;    // ESC ( B
81                                 case 0x1B284A: switch_mode(JISX0201); break; // ESC ( J
82                                 case 0x1B2440:                               // ESC $ @
83                                 case 0x1B2442: switch_mode(JISX0208); break; // ESC $ B
84                                 default: throw CodecError("Invalid ISO-2022-JP escape sequence");
85                                 }
86                                 escape=0;
87                         }
88                         ++i;
89                 }
90                 else if(*i==0x1B)
91                 {
92                         escape=0x1B;
93                         ++i;
94                 }
95                 else
96                 {
97                         dec->decode_char(str, i);
98                         break;
99                 }
100         }
101 }
102
103 void Iso2022Jp::Decoder::sync()
104 {
105         if(escape)
106                 throw CodecError("Sync in middle of ISO-2022-JP escape sequence");
107         if(mode!=ASCII)
108                 throw CodecError("Sync while not in ASCII mode");
109         append(dec->get());
110         dec->flush();
111 }
112
113 void Iso2022Jp::Decoder::reset()
114 {
115         switch_mode(ASCII);
116         escape=0;
117 }
118
119 void Iso2022Jp::Decoder::switch_mode(Mode m)
120 {
121         append(dec->get());
122         delete dec;
123
124         mode=m;
125         switch(mode)
126         {
127         case ASCII: dec=new Ascii::Decoder; break;
128         case JISX0201: dec=new JisX0201::Decoder; break;
129         case JISX0208: dec=new JisX0208::Decoder; break;
130         }
131 }
132
133 } // namespace Msp