1 /* 2 * Copyright (c) 2008, 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.regex.*; 30 import java.util.*; 31 import static build.tools.charsetmapping.Utils.*; 32 33 public class JIS0213 { 34 35 // regex pattern to parse the "jis0213.map" file 36 static Pattern sjis0213 = Pattern.compile("0x(\\p{XDigit}++)\\s++U\\+(\\p{XDigit}++)(?:\\+(\\p{XDigit}++))?\\s++#.*"); 37 38 static void genClass(String argv[]) throws IOException 39 { 40 InputStream in = new FileInputStream(argv[0]) ; 41 OutputStream out = new FileOutputStream(argv[1]); 42 43 int[] sb = new int[0x100]; // singlebyte 44 int[] db = new int[0x10000]; // doublebyte 45 int[] indexC2B = new int[256]; 46 Entry[] supp = new Entry[0x10000]; 47 Entry[] comp = new Entry[0x100]; 48 int suppTotal = 0; 49 int compTotal = 0; 50 51 int b1Min1 = 0x81; 52 int b1Max1 = 0x9f; 53 int b1Min2 = 0xe0; 54 int b1Max2 = 0xfc; 55 int b2Min = 0x40; 56 int b2Max = 0xfe; 57 58 //init 59 for (int i = 0; i < 0x80; i++) sb[i] = i; 60 for (int i = 0x80; i < 0x100; i++) sb[i] = UNMAPPABLE_DECODING; 61 for (int i = 0; i < 0x10000; i++) db[i] = UNMAPPABLE_DECODING; 62 try { 63 Parser p = new Parser(in, sjis0213); 64 Entry e = null; 65 while ((e = p.next()) != null) { 66 if (e.cp2 != 0) { 67 comp[compTotal++] = e; 68 } else { 69 if (e.cp <= 0xffff) { 70 if (e.bs <= 0xff) 71 sb[e.bs] = e.cp; 72 else 73 db[e.bs] = e.cp; 74 indexC2B[e.cp>>8] = 1; 75 } else { 76 supp[suppTotal++] = e; 77 } 78 } 79 } 80 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 81 // c2b Index Table, always the first one 82 writeINDEXC2B(baos, indexC2B); 83 writeSINGLEBYTE(baos, sb); 84 writeDOUBLEBYTE1(baos, db, b1Min1, b1Max1, b2Min, b2Max); 85 writeDOUBLEBYTE2(baos, db, b1Min2, b1Max2, b2Min, b2Max); 86 writeSUPPLEMENT(baos, supp, suppTotal); 87 writeCOMPOSITE(baos, comp, compTotal); 88 writeSIZE(out, baos.size()); 89 baos.writeTo(out); 90 out.close(); 91 } catch (Exception x) { 92 x.printStackTrace(); 93 } 94 } 95 96 static Comparator<Entry> comparatorCP = 97 new Comparator<Entry>() { 98 public int compare(Entry m1, Entry m2) { 99 return m1.cp - m2.cp; 100 } 101 public boolean equals(Object obj) { 102 return this == obj; 103 } 104 }; 105 106 // tags of different charset mapping tables 107 private final static int MAP_SINGLEBYTE = 0x1; // 0..256 : c 108 private final static int MAP_DOUBLEBYTE1 = 0x2; // min..max: c 109 private final static int MAP_DOUBLEBYTE2 = 0x3; // min..max: c [DB2] 110 private final static int MAP_SUPPLEMENT = 0x5; // db,c 111 private final static int MAP_SUPPLEMENT_C2B = 0x6; // c,db 112 private final static int MAP_COMPOSITE = 0x7; // db,base,cc 113 private final static int MAP_INDEXC2B = 0x8; // index table of c->bb 114 115 private static final void writeShort(OutputStream out, int data) 116 throws IOException 117 { 118 out.write((data >>> 8) & 0xFF); 119 out.write((data ) & 0xFF); 120 } 121 122 private static final void writeShortArray(OutputStream out, 123 int type, 124 int[] array, 125 int off, 126 int size) // exclusive 127 throws IOException 128 { 129 writeShort(out, type); 130 writeShort(out, size); 131 for (int i = off; i < size; i++) { 132 writeShort(out, array[off+i]); 133 } 134 } 135 136 private static final void writeSIZE(OutputStream out, int data) 137 throws IOException 138 { 139 out.write((data >>> 24) & 0xFF); 140 out.write((data >>> 16) & 0xFF); 141 out.write((data >>> 8) & 0xFF); 142 out.write((data ) & 0xFF); 143 } 144 145 private static void writeINDEXC2B(OutputStream out, int[] indexC2B) 146 throws IOException 147 { 148 writeShort(out, MAP_INDEXC2B); 149 writeShort(out, indexC2B.length); 150 int off = 0; 151 for (int i = 0; i < indexC2B.length; i++) { 152 if (indexC2B[i] != 0) { 153 writeShort(out, off); 154 off += 256; 155 } else { 156 writeShort(out, -1); 157 } 158 } 159 } 160 161 private static void writeSINGLEBYTE(OutputStream out, int[] sb) 162 throws IOException 163 { 164 writeShortArray(out, MAP_SINGLEBYTE, sb, 0, 256); 165 } 166 167 private static void writeDOUBLEBYTE(OutputStream out, 168 int type, 169 int[] db, 170 int b1Min, int b1Max, 171 int b2Min, int b2Max) 172 throws IOException 173 { 174 writeShort(out, type); 175 writeShort(out, b1Min); 176 writeShort(out, b1Max); 177 writeShort(out, b2Min); 178 writeShort(out, b2Max); 179 writeShort(out, (b1Max - b1Min + 1) * (b2Max - b2Min + 1)); 180 181 for (int b1 = b1Min; b1 <= b1Max; b1++) { 182 for (int b2 = b2Min; b2 <= b2Max; b2++) { 183 writeShort(out, db[b1 * 256 + b2]); 184 } 185 } 186 } 187 188 private static void writeDOUBLEBYTE1(OutputStream out, 189 int[] db, 190 int b1Min, int b1Max, 191 int b2Min, int b2Max) 192 throws IOException 193 { 194 writeDOUBLEBYTE(out, MAP_DOUBLEBYTE1, db, b1Min, b1Max, b2Min, b2Max); 195 } 196 197 private static void writeDOUBLEBYTE2(OutputStream out, 198 int[] db, 199 int b1Min, int b1Max, 200 int b2Min, int b2Max) 201 throws IOException 202 { 203 writeDOUBLEBYTE(out, MAP_DOUBLEBYTE2, db, b1Min, b1Max, b2Min, b2Max); 204 } 205 206 // the c2b table is output as well 207 private static void writeSUPPLEMENT(OutputStream out, Entry[] supp, int size) 208 throws IOException 209 { 210 writeShort(out, MAP_SUPPLEMENT); 211 writeShort(out, size * 2); 212 // db at first half, cc at the low half 213 for (int i = 0; i < size; i++) { 214 writeShort(out, supp[i].bs); 215 } 216 for (int i = 0; i < size; i++) { 217 writeShort(out, supp[i].cp); 218 } 219 220 //c2b 221 writeShort(out, MAP_SUPPLEMENT_C2B); 222 writeShort(out, size*2); 223 Arrays.sort(supp, 0, size, comparatorCP); 224 for (int i = 0; i < size; i++) { 225 writeShort(out, supp[i].cp); 226 } 227 for (int i = 0; i < size; i++) { 228 writeShort(out, supp[i].bs); 229 } 230 } 231 232 private static void writeCOMPOSITE(OutputStream out, Entry[] comp, int size) 233 throws IOException 234 { 235 writeShort(out, MAP_COMPOSITE); 236 writeShort(out, size*3); 237 // comp is sorted already 238 for (int i = 0; i < size; i++) { 239 writeShort(out, (char)comp[i].bs); 240 writeShort(out, (char)comp[i].cp); 241 writeShort(out, (char)comp[i].cp2); 242 } 243 } 244 }