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 
  26 package build.tools.charsetmapping;
  27 
  28 import java.io.*;
  29 import java.util.Arrays;
  30 import java.util.ArrayList;
  31 import java.util.Scanner;
  32 import java.util.Formatter;
  33 import java.util.regex.*;
  34 import java.nio.charset.*;
  35 import static build.tools.charsetmapping.Utils.*;
  36 
  37 public 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)
  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                   "");
  57     }
  58 
  59     static void genClassXP(String srcDir, String dstDir, String pkgName)
  60         throws Exception
  61     {
  62         genClass0(new FileInputStream(new File(srcDir, "HKSCS_XP.map")),
  63                   null,
  64                   new PrintStream(new File(dstDir, "HKSCS_XPMapping.java"),
  65                                   "ISO-8859-1"),
  66                   pkgName,
  67                   "HKSCS_XPMapping",
  68                   false,
  69                   "");
  70     }
  71 
  72     static void genClass2001(String args[]) throws Exception {
  73         // hkscs2001
  74         genClass0(new FileInputStream(new File(args[0], "HKSCS2001.map")),
  75                   new FileInputStream(new File(args[0], "HKSCS2001.c2b")),
  76                   new PrintStream(new File(args[1], "HKSCS2001Mapping.java"),
  77                                   "ISO-8859-1"),
  78                   "sun.nio.cs.ext",
  79                   "HKSCS2001Mapping",
  80                   false,
  81                   getCopyright(new File(args[3])));
  82     }
  83 
  84     static void genClass0(InputStream isB2C,
  85                           InputStream isC2B,
  86                           PrintStream ps,
  87                           String pkgName,
  88                           String clzName,
  89                           boolean isPublic,
  90                           String copyright)
  91         throws Exception
  92     {
  93         // ranges of byte1 and byte2, something should come from a "config" file
  94         int b1Min = 0x87;
  95         int b1Max = 0xfe;
  96         int b2Min = 0x40;
  97         int b2Max = 0xfe;
  98 
  99         try {
 100             char[] bmp = new char[0x10000];
 101             char[] supp = new char[0x10000];
 102 
 103             boolean[] b2cBmp = new boolean[0x100];
 104             boolean[] b2cSupp = new boolean[0x100];
 105             // pua should be in range of e000-f8ff. Expand
 106             // it to 0xf93b becase the hkscs2001.c2b has
 107             // the f920-f93b filled
 108             //char[] pua = new char[0xF8FF - 0xE000 + 1];
 109             char[] pua = new char[0xF93b - 0xE000 + 1];
 110             boolean hasSupp = false;
 111             boolean hasPua = false;
 112 
 113             Arrays.fill(bmp, UNMAPPABLE_DECODING);
 114             Arrays.fill(supp, UNMAPPABLE_DECODING);
 115             Arrays.fill(pua, UNMAPPABLE_DECODING);
 116 
 117             Parser p = new Parser(isB2C, hkscs);
 118             Entry  e = null;
 119             while ((e = p.next()) != null) {
 120                 if (e.cp >= 0x10000) {
 121                     supp[e.bs] = (char)e.cp;
 122                     b2cSupp[e.bs>>8] = true;
 123                     hasSupp = true;
 124                 } else {
 125                     bmp[e.bs] = (char)e.cp;
 126                     b2cBmp[e.bs>>8] = true;
 127                 }
 128                 if (e.cp2 != 0 && e.cp2 >= 0xe000 && e.cp2 <= 0xf8ff) {
 129                     hasPua = true;
 130                     pua[e.cp2 - 0xE000] = (char)e.bs;
 131                 }
 132             }
 133 
 134             if (isC2B != null) {
 135                 p = new Parser(isC2B, hkscs);
 136                 e = null;
 137                 while ((e = p.next()) != null) {
 138                     pua[e.cp - 0xE000] = (char)e.bs;
 139                 }
 140                 hasPua = true;
 141             }
 142 
 143             StringBuilder sb = new StringBuilder();
 144             Output out = new Output(new Formatter(sb));
 145 
 146             out.format(copyright);
 147             out.format("%n// -- This file was mechanically generated: Do not edit! -- //%n");
 148             out.format("package %s;%n%n", pkgName);
 149             out.format("%sclass %s {%n%n", isPublic ? "public " : "", clzName);
 150 
 151             /* hardcoded in sun.nio.cs.ext.HKSCS.java
 152             out.format("    final static int b1Min = 0x%x;%n", b1Min);
 153             out.format("    final static int b1Max = 0x%x;%n", b1Max);
 154             out.format("    final static int b2Min = 0x%x;%n", b2Min);
 155             out.format("    final static int b2Max = 0x%x;%n", b2Max);
 156             */
 157 
 158             // bmp tables
 159             out.format("%n    %sstatic final String[] b2cBmpStr = new String[] {%n",
 160                        isPublic ? "public " : "");
 161             for (int i = 0; i < 0x100; i++) {
 162                 if (b2cBmp[i])
 163                     out.format(bmp, i, b2Min, b2Max, ",");
 164                 else
 165                     out.format("        null,%n");  //unmappable segments
 166             }
 167             out.format("        };%n");
 168 
 169             // supp tables
 170             out.format("%n    %sstatic final String[] b2cSuppStr =",
 171                        isPublic ? "public " : "");
 172             if (hasSupp) {
 173                 out.format(" new String[] {%n");
 174                 for (int i = 0; i < 0x100; i++) {
 175                     if (b2cSupp[i])
 176                         out.format(supp, i, b2Min, b2Max, ",");
 177                     else
 178                         out.format("        null,%n");  //unmappable segments
 179                 }
 180                 out.format("        };%n");
 181             } else {
 182                 out.format(" null;%n");
 183             }
 184 
 185             // private area tables
 186             out.format("%n    %sfinal static String pua =",
 187                        isPublic ? "public " : "");
 188             if (hasPua) {
 189                 out.format("%n");
 190                 out.format(pua, 0, pua.length, ";");
 191             } else {
 192                 out.format(" null;%n");
 193             }
 194             out.format("%n");
 195             out.format("}");
 196 
 197             out.close();
 198 
 199             ps.println(sb.toString());
 200             ps.close();
 201 
 202         } catch (Exception x) {
 203             x.printStackTrace();
 204         }
 205     }
 206 }