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

com.hazelcast.internal.memory.impl.EndiannessUtil Maven / Gradle / Ivy

There is a newer version: 3.9.3
Show newest version
/*
 * Copyright (c) 2008-2016, Hazelcast, Inc. All Rights Reserved.
 *
 * 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 com.hazelcast.internal.memory.impl;

import com.hazelcast.internal.memory.ByteAccessStrategy;
import com.hazelcast.internal.memory.GlobalMemoryAccessorRegistry;
import com.hazelcast.internal.memory.MemoryAccessor;

import java.io.DataInput;
import java.io.IOException;
import java.io.UTFDataFormatException;

/**
 * A utility class with methods that read/write multibyte values from/to byte-addressed memory, with
 * explicitly specified endianness. The low-level strategy of reading and writing individual bytes is
 * supplied by an instance of {@link ByteAccessStrategy}.
 */
@SuppressWarnings({"checkstyle:magicnumber", "MagicNumber", "checkstyle:methodcount", "checkstyle:booleanexpressioncomplexity"})
public final class EndiannessUtil {

    /** Accesses bytes in a Java byte array */
    public static final ByteAccessStrategy BYTE_ARRAY_ACCESS = ByteArrayAccessStrategy.INSTANCE;

    /** Accesses bytes in CPU's native address space */
    public static final ByteAccessStrategy NATIVE_ACCESS = GlobalMemoryAccessorRegistry.MEM;

    public static final ByteAccessStrategy CUSTOM_ACCESS = CustomByteAccessStrategy.INSTANCE;

    private EndiannessUtil() {
    }

    public static  char readChar(
            ByteAccessStrategy strategy, R resource, long offset, boolean useBigEndian) {
        return useBigEndian ? readCharB(strategy, resource, offset) : readCharL(strategy, resource, offset);
    }

    public static  char readCharB(ByteAccessStrategy strategy, R resource, long offset) {
        int byte1 = strategy.getByte(resource, offset) & 0xFF;
        int byte0 = strategy.getByte(resource, offset + 1) & 0xFF;
        return (char) ((byte1 << 8) | byte0);
    }

    public static  char readCharL(ByteAccessStrategy strategy, R resource, long offset) {
        int byte1 = strategy.getByte(resource, offset) & 0xFF;
        int byte0 = strategy.getByte(resource, offset + 1) & 0xFF;
        return (char) ((byte0 << 8) | byte1);
    }

    public static  void writeChar(
            ByteAccessStrategy strategy, R resource, long offset, char v, boolean useBigEndian) {
        if (useBigEndian) {
            writeCharB(strategy, resource, offset, v);
        } else {
            writeCharL(strategy, resource, offset, v);
        }
    }

    public static  void writeCharB(ByteAccessStrategy strategy, R resource, long offset, char v) {
        strategy.putByte(resource, offset, (byte) ((v >>> 8) & 0xFF));
        strategy.putByte(resource, offset + 1, (byte) ((v) & 0xFF));
    }

    public static  void writeCharL(ByteAccessStrategy strategy, R resource, long offset, char v) {
        strategy.putByte(resource, offset, (byte) ((v) & 0xFF));
        strategy.putByte(resource, offset + 1, (byte) ((v >>> 8) & 0xFF));
    }

    //////////////////////////////////////////////////////////////////////////////////////////

    public static  short readShort(ByteAccessStrategy strategy, R resource, long offset, boolean useBigEndian) {
        return useBigEndian ? readShortB(strategy, resource, offset) : readShortL(strategy, resource, offset);
    }

    public static  short readShortB(ByteAccessStrategy strategy, R resource, long offset) {
        int byte1 = strategy.getByte(resource, offset) & 0xFF;
        int byte0 = strategy.getByte(resource, offset + 1) & 0xFF;
        return (short) ((byte1 << 8) | byte0);
    }

    public static  short readShortL(ByteAccessStrategy strategy, R resource, long offset) {
        int byte1 = strategy.getByte(resource, offset) & 0xFF;
        int byte0 = strategy.getByte(resource, offset + 1) & 0xFF;
        return (short) ((byte0 << 8) | byte1);
    }

    public static  void writeShort(
            ByteAccessStrategy strategy, R resource, long offset, short v, boolean useBigEndian) {
        if (useBigEndian) {
            writeShortB(strategy, resource, offset, v);
        } else {
            writeShortL(strategy, resource, offset, v);
        }
    }

    public static  void writeShortB(ByteAccessStrategy strategy, R resource, long offset, short v) {
        strategy.putByte(resource, offset, (byte) ((v >>> 8) & 0xFF));
        strategy.putByte(resource, offset + 1, (byte) ((v) & 0xFF));
    }

    public static  void writeShortL(ByteAccessStrategy strategy, R resource, long offset, short v) {
        strategy.putByte(resource, offset, (byte) ((v) & 0xFF));
        strategy.putByte(resource, offset + 1, (byte) ((v >>> 8) & 0xFF));
    }


    //////////////////////////////////////////////////////////////////////////////////////////


    public static  int readInt(ByteAccessStrategy strategy, R resource, long offset, boolean useBigEndian) {
        return useBigEndian ? readIntB(strategy, resource, offset) : readIntL(strategy, resource, offset);
    }

    public static  int readIntB(ByteAccessStrategy strategy, R resource, long offset) {
        int byte3 = (strategy.getByte(resource, offset) & 0xFF) << 24;
        int byte2 = (strategy.getByte(resource, offset + 1) & 0xFF) << 16;
        int byte1 = (strategy.getByte(resource, offset + 2) & 0xFF) << 8;
        int byte0 = strategy.getByte(resource, offset + 3) & 0xFF;
        return byte3 | byte2 | byte1 | byte0;
    }

    public static  int readIntL(ByteAccessStrategy strategy, R resource, long offset) {
        int byte3 = strategy.getByte(resource, offset) & 0xFF;
        int byte2 = (strategy.getByte(resource, offset + 1) & 0xFF) << 8;
        int byte1 = (strategy.getByte(resource, offset + 2) & 0xFF) << 16;
        int byte0 = (strategy.getByte(resource, offset + 3) & 0xFF) << 24;
        return byte3 | byte2 | byte1 | byte0;
    }

    public static  void writeInt(
            ByteAccessStrategy strategy, R resource, long offset, int v, boolean useBigEndian) {
        if (useBigEndian) {
            writeIntB(strategy, resource, offset, v);
        } else {
            writeIntL(strategy, resource, offset, v);
        }
    }

    public static  void writeIntB(ByteAccessStrategy strategy, R resource, long offset, int v) {
        strategy.putByte(resource, offset, (byte) ((v >>> 24) & 0xFF));
        strategy.putByte(resource, offset + 1, (byte) ((v >>> 16) & 0xFF));
        strategy.putByte(resource, offset + 2, (byte) ((v >>> 8) & 0xFF));
        strategy.putByte(resource, offset + 3, (byte) ((v) & 0xFF));
    }

    public static  void writeIntL(ByteAccessStrategy strategy, R resource, long offset, int v) {
        strategy.putByte(resource, offset, (byte) ((v) & 0xFF));
        strategy.putByte(resource, offset + 1, (byte) ((v >>> 8) & 0xFF));
        strategy.putByte(resource, offset + 2, (byte) ((v >>> 16) & 0xFF));
        strategy.putByte(resource, offset + 3, (byte) ((v >>> 24) & 0xFF));
    }


    //////////////////////////////////////////////////////////////////////////////////////////

    public static  float readFloat(ByteAccessStrategy strategy, R resource, long offset, boolean useBigEndian) {
        return useBigEndian ? readFloatB(strategy, resource, offset) : readFloatL(strategy, resource, offset);
    }
    public static  float readFloatB(ByteAccessStrategy strategy, R resource, long offset) {
        return Float.intBitsToFloat(readIntB(strategy, resource, offset));
    }

    public static  float readFloatL(ByteAccessStrategy strategy, R resource, long offset) {
        return Float.intBitsToFloat(readIntL(strategy, resource, offset));
    }

