Subversion Repositories mkgmap

Rev

Rev 711 | 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: 23-Sep-2007
 */

package uk.me.parabola.io;

import java.io.IOException;
import java.io.InputStream;

/**
 * An input stream used to make reading little endian integers and strings from
 * the tdb file.
 *
 * @author Steve Ratcliffe
 */

public class StructuredInputStream extends InputStream {
        private final InputStream in;
        private boolean eof;

        public StructuredInputStream(InputStream in) {
                this.in = in;
        }

        /**
         * Implementation of read that delegates to the underlying stream.  It however
         * also keeps track of the end of file status.
         *
         * @return The next byte, or -1 on eof.
         * @throws IOException For problems reading.
         */

        public int read() throws IOException {
                int r = in.read();
                if (r == -1)
                        eof = true;
                return r;
        }

        /**
         * Read a 2 byte little endian integer.
         *
         * @return The integer.
         * @throws IOException If the stream could not be read.
         */

        public int read2() throws IOException {
                int a = read() & 0xff;
                int b = read() & 0xff;

                if (isEof())
                        throw new EndOfFileException();

                return (b << 8) + a;
        }

        /**
         * Read a 4 byte integer quantity.  As always this is little endian.
         *
         * @return The integer.
         * @throws IOException If the stream could not be read.
         */

        public int read4() throws IOException {
                int a = read() & 0xff;
                int b = read() & 0xff;
                int c = read() & 0xff;
                int d = read() & 0xff;

                return (d << 24) | (c << 16) | (b << 8) | a;
        }

        /**
         * Read a nul terminated string from the input stream.
         *
         * @return A string, without the null terminator.
         * @throws IOException If the stream cannot be read.
         */

        public String readString() throws IOException {
                StringBuffer name = new StringBuffer();
                int b;
                while ((b = read()) != '\0' && b != -1) {
                        name.append((char) (b & 0xff));
                }
                return name.toString();
        }

        boolean isEof() {
                return eof;
        }

        /**
         * Test if we are at the end of the file by marking the position and trying
         * to read the next byte.  If not at the end then the stream position is
         * reset and all is as before.
         *
         * @return True if we are at the end of the stream.
         */

        public boolean testEof() {
                assert in.markSupported();
                in.mark(1);
                try {
                        int b = in.read();
                        if (b == -1) {
                                eof = true;
                        } else {
                                in.reset();
                        }
                        return isEof();
                } catch (IOException e) {
                        return true;
                }
        }

}