1/*
2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package build.tools.charsetmapping;
27
28import java.io.*;
29import java.util.Arrays;
30import java.util.ArrayList;
31import java.util.Scanner;
32import java.util.Formatter;
33import java.util.regex.*;
34import java.nio.charset.*;
35import static build.tools.charsetmapping.Utils.*;
36
37public class HKSCS {
38
39    // HKSCS2001.map has the third column for "UnicodeAlternate", which
40    // is for c->b non-roundtrip mapping.
41    // For HKSCS2008, those non-roundtrip mappings are in .nr file
42    private static Pattern hkscs =
43        Pattern.compile("(?:0x)?+(\\p{XDigit}++)\\s++(?:0x|U\\+)?+(\\p{XDigit}++)?\\s*+(?:0x|U\\+)?(\\p{XDigit}++)?\\s*+.*");
44
45    static void genClass2008(String srcDir, String dstDir, String pkgName, File copyright)
46        throws Exception
47    {
48        // hkscs2008
49        genClass0(new FileInputStream(new File(srcDir, "HKSCS2008.map")),
50                  new FileInputStream(new File(srcDir, "HKSCS2008.c2b")),
51                  new PrintStream(new File(dstDir, "HKSCSMapping.java"),
52                                  "ISO-8859-1"),
53                  pkgName,
54                  "HKSCSMapping",
55                  true,
56                  getCopyright(copyright));
57
58    }
59
60    static void genClassXP(String srcDir, String dstDir, String pkgName, File copyright)
61        throws Exception
62    {
63        genClass0(new FileInputStream(new File(srcDir, "HKSCS_XP.map")),
64                  null,
65                  new PrintStream(new File(dstDir, "HKSCS_XPMapping.java"),
66                                  "ISO-8859-1"),
67                  pkgName,
68                  "HKSCS_XPMapping",
69                  false,
70                  getCopyright(copyright));
71    }
72
73    static void genClass2001(String args[]) throws Exception {
74        // hkscs2001
75        genClass0(new FileInputStream(new File(args[0], "HKSCS2001.map")),
76                  new FileInputStream(new File(args[0], "HKSCS2001.c2b")),
77                  new PrintStream(new File(args[1], "HKSCS2001Mapping.java"),
78                                  "ISO-8859-1"),
79                  "sun.nio.cs.ext",
80                  "HKSCS2001Mapping",
81                  false,
82                  getCopyright(new File(args[3])));
83    }
84
85    static void genClass0(InputStream isB2C,
86                          InputStream isC2B,
87                          PrintStream ps,
88                          String pkgName,
89                          String clzName,
90                          boolean isPublic,
91                          String copyright)
92        throws Exception
93    {
94        // ranges of byte1 and byte2, something should come from a "config" file
95        int b1Min = 0x87;
96        int b1Max = 0xfe;
97        int b2Min = 0x40;
98        int b2Max = 0xfe;
99
100        try {
101            char[] bmp = new char[0x10000];
102            char[] supp = new char[0x10000];
103
104            boolean[] b2cBmp = new boolean[0x100];
105            boolean[] b2cSupp = new boolean[0x100];
106            // pua should be in range of e000-f8ff. Expand
107            // it to 0xf93b becase the hkscs2001.c2b has
108            // the f920-f93b filled
109            //char[] pua = new char[0xF8FF - 0xE000 + 1];
110            char[] pua = new char[0xF93b - 0xE000 + 1];
111            boolean hasSupp = false;
112            boolean hasPua = false;
113
114            Arrays.fill(bmp, UNMAPPABLE_DECODING);
115            Arrays.fill(supp, UNMAPPABLE_DECODING);
116            Arrays.fill(pua, UNMAPPABLE_DECODING);
117
118            Parser p = new Parser(isB2C, hkscs);
119            Entry  e = null;
120            while ((e = p.next()) != null) {
121                if (e.cp >= 0x10000) {
122                    supp[e.bs] = (char)e.cp;
123                    b2cSupp[e.bs>>8] = true;
124                    hasSupp = true;
125                } else {
126                    bmp[e.bs] = (char)e.cp;
127                    b2cBmp[e.bs>>8] = true;
128                }
129                if (e.cp2 != 0 && e.cp2 >= 0xe000 && e.cp2 <= 0xf8ff) {
130                    hasPua = true;
131                    pua[e.cp2 - 0xE000] = (char)e.bs;
132                }
133            }
134
135            if (isC2B != null) {
136                p = new Parser(isC2B, hkscs);
137                e = null;
138                while ((e = p.next()) != null) {
139                    pua[e.cp - 0xE000] = (char)e.bs;
140                }
141                hasPua = true;
142            }
143
144            StringBuilder sb = new StringBuilder();
145            Output out = new Output(new Formatter(sb));
146
147            out.format(copyright);
148            out.format("%n// -- This file was mechanically generated: Do not edit! -- //%n");
149            out.format("package %s;%n%n", pkgName);
150            out.format("%sclass %s {%n%n", isPublic ? "public " : "", clzName);
151
152            /* hardcoded in sun.nio.cs.ext.HKSCS.java
153            out.format("    final static int b1Min = 0x%x;%n", b1Min);
154            out.format("    final static int b1Max = 0x%x;%n", b1Max);
155            out.format("    final static int b2Min = 0x%x;%n", b2Min);
156            out.format("    final static int b2Max = 0x%x;%n", b2Max);
157            */
158
159            // bmp tables
160            out.format("%n    %sstatic final String[] b2cBmpStr = new String[] {%n",
161                       isPublic ? "public " : "");
162            for (int i = 0; i < 0x100; i++) {
163                if (b2cBmp[i])
164                    out.format(bmp, i, b2Min, b2Max, ",");
165                else
166                    out.format("        null,%n");  //unmappable segments
167            }
168            out.format("        };%n");
169
170            // supp tables
171            out.format("%n    %sstatic final String[] b2cSuppStr =",
172                       isPublic ? "public " : "");
173            if (hasSupp) {
174                out.format(" new String[] {%n");
175                for (int i = 0; i < 0x100; i++) {
176                    if (b2cSupp[i])
177                        out.format(supp, i, b2Min, b2Max, ",");
178                    else
179                        out.format("        null,%n");  //unmappable segments
180                }
181                out.format("        };%n");
182            } else {
183                out.format(" null;%n");
184            }
185
186            // private area tables
187            out.format("%n    %sfinal static String pua =",
188                       isPublic ? "public " : "");
189            if (hasPua) {
190                out.format("%n");
191                out.format(pua, 0, pua.length, ";");
192            } else {
193                out.format(" null;%n");
194            }
195            out.format("%n");
196            out.format("}");
197
198            out.close();
199
200            ps.println(sb.toString());
201            ps.close();
202
203        } catch (Exception x) {
204            x.printStackTrace();
205        }
206    }
207}
208