Subversion Repositories mkgmap

Rev

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

/*
 * Copyright (C) 2011.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 or
 * 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.
 */

package uk.me.parabola.mkgmap.typ;

import java.io.Reader;

import uk.me.parabola.imgfmt.app.typ.TypData;
import uk.me.parabola.log.Logger;
import uk.me.parabola.mkgmap.scan.SyntaxException;
import uk.me.parabola.mkgmap.scan.TokType;
import uk.me.parabola.mkgmap.scan.Token;
import uk.me.parabola.mkgmap.scan.TokenScanner;

/**
 * Read in a TYP file in the text format.
 *
 * @author Steve Ratcliffe
 */

public class TypTextReader {
        private static final Logger log = Logger.getLogger(TypTextReader.class);

        // As the file is read in, the information is saved into this data structure.
        private final TypData data = new TypData();

        public void read(String filename, Reader r) {
                TokenScanner scanner = new TokenScanner(filename, r);
                scanner.setCommentChar(null); // the '#' comment character is not appropriate for this file

                ProcessSection currentSection = null;

                while (!scanner.isEndOfFile()) {
                        Token tok = scanner.nextToken();
                        if (tok.getType() == TokType.EOF)
                                break;

                        // We deal with whole line comments here
                        if (tok.isValue(";")) {
                                scanner.skipLine();
                                continue;
                        }

                        if (tok.getType() == TokType.SYMBOL) {
                                switch (tok.getValue().charAt(0)) {
                                case ';':
                                        scanner.skipLine();
                                        break;
                                case '[':
                                        ProcessSection newSection = readSectionType(scanner);
                                        if (currentSection != null)
                                                currentSection.finish(scanner);
                                        currentSection = newSection;
                                        break;
                                case '"':
                                        scanner.skipLine();
                                        break;
                                }
                        } else {
                                // Line inside a section
                                String name = tok.getValue();

                                String sep = scanner.nextValue();
                                if (!sep.equals("=") && !sep.equals(":"))
                                        throw new SyntaxException(scanner, "Expecting '=' or ':' instead of " + sep);

                                String value = scanner.readLine();

                                if (currentSection == null)
                                        throw new SyntaxException(scanner, "Missing section start");

                                currentSection.processLine(scanner, name, value);
                        }
                        scanner.skipSpace();
                }
        }

        /**
         * Read the section name and return a section processor for it.
         *
         * The input stream must be positioned just after the open bracket of the section name. The closing bracket
         * is also consumed. The section name is case insensitive.
         *
         * Unknown sections result in a processor that ignores all lines in the section.
         *
         * @param scanner Input token stream.
         * @return A section processor to process lines from the section. Returns null if this is
         * the end of the section rather than the start.
         */

        private ProcessSection readSectionType(TokenScanner scanner) {
                String sectionName = scanner.nextValue().toLowerCase();
                scanner.validateNext("]"); // Check for closing bracket

                // End of the section, so the processor is reset to null
                if ("end".equals(sectionName)) {
                        return null;

                } else if ("_point".equals(sectionName)) {
                        return new PointSection(data);
                } else if ("_line".equals(sectionName)) {
                        return new LineSection(data);
                } else if ("_polygon".equals(sectionName)) {
                        return new PolygonSection(data);
                } else if ("_draworder".equals(sectionName)) {
                        return new DrawOrderSection(data);
                } else if ("_icons".equals(sectionName)) {
                        return new IconSection(data);
                } else if ("_id".equals(sectionName)) {
                        return new IdSection(data);
                } else {
                        log.warn("Unrecognised section " + sectionName);
                        return new IgnoreSection(data);
                }
        }

        public TypData getData() {
                return data;
        }
}