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

org.joda.beans.ser.bin.MsgPackInput Maven / Gradle / Ivy

/*
 *  Copyright 2001-present Stephen Colebourne
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.joda.beans.ser.bin;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * Receives and processes MsgPack data.
 */
abstract class MsgPackInput extends MsgPack {

    /**
     * The stream to read.
     */
    private final DataInputStream input;

    /**
     * Creates an instance.
     * 
     * @param bytes  the bytes to read, not null
     */
    MsgPackInput(byte[] bytes) {
        this(new ByteArrayInputStream(bytes));
    }

    /**
     * Creates an instance.
     * 
     * @param stream  the stream to read from, not null
     */
    MsgPackInput(InputStream stream) {
        this(new DataInputStream(stream));
    }

    /**
     * Creates an instance.
     * 
     * @param stream  the stream to read from, not null
     */
    MsgPackInput(DataInputStream stream) {
        this.input = stream;
    }

    //-----------------------------------------------------------------------
    /**
     * Reads all the data in the stream, closing the stream.
     */
    void readAll() {
        try {
            try {
                int b = input.read();
                while (b >= 0) {
                    readObject(b);
                    b = input.read();
                }
            } finally {
                input.close();
            }
        } catch (IOException ex) {
            throw new IllegalStateException(ex);
        }
    }

    //-----------------------------------------------------------------------
    void readObject(int unsigned) throws IOException {
        handleObjectStart();
        byte b = (byte) unsigned;
        if (b >= MIN_FIX_INT) {  // no need to check for b <= MAX_FIX_INT
            handleInt(b);
            
        } else if (b >= MIN_FIX_STR && b <= MAX_FIX_STR) {
            string(b - MIN_FIX_STR);
            
        } else if (b >= MIN_FIX_ARRAY && b <= MAX_FIX_ARRAY) {
            array(b - MIN_FIX_ARRAY);
            
        } else if (b >= MIN_FIX_MAP && b <= MAX_FIX_MAP) {
            map(b - MIN_FIX_MAP);
            
        } else {
            switch ((int) b) {
                case NIL:
                    handleNil();
                    break;
                case FALSE:
                    handleBoolean(false);
                    break;
                case TRUE:
                    handleBoolean(true);
                    break;
                case BIN_8: {
                    binary(input.readUnsignedByte());
                    break;
                }
                case BIN_16: {
                    binary(input.readUnsignedShort());
                    break;
                }
                case BIN_32: {
                    binary(input.readInt());
                    break;
                }
                case EXT_8: {
                    extension(input.readUnsignedByte(), false);
                    break;
                }
                case EXT_16: {
                    extension(input.readUnsignedShort(), false);
                    break;
                }
                case EXT_32: {
                    extension(input.readInt(), false);
                    break;
                }
                case FLOAT_32: {
                    float value = input.readFloat();
                    handleFloat(value);
                    break;
                }
                case FLOAT_64: {
                    double value = input.readDouble();
                    handleDouble(value);
                    break;
                }
                case UINT_8: {
                    int value = input.readUnsignedByte();
                    handleInt(value);
                    break;
                }
                case UINT_16: {
                    int value = input.readUnsignedShort();
                    handleInt(value);
                    break;
                }
                case UINT_32: {
                    int val = input.readInt();
                    if (val >= 0) {
                        handleInt(val);
                    } else {
                        long value = ((long) val) & 0xFFFFFFFFL;
                        handleUnsignedLong(value);
                    }
                    break;
                }
                case UINT_64: {
                    long value = input.readLong();
                    handleUnsignedLong(value);
                    break;
                }
                case SINT_8: {
                    int value = input.readByte();
                    handleInt(value);
                    break;
                }
                case SINT_16: {
                    int value = input.readShort();
                    handleInt(value);
                    break;
                }
                case SINT_32: {
                    int value = input.readInt();
                    handleInt(value);
                    break;
                }
                case SINT_64: {
                    long value = input.readLong();
                    handleSignedLong(value);
                    break;
                }
                case FIX_EXT_1: {
                    extension(1, true);
                    break;
                }
                case FIX_EXT_2: {
                    extension(2, true);
                    break;
                }
                case FIX_EXT_4: {
                    extension(4, true);
                    break;
                }
                case FIX_EXT_8: {
                    extension(8, true);
                    break;
                }
                case FIX_EXT_16: {
                    extension(16, true);
                    break;
                }
                case STR_8: {
                    string(input.readUnsignedByte());
                    break;
                }
                case STR_16: {
                    string(input.readUnsignedShort());
                    break;
                }
                case STR_32: {
                    string(input.readInt());
                    break;
                }
                case ARRAY_16: {
                    array(input.readUnsignedShort());
                    break;
                }
                case ARRAY_32: {
                    array(input.readInt());
                    break;
                }
                case MAP_16: {
                    map(input.readUnsignedShort());
                    break;
                }
                case MAP_32: {
                    map(input.readInt());
                    break;
                }
                default:
                    handleUnknown(b);
            }
        }
    }

    private void string(int size) throws IOException {
        if (size < 0) {
            throw new IllegalStateException("String too large");
        }
        byte[] bytes = new byte[size];
        input.readFully(bytes);
        String str = new String(bytes, UTF_8);
        handleString(str);
    }

    private void array(int size) throws IOException {
        handleArrayHeader(size);
        for (int i = 0; i < size; i++) {
            readArrayItem();
        }
    }

    void readArrayItem() throws IOException {
        int next = input.readUnsignedByte();
        readObject(next);
    }

    private void map(int size) throws IOException {
        handleMapHeader(size);
        for (int i = 0; i < size; i++) {
            readMapKey();
            readMapValue();
        }
    }

    void readMapKey() throws IOException {
        int next = input.readUnsignedByte();
        readObject(next);
    }

    void readMapValue() throws IOException {
        int next = input.readUnsignedByte();
        readObject(next);
    }

    private void binary(int size) throws IOException {
        if (size < 0) {
            throw new IllegalStateException("Binary too large");
        }
        byte[] bytes = new byte[size];
        input.readFully(bytes);
        handleBinary(bytes);
    }

    private void extension(int size, boolean numeric) throws IOException {
        int type = input.readByte();
        if (size < 0) {
            throw new IllegalStateException("Extension too large");
        }
        byte[] bytes = new byte[size];
        input.readFully(bytes);
        handleExtension(type, numeric, bytes);
    }

    void handleObjectStart() {
    }

    void handleBoolean(boolean bool) {
    }

    void handleNil() {
    }

    void handleInt(int value) {
    }

    void handleUnsignedLong(long value) {
    }

    void handleSignedLong(long value) {
    }

    void handleFloat(float value) {
    }

    void handleDouble(double value) {
    }

    void handleUnknown(byte b) {
    }

    void handleString(String str) {
    }

    void handleArrayHeader(int size) {
    }

    void handleMapHeader(int size) {
    }

    void handleBinary(byte[] bytes) throws IOException {
    }

    void handleExtension(int type, boolean numeric, byte[] bytes) throws IOException {
    }

    //-----------------------------------------------------------------------
    /**
     * Skips over the next object in an input stream.
     * 
     * @param input  the input stream, not null
     * @throws IOException if an error occurs
     */
    public static void skipObject(DataInputStream input) throws IOException {
        new Skipper(input).skip(input.readByte());
    }

    private static class Skipper extends MsgPackInput {
        Skipper(DataInputStream input) {
            super(input);
        }
        void skip(int typeByte) throws IOException {
            readObject(typeByte);
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy