Package gps.garmin.img

Source Code of gps.garmin.img.Parser

package gps.garmin.img;

import gps.garmin.img.structure.IMG;
import gps.garmin.img.structure.data.MapLevel;
import gps.garmin.img.structure.data.ObjectType;
import gps.garmin.img.structure.data.Point;
import gps.garmin.img.structure.data.PointSubtype;
import gps.garmin.img.structure.data.PointType;
import gps.garmin.img.structure.data.Polygon;
import gps.garmin.img.structure.data.PolygonType;
import gps.garmin.img.structure.data.Polyline;
import gps.garmin.img.structure.data.PolylineType;
import gps.garmin.img.structure.data.Subdivision;
import gps.garmin.img.structure.data.Subfile;
import gps.garmin.img.structure.data.SubfileHeaderTRE;
import gps.garmin.img.structure.data.SubfileLBL;
import gps.garmin.img.structure.data.SubfileMDR;
import gps.garmin.img.structure.data.SubfileNET;
import gps.garmin.img.structure.data.SubfileNOD;
import gps.garmin.img.structure.data.SubfileNone;
import gps.garmin.img.structure.data.SubfileRGN;
import gps.garmin.img.structure.data.SubfileTRE;
import gps.garmin.img.structure.fat.FATBlock;
import gps.garmin.img.structure.fat.FATBlockType;
import gps.garmin.img.structure.Header;
import gps.garmin.img.structure.fat.PartitionTable;
import gps.garmin.img.structure.data.SubfileCommonHeader;
import gps.garmin.img.structure.data.SubfileLockStatus;
import gps.garmin.img.structure.data.SubfileType;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;

public abstract class Parser {
   
    protected IMG img;
   
    protected boolean isXorEd;
    protected int xorByte;
   
    protected int currentByte;
    protected int[] currentBytes;
    protected int currentByteQuantity;

    private HashMap<SubfileType, FATBlock> fatBlocks;
   
    private boolean alreadyParsed;
   
    protected Parser(String name) {
        img = new IMG();
        img.setName(name);
       
        fatBlocks = new HashMap<SubfileType, FATBlock>();
        alreadyParsed = false;
    }
   
    public void parse() throws ParseException {
        try {
            if (alreadyParsed) {
                throw new ParseException("IMG file already parsed");
            }

            parseHeader();

            parseTRESubfile();

            alreadyParsed = true;
        } catch (ParseException e) {
            System.out.println("Current byte quantity: " + currentByteQuantity);
            System.out.println("Current byte: " + currentByte);
            System.out.print("Current bytes:");
            for (int b : currentBytes) {
                System.out.print(" " + b);
            }
            System.out.println("");
           
            System.out.println("Current byte pointer: " + getBytePointer());
           
            throw e;
        } catch (RuntimeException e) {
            System.out.println("Current byte quantity: " + currentByteQuantity);
            System.out.println("Current byte: " + currentByte);
            System.out.print("Current bytes:");
            for (int b : currentBytes) {
                System.out.print(" " + b);
            }
            System.out.println("");
           
            System.out.println("Current byte pointer: " + getBytePointer());
           
            throw e;
        }
    }
   
    public IMG getIMG() throws ParseException {
        if (!alreadyParsed) {
            throw new ParseException("IMG file not parsed yet");
        }
       
        return img;
    }
   
    protected abstract int nextByte() throws ParseException;
   
    protected abstract void nextBytes(int quantity) throws ParseException;
   
    protected abstract long getBytePointer() throws ParseException;
   
    protected abstract void seek(long offset) throws ParseException;
   
    protected abstract void skipBytes(int length) throws ParseException;
   
    protected void parseHeader() throws ParseException {
        Header imgHeader = new Header();
        img.setImgHeader(imgHeader);

        parseXorByte(imgHeader);

        // 0x00 x9
        skipBytes(9);

        // Update month
        imgHeader.setUpdateMonth(nextByte());

        // Update year
        nextByte();
        if (currentByte <= 0x62) {
            imgHeader.setUpdateYear(currentByte + 2000);
        } else // >= 0x63
            imgHeader.setUpdateYear(currentByte + 1900);
        }

        // 0x00 x3
        skipBytes(3);

        // Checksum
        imgHeader.setChecksum(nextByte());

        // Signature
        imgHeader.setSignature(parseString(7));

        // 0x02 x1
        skipBytes(1);

