Subversion Repositories mkgmap

Rev

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

/*
 * Copyright (C) 2006 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: 03-Dec-2006
 */

package uk.me.parabola.imgfmt;

import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Calendar;
import java.util.Date;
import java.util.zip.GZIPInputStream;

/**
 * Some miscellaneous functions that are used within the .img code.
 *
 * @author Steve Ratcliffe
 */

public class Utils {
        /**
         * Routine to convert a string to bytes and pad with a character up
         * to a given length.
         * Only to be used for strings that are expressible in latin1.
         *
         * @param s The original string.
         * @param len The length to pad to.
         * @param pad The byte used to pad.
         * @return An array created from the string.
         */

        public static byte[] toBytes(String s, int len, byte pad) {
                if (s == null)
                        throw new IllegalArgumentException("null string provided");

                byte[] out = new byte[len];
                for (int i = 0; i < len; i++) {
                        if (i > s.length()) {
                                out[i] = pad;
                        } else {
                                out[i] = (byte) s.charAt(i);
                        }
                }
                return out;
        }

        public static byte[] toBytes(String s) {
                return toBytes(s, s.length(), (byte) 0);
        }

        /**
         * Convert from bytes to a string.  Only to be used when the character set
         * is ascii or latin1.
         *
         * @param buf A byte buffer to get the bytes from.  Should be ascii or latin1.
         * @param off The offset into buf.
         * @param len The length to get.
         * @return A string.
         */

        public static String bytesToString(ByteBuffer buf, int off, int len) {
                if (buf == null)
                        throw new IllegalArgumentException("null byte buffer provided");

                byte[] bbuf = new byte[len];
                buf.position(off);
                buf.get(bbuf);
                char[] cbuf = new char[len];
                for (int i = 0; i < bbuf.length; i++) {
                        cbuf[i] = (char) bbuf[i];
                }

                return new String(cbuf);
        }

        /**
         * Set the creation date.  Note that the year is encoded specially.
         *
         * @param buf The buffer to write into.  It must have been properly positioned
         * beforehand.
         * @param date The date to set.
         */

        public static void setCreationTime(ByteBuffer buf, Date date) {
                Calendar cal = Calendar.getInstance();

                if (date != null)
                        cal.setTime(date);

                fillBufFromTime(buf, cal);
        }

        /**
         * A map unit is an integer value that is 1/(2^24) degrees of latitude or
         * longitude.
         *
         * @param l The lat or long as decimal degrees.
         * @return An integer value in map units.
         */

        public static int toMapUnit(double l) {
                double DELTA = 360.0D / (1 << 24) / 2; //Correct rounding
                if (l > 0)
                        return (int) ((l + DELTA) * (1 << 24)/360);
                else
                        return (int) ((l - DELTA) * (1 << 24)/360);
        }

        /**
         * Convert a date into the in-file representation of a date.
         *
         * @param date The date.
         * @return A byte stream in .img format.
         */

        public static byte[] makeCreationTime(Date date) {
                Calendar cal = Calendar.getInstance();

                if (date != null)
                        cal.setTime(date);

                byte[] ret = new byte[7];

                ByteBuffer buf = ByteBuffer.wrap(ret);
                buf.order(ByteOrder.LITTLE_ENDIAN);
                fillBufFromTime(buf, cal);
               
                return ret;
        }

        private static void fillBufFromTime(ByteBuffer buf, Calendar cal) {
                buf.putChar((char) cal.get(Calendar.YEAR));
                buf.put((byte) (cal.get(Calendar.MONTH)+1));
                buf.put((byte) cal.get(Calendar.DAY_OF_MONTH));
                buf.put((byte) cal.get(Calendar.HOUR_OF_DAY));
                buf.put((byte) cal.get(Calendar.MINUTE));
                buf.put((byte) cal.get(Calendar.SECOND));
        }

        /**
         * Make a date from the garmin representation.
         * @param date The bytes representing the date.
         * @return A java date.
         */

        public static Date makeCreationTime(byte[] date) {
                Calendar cal = Calendar.getInstance();

                int y = ((date[1] & 0xff) << 8) + (date[0] & 0xff);
                cal.set(y, date[2]-1, date[3], date[4], date[5], date[6]);

                return cal.getTime();
        }

        /**
         * Convert an angle in map units to degrees.
         */

        public static double toDegrees(int val) {
                return (double) val * (360.0 / (1 << 24));
        }

        /**
         * Convert an angle in map units to radians.
         */

        public static double toRadians(int mapunits) {
                return toDegrees(mapunits) * (Math.PI / 180);
        }

        public static void closeFile(Closeable f) {
                if (f != null) {
                        try {
                                f.close();
                        } catch (IOException e) {
                                e.printStackTrace();
                        }
                }
        }

        /**
         * Open a file and apply filters necessary for reading it such as
         * decompression.
         *
         * @param name The file to open.
         * @return A stream that will read the file, positioned at the beginning.
         * @throws FileNotFoundException If the file cannot be opened for any reason.
         */

        public static InputStream openFile(String name) throws FileNotFoundException {
                InputStream is = new FileInputStream(name);
                if (name.endsWith(".gz")) {
                        try {
                                is = new GZIPInputStream(is);
                        } catch (IOException e) {
                                throw new FileNotFoundException( "Could not read as compressed file");
                        }
                }
                return is;
        }

        public static String joinPath(String dir, String basename, String ext) {
                return joinPath(dir, basename + "." + ext);
        }
        public static String joinPath(String dir, String basename) {
                File file = new File(dir, basename);
                return file.getAbsolutePath();
        }

        /**
         * Rounds an integer up to the nearest multiple of {@code 2^shift}.
         * Works with both positive and negative integers.
         * @param val the integer to round up.
         * @param shift the power of two to round up to.
         * @return the rounded integer.
         */

        public static int roundUp(int val, int shift) {
                return (val + (1 << shift) - 1) >>> shift << shift;
        }
       
       
}