    public static  void writeFloat(
            ByteAccessStrategy strategy, R resource, long offset, float v, boolean useBigEndian) {
        if (useBigEndian) {
            writeFloatB(strategy, resource, offset, v);
        } else {
            writeFloatL(strategy, resource, offset, v);
        }
    }

    public static  void writeFloatB(ByteAccessStrategy strategy, R resource, long offset, float v) {
        writeIntB(strategy, resource, offset, Float.floatToRawIntBits(v));
    }

    public static  void writeFloatL(ByteAccessStrategy strategy, R resource, long offset, float v) {
        writeIntL(strategy, resource, offset, Float.floatToRawIntBits(v));
    }


    //////////////////////////////////////////////////////////////////////////////////////////

    public static  long readLong(ByteAccessStrategy strategy, R resource, long offset, boolean useBigEndian) {
        return useBigEndian ? readLongB(strategy, resource, offset) : readLongL(strategy, resource, offset);
    }

    public static  long readLongB(ByteAccessStrategy strategy, R resource, long offset) {
        long byte7 = (long) strategy.getByte(resource, offset) << 56;
        long byte6 = (long) (strategy.getByte(resource, offset + 1) & 0xFF) << 48;
        long byte5 = (long) (strategy.getByte(resource, offset + 2) & 0xFF) << 40;
        long byte4 = (long) (strategy.getByte(resource, offset + 3) & 0xFF) << 32;
        long byte3 = (long) (strategy.getByte(resource, offset + 4) & 0xFF) << 24;
        long byte2 = (long) (strategy.getByte(resource, offset + 5) & 0xFF) << 16;
        long byte1 = (long) (strategy.getByte(resource, offset + 6) & 0xFF) << 8;
        long byte0 = (long) (strategy.getByte(resource, offset + 7) & 0xFF);
        return byte7 | byte6 | byte5 | byte4 | byte3 | byte2 | byte1 | byte0;
    }

    public static  long readLongL(ByteAccessStrategy strategy, R resource, long offset) {
        long byte7 = (long) (strategy.getByte(resource, offset) & 0xFF);
        long byte6 = (long) (strategy.getByte(resource, offset + 1) & 0xFF) << 8;
        long byte5 = (long) (strategy.getByte(resource, offset + 2) & 0xFF) << 16;
        long byte4 = (long) (strategy.getByte(resource, offset + 3) & 0xFF) << 24;
        long byte3 = (long) (strategy.getByte(resource, offset + 4) & 0xFF) << 32;
        long byte2 = (long) (strategy.getByte(resource, offset + 5) & 0xFF) << 40;
        long byte1 = (long) (strategy.getByte(resource, offset + 6) & 0xFF) << 48;
        long byte0 = (long) (strategy.getByte(resource, offset + 7) & 0xFF) << 56;
        return byte7 | byte6 | byte5 | byte4 | byte3 | byte2 | byte1 | byte0;
    }

    public static  void writeLong(
            ByteAccessStrategy strategy, R resource, long offset, long v, boolean useBigEndian) {
        if (useBigEndian) {
            writeLongB(strategy, resource, offset, v);
        } else {
            writeLongL(strategy, resource, offset, v);
        }
    }

    public static  void writeLongB(ByteAccessStrategy strategy, R resource, long offset, long v) {
        strategy.putByte(resource, offset, (byte) (v >>> 56));
        strategy.putByte(resource, offset + 1, (byte) (v >>> 48));
        strategy.putByte(resource, offset + 2, (byte) (v >>> 40));
        strategy.putByte(resource, offset + 3, (byte) (v >>> 32));
        strategy.putByte(resource, offset + 4, (byte) (v >>> 24));
        strategy.putByte(resource, offset + 5, (byte) (v >>> 16));
        strategy.putByte(resource, offset + 6, (byte) (v >>> 8));
        strategy.putByte(resource, offset + 7, (byte) (v));
    }

    public static  void writeLongL(ByteAccessStrategy strategy, R resource, long offset, long v) {
        strategy.putByte(resource, offset, (byte) (v));
        strategy.putByte(resource, offset + 1, (byte) (v >>> 8));
        strategy.putByte(resource, offset + 2, (byte) (v >>> 16));
        strategy.putByte(resource, offset + 3, (byte) (v >>> 24));
        strategy.putByte(resource, offset + 4, (byte) (v >>> 32));
        strategy.putByte(resource, offset + 5, (byte) (v >>> 40));
        strategy.putByte(resource, offset + 6, (byte) (v >>> 48));
        strategy.putByte(resource, offset + 7, (byte) (v >>> 56));
    }


