📄 localizedstringsgenerator.java
字号:
/** The current search location. */ int index; /** The offset of the current item. */ int offset; /** The length of the table. */ int length; /** The data contents. */ String string;}/** * This class deals with generating the LocalizedStringsBase<locale>.c * files. We try to compress the footprint of the data, since we * don't read from the localized string tables very often */class CSourceWriter { /** The locale used. */ LocalizedStringSet locale; /** Output stream writer. */ PrintWriter writer; /** Array of strings to be processed. */ LocalizedString strings[]; /** * Sort all string data so they can be more easily compressed * @return the sorted array */ ArrayList sort() { ArrayList list = new ArrayList(); Vector strTable = locale.strings; for (int i = 0; i < strTable.size(); ++i) { String value = (String)strTable.get(i); if (strings[i] != null) { System.out.println("Duplicated content definiton for index " + i); throw new Error(); } strings[i] = new LocalizedString(i, value); list.add(strings[i]); } /** * Sorting function. */ Collections.sort(list, new Comparator() { /** * Comparison method. * @param o1 left hand operand * @param o2 right hand operand * @return positive value if o2 is greater than o1, * negative is o2 is less than o1 */ public int compare(Object o1, Object o2) { LocalizedString r1 = (LocalizedString)o1; LocalizedString r2 = (LocalizedString)o2; return (r1.string.length() < r2.string.length()) ? 1 : -1; } }); return list; } /** * Writes the C source file that stores the local string data in a * compact data structure * @param locale the target locale for comparison purposes * @param filename the source for processing * @param classname the locale handler */ void writeCSource(LocalizedStringSet locale, String filename, String classname) throws IOException { this.locale = locale; this.strings = new LocalizedString[locale.strings.size()]; FileOutputStream out = new FileOutputStream(filename); writer = new PrintWriter(new OutputStreamWriter(out)); pl("/* This file is auto-generated. Do not edit! */"); pl("#include <kni.h>"); pl("#include <string.h>"); pl("#include <midpMalloc.h>"); try { int type = writeOptimizedArray(); pl("KNIEXPORT KNI_RETURNTYPE_OBJECT"); pl("KNIDECL(com_sun_midp_l10n_" + classname + "_getContent) {"); if (type != UNICODE) { pl(" char stackbuffer[128];"); pl(" char *utf8; /*0-terminated*/"); } pl(" int index = KNI_GetParameterAsInt(1);"); pl(" KNI_StartHandles(1);"); pl(" KNI_DeclareHandle(string);"); pl(" if (index >= 0 && index <= max_index) {"); pl(" int offset = (int)offset_data[index * 2 + 0];"); pl(" int length = (int)offset_data[index * 2 + 1];"); pl(" if (offset >= 0) {"); if (type == UNICODE) { plx("KNI_NewString(string_data+offset, length, string);"); } else { plx("const unsigned char *p = string_data+offset;"); plx("if (length < 128) {"); plx(" utf8 = stackbuffer;"); plx("} else {"); plx(" utf8 = (char*)midpMalloc(length+1);"); plx("}"); plx("if (utf8) {"); plx(" memcpy(utf8, p, length);"); plx(" utf8[length] = 0;"); plx(" KNI_NewStringUTF(utf8, string);"); plx("}"); plx("if (utf8 && utf8 != stackbuffer) {"); plx(" midpFree(utf8);"); plx("}"); } pl(" }"); pl(" }"); pl(" KNI_EndHandlesAndReturnObject(string)"); pl("}"); } catch (Throwable t) { t.printStackTrace(); } writer.close(); } /** * Short-hand for printing a line to the output file * @param s the string to output */ void pl(String s) { writer.println(s); } /** * Short-hand for printing a line to the output file (with a 12-space * prefix) * @param s the string to output */ void plx(String s) { writer.print(" "); writer.println(s); } /** * Short-hand for printing a string into the output file * @param s the string to output */ void p(String s) { writer.print(s); } /** Indicate that a table should be stored as an UTF8 array in C code. */ public final int UTF8 = 1; /** Indicate that a table should be stored as an UNICODE array in C code.*/ public final int UNICODE = 2; /** * Write the string data using UTF8 or UNICODE, depending on which * is smaller. * @return the storage type */ int writeOptimizedArray() throws Throwable { // (1) Sort all strings and then merge them into a single String. // This allows shorter strings that are substrings of longer strings // to be omitted. ArrayList list = sort(); StringBuffer sbuf = new StringBuffer(); for (int i=0; i<list.size(); i++) { LocalizedString r = (LocalizedString)list.get(i); if (r != null) { int n = sbuf.indexOf(r.string); if (n >= 0) { r.offset = n; } else { r.offset = sbuf.length(); sbuf.append(r.string); } r.length = r.string.length(); } } int type = getStorageType(sbuf); switch (type) { case UTF8: writeUTF8(sbuf, list); break; case UNICODE: writeUNICODE(sbuf); break; } writeOffsetTable(); return type; } /** * Tell which one of UTF8 or UNICODE is smaller * @param sbuf the string data to be processed * @return the storage type */ int getStorageType(StringBuffer sbuf) throws Throwable { boolean hasZero = false; for (int i=0; i<sbuf.length(); i++) { char c = sbuf.charAt(i); if (c == 0x0) { hasZero = true; } } if (hasZero) { // The VM's handling of 0 is different than specified in // the "official" UTF8 encoding, so let's not do it. } else { String s = sbuf.toString(); byte bytes[] = s.getBytes("UTF-8"); if (bytes.length < sbuf.length() * 2) { return UTF8; } } return UNICODE; } /** Hex digits for output. */ static char digits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; /** * Prints a hex number for the given character. * @param c the character to convert * @param numdigits the output field width */ void printHex(char c, int numdigits) { p("0x"); for (int i=numdigits-1; i>= 0; i--) { int shift = i * 4; int n = ((((int)c) >> shift)) & 0x0f; writer.print(Character.toString(digits[n])); } } /** * Write all the data in a UNICODE array * @param sbuf the string data to be processed */ void writeUNICODE(StringBuffer sbuf) { int STEP = 10; int MAX = sbuf.length(); pl("static const jchar string_data[] = {"); for (int i=0; i<MAX; i ++) { if ((i % STEP) == 0) { pl(""); p(" "); } char c = sbuf.charAt(i); printHex(c, 4); p(","); } pl("};"); } /** * Write all the data in a UTF8 array * @param sbuf the string data to be processed * @param list the data to be processed */ void writeUTF8(StringBuffer sbuf, ArrayList list) throws Throwable { // Recompute the offset and length of each item byte array[] = new byte[sbuf.length() * 2]; // MAX possible size int end = 0; for (int i=0; i<list.size(); i++) { LocalizedString r = (LocalizedString)list.get(i); if (r != null) { byte bytes[] = r.string.getBytes("UTF-8"); int n = search(bytes, array, end); if (n >= 0) { r.offset = n; } else { r.offset = end; for (int x=0; x<bytes.length; x++) { array[end++] = bytes[x]; } } r.length = bytes.length; } } // Now write the strings to C source code. int STEP = 10; int MAX = end; p("static const unsigned char string_data[] = {"); for (int i=0; i<MAX; i ++) { if ((i % STEP) == 0) { pl(""); p(" "); } char c = (char)array[i]; printHex(c, 2); p(","); } pl("};"); } /** * Equivalent of String.indexOf(), but works on a UTF8 byte array. * @param needle the item to be found * @param haystack the data to be searched * @param end the limit of the search * @return index of the found data or -1 if not found */ int search(byte needle[], byte haystack[], int end) { int needleLen = needle.length; if (needleLen == 0) { return -1; } end -= needleLen; byte b = needle[0]; for (int i=0; i<end; i++) { inner: { if (haystack[i] == b) { for (int j=1; j<needleLen; j++) { if (haystack[i+j] != needle[j]) { break inner; } } return i; } } } return -1; } /** * Write a table of localized string offsets */ void writeOffsetTable() { int maxOffset = 0, maxLen = 0; for (int i=0; i<strings.length; i++) { LocalizedString r = strings[i]; if (r == null) { System.err.println("Warning: resource index " + i + " not defined in class " + locale.className); } else { if (maxOffset < r.offset) { maxOffset = r.offset; } if (maxLen < r.length) { maxLen = r.length; } } } String type = "int"; if (maxOffset < 0x7fff && maxLen < 0x7fff) { type = "short"; } p("static const " + type + " offset_data[] = {"); int STEP = 4; for (int i=0; i<strings.length; i++) { if ((i % STEP) == 0) { pl(""); p(" "); } LocalizedString r = strings[i]; if (r == null) { p("-1, -1,"); } else { p(r.offset + ", " + r.length + ", "); } } pl("};"); pl("static int max_index = " + strings.length + ";"); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -