/* * Copyright (C) 2008 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, Robert Vollmert * Create date: 18-Jul-2008 */ package uk.me.parabola.imgfmt.app.net; import java.util.ArrayList; import java.util.List; import uk.me.parabola.imgfmt.FormatException; import uk.me.parabola.imgfmt.app.ImgFileWriter; /** * @author Steve Ratcliffe, Robert Vollmert */ public class TableC { // size of the table, excluding the size field private int size; private final TableA tabA; private final List<RouteRestriction> restrictions = new ArrayList<RouteRestriction>(); public TableC(TableA tabA) { this.tabA = tabA; } /** * Write the table including size field. */ public void write(ImgFileWriter writer, int tablesOffset) { if (!restrictions.isEmpty()) { if (size < 0x100) writer.put((byte) size); else writer.putChar((char) size); for (RouteRestriction restr : restrictions) restr.write(writer, tablesOffset); } if(tabA.numRoundaboutArcs() > 0) writer.put((byte)tabA.numRoundaboutArcs()); if(tabA.numUnpavedArcs() > 0) writer.put((byte)tabA.numUnpavedArcs()); if(tabA.numFerryArcs() > 0) writer.put((byte)tabA.numFerryArcs()); } /** * Add a restriction. * * @param restr A new restriction. * @return The offset into Table C at which the restriction will * be written. */ public int addRestriction(RouteRestriction restr) { int offset = size; restrictions.add(restr); size += restr.getSize(); return offset; } /** * The size of restriction indices in the nodes area. */ private byte getOffsetSize() { if (size < 0x80) return 1; // allows 7 bit index (8th bit is flag) else if (size < 0x8000) return 2; // allows 15 bit index (16th bit is flag) else // XXX: haven't seen larger than 2, may well be possible throw new FormatException("too many restrictions"); } public void propagateSizeBytes() { byte b = getOffsetSize(); for (RouteRestriction restr : restrictions) restr.setOffsetSize(b); } public byte getFormat() { // Table C format bitmask // 0x01 = 1-255 bytes of restrictions // 0x02 = 256-65535 bytes of restrictions // 0x08 = unpaved roads count present // 0x10 = ferry count present int format = 0; if(size > 0) { ++format; if(size > 0xff) ++format; } if(tabA.numRoundaboutArcs() > 0) format |= 0x04; if(tabA.numUnpavedArcs() > 0) format |= 0x08; if(tabA.numFerryArcs() > 0) format |= 0x10; return (byte)format; } }