    //////////////////////////////////////////////////////////////////////////////////////////

    public static  double readDouble(
            ByteAccessStrategy strategy, R resource, long offset, boolean useBigEndian) {
        return useBigEndian ? readDoubleB(strategy, resource, offset) : readDoubleL(strategy, resource, offset);
    }
    public static  double readDoubleB(ByteAccessStrategy strategy, R resource, long offset) {
        return Double.longBitsToDouble(readLongB(strategy, resource, offset));
    }

    public static  double readDoubleL(ByteAccessStrategy strategy, R resource, long offset) {
        return Double.longBitsToDouble(readLongL(strategy, resource, offset));
    }

    public static  void writeDouble(
            ByteAccessStrategy strategy, R resource, long offset, double v, boolean useBigEndian) {
        if (useBigEndian) {
            writeDoubleB(strategy, resource, offset, v);
        } else {
            writeDoubleL(strategy, resource, offset, v);
        }
    }

    public static  void writeDoubleB(
            ByteAccessStrategy memoryAccessStrategy, R resource, long offset, double v) {
        writeLongB(memoryAccessStrategy, resource, offset, Double.doubleToRawLongBits(v));
    }

    public static  void writeDoubleL(
            ByteAccessStrategy memoryAccessStrategy, R resource, long offset, double v) {
        writeLongL(memoryAccessStrategy, resource, offset, Double.doubleToRawLongBits(v));
    }


    //////////////////////////////////////////////////////////////////

    public static  int writeUtf8Char(ByteAccessStrategy strategy, R resource, long pos, int c) {
        if (c <= 0x007F) {
            strategy.putByte(resource, pos, (byte) c);
            return 1;
        } else if (c > 0x07FF) {
            strategy.putByte(resource, pos, (byte) (0xE0 | c >> 12 & 0x0F));
            strategy.putByte(resource, pos + 1, (byte) (0x80 | c >> 6 & 0x3F));
            strategy.putByte(resource, pos + 2, (byte) (0x80 | c & 0x3F));
            return 3;
        } else {
            strategy.putByte(resource, pos, (byte) (0xC0 | c >> 6 & 0x1F));
            strategy.putByte(resource, pos + 1, (byte) (0x80 | c & 0x3F));
            return 2;
        }
    }

    public static char readUtf8Char(DataInput in, byte firstByte) throws IOException {
        int b = firstByte & 0xFF;
        switch (b >> 4) {
            case 0:
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
            case 6:
            case 7:
                return (char) b;
            case 12:
            case 13:
                int first = (b & 0x1F) << 6;
                int second = in.readByte() & 0x3F;
                return (char) (first | second);
            case 14:
                int first2 = (b & 0x0F) << 12;
                int second2 = (in.readByte() & 0x3F) << 6;
                int third2 = in.readByte() & 0x3F;
                return (char) (first2 | second2 | third2);
            default:
                throw new UTFDataFormatException("Malformed byte sequence");
        }
    }

    public static int readUtf8Char(byte[] buffer, int pos, char[] dst, int dstPos) throws IOException {
        int b = buffer[pos] & 0xFF;
        switch (b >> 4) {
            case 0:
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
            case 6:
            case 7:
                dst[dstPos] = (char) b;
                return 1;
            case 12:
            case 13:
                int first = (b & 0x1F) << 6;
                int second = buffer[pos + 1] & 0x3F;
                dst[dstPos] = (char) (first | second);
                return 2;
            case 14:
                int first2 = (b & 0x0F) << 12;
                int second2 = (buffer[pos + 1] & 0x3F) << 6;
                int third2 = buffer[pos + 2] & 0x3F;
                dst[dstPos] = (char) (first2 | second2 | third2);
                return 3;
            default:
                throw new UTFDataFormatException("Malformed byte sequence");
        }
    }
}