All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.oscim.tiling.source.mapfile.ReadBuffer Maven / Gradle / Ivy

/*
 * Copyright 2010, 2011, 2012 mapsforge.org
 * Copyright 2017-2018 devemux86
 * Copyright 2017 Gustl22
 *
 * This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
 *
 * This program is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with
 * this program. If not, see .
 */
package org.oscim.tiling.source.mapfile;

import org.oscim.core.Tag;
import org.oscim.core.TagSet;
import org.oscim.utils.Parameters;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

/**
 * Reads from a {@link RandomAccessFile} into a buffer and decodes the data.
 */
public class ReadBuffer {
    private static final String CHARSET_UTF8 = "UTF-8";
    private static final Logger LOG = Logger.getLogger(ReadBuffer.class.getName());

    private byte[] mBufferData;
    private int mBufferPosition;
    private final RandomAccessFile mInputFile;

    private final List mTagIds = new ArrayList<>();

    ReadBuffer(RandomAccessFile inputFile) {
        mInputFile = inputFile;
    }

    /**
     * Returns one signed byte from the read buffer.
     *
     * @return the byte value.
     */
    public byte readByte() {
        return mBufferData[mBufferPosition++];
    }

    /**
     * Converts four bytes from the read buffer to a float.
     * 

* The byte order is big-endian. * * @return the float value. */ public float readFloat() { return Float.intBitsToFloat(readInt()); } /** * Reads the given amount of bytes from the file into the read buffer and * resets the internal buffer position. If * the capacity of the read buffer is too small, a larger one is created * automatically. * * @param length the amount of bytes to read from the file. * @return true if the whole data was read successfully, false otherwise. * @throws IOException if an error occurs while reading the file. */ public boolean readFromFile(int length) throws IOException { // ensure that the read buffer is large enough if (mBufferData == null || mBufferData.length < length) { // ensure that the read buffer is not too large if (length > Parameters.MAXIMUM_BUFFER_SIZE) { LOG.warning("invalid read length: " + length); return false; } mBufferData = new byte[length]; } mBufferPosition = 0; // reset the buffer position and read the data into the buffer // bufferPosition = 0; return mInputFile.read(mBufferData, 0, length) == length; } /** * Converts four bytes from the read buffer to a signed int. *

* The byte order is big-endian. * * @return the int value. */ public int readInt() { int pos = mBufferPosition; byte[] data = mBufferData; mBufferPosition += 4; return data[pos] << 24 | (data[pos + 1] & 0xff) << 16 | (data[pos + 2] & 0xff) << 8 | (data[pos + 3] & 0xff); } /** * Converts eight bytes from the read buffer to a signed long. *

* The byte order is big-endian. * * @return the long value. */ public long readLong() { int pos = mBufferPosition; byte[] data = mBufferData; mBufferPosition += 8; return (data[pos] & 0xffL) << 56 | (data[pos + 1] & 0xffL) << 48 | (data[pos + 2] & 0xffL) << 40 | (data[pos + 3] & 0xffL) << 32 | (data[pos + 4] & 0xffL) << 24 | (data[pos + 5] & 0xffL) << 16 | (data[pos + 6] & 0xffL) << 8 | (data[pos + 7] & 0xffL); } /** * Converts two bytes from the read buffer to a signed int. *

* The byte order is big-endian. * * @return the int value. */ public int readShort() { mBufferPosition += 2; return mBufferData[mBufferPosition - 2] << 8 | (mBufferData[mBufferPosition - 1] & 0xff); } /** * Converts a variable amount of bytes from the read buffer to a signed int. *

* The first bit is for continuation info, the other six (last byte) or * seven (all other bytes) bits are for data. The second bit in the last * byte indicates the sign of the number. * * @return the value. */ public int readSignedInt() { int pos = mBufferPosition; byte[] data = mBufferData; int flag; if ((data[pos] & 0x80) == 0) { mBufferPosition += 1; flag = ((data[pos] & 0x40) >> 6); return ((data[pos] & 0x3f) ^ -flag) + flag; } if ((data[pos + 1] & 0x80) == 0) { mBufferPosition += 2; flag = ((data[pos + 1] & 0x40) >> 6); return (((data[pos] & 0x7f) | (data[pos + 1] & 0x3f) << 7) ^ -flag) + flag; } if ((data[pos + 2] & 0x80) == 0) { mBufferPosition += 3; flag = ((data[pos + 2] & 0x40) >> 6); return (((data[pos] & 0x7f) | (data[pos + 1] & 0x7f) << 7 | (data[pos + 2] & 0x3f) << 14) ^ -flag) + flag; } if ((data[pos + 3] & 0x80) == 0) { mBufferPosition += 4; flag = ((data[pos + 3] & 0x40) >> 6); return (((data[pos] & 0x7f) | ((data[pos + 1] & 0x7f) << 7) | ((data[pos + 2] & 0x7f) << 14) | ((data[pos + 3] & 0x3f) << 21)) ^ -flag) + flag; } mBufferPosition += 5; flag = ((data[pos + 4] & 0x40) >> 6); return ((((data[pos] & 0x7f) | (data[pos + 1] & 0x7f) << 7 | (data[pos + 2] & 0x7f) << 14 | (data[pos + 3] & 0x7f) << 21 | (data[pos + 4] & 0x3f) << 28)) ^ -flag) + flag; } /** * Converts a variable amount of bytes from the read buffer to a signed int * array. *

* The first bit is for continuation info, the other six (last byte) or * seven (all other bytes) bits are for data. The second bit in the last * byte indicates the sign of the number. * * @param values result values * @param length number of values to read */ public void readSignedInt(int[] values, int length) { int pos = mBufferPosition; byte[] data = mBufferData; int flag; for (int i = 0; i < length; i++) { if ((data[pos] & 0x80) == 0) { flag = ((data[pos] & 0x40) >> 6); values[i] = ((data[pos] & 0x3f) ^ -flag) + flag; pos += 1; } else if ((data[pos + 1] & 0x80) == 0) { flag = ((data[pos + 1] & 0x40) >> 6); values[i] = (((data[pos] & 0x7f) | ((data[pos + 1] & 0x3f) << 7)) ^ -flag) + flag; pos += 2; } else if ((data[pos + 2] & 0x80) == 0) { flag = ((data[pos + 2] & 0x40) >> 6); values[i] = (((data[pos] & 0x7f) | ((data[pos + 1] & 0x7f) << 7) | ((data[pos + 2] & 0x3f) << 14)) ^ -flag) + flag; pos += 3; } else if ((data[pos + 3] & 0x80) == 0) { flag = ((data[pos + 3] & 0x40) >> 6); values[i] = (((data[pos] & 0x7f) | ((data[pos + 1] & 0x7f) << 7) | ((data[pos + 2] & 0x7f) << 14) | ((data[pos + 3] & 0x3f) << 21)) ^ -flag) + flag; pos += 4; } else { flag = ((data[pos + 4] & 0x40) >> 6); values[i] = ((((data[pos] & 0x7f) | ((data[pos + 1] & 0x7f) << 7) | ((data[pos + 2] & 0x7f) << 14) | ((data[pos + 3] & 0x7f) << 21) | ((data[pos + 4] & 0x3f) << 28))) ^ -flag) + flag; pos += 5; } } mBufferPosition = pos; } /** * Converts a variable amount of bytes from the read buffer to an unsigned * int. *

* The first bit is for continuation info, the other seven bits are for * data. * * @return the int value. */ public int readUnsignedInt() { int pos = mBufferPosition; byte[] data = mBufferData; if ((data[pos] & 0x80) == 0) { mBufferPosition += 1; return (data[pos] & 0x7f); } if ((data[pos + 1] & 0x80) == 0) { mBufferPosition += 2; return (data[pos] & 0x7f) | (data[pos + 1] & 0x7f) << 7; } if ((data[pos + 2] & 0x80) == 0) { mBufferPosition += 3; return (data[pos] & 0x7f) | ((data[pos + 1] & 0x7f) << 7) | ((data[pos + 2] & 0x7f) << 14); } if ((data[pos + 3] & 0x80) == 0) { mBufferPosition += 4; return (data[pos] & 0x7f) | ((data[pos + 1] & 0x7f) << 7) | ((data[pos + 2] & 0x7f) << 14) | ((data[pos + 3] & 0x7f) << 21); } mBufferPosition += 5; return (data[pos] & 0x7f) | ((data[pos + 1] & 0x7f) << 7) | ((data[pos + 2] & 0x7f) << 14) | ((data[pos + 3] & 0x7f) << 21) | ((data[pos + 4] & 0x7f) << 28); } /** * Decodes a variable amount of bytes from the read buffer to a string. * * @return the UTF-8 decoded string (may be null). */ public String readUTF8EncodedString() { return readUTF8EncodedString(readUnsignedInt()); } /** * @return ... */ public int getPositionAndSkip() { int pos = mBufferPosition; int length = readUnsignedInt(); skipBytes(length); return pos; } /** * Decodes the given amount of bytes from the read buffer to a string. * * @param stringLength the length of the string in bytes. * @return the UTF-8 decoded string (may be null). */ public String readUTF8EncodedString(int stringLength) { if (stringLength > 0 && mBufferPosition + stringLength <= mBufferData.length) { mBufferPosition += stringLength; try { return new String(mBufferData, mBufferPosition - stringLength, stringLength, CHARSET_UTF8); } catch (UnsupportedEncodingException e) { throw new IllegalStateException(e); } } LOG.warning("invalid string length: " + stringLength); return null; } /** * Decodes a variable amount of bytes from the read buffer to a string. * * @param position buffer offset position of string * @return the UTF-8 decoded string (may be null). */ public String readUTF8EncodedStringAt(int position) { int curPosition = mBufferPosition; mBufferPosition = position; String result = readUTF8EncodedString(readUnsignedInt()); mBufferPosition = curPosition; return result; } /** * @return the current buffer position. */ int getBufferPosition() { return mBufferPosition; } /** * @return the current size of the read buffer. */ int getBufferSize() { return mBufferData.length; } /** * Sets the buffer position to the given offset. * * @param bufferPosition the buffer position. */ void setBufferPosition(int bufferPosition) { mBufferPosition = bufferPosition; } /** * Skips the given number of bytes in the read buffer. * * @param bytes the number of bytes to skip. */ void skipBytes(int bytes) { mBufferPosition += bytes; } boolean readTags(TagSet tags, Tag[] tagsArray, byte numberOfTags) { tags.clear(); mTagIds.clear(); int maxTag = tagsArray.length; for (byte i = 0; i < numberOfTags; i++) { int tagId = readUnsignedInt(); if (tagId < 0 || tagId >= maxTag) { LOG.warning("invalid tag ID: " + tagId); break; } mTagIds.add(tagId); } for (int tagId : mTagIds) { Tag tag = tagsArray[tagId]; // Decode variable values of tags if (tag.value.length() == 2 && tag.value.charAt(0) == '%') { String value = tag.value; if (value.charAt(1) == 'b') { value = String.valueOf(readByte()); } else if (value.charAt(1) == 'i') { if (tag.key.contains(":colour")) { value = "#" + Integer.toHexString(readInt()); } else { value = String.valueOf(readInt()); } } else if (value.charAt(1) == 'f') { value = String.valueOf(readFloat()); } else if (value.charAt(1) == 'h') { value = String.valueOf(readShort()); } else if (value.charAt(1) == 's') { value = readUTF8EncodedString(); } tag = new Tag(tag.key, value); } tags.add(tag); } return true; } private static final int WAY_NUMBER_OF_TAGS_BITMASK = 0x0f; int lastTagPosition; int skipWays(int queryTileBitmask, int elements) { int pos = mBufferPosition; byte[] data = mBufferData; int cnt = elements; int skip; lastTagPosition = -1; while (cnt > 0) { // read way size (unsigned int) if ((data[pos] & 0x80) == 0) { skip = (data[pos] & 0x7f); pos += 1; } else if ((data[pos + 1] & 0x80) == 0) { skip = (data[pos] & 0x7f) | (data[pos + 1] & 0x7f) << 7; pos += 2; } else if ((data[pos + 2] & 0x80) == 0) { skip = (data[pos] & 0x7f) | ((data[pos + 1] & 0x7f) << 7) | ((data[pos + 2] & 0x7f) << 14); pos += 3; } else if ((data[pos + 3] & 0x80) == 0) { skip = (data[pos] & 0x7f) | ((data[pos + 1] & 0x7f) << 7) | ((data[pos + 2] & 0x7f) << 14) | ((data[pos + 3] & 0x7f) << 21); pos += 4; } else { skip = (data[pos] & 0x7f) | ((data[pos + 1] & 0x7f) << 7) | ((data[pos + 2] & 0x7f) << 14) | ((data[pos + 3] & 0x7f) << 21) | ((data[pos + 4] & 0x7f) << 28); pos += 5; } // invalid way size if (skip < 0) { mBufferPosition = pos; return -1; } // check if way matches queryTileBitmask if ((((data[pos] << 8) | (data[pos + 1] & 0xff)) & queryTileBitmask) == 0) { // remember last tags position if ((data[pos + 2] & WAY_NUMBER_OF_TAGS_BITMASK) != 0) lastTagPosition = pos + 2; pos += skip; cnt--; } else { pos += 2; break; } } mBufferPosition = pos; return cnt; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy