Source Code Cross Referenced for LocalizedStringsGenerator.java in  » 6.0-JDK-Modules » j2me » com » sun » midp » l10n » generator » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » j2me » com.sun.midp.l10n.generator 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         *
003:         *
004:         * Copyright  1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006:         * 
007:         * This program is free software; you can redistribute it and/or
008:         * modify it under the terms of the GNU General Public License version
009:         * 2 only, as published by the Free Software Foundation.
010:         * 
011:         * This program is distributed in the hope that it will be useful, but
012:         * WITHOUT ANY WARRANTY; without even the implied warranty of
013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014:         * General Public License version 2 for more details (a copy is
015:         * included at /legal/license.txt).
016:         * 
017:         * You should have received a copy of the GNU General Public License
018:         * version 2 along with this work; if not, write to the Free Software
019:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020:         * 02110-1301 USA
021:         * 
022:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023:         * Clara, CA 95054 or visit www.sun.com if you need additional
024:         * information or have any questions.
025:         *
026:         */
027:
028:        /**
029:         * Generates localized string data from source XML file.
030:         */package com.sun.midp.l10n.generator;
031:
032:        import java.io.*;
033:        import java.util.*;
034:
035:        import javax.xml.parsers.*;
036:        import javax.xml.transform.*;
037:        import javax.xml.transform.dom.*;
038:        import javax.xml.transform.stream.StreamResult;
039:        import javax.xml.transform.stream.StreamSource;
040:        import org.w3c.dom.*;
041:        import org.xml.sax.ErrorHandler;
042:        import org.xml.sax.SAXParseException;
043:        import org.xml.sax.SAXException;
044:
045:        /**
046:         *  Driver class with main(). Parses command line arguments and invokes
047:         *  LocalizedStringsGeneratorImpl instance that does all the transformation work.
048:         */
049:        public class LocalizedStringsGenerator {
050:            /** Transformer that does actual transformation */
051:            private static LocalizedStringsGeneratorImpl transformer = null;
052:
053:            /** XML file name to apply transformation to */
054:            public static String xmlFileName = "";
055:
056:            /** Output file name */
057:            public static String outFileName = "";
058:
059:            /** Print debug output while running */
060:            private static boolean debug = false;
061:
062:            /** Print usage info and exit */
063:            private static boolean printHelp = false;
064:
065:            /**
066:             * Main method
067:             *
068:             * @param args Command line arguments
069:             */
070:            public static void main(String[] args) {
071:                try {
072:                    parseArgs(args);
073:                    if (printHelp) {
074:                        printHelp();
075:                        return;
076:                    }
077:
078:                    transformer = new LocalizedStringsGeneratorImpl(debug);
079:                    transformer.transform(xmlFileName, outFileName);
080:                } catch (SAXException e) {
081:                    // error was already reported
082:                    e.printStackTrace();
083:                    System.exit(1);
084:                } catch (Exception e) {
085:                    e.printStackTrace();
086:                    System.exit(1);
087:                }
088:            }
089:
090:            /**
091:             * Parse command line arguments, adding Transformation objects to
092:             * <tt>transformations</tt> vector for each transformation specified.
093:             *
094:             * @param args command line arguments
095:             */
096:            private static void parseArgs(String[] args) {
097:                for (int i = 0; i < args.length; ++i) {
098:                    String arg = args[i];
099:                    if (debug) {
100:                        System.err.println("arg: " + arg);
101:                    }
102:                    if (arg.equals("-xml")) {
103:                        xmlFileName = args[++i];
104:                    } else if (arg.equals("-out")) {
105:                        outFileName = args[++i];
106:                    } else if (arg.equals("-debug")) {
107:                        debug = true;
108:                    } else {
109:                        printHelp = true;
110:                    }
111:                }
112:            }
113:
114:            /**
115:             * Print usage information
116:             */
117:            private static void printHelp() {
118:                /**
119:                 * Following options are recognized:
120:                 * -xml:        Source XML file.
121:                 * -out:        Output file. If empty, output will be to stdout.
122:                 * -help:       Print usage information
123:                 * -debug:      Be verbose: print some debug info while running.
124:                 */
125:                System.err.println("Usage: java -jar <l10n_generator_jar_file>"
126:                        + "-xml <localXMLFile> " + "-out <localOutputFile> "
127:                        + "[-debug] " + "[-help]");
128:            }
129:        }
130:
131:        /**
132:         * Perform the transformation
133:         */
134:        class LocalizedStringsGeneratorImpl {
135:            /** Factory constructing Transformer objects */
136:            private TransformerFactory transformerFactory = TransformerFactory
137:                    .newInstance();
138:
139:            /** Be verbose: print some debug info while running */
140:            private boolean debug = false;
141:
142:            /**
143:             * Constructor
144:             *
145:             * @param dbg print some debug output while running
146:             */
147:            public LocalizedStringsGeneratorImpl(boolean dbg) {
148:                debug = dbg;
149:            }
150:
151:            /**
152:             * Converts errors.
153:             */
154:            class GeneratorErrorHandler implements  ErrorHandler {
155:
156:                /**
157:                 * Handles errors.
158:                 * @param e the parsing exception
159:                 */
160:                public void error(SAXParseException e) throws SAXParseException {
161:                    reportError(e);
162:                    // rethrow exception to stop processing on first error
163:                    throw e;
164:                }
165:
166:                /**
167:                 * Handles fatal errors.
168:                 * @param e the parsing exception
169:                 */
170:                public void fatalError(SAXParseException e) {
171:                    reportError(e);
172:                }
173:
174:                /**
175:                 * Handles warnings.
176:                 * @param e the parsing exception
177:                 */
178:                public void warning(SAXParseException e) {
179:                    reportError(e);
180:                }
181:
182:                /**
183:                 * Outputs diagnostic messages.
184:                 * @param e the parsing exception
185:                 */
186:                private void reportError(SAXParseException e) {
187:                    String msg = e.getMessage();
188:                    String location = e.getSystemId();
189:                    int line = e.getLineNumber();
190:
191:                    System.err.print("Error: URI=" + location);
192:                    System.err.println(" Line=" + line + ": " + msg);
193:                }
194:            }
195:
196:            /**
197:             * Do the actual transformation
198:             *
199:             * @param tr transformation to perform
200:             */
201:            public void transform(String xmlFileName, String outFileName)
202:                    throws Exception {
203:
204:                if (debug) {
205:                    System.err.println("xml file: " + xmlFileName);
206:                    System.err.println("out file: " + outFileName);
207:                }
208:
209:                // load XML file as DOM tree
210:                DocumentBuilderFactory domFactory = DocumentBuilderFactory
211:                        .newInstance();
212:
213:                DocumentBuilder domBuilder = domFactory.newDocumentBuilder();
214:
215:                domBuilder.setErrorHandler(new GeneratorErrorHandler());
216:                Document doc = domBuilder.parse(new File(xmlFileName));
217:
218:                // make source from it
219:                DOMSource source = new DOMSource(doc);
220:
221:                generateLocalizedStrings(doc, outFileName);
222:            }
223:
224:            /**
225:             * Creates a directory structure.
226:             *
227:             * @param fullFileName Full path to the file to be created. If directory
228:             * in which file is to be created doesn't exists, it will be created
229:             * @exception IOException is thrown if directory couldn't be created
230:             */
231:            private void makeDirectoryTree(String fullFileName)
232:                    throws IOException {
233:                if (debug == true) {
234:                    System.out.println("mkdir: " + fullFileName);
235:                }
236:                int index = fullFileName.lastIndexOf(File.separatorChar);
237:                if (index == -1) {
238:                    // To be compatible with MKS-hosted build on win32, which
239:                    // does not translate / to \.
240:                    index = fullFileName.lastIndexOf('/');
241:                }
242:                File outputDirectory = new File(fullFileName
243:                        .substring(0, index));
244:
245:                if (!(outputDirectory).exists()) {
246:                    if (!(outputDirectory).mkdirs()) {
247:                        throw new IOException(
248:                                "failed to create output directory");
249:                    }
250:                }
251:            }
252:
253:            /**
254:             * Generates localized strings.
255:             * @param doc the current  working file
256:             * @param outDir the target output directory
257:             */
258:            private void generateLocalizedStrings(Document doc, String outDir)
259:                    throws Exception {
260:                processLocalizedStrings(doc.getDocumentElement(), null);
261:                for (Enumeration e = locales.keys(); e.hasMoreElements();) {
262:                    String key = (String) e.nextElement();
263:                    LocalizedStringSet locale = (LocalizedStringSet) locales
264:                            .get(key);
265:                    String filename = outDir + File.separatorChar
266:                            + locale.className;
267:                    makeDirectoryTree(filename);
268:
269:                    // Write LocalizedStrings<locale>.c file
270:                    CSourceWriter cwriter = new CSourceWriter();
271:                    cwriter.writeCSource(locale, filename + ".c",
272:                            locale.className);
273:
274:                    // Write LocalizedStrings<locale>.java file
275:                    FileOutputStream out = new FileOutputStream(filename
276:                            + ".java");
277:                    PrintWriter writer = new PrintWriter(
278:                            new OutputStreamWriter(out));
279:                    writer
280:                            .println("// This file is auto-generated. Don't edit!");
281:                    writer.println("package com.sun.midp.l10n;");
282:                    writer.println("abstract class " + locale.className + " {");
283:                    writer
284:                            .println("    native static String getContent(int index);");
285:                    writer.println("}");
286:                    writer.close();
287:                }
288:            }
289:
290:            /**
291:             * Walk the XML tree to discover all <localized_string> elements,
292:             * collect them and write the data tables specific for each
293:             * locale to a pair of Java and C source files.
294:             * @param n the current node to be processed
295:             * @param className the name of the class to handle this node
296:             */
297:            private void processLocalizedStrings(Node n, String className)
298:                    throws Exception {
299:                if (n.getNodeName().equals("localized_strings")
300:                        && (n instanceof  Element)) {
301:                    Element e = (Element) n;
302:                    String pkg = e.getAttribute("Package");
303:                    String name = e.getAttribute("Name");
304:                    className = name;
305:                } else if (n.getNodeName().equals("localized_string")
306:                        && (n instanceof  Element) && className != null) {
307:                    Element e = (Element) n;
308:                    String value = e.getAttribute("Value");
309:                    // we use key value as index
310:                    int valueIndex = Integer.parseInt(e
311:                            .getAttribute("KeyValue"));
312:
313:                    addLocalizedString(className, valueIndex, value);
314:                }
315:
316:                NodeList list = n.getChildNodes();
317:                for (int i = 0; i < list.getLength(); i++) {
318:                    processLocalizedStrings(list.item(i), className);
319:                }
320:            }
321:
322:            /** Supported locales table. */
323:            Hashtable locales = new Hashtable();
324:
325:            /**
326:             * Add one <localized_string> element to the LocalizedStringSet of
327:             * the enclosing <localized_strings>.
328:             * @param className the locales handler
329:             * @param valueIndex key for this entry
330:             * @param value data for this entry
331:             */
332:            private void addLocalizedString(String className, int valueIndex,
333:                    String value) throws Exception {
334:                LocalizedStringSet locale = (LocalizedStringSet) locales
335:                        .get(className);
336:                if (locale == null) {
337:                    locale = new LocalizedStringSet(className);
338:                    locales.put(className, locale);
339:                }
340:                locale.put(valueIndex, value);
341:            }
342:        }
343:
344:        /**
345:         * Records all localized strings for the locale represented by
346:         * a given Java class.
347:         */
348:        class LocalizedStringSet {
349:            /** This Java class represents a given locale. */
350:            String className;
351:
352:            /** All localized strings for this locale */
353:            Vector strings;
354:
355:            /**
356:             * Default constructor.
357:             * @param className class name of locale handler
358:             */
359:            LocalizedStringSet(String className) {
360:                this .className = className;
361:                strings = new Vector(512);
362:            }
363:
364:            /**
365:             * Stores the current entry.
366:             * @param idx the key
367:             * @param value the data
368:             */
369:            void put(int idx, String value) {
370:                if (strings.size() < idx + 1) {
371:                    strings.setSize(idx + 1);
372:                }
373:                strings.set(idx, value);
374:            }
375:        }
376:
377:        /**
378:         * This class records related information about each localized string
379:         */
380:        class LocalizedString {
381:            /**
382:             * Constructor with initial data.
383:             * @param i the key
384:             * @param s the value
385:             */
386:            LocalizedString(int i, String s) {
387:                this .index = i;
388:                this .string = s;
389:            }
390:
391:            /** The current search location. */
392:            int index;
393:            /** The offset of the current item. */
394:            int offset;
395:            /** The length of the table. */
396:            int length;
397:            /** The data contents. */
398:            String string;
399:        }
400:
401:        /**
402:         * This class deals with generating the LocalizedStringsBase<locale>.c
403:         * files. We try to compress the footprint of the data, since we
404:         * don't read from the localized string tables very often
405:         */
406:        class CSourceWriter {
407:            /** The locale used. */
408:            LocalizedStringSet locale;
409:            /** Output stream writer. */
410:            PrintWriter writer;
411:            /** Array of strings to be processed. */
412:            LocalizedString strings[];
413:
414:            /**
415:             * Sort all string data so they can be more easily compressed
416:             * @return the sorted array
417:             */
418:            ArrayList sort() {
419:                ArrayList list = new ArrayList();
420:                Vector strTable = locale.strings;
421:                for (int i = 0; i < strTable.size(); ++i) {
422:                    String value = (String) strTable.get(i);
423:
424:                    if (strings[i] != null) {
425:                        System.out
426:                                .println("Duplicated content definiton for index "
427:                                        + i);
428:                        throw new Error();
429:                    }
430:                    strings[i] = new LocalizedString(i, value);
431:                    list.add(strings[i]);
432:                }
433:
434:                /**
435:                 * Sorting function.
436:                 */
437:                Collections.sort(list, new Comparator() {
438:                    /**
439:                     * Comparison method.
440:                     * @param o1 left hand operand
441:                     * @param o2 right hand operand
442:                     * @return positive value if o2 is greater than o1,
443:                     * negative is o2 is less than o1
444:                     */
445:                    public int compare(Object o1, Object o2) {
446:                        LocalizedString r1 = (LocalizedString) o1;
447:                        LocalizedString r2 = (LocalizedString) o2;
448:                        return (r1.string.length() < r2.string.length()) ? 1
449:                                : -1;
450:                    }
451:                });
452:
453:                return list;
454:            }
455:
456:            /**
457:             * Writes the C source file that stores the local string data in a
458:             * compact data structure
459:             * @param locale the target locale for comparison purposes
460:             * @param filename the source for processing
461:             * @param classname the locale handler
462:             */
463:            void writeCSource(LocalizedStringSet locale, String filename,
464:                    String classname) throws IOException {
465:                this .locale = locale;
466:                this .strings = new LocalizedString[locale.strings.size()];
467:
468:                FileOutputStream out = new FileOutputStream(filename);
469:                writer = new PrintWriter(new OutputStreamWriter(out));
470:                pl("/* This file is auto-generated. Do not edit! */");
471:                pl("#include <kni.h>");
472:                pl("#include <string.h>");
473:                pl("#include <midpMalloc.h>");
474:
475:                try {
476:                    int type = writeOptimizedArray();
477:
478:                    pl("KNIEXPORT KNI_RETURNTYPE_OBJECT");
479:                    pl("KNIDECL(com_sun_midp_l10n_" + classname
480:                            + "_getContent) {");
481:                    if (type != UNICODE) {
482:                        pl("    char stackbuffer[128];");
483:                        pl("    char *utf8; /*0-terminated*/");
484:                    }
485:                    pl("    int index = KNI_GetParameterAsInt(1);");
486:                    pl("    KNI_StartHandles(1);");
487:                    pl("    KNI_DeclareHandle(string);");
488:                    pl("    if (index >= 0 && index <= max_index) {");
489:                    pl("        int offset = (int)offset_data[index * 2 + 0];");
490:                    pl("        int length = (int)offset_data[index * 2 + 1];");
491:                    pl("        if (offset >= 0) {");
492:                    if (type == UNICODE) {
493:                        plx("KNI_NewString(string_data+offset, length, string);");
494:                    } else {
495:                        plx("const char *p = string_data+offset;");
496:                        plx("if (length < 128) {");
497:                        plx("    utf8 = stackbuffer;");
498:                        plx("} else {");
499:                        plx("    utf8 = (char*)midpMalloc(length+1);");
500:                        plx("}");
501:                        plx("if (utf8) {");
502:                        plx("    memcpy(utf8, p, length);");
503:                        plx("    utf8[length] = 0;");
504:                        plx("    KNI_NewStringUTF(utf8, string);");
505:                        plx("}");
506:                        plx("if (utf8 && utf8 != stackbuffer) {");
507:                        plx("    midpFree(utf8);");
508:                        plx("}");
509:                    }
510:                    pl("        }");
511:                    pl("    }");
512:                    pl("    KNI_EndHandlesAndReturnObject(string)");
513:                    pl("}");
514:                } catch (Throwable t) {
515:                    t.printStackTrace();
516:                }
517:
518:                writer.close();
519:            }
520:
521:            /**
522:             * Short-hand for printing a line to the output file
523:             * @param s the string to output
524:             */
525:            void pl(String s) {
526:                writer.println(s);
527:            }
528:
529:            /**
530:             * Short-hand for printing a line to the output file (with a 12-space
531:             * prefix)
532:             * @param s the string to output
533:             */
534:            void plx(String s) {
535:                writer.print("            ");
536:                writer.println(s);
537:            }
538:
539:            /**
540:             * Short-hand for printing a string into the output file
541:             * @param s the string to output
542:             */
543:            void p(String s) {
544:                writer.print(s);
545:            }
546:
547:            /** Indicate that a table should be stored as an UTF8 array in C code. */
548:            public final int UTF8 = 1;
549:
550:            /** Indicate that a table should be stored as an UNICODE array in C code.*/
551:            public final int UNICODE = 2;
552:
553:            /**
554:             * Write the string data using UTF8 or UNICODE, depending on which
555:             * is smaller.
556:             * @return the storage type
557:             */
558:            int writeOptimizedArray() throws Throwable {
559:                // (1) Sort all strings and then merge them into a single String.
560:                // This allows shorter strings that are substrings of longer strings
561:                // to be omitted.
562:                ArrayList list = sort();
563:                StringBuffer sbuf = new StringBuffer();
564:                for (int i = 0; i < list.size(); i++) {
565:                    LocalizedString r = (LocalizedString) list.get(i);
566:                    if (r != null) {
567:                        int n = sbuf.indexOf(r.string);
568:                        if (n >= 0) {
569:                            r.offset = n;
570:                        } else {
571:                            r.offset = sbuf.length();
572:                            sbuf.append(r.string);
573:                        }
574:                        r.length = r.string.length();
575:                    }
576:                }
577:                int type = getStorageType(sbuf);
578:                switch (type) {
579:                case UTF8:
580:                    writeUTF8(sbuf, list);
581:                    break;
582:                case UNICODE:
583:                    writeUNICODE(sbuf);
584:                    break;
585:                }
586:
587:                writeOffsetTable();
588:
589:                return type;
590:            }
591:
592:            /**
593:             * Tell which one of UTF8 or UNICODE is smaller
594:             * @param sbuf the string data to be processed
595:             * @return the storage type
596:             */
597:            int getStorageType(StringBuffer sbuf) throws Throwable {
598:                boolean hasZero = false;
599:                for (int i = 0; i < sbuf.length(); i++) {
600:                    char c = sbuf.charAt(i);
601:                    if (c == 0x0) {
602:                        hasZero = true;
603:                    }
604:                }
605:
606:                if (hasZero) {
607:                    // The VM's handling of 0 is different than specified in
608:                    // the "official" UTF8 encoding, so let's not do it.
609:                } else {
610:                    String s = sbuf.toString();
611:                    byte bytes[] = s.getBytes("UTF-8");
612:                    if (bytes.length < sbuf.length() * 2) {
613:                        return UTF8;
614:                    }
615:                }
616:
617:                return UNICODE;
618:            }
619:
620:            /** Hex digits for output. */
621:            static char digits[] = { '0', '1', '2', '3', '4', '5', '6', '7',
622:                    '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
623:
624:            /**
625:             * Prints a hex number for the given character.
626:             * @param c the character to convert
627:             * @param numdigits the output field width
628:             */
629:            void printHex(char c, int numdigits) {
630:                p("0x");
631:                for (int i = numdigits - 1; i >= 0; i--) {
632:                    int shift = i * 4;
633:                    int n = ((((int) c) >> shift)) & 0x0f;
634:                    writer.print(Character.toString(digits[n]));
635:                }
636:            }
637:
638:            /**
639:             * Write all the data in a UNICODE array
640:             * @param sbuf the string data to be processed
641:             */
642:            void writeUNICODE(StringBuffer sbuf) {
643:                int STEP = 10;
644:                int MAX = sbuf.length();
645:                pl("static const jchar string_data[] = {");
646:
647:                for (int i = 0; i < MAX; i++) {
648:                    if ((i % STEP) == 0) {
649:                        pl("");
650:                        p("    ");
651:                    }
652:                    char c = sbuf.charAt(i);
653:                    printHex(c, 4);
654:                    p(",");
655:                }
656:                pl("};");
657:            }
658:
659:            /**
660:             * Write all the data in a UTF8 array
661:             * @param sbuf the string data to be processed
662:             * @param list the data to be processed
663:             */
664:            void writeUTF8(StringBuffer sbuf, ArrayList list) throws Throwable {
665:                // Recompute the offset and length of each item
666:                byte array[] = new byte[sbuf.length() * 2]; // MAX possible size
667:                int end = 0;
668:
669:                for (int i = 0; i < list.size(); i++) {
670:                    LocalizedString r = (LocalizedString) list.get(i);
671:                    if (r != null) {
672:                        byte bytes[] = r.string.getBytes("UTF-8");
673:                        int n = search(bytes, array, end);
674:                        if (n >= 0) {
675:                            r.offset = n;
676:                        } else {
677:                            r.offset = end;
678:                            for (int x = 0; x < bytes.length; x++) {
679:                                array[end++] = bytes[x];
680:                            }
681:                        }
682:                        r.length = bytes.length;
683:                    }
684:                }
685:
686:                // Now write the strings to C source code.
687:                int STEP = 10;
688:                int MAX = end;
689:
690:                p("static const char string_data[] = {");
691:                for (int i = 0; i < MAX; i++) {
692:                    if ((i % STEP) == 0) {
693:                        pl("");
694:                        p("    ");
695:                    }
696:                    char c = (char) array[i];
697:                    printHex(c, 2);
698:                    p(",");
699:                }
700:                pl("};");
701:            }
702:
703:            /**
704:             * Equivalent of String.indexOf(), but works on a UTF8 byte array.
705:             * @param needle the item to be found
706:             * @param haystack the data to be searched
707:             * @param end the limit of the search
708:             * @return index of the found data or -1 if not found
709:             */
710:            int search(byte needle[], byte haystack[], int end) {
711:                int needleLen = needle.length;
712:                if (needleLen == 0) {
713:                    return -1;
714:                }
715:                end -= needleLen;
716:                byte b = needle[0];
717:
718:                for (int i = 0; i < end; i++) {
719:                    inner: {
720:                        if (haystack[i] == b) {
721:                            for (int j = 1; j < needleLen; j++) {
722:                                if (haystack[i + j] != needle[j]) {
723:                                    break inner;
724:                                }
725:                            }
726:                            return i;
727:                        }
728:                    }
729:                }
730:
731:                return -1;
732:            }
733:
734:            /**
735:             * Write a table of localized string offsets
736:             */
737:            void writeOffsetTable() {
738:                int maxOffset = 0, maxLen = 0;
739:
740:                for (int i = 0; i < strings.length; i++) {
741:                    LocalizedString r = strings[i];
742:                    if (r == null) {
743:                        System.err.println("Warning: resource index " + i
744:                                + " not defined in class " + locale.className);
745:                    } else {
746:                        if (maxOffset < r.offset) {
747:                            maxOffset = r.offset;
748:                        }
749:                        if (maxLen < r.length) {
750:                            maxLen = r.length;
751:                        }
752:                    }
753:                }
754:                String type = "int";
755:                if (maxOffset < 0x7fff && maxLen < 0x7fff) {
756:                    type = "short";
757:                }
758:                p("static const " + type + " offset_data[] = {");
759:
760:                int STEP = 4;
761:                for (int i = 0; i < strings.length; i++) {
762:                    if ((i % STEP) == 0) {
763:                        pl("");
764:                        p("    ");
765:                    }
766:                    LocalizedString r = strings[i];
767:                    if (r == null) {
768:                        p("-1, -1,");
769:                    } else {
770:                        p(r.offset + ", " + r.length + ", ");
771:                    }
772:                }
773:                pl("};");
774:
775:                pl("static int max_index = " + strings.length + ";");
776:            }
777:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.