/* * 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; } }