Subversion Repositories mkgmap

Rev

Rev 2636 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * Copyright (C) 2007 Steve Ratcliffe
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2 as
 *  published by the Free Software Foundation.
 *
 *  This program 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 for more details.
 *
 *
 * Author: Steve Ratcliffe
 * Create date: Jan 1, 2008
 */

package uk.me.parabola.imgfmt.app.labelenc;

import uk.me.parabola.imgfmt.ExitException;

/**
 * @author Steve Ratcliffe
 */

public class CodeFunctions {
        // Label encoding length
        public static final int ENCODING_FORMAT6 = 6;
        private static final int ENCODING_FORMAT9 = 9;
        private static final int ENCODING_FORMAT10 = 10;

        private int codepage;
        private int encodingType;
        private CharacterEncoder encoder;
        private CharacterDecoder decoder;
        private Transliterator transliterator = new TableTransliterator("ascii");

        protected void setEncoder(CharacterEncoder encoder) {
                this.encoder = encoder;
        }

        public CharacterEncoder getEncoder() {
                return encoder;
        }

        protected void setDecoder(CharacterDecoder decoder) {
                this.decoder = decoder;
        }

        public CharacterDecoder getDecoder() {
                return decoder;
        }

        public int getEncodingType() {
                return encodingType;
        }

        protected void setEncodingType(int encodingType) {
                this.encodingType = encodingType;
        }

        public int getCodepage() {
                return codepage;
        }

        protected void setCodepage(int codepage) {
                this.codepage = codepage;
        }

        public Transliterator getTransliterator() {
                return transliterator;
        }

        public void setTransliterator(Transliterator transliterator) {
                this.transliterator = transliterator;
        }

        /**
         * Create a CharacterEncoder for the given charset option.  Note that this
         * routine also writes to the lblHeader parameter to set the encoding type.
         * @param charset The mkgmap command line option to be interpreted.
         * @return The various character set parameters that will be needed.
         */

        public static CodeFunctions createEncoderForLBL(String charset) {
                CodeFunctions funcs = new CodeFunctions();

                if ("ascii".equals(charset)) {
                        funcs.setEncodingType(ENCODING_FORMAT6);
                        funcs.setEncoder(new Format6Encoder());
                        funcs.setTransliterator(getDefaultTransliterator());
                        funcs.setDecoder(new Format6Decoder());
                } else if ("latin1".equals(charset)) {
                        funcs.setEncodingType(ENCODING_FORMAT9);
                        funcs.setEncoder(new LatinEncoder());
                        funcs.setTransliterator(new TableTransliterator("latin1"));
                        funcs.setDecoder(new AnyCharsetDecoder("cp1252"));
                        funcs.setCodepage(1252);
                } else if ("unicode".equals(charset)) {
                        funcs.setEncodingType(ENCODING_FORMAT10);
                        funcs.setEncoder(new Utf8Encoder());
                        funcs.setDecoder(new Utf8Decoder());
                } else if ("cp65001".equals(charset)) {
                        funcs.setEncodingType(ENCODING_FORMAT10);
                        funcs.setEncoder(new Utf8Encoder());
                        funcs.setDecoder(new Utf8Decoder());
                        funcs.setTransliterator(new NullTransliterator());
                        funcs.setCodepage(65001);
                } else if ("simple8".equals(charset)) {
                        funcs.setEncodingType(ENCODING_FORMAT9);
                        funcs.setEncoder(new Simple8Encoder());
                } else if ("cp932".equals(charset) || "ms932".equals(charset)) {
                        funcs.setEncodingType(ENCODING_FORMAT10);
                        funcs.setEncoder(new AnyCharsetEncoder("ms932"));
                        funcs.setDecoder(new AnyCharsetDecoder("ms932"));
                        funcs.setTransliterator(new SparseTransliterator("nomacron"));
                        funcs.setCodepage(932);
                } else {
                        funcs.setEncodingType(ENCODING_FORMAT9);
                        funcs.setDecoder(new AnyCharsetDecoder(charset));
                        funcs.setEncoder(new AnyCharsetEncoder(charset));
                        guessCodepage(funcs, charset);
                }

                return funcs;
        }

        /**
         * Guess the code page from the given charset.  Only works with things
         * like cp1252, windows-1252 and some well known ones.
         * @param funcs The code page functions.
         * @param charset The charset that was given.
         */

        private static void guessCodepage(CodeFunctions funcs, String charset) {
                String cs = charset.toLowerCase();
                Transliterator transliterator = new NullTransliterator();
                if (cs.startsWith("cp")) {
                        try {
                                funcs.setCodepage(Integer.parseInt(charset.substring(2)));
                                if (cs.equals("cp1252"))
                                        transliterator = new TableTransliterator("latin1");
                        } catch (NumberFormatException e) {
                                // wasn't in the right form
                                throw new ExitException("Invalid character set: " + cs);
                        }
                } else if (cs.startsWith("windows-")) {
                        try {
                                funcs.setCodepage(Integer.parseInt(charset.substring(8)));
                        } catch (NumberFormatException e) {
                                // wasn't in the right form to guess
                        }
                } else if (cs.equals("latin1")) {
                        funcs.setCodepage(1252);
                        transliterator = new TableTransliterator("latin1");
                }
                funcs.setTransliterator(transliterator);
        }

        /**
         * Sets encoding functions for a given format and code page.  This is used
         * when reading from an existing file.
         *
         *
         * @param format The format from the lbl header.
         * @param codePage The codepage found in the header.
         * @return The various character set parameters that will be needed.
         */

        public static CodeFunctions createEncoderForLBL(int format, int codePage) {
                CodeFunctions funcs = new CodeFunctions();

                if (format == ENCODING_FORMAT6) {
                        funcs.setEncodingType(ENCODING_FORMAT6);
                        funcs.setEncoder(new Format6Encoder());
                        funcs.setDecoder(new Format6Decoder());
                } else if (codePage == 932) {
                        funcs.setEncodingType(ENCODING_FORMAT10);
                        funcs.setEncoder(new AnyCharsetEncoder("ms932"));
                        funcs.setDecoder(new AnyCharsetDecoder("ms932"));
                } else if (format == ENCODING_FORMAT9) {
                        funcs.setEncodingType(ENCODING_FORMAT9);
                        String cpName = "cp" + codePage;
                        if (codePage == 1252)
                                funcs.setEncoder(new LatinEncoder());
                        else
                                funcs.setEncoder(new AnyCharsetEncoder(cpName));
                        guessCodepage(funcs, cpName);

                        funcs.setDecoder(new AnyCharsetDecoder(cpName));
                } else {
                        // TODO TEMP...
                        funcs.setEncodingType(ENCODING_FORMAT9);
                        funcs.setEncoder(new AnyCharsetEncoder("cp1252"));
                        funcs.setDecoder(new AnyCharsetDecoder("cp1252"));
                }

                return funcs;
        }

        public static CharacterEncoder getDefaultEncoder() {
                return new Format6Encoder();
        }

        public static CharacterDecoder getDefaultDecoder() {
                return new Format6Decoder();
        }

        public static Transliterator getDefaultTransliterator() {
                TableTransliterator ascii = new TableTransliterator("ascii");
                ascii.forceUppercase(true);
                return ascii;
        }
}