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

org.gwtproject.rpc.serialization.api.impl.AbstractSerializationStreamReader Maven / Gradle / Ivy

There is a newer version: 1.0-alpha-8
Show newest version
package org.gwtproject.rpc.serialization.api.impl;

import org.gwtproject.rpc.serialization.api.SerializationException;
import org.gwtproject.rpc.serialization.api.SerializationStreamReader;

import java.util.ArrayList;

/**
 * Base class for the client and server serialization streams. This class
 * handles the basic serialization and deserialization formatting for primitive
 * types since these are common between the client and the server.
 */
public abstract class AbstractSerializationStreamReader extends
        AbstractSerializationStream implements SerializationStreamReader {

    private static final double TWO_PWR_15_DBL = 0x8000;
    private static final double TWO_PWR_16_DBL = 0x10000;
    private static final double TWO_PWR_22_DBL = 0x400000;
    private static final double TWO_PWR_31_DBL = TWO_PWR_16_DBL * TWO_PWR_15_DBL;
    private static final double TWO_PWR_32_DBL = TWO_PWR_16_DBL * TWO_PWR_16_DBL;
    private static final double TWO_PWR_44_DBL = TWO_PWR_22_DBL * TWO_PWR_22_DBL;
    private static final double TWO_PWR_63_DBL = TWO_PWR_32_DBL * TWO_PWR_31_DBL;

    /**
     * Return a long from a pair of doubles { low, high } such that the
     * actual value is equal to high + low.
     */
    public static long fromDoubles(double lowDouble, double highDouble) {
        long high = fromDouble(highDouble);
        long low = fromDouble(lowDouble);
        return high + low;
    }

    private static long fromDouble(double value) {
        if (Double.isNaN(value)) {
            return 0L;
        }
        if (value < -TWO_PWR_63_DBL) {
            return Long.MIN_VALUE;
        }
        if (value >= TWO_PWR_63_DBL) {
            return Long.MAX_VALUE;
        }

        boolean negative = false;
        if (value < 0) {
            negative = true;
            value = -value;
        }
        int a2 = 0;
        if (value >= TWO_PWR_44_DBL) {
            a2 = (int) (value / TWO_PWR_44_DBL);
            value -= a2 * TWO_PWR_44_DBL;
        }
        int a1 = 0;
        if (value >= TWO_PWR_22_DBL) {
            a1 = (int) (value / TWO_PWR_22_DBL);
            value -= a1 * TWO_PWR_22_DBL;
        }
        int a0 = (int) value;

        long result = ((long) a2 << 44) | ((long) a1 << 22) | a0;
        if (negative) {
            result = -result;
        }
        return result;
    }

    private ArrayList seenArray = new ArrayList();

    //TODO set some standards on all wrapped input like version and int?
    //TODO allow reusing/rereading a stream (as in "seenArray.clear()")?
//    /**
//     * Prepare to read the stream.
//     *
//     * @param encoded unused true if the stream is encoded
//     */
//    public void prepareToRead(String encoded) throws SerializationException {
//        seenArray.clear();
//
//        // Read the stream version number
//        //
//        setVersion(readInt());
//
//        // Read the flags from the stream
//        //
//        setFlags(readInt());
//    }

    public final Object readObject() throws com.google.gwt.user.client.rpc.SerializationException {
        int token = readInt();

        if (token < 0) {
            // Negative means a previous object
            // Transform negative 1-based to 0-based.
            return seenArray.get(-(token + 1));
        }

        // Positive means a new object
        String typeSignature = getString(token);
        if (typeSignature == null) {
            // a null string means a null instance
            return null;
        }

        return deserialize(typeSignature);
    }

    /**
     * Deserialize an object with the given type signature.
     *
     * @param typeSignature the type signature to deserialize
     * @return the deserialized object
     * @throws SerializationException
     */
    protected abstract Object deserialize(String typeSignature)
            throws com.google.gwt.user.client.rpc.SerializationException;

    /**
     * Get the previously seen object at the given index which must be 1-based.
     *
     * @param index a 1-based index into the seen objects
     *
     * @return the object stored in the seen array at index - 1
     */
    protected final Object getDecodedObject(int index) {
        // index is 1-based
        return seenArray.get(index - 1);
    }

    /**
     * Gets a string out of the string table.
     *
     * @param index the index of the string to get
     * @return the string
     */
    protected abstract String getString(int index);

    /**
     * Set an object in the seen list.
     *
     * @param index a 1-based index into the seen objects
     * @param o the object to remember
     */

    protected final void rememberDecodedObject(int index, Object o) {
        // index is 1-based
        seenArray.set(index - 1, o);
    }

    /**
     * Reserve an entry for an object in the seen list.
     *
     * @return the index to be used in future for the object
     */
    protected final int reserveDecodedObjectIndex() {
        seenArray.add(null);

        // index is 1-based
        return seenArray.size();
    }
}