| /* |
| * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package build.tools.charsetmapping; |
| |
| import java.io.*; |
| import java.util.regex.*; |
| import java.util.*; |
| import static build.tools.charsetmapping.Utils.*; |
| |
| public class JIS0213 { |
| |
| // regex pattern to parse the "jis0213.map" file |
| static Pattern sjis0213 = Pattern.compile("0x(\\p{XDigit}++)\\s++U\\+(\\p{XDigit}++)(?:\\+(\\p{XDigit}++))?\\s++#.*"); |
| |
| static void genClass(String argv[]) throws IOException |
| { |
| InputStream in = new FileInputStream(argv[0]) ; |
| OutputStream out = new FileOutputStream(argv[1]); |
| |
| int[] sb = new int[0x100]; // singlebyte |
| int[] db = new int[0x10000]; // doublebyte |
| int[] indexC2B = new int[256]; |
| Entry[] supp = new Entry[0x10000]; |
| Entry[] comp = new Entry[0x100]; |
| int suppTotal = 0; |
| int compTotal = 0; |
| |
| int b1Min1 = 0x81; |
| int b1Max1 = 0x9f; |
| int b1Min2 = 0xe0; |
| int b1Max2 = 0xfc; |
| int b2Min = 0x40; |
| int b2Max = 0xfe; |
| |
| //init |
| for (int i = 0; i < 0x80; i++) sb[i] = i; |
| for (int i = 0x80; i < 0x100; i++) sb[i] = UNMAPPABLE_DECODING; |
| for (int i = 0; i < 0x10000; i++) db[i] = UNMAPPABLE_DECODING; |
| try { |
| Parser p = new Parser(in, sjis0213); |
| Entry e = null; |
| while ((e = p.next()) != null) { |
| if (e.cp2 != 0) { |
| comp[compTotal++] = e; |
| } else { |
| if (e.cp <= 0xffff) { |
| if (e.bs <= 0xff) |
| sb[e.bs] = e.cp; |
| else |
| db[e.bs] = e.cp; |
| indexC2B[e.cp>>8] = 1; |
| } else { |
| supp[suppTotal++] = e; |
| } |
| } |
| } |
| ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
| // c2b Index Table, always the first one |
| writeINDEXC2B(baos, indexC2B); |
| writeSINGLEBYTE(baos, sb); |
| writeDOUBLEBYTE1(baos, db, b1Min1, b1Max1, b2Min, b2Max); |
| writeDOUBLEBYTE2(baos, db, b1Min2, b1Max2, b2Min, b2Max); |
| writeSUPPLEMENT(baos, supp, suppTotal); |
| writeCOMPOSITE(baos, comp, compTotal); |
| writeSIZE(out, baos.size()); |
| baos.writeTo(out); |
| out.close(); |
| } catch (Exception x) { |
| x.printStackTrace(); |
| } |
| } |
| |
| static Comparator<Entry> comparatorCP = |
| new Comparator<Entry>() { |
| public int compare(Entry m1, Entry m2) { |
| return m1.cp - m2.cp; |
| } |
| public boolean equals(Object obj) { |
| return this == obj; |
| } |
| }; |
| |
| // tags of different charset mapping tables |
| private final static int MAP_SINGLEBYTE = 0x1; // 0..256 : c |
| private final static int MAP_DOUBLEBYTE1 = 0x2; // min..max: c |
| private final static int MAP_DOUBLEBYTE2 = 0x3; // min..max: c [DB2] |
| private final static int MAP_SUPPLEMENT = 0x5; // db,c |
| private final static int MAP_SUPPLEMENT_C2B = 0x6; // c,db |
| private final static int MAP_COMPOSITE = 0x7; // db,base,cc |
| private final static int MAP_INDEXC2B = 0x8; // index table of c->bb |
| |
| private static final void writeShort(OutputStream out, int data) |
| throws IOException |
| { |
| out.write((data >>> 8) & 0xFF); |
| out.write((data ) & 0xFF); |
| } |
| |
| private static final void writeShortArray(OutputStream out, |
| int type, |
| int[] array, |
| int off, |
| int size) // exclusive |
| throws IOException |
| { |
| writeShort(out, type); |
| writeShort(out, size); |
| for (int i = off; i < size; i++) { |
| writeShort(out, array[off+i]); |
| } |
| } |
| |
| private static final void writeSIZE(OutputStream out, int data) |
| throws IOException |
| { |
| out.write((data >>> 24) & 0xFF); |
| out.write((data >>> 16) & 0xFF); |
| out.write((data >>> 8) & 0xFF); |
| out.write((data ) & 0xFF); |
| } |
| |
| private static void writeINDEXC2B(OutputStream out, int[] indexC2B) |
| throws IOException |
| { |
| writeShort(out, MAP_INDEXC2B); |
| writeShort(out, indexC2B.length); |
| int off = 0; |
| for (int i = 0; i < indexC2B.length; i++) { |
| if (indexC2B[i] != 0) { |
| writeShort(out, off); |
| off += 256; |
| } else { |
| writeShort(out, -1); |
| } |
| } |
| } |
| |
| private static void writeSINGLEBYTE(OutputStream out, int[] sb) |
| throws IOException |
| { |
| writeShortArray(out, MAP_SINGLEBYTE, sb, 0, 256); |
| } |
| |
| private static void writeDOUBLEBYTE(OutputStream out, |
| int type, |
| int[] db, |
| int b1Min, int b1Max, |
| int b2Min, int b2Max) |
| throws IOException |
| { |
| writeShort(out, type); |
| writeShort(out, b1Min); |
| writeShort(out, b1Max); |
| writeShort(out, b2Min); |
| writeShort(out, b2Max); |
| writeShort(out, (b1Max - b1Min + 1) * (b2Max - b2Min + 1)); |
| |
| for (int b1 = b1Min; b1 <= b1Max; b1++) { |
| for (int b2 = b2Min; b2 <= b2Max; b2++) { |
| writeShort(out, db[b1 * 256 + b2]); |
| } |
| } |
| } |
| |
| private static void writeDOUBLEBYTE1(OutputStream out, |
| int[] db, |
| int b1Min, int b1Max, |
| int b2Min, int b2Max) |
| throws IOException |
| { |
| writeDOUBLEBYTE(out, MAP_DOUBLEBYTE1, db, b1Min, b1Max, b2Min, b2Max); |
| } |
| |
| private static void writeDOUBLEBYTE2(OutputStream out, |
| int[] db, |
| int b1Min, int b1Max, |
| int b2Min, int b2Max) |
| throws IOException |
| { |
| writeDOUBLEBYTE(out, MAP_DOUBLEBYTE2, db, b1Min, b1Max, b2Min, b2Max); |
| } |
| |
| // the c2b table is output as well |
| private static void writeSUPPLEMENT(OutputStream out, Entry[] supp, int size) |
| throws IOException |
| { |
| writeShort(out, MAP_SUPPLEMENT); |
| writeShort(out, size * 2); |
| // db at first half, cc at the low half |
| for (int i = 0; i < size; i++) { |
| writeShort(out, supp[i].bs); |
| } |
| for (int i = 0; i < size; i++) { |
| writeShort(out, supp[i].cp); |
| } |
| |
| //c2b |
| writeShort(out, MAP_SUPPLEMENT_C2B); |
| writeShort(out, size*2); |
| Arrays.sort(supp, 0, size, comparatorCP); |
| for (int i = 0; i < size; i++) { |
| writeShort(out, supp[i].cp); |
| } |
| for (int i = 0; i < size; i++) { |
| writeShort(out, supp[i].bs); |
| } |
| } |
| |
| private static void writeCOMPOSITE(OutputStream out, Entry[] comp, int size) |
| throws IOException |
| { |
| writeShort(out, MAP_COMPOSITE); |
| writeShort(out, size*3); |
| // comp is sorted already |
| for (int i = 0; i < size; i++) { |
| writeShort(out, (char)comp[i].bs); |
| writeShort(out, (char)comp[i].cp); |
| writeShort(out, (char)comp[i].cp2); |
| } |
| } |
| } |