        // Sector? x2
        skipBytes(2);

        // Heads? x2
        skipBytes(2);

        // Cylinders? x2
        skipBytes(2);

        // 0x00 x2
        skipBytes(2);

        // 0x00 x25
        skipBytes(25);
       
        // Creation date
        imgHeader.setCreationDate(parseDate());

        // 0x02 x1
        skipBytes(1);

        // Map file identifier
        imgHeader.setMapFileIdentifier(parseString(7));

        // 0x00 x1
        skipBytes(1);

        // Description (first)
        imgHeader.setDescription(parseString(20));

        // Heads? x2
        skipBytes(2);

        // Sectors? x2
        skipBytes(2);

        // Exponent1
        imgHeader.setBlockSizeExponent1(nextByte());

        // Exponent2
        imgHeader.setBlockSizeExponent2(nextByte());

        // FAT block size
        imgHeader.setFatBlockSize(
            (int)
            Math.pow(
                2, imgHeader.getBlockSizeExponent1() + imgHeader.getBlockSizeExponent2()));

        // ???
        skipBytes(2);

        // Description (second)
        imgHeader.setDescription(imgHeader.getDescription() + parseString(31));

        // 0x00 x314
        skipBytes(314);

        // Partition table
        PartitionTable imgPartitionTable = new PartitionTable();
        imgHeader.setPartitionTable(imgPartitionTable);

        // Boot
        imgPartitionTable.setBoot(nextByte());

        // Start head
        imgPartitionTable.setStartHead(nextByte());

        // Start sector
        imgPartitionTable.setStartSector(nextByte());

        // Start cylinder
        imgPartitionTable.setStartCylinder(nextByte());

        // System type
        imgPartitionTable.setSystemType(nextByte());

        // End head
        imgPartitionTable.setEndHead(nextByte());

        // End sector
        imgPartitionTable.setEndSector(nextByte());

        // End cylinder
        imgPartitionTable.setEndCylinder(nextByte());

        // Rel sectors
        imgPartitionTable.setRelSectors(getLittleEndianDWord(4));

        // Number of sectors
        imgPartitionTable.setNumberOfSectors(getLittleEndianDWord(4));

        // 0x00 x48
        skipBytes(48);

        // 0x55
        if (nextByte() != 0x55) {
            throw new IllegalStateException()// fixme
        }

        // 0xAA
        if (nextByte() != 0xAA) {
            throw new IllegalStateException()// fixme
        }

        // End of partition table

        // 0x00 x512
        skipBytes(512);

        // 0x01 x1
        skipBytes(1);

        // 0x20 x11
        skipBytes(11);

        // First subfile offset
        imgHeader.setFirstSubfileOffset(getLittleEndianWord(4));

        // 0x03 x 1
        skipBytes(1);

        // 0x00 x 15
        skipBytes(15);
       
        // Block sequence numbers
        int blockSequenceCounter = 0;
        for (int i = 0; i < 240; i++) {
            int blockSequence = getLittleEndianWord(2);

            if (blockSequence == blockSequenceCounter) {
                imgHeader.getBlockSequence().add(blockSequence);

                blockSequenceCounter++;
            } else {
                // Fill block sequence
                // fixme, que debo hacer acá?
            }
        }

        // Header size
        imgHeader.setHeaderSize(
            imgHeader.getFatBlockSize() * imgHeader.getBlockSequence().size());

        // FAT blocks total size within header
        imgHeader.setFatBlocksTotalSize(imgHeader.getFirstSubfileOffset() - 0x600);
       
