Subversion Repositories mkgmap

Rev

Rev 4825 | 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: Dec 14, 2007
 */

package uk.me.parabola.imgfmt.app;

import java.nio.charset.StandardCharsets;
import java.util.Date;

import uk.me.parabola.imgfmt.ReadFailedException;
import uk.me.parabola.imgfmt.Utils;

/**
 * The header that is common to all application files within the .img file.
 * It basically contains two things of interest, the size of the header and
 * its type.  The type is usually of the form 'GARMIN.YYY' where YYY is the
 * file extension of the type eg TRE, LBL, RGN etc.
 *
 * @author Steve Ratcliffe
 */

public abstract class CommonHeader {
        protected static final int COMMON_HEADER_LEN = 21;
        private static final int TYPE_LEN = 10;

        // The common header contains the length and the type which are set at
        // construction time.
        private int headerLength;
        private String type;

        // Set to 0x80 on locked maps.  We are not interested in creating locked
        // maps, but may be useful to recognise them for completeness.
        private byte lockFlag;

        // A date of creation.
        private Date creationDate;

        protected CommonHeader(int headerLength, String type) {
                this.headerLength = headerLength;
                this.type = type;
        }

        /**
         * Writes out the header that is common to all the file types.  It should
         * be called by the sync() methods of subclasses when they are ready.
         * @param writer Used to write the header.
         */

        public final void writeHeader(ImgFileWriter writer)  {
                writePrepare();

                writer.position(0);

                writer.put2u(headerLength);
                writer.put(Utils.toBytes(type, TYPE_LEN, (byte) 0));

                writer.put1u(1);  // unknown
                writer.put1u(0);  // not locked

                byte[] date = Utils.makeCreationTime(new Date());
                writer.put(date);

                writeFileHeader(writer);
        }

        /**
         * Read the common header.  It starts at the beginning of the file.
         * @param reader Used to read the header.
         */

        public final void readHeader(ImgFileReader reader) throws ReadFailedException {
                reader.position(reader.getGMPOffset());
                headerLength = reader.get2u();
                byte[] bytes = reader.get(TYPE_LEN);
                type = new String(bytes, StandardCharsets.US_ASCII);
                reader.get(); // ignore
                this.lockFlag = reader.get(); // 0x80 if locked

                byte[] date = reader.get(7);
                creationDate = Utils.makeCreationTime(date);

                readFileHeader(reader);
        }

        /**
         * Read the rest of the header.  Specific to the given file.  It is
         * guaranteed that the file position will be set to the correct place
         * before this is called.
         * @param reader The header is read from here.
         */

        protected abstract void readFileHeader(ImgFileReader reader) throws ReadFailedException;

        /**
         * Write the rest of the header.  It is guaranteed that the writer will
         * be set to the correct position before calling.
         * @param writer The header is written here.
         */

        protected abstract void writeFileHeader(ImgFileWriter writer);

        public int getHeaderLength() {
                return headerLength;
        }

        private void writePrepare() {
                // Prepare for write by setting our defaults.
                // lockFlag = 0;
                if (creationDate == null)
                        creationDate = new Date();
        }

        /**
         * @return the lockFlag
         */

        public byte getLockFlag() {
                return lockFlag;
        }
}