summaryrefslogtreecommitdiff
path: root/enc/trans/iso2022.erb.c
blob: 72553f40542731edeed1c03b62c7092e6b749a2b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#include "transcode_data.h"

<%
  map = {}
  map["1b2842"] = :func_so       # designate US-ASCII to G0.             "ESC ( B"
  map["1b284a"] = :func_so       # designate JIS X 0201 latin to G0.     "ESC ( J"
  map["1b2440"] = :func_so       # designate JIS X 0208 1978 to G0.      "ESC $ @"
  map["1b2442"] = :func_so       # designate JIS X 0208 1983 to G0.      "ESC $ B"
  map["{00-0d,10-1a,1c-7f}"] = :func_si

  map_jisx0208_rest = {}
  map_jisx0208_rest["{21-7e}"] = :func_so
%>

<%= transcode_generate_node(ActionMap.parse(map), "iso2022jp_to_eucjp") %>
<%= transcode_generate_node(ActionMap.parse(map_jisx0208_rest), "iso2022jp_to_eucjp_jisx0208_rest") %>

static VALUE
fun_si_iso2022jp_to_eucjp(rb_transcoding* t, const unsigned char* s, size_t l)
{
    if (t->stateful[0] == 0)
        return (VALUE)NOMAP;
    else if (0x21 <= s[0] && s[0] <= 0x7e)
        return (VALUE)&iso2022jp_to_eucjp_jisx0208_rest;
    else
        return (VALUE)INVALID;
}

static int
fun_so_iso2022jp_to_eucjp(rb_transcoding* t, const unsigned char* s, size_t l, unsigned char* o)
{
    if (s[0] == 0x1b) {
        if (s[1] == '(') {
            switch (s[l-1]) {
              case 'B':
              case 'J':
                t->stateful[0] = 0;
                break;
            }
        }
        else {
            switch (s[l-1]) {
              case '@':
              case 'B':
                t->stateful[0] = 1;
                break;
            }
        }
        return 0;
    }
    else {
        o[0] = s[0] | 0x80;
        o[1] = s[1] | 0x80;
        return 2;
    }
}

static const rb_transcoder
rb_ISO_2022_JP_to_EUC_JP = {
    "ISO-2022-JP", "EUC-JP", &iso2022jp_to_eucjp, 1, 3,
    NULL, fun_si_iso2022jp_to_eucjp, NULL, fun_so_iso2022jp_to_eucjp
};

<%
  map_eucjp = {
    "{0e,0f,1b}" => :undef,
    "{00-0d,10-1a,1c-7f}" => :func_so,
    "{a1-fe}{a1-fe}" => :func_so,
    "8e{a1-fe}" => :undef,
    "8f{a1-fe}{a1-fe}" => :undef,
  }
%>

<%= transcode_generate_node(ActionMap.parse(map_eucjp), "eucjp_to_iso2022jp") %>

static int
fun_so_eucjp_to_iso2022jp(rb_transcoding *t, const unsigned char *s, size_t l, unsigned char *o)
{
    unsigned char *output0 = o;

    if (t->stateful[0] == 0) {
        t->stateful[0] = 1; /* initialized flag */
        t->stateful[1] = 1; /* ASCII mode */
    }

    if (l != t->stateful[1]) {
        if (l == 1) {
            *o++ = 0x1b;
            *o++ = '(';
            *o++ = 'B';
            t->stateful[1] = 1;
        }
        else {
            *o++ = 0x1b;
            *o++ = '$';
            *o++ = 'B';
            t->stateful[1] = 2;
        }
    }

    if (l == 1) {
        *o++ = s[0] & 0x7f;
    }
    else {
        *o++ = s[0] & 0x7f;
        *o++ = s[1] & 0x7f;
    }

    return o - output0;
}

static int
finish_eucjp_to_iso2022jp(rb_transcoding *t, unsigned char *o)
{
    unsigned char *output0 = o;

    if (t->stateful[0] == 0)
        return 0;

    if (t->stateful[1] != 1) {
        *o++ = 0x1b;
        *o++ = '(';
        *o++ = 'B';
        t->stateful[1] = 1;
    }

    return o - output0;
}

static const rb_transcoder
rb_EUC_JP_to_ISO_2022_JP = {
    "EUC-JP", "ISO-2022-JP", &eucjp_to_iso2022jp, 1, 5,
    NULL, NULL, NULL, fun_so_eucjp_to_iso2022jp, finish_eucjp_to_iso2022jp
};

void
Init_iso2022(void)
{
    rb_register_transcoder(&rb_ISO_2022_JP_to_EUC_JP);
    rb_register_transcoder(&rb_EUC_JP_to_ISO_2022_JP);
}