        // FAT Blocks
        while (getBytePointer() < imgHeader.getFirstSubfileOffset()) {
            FATBlock fatBlock = new FATBlock();
            imgHeader.getFatBlocks().add(fatBlock);

            // Block type
            if (nextByte() == 0x01) {
                fatBlock.setType(FATBlockType.TRUE);
            } else {
                fatBlock.setType(FATBlockType.DUMMY);
            }

            if (fatBlock.getType() == FATBlockType.TRUE) {
                // Subfile name
                fatBlock.setSubfileName(parseString(8));

                // Subfile type
                fatBlock.setSubfileType(SubfileType.valueOf(parseString(3)));

                // Subfile size
                fatBlock.setSubfileSizeInBytes(getLittleEndianWord(4));

                // Subfile part
                fatBlock.setSubfilePart(getLittleEndianDWord(2));

                // Subfile offset
                if (fatBlock.getSubfilePart() == 0) {
                    fatBlock.setSubfileOffset(
                        blockSequenceCounter * imgHeader.getFatBlockSize());
                }

                // 0x00 x14
                skipBytes(14);

                // Block sequence numbers
                for (int i = 0; i < 240; i++) {
                    int blockSequence = getLittleEndianWord(2);

                    if (blockSequence == blockSequenceCounter) {
                        fatBlock.getBlockSequence().add(blockSequence);

                        blockSequenceCounter++;
                    } else {
                        // Fill block sequence
                        // fixme, debo hacer algo acá?
                    }
                }
            } else {
                skipBytes(8 + 3 + 4 + 2 + 14 + 480)// Total 511
               
                fatBlock.setSubfileType(SubfileType.NONE);
            }

            if (fatBlock.getSubfilePart() == 0) {
                fatBlocks.put(fatBlock.getSubfileType(), fatBlock);
            } else {
                FATBlock firstFatBlock = fatBlocks.get(fatBlock.getSubfileType());

                while (firstFatBlock.getNextFatBlock() != null) {
                    firstFatBlock = firstFatBlock.getNextFatBlock();
                }

                firstFatBlock.setNextFatBlock(fatBlock);
            }
        }
    }
   
    protected void parseXorByte(final Header imgHeader) throws ParseException {
        // XOR'ed?
        nextByte();
        if (currentByte != 0) {
            xorByte = currentByte;
           
            imgHeader.setXorEd(true);
            imgHeader.setXorByte(xorByte);
           
            isXorEd = true;
        } else {
            imgHeader.setXorEd(false);
           
            isXorEd = false;
        }
    }
   
    protected void parseTRESubfile() throws ParseException {
        FATBlock treFatBlock = fatBlocks.get(SubfileType.TRE);
        seek(treFatBlock.getSubfileOffset());

        SubfileTRE subfile =
            (SubfileTRE) parseSubfileCommonHeader(treFatBlock.getSubfileOffset());
        SubfileHeaderTRE treHeader = subfile.getHeader();

        // North boundary
        treHeader.setNorthBoundary(Utils.convertMapUnitsToDegrees(getSignedInteger(3)));

        // East boundary
        treHeader.setEastBoundary(Utils.convertMapUnitsToDegrees(getSignedInteger(3)));

        // South boundary
        treHeader.setSouthBoundary(Utils.convertMapUnitsToDegrees(getSignedInteger(3)));

        // West boundary
        treHeader.setWestBoundary(Utils.convertMapUnitsToDegrees(getSignedInteger(3)));

        // Map levels section offset
        treHeader.setMapLevelsSectionOffset(getLittleEndianWord(4));

        // Map levels section size
        treHeader.setMapLevelsSectionSize(getLittleEndianWord(4));

        // Subdivisions section offset
        treHeader.setSubdivisionsSectionOffset(getLittleEndianWord(4));

        // Subdivisions section size
        treHeader.setSubdivisionsSectionSize(getLittleEndianWord(4));

        // Copyright section offset
        treHeader.setCopyrightSectionOffset(getLittleEndianWord(4));

        // Copyright section size
        treHeader.setCopyrightSectionSize(getLittleEndianWord(4));

        // Copyright record size
        treHeader.setCopyrightRecordSize(getLittleEndianWord(2));

        // 0x00 x4
        skipBytes(4);

        // POI display flags
        nextByte();
        treHeader.setTransparentMap((currentByte & 1) == 1);
        treHeader.setShowStreetBeforeStreetNumber((currentByte & 2) == 2);
        treHeader.setShowZipBeforeCity((currentByte & 4) == 4);

        skipBytes(3);
        skipBytes(4);

        // 0x0001
        skipBytes(2);

        // 0x00
        skipBytes(1);

        // Polyline overview section offset
        treHeader.setPolylineOverviewSectionOffset(getLittleEndianWord(4));

        // Polyline overview section length
        treHeader.setPolylineOverviewSectionLength(getLittleEndianWord(4));

        // Polyline overview records size
        treHeader.setPolylineOverviewRecordsSize(getLittleEndianWord(2));

        skipBytes(2);

        // 0x0000
        skipBytes(2);

        // Polygon overview section offset
        treHeader.setPolygonOverviewSectionOffset(getLittleEndianWord(4));

        // Polygon overview section length
        treHeader.setPolygonOverviewSectionLength(getLittleEndianWord(4));

        // Polygon overview records size
        treHeader.setPolygonOverviewRecordsSize(getLittleEndianWord(2));

        skipBytes(2);

        // 0x0000
        skipBytes(2);

        // Point overview section offset
        treHeader.setPointOverviewSectionOffset(getLittleEndianWord(4));

        // Point overview section length
        treHeader.setPointOverviewSectionLength(getLittleEndianWord(4));

        // Point overview records size
        treHeader.setPointOverviewRecordsSize(getLittleEndianWord(2));

        skipBytes(2);

        // 0x0000
        skipBytes(2);

        // Header longer than 116 bytes
        if (subfile.getCommonHeader().getHeadersLength() > SubfileHeaderTRE.LENGTH_116) {
            // Map ID
            treHeader.setMapID(String.valueOf(getLittleEndianWord(4)));

            // Header longer than 120 bytes
            if (subfile.getCommonHeader().getHeadersLength() > SubfileHeaderTRE.LENGTH_120) {
                // 0x00000000
                skipBytes(4);

                // TRE7 section offset
                treHeader.setTre7SectionOffset(getLittleEndianWord(4));

                // TRE7 section length
                treHeader.setTre7SectionLength(getLittleEndianWord(4));

                // TRE7 records size
                treHeader.setTre7RecordsSize(getLittleEndianWord(2));

                skipBytes(4);

                // TRE8 section offset
                treHeader.setTre8SectionOffset(getLittleEndianWord(4));

                // TRE8 secion length
                treHeader.setTre8SectionLength(getLittleEndianWord(4));

                skipBytes(4);

                // 0x0000
                skipBytes(4);

                // Header longer than 154 bytes
                if (subfile.getCommonHeader().getHeadersLength() > SubfileHeaderTRE.LENGTH_154) {
                    // Map level encryption key
                    treHeader.setMapLevelsSectionEncryptionKey(parseString(20));

                    // TRE9 section offset
                    treHeader.setTre9SectionOffset(getLittleEndianWord(4));

                    // TRE9 section length
                    treHeader.setTre9SectionLength(getLittleEndianWord(4));

                    // TRE9 records size
                    treHeader.setTre9RecordsSize(getLittleEndianWord(2));

                    // 0x00000000
                    skipBytes(4);
                }
            }
        }

        // Map descriptor
        String mapDescriptor = "";
        nextByte();
        while (currentByte != 0) {
            mapDescriptor += (char) currentByte;
            nextByte();
        }
        treHeader.setMapDescriptor(mapDescriptor);

        // Copyright section
        seek(treFatBlock.getSubfileOffset() + treHeader.getCopyrightSectionOffset());
        int numberOfRecords =
            treHeader.getCopyrightSectionSize() / treHeader.getCopyrightRecordSize();
        for (int i = 0; i < numberOfRecords; i++) {
            subfile.getCopyrights().add(getLittleEndianWord(treHeader.getCopyrightRecordSize()));
        }
       
        // Map levels section
        seek(treFatBlock.getSubfileOffset() + treHeader.getMapLevelsSectionOffset());
        int numberOfLevels = treHeader.getMapLevelsSectionSize() / 4// fixme, porque 4?
        for (int i = 0; i < numberOfLevels; i++) {
            MapLevel mapLevel = new MapLevel();
            mapLevel.setNumber(numberOfLevels - i - 1);

            // Inherited
            nextByte();
            mapLevel.setInherited((currentByte & 128) == 128);
            // Zoom level
            mapLevel.setZoomLevel(currentByte & 15);

            // Bits per coord
            mapLevel.setBitsPerCoordinate(nextByte());

            // Subdivisions
            mapLevel.setQuantityOfSubdivisions(getLittleEndianWord(2));

            subfile.getMapLevels().add(mapLevel);
        }

        // Subdivisions section
        seek(treFatBlock.getSubfileOffset() + treHeader.getSubdivisionsSectionOffset());
        boolean firstSubdivision = true;
        int subdivisionCounter = 1;
        Subdivision contiguousPreviousSubdivision = null;
        Collection<Subdivision> subdivisionsTemp = new ArrayList<Subdivision>();
        for (MapLevel mapLevel : subfile.getMapLevels()) {
            for (int i = 0; i < mapLevel.getQuantityOfSubdivisions(); i++) {
                Subdivision subdivision = new Subdivision();
                subdivision.setLevel(mapLevel);
                subdivision.setNumber(subdivisionCounter++);

                // Offset in RGN subfile
                subdivision.setOffsetInRGNSubfile(getLittleEndianWord(3));

                // Object types
                subdivision.setObjectTypes(getTRESubfileObjectTypes());

                // Longitude center
                subdivision.setLongitudeCenter(
                    Utils.convertMapUnitsToDegrees(getSignedInteger(3)));

                // Latitude center
                subdivision.setLatitudeCenter(
                    Utils.convertMapUnitsToDegrees(getSignedInteger(3)));

                // Width
                int value = getLittleEndianWord(2);
                subdivision.setWidth(value & 32767);
                subdivision.setTotalWidth((subdivision.getWidth() * 2) + 1);

                subdivision.setTerminatingFlag((value & 32768) == 32768);
                if (contiguousPreviousSubdivision != null) {
                    contiguousPreviousSubdivision.setContiguousSubdivision(subdivision);
                }
                if (subdivision.isTerminatingFlag()) {
                    contiguousPreviousSubdivision = null;
                } else {
                    contiguousPreviousSubdivision = subdivision;
                }

                // Height
                subdivision.setHeight(getLittleEndianWord(2));
                subdivision.setTotalHeight((subdivision.getHeight() * 2) + 1);

                if (mapLevel.getNumber() != 0) {
                    // Next level subdivision
                    int nextSubdivisionNumber = getLittleEndianWord(2);
                    if (nextSubdivisionNumber != 0) {
                        Subdivision subdivisionTemp = new Subdivision();
                        subdivisionTemp.setNumber(nextSubdivisionNumber);
                        subdivision.setNextLevelSubdivision(subdivisionTemp);
                    }
                }

                if (firstSubdivision) {
                    subfile.setFirstSubdivision(subdivision);
                    firstSubdivision = false;
                }

                for (Subdivision subdivisionTemp : subdivisionsTemp) {
                    if (subdivisionTemp.getNextLevelSubdivision() != null) {
                        if (subdivisionTemp.getNextLevelSubdivision().getNumber() == subdivision.getNumber()) {
                            subdivisionTemp.setNextLevelSubdivision(subdivision);
                        }
                    }
                }
                subdivisionsTemp.add(subdivision);
            }
        }

        // Polyline section
        seek(treFatBlock.getSubfileOffset() + treHeader.getPolylineOverviewSectionOffset());
        int numberOfPolylines =
            treHeader.getPolylineOverviewSectionLength() /
            treHeader.getPolylineOverviewRecordsSize();
        for (int i = 0; i < numberOfPolylines; i++) {
            Polyline polyline = new Polyline();
            polyline.setNumber(i + 1);

            // Polyline type
            nextByte()// fixme, siempre es por default? no se usa el byte?
            polyline.setType(PolylineType.DEFAULT);

            // Maximum level
            polyline.setMaximumLevelWherePresent(nextByte());

            if (treHeader.getPolylineOverviewRecordsSize() == 3) {
                skipBytes(1);
            }

            subfile.getPolylines().add(polyline);
        }

        // Polygon section
        seek(treFatBlock.getSubfileOffset() + treHeader.getPolygonOverviewSectionOffset());
        int numberOfPolygons =
            treHeader.getPolygonOverviewSectionLength() /
            treHeader.getPolygonOverviewRecordsSize();
        for (int i = 0; i < numberOfPolygons; i++) {
            Polygon polygon = new Polygon();
            polygon.setNumber(i + 1);

            // Polygon type
            nextByte()// fixme, siempre es por default? no se usa el byte?
            polygon.setType(PolygonType.DEFAULT);

            // Maximum level
            polygon.setMaximumLevelWherePresent(nextByte());

            if (treHeader.getPolygonOverviewRecordsSize() == 3) {
                skipBytes(1);
            }

            subfile.getPolygons().add(polygon);
        }

        // Point section
        seek(treFatBlock.getSubfileOffset() + treHeader.getPointOverviewSectionOffset());
        int numberOfPoints =
            treHeader.getPointOverviewSectionLength() /
            treHeader.getPointOverviewRecordsSize();
        for (int i = 0; i < numberOfPoints; i++) {
            Point point = new Point();
            point.setNumber(i + 1);

            // Point type
            nextByte()// fixme, siempre es por default? no se usa el byte?
            point.setType(PointType.DEFAULT);

            // Maximum level
            point.setMaximumLevelWherePresent(nextByte());

            // Point subtype
            nextByte()// fixme, siempre es por default? no se usa el byte?
            point.setSubtype(PointSubtype.DEFAULT);

            subfile.getPoints().add(point);
        }
       
        img.getSubfiles().add(subfile);
    }

    protected final Subfile parseSubfileCommonHeader(int subfileOffset) throws ParseException {
        Subfile subfile = null;

        // Subfile common header
        SubfileCommonHeader commonHeader = new SubfileCommonHeader();

        // Subfile headers length
        commonHeader.setHeadersLength(getLittleEndianWord(2));

        // Subfile type
        commonHeader.setType(SubfileType.getType(parseString(10)));
        switch (commonHeader.getType()) {
            case RGN: subfile = new SubfileRGN(); break;
            case TRE: subfile = new SubfileTRE(); break;
            case LBL: subfile = new SubfileLBL(); break;
            case NOD: subfile = new SubfileNOD(); break;
            case NET: subfile = new SubfileNET(); break;
            case MDR: subfile = new SubfileMDR(); break;
            default: subfile = new SubfileNone(); break;
        }
        subfile.setOffset(subfileOffset);
        subfile.setCommonHeader(commonHeader);

        // 0x01 x1
        skipBytes(1);

        // Subfile lock status
        if (nextByte() == 0) {
            commonHeader.setLockStatus(SubfileLockStatus.NOT_LOCKED);
        } else {
            commonHeader.setLockStatus(SubfileLockStatus.LOCKED);
        }

        // Subfile creation date
        commonHeader.setCreationDate(parseDate());

        return subfile;
    }

    protected final Collection<ObjectType> getTRESubfileObjectTypes() throws ParseException {
        Collection<ObjectType> result = new ArrayList<ObjectType>();
       
        int value = nextByte();
        while (value > 0) {
            if (value >= 0x80) {
                result.add(ObjectType.POLYGON);
                value -= 0x80;
            } else if (value >= 0x40) {
                result.add(ObjectType.POLYLINE);
                value -= 0x40;
            } else if (value >= 0x20) {
                result.add(ObjectType.INDEXED_POINT);
                value -= 0x20;
            } else {
                result.add(ObjectType.POINT);
                value -= 0x10;
            }
        }
       
        return result;
    }

    protected final Date parseDate() throws ParseException {
        Calendar calendar = Calendar.getInstance();
        calendar.setLenient(false);
        calendar.set(Calendar.MILLISECOND, 0);
       
        // Year
        calendar.set(Calendar.YEAR, getLittleEndianWord(2));

        // Month
        calendar.set(Calendar.MONTH, nextByte() - 1);

        // Day
        calendar.set(Calendar.DAY_OF_MONTH, nextByte());

        // Hour
        calendar.set(Calendar.HOUR_OF_DAY, nextByte());

        // Minute
        calendar.set(Calendar.MINUTE, nextByte());

        // Second
        calendar.set(Calendar.SECOND, nextByte());
       
        return calendar.getTime();
    }
   
    protected final String parseString(int length) throws ParseException {
        nextBytes(length);
        return new String(currentBytes, 0, length);
    }

    protected final int getLittleEndianWord(int length) throws ParseException {
        nextBytes(length);
       
        int result = 0;
       
        for (int i = currentByteQuantity - 1; i >= 0; i--) {
            result += (currentBytes[i] << (8 * i));
        }
       
        return result;
    }
   
    protected final int getLittleEndianDWord(int length) throws ParseException {
        nextBytes(length);
       
        int result = 0;
       
        for (int i = currentByteQuantity - 1; i >= 0; i = i - 2) {
            result += (currentBytes[i - 1] << (8 * i));
            result += (currentBytes[i] << (8 * (i - 1)));
        }
       
        return result;
    }
   
    protected final int getSignedInteger(int length) throws ParseException {
        int value = getLittleEndianWord(length);
       
        int positiveMaximum = 0x7F;
        int negativeMaximum = 0xFF;
        for (int i = 0; i < currentByteQuantity - 1; i++) {
            positiveMaximum = (positiveMaximum << 8) + 0xFF;
            negativeMaximum = (negativeMaximum << 8) + 0xFF;
        }
       
        if (value > positiveMaximum) {
            value = value - negativeMaximum;
        }
       
        return value;
    }
   
}
TOP

Related Classes of gps.garmin.img.Parser

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.