uk.co.real_logic.sbe.PrimitiveValue Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sbe-all Show documentation
Show all versions of sbe-all Show documentation
FIX/SBE - OSI layer 6 presentation for encoding and decoding application messages in binary format for low-latency applications.
/*
* Copyright 2013-2024 Real Logic Limited.
*
* 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
*
* https://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 uk.co.real_logic.sbe;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.util.Arrays;
import static java.lang.Double.doubleToLongBits;
import static java.nio.charset.Charset.forName;
import static java.nio.charset.StandardCharsets.US_ASCII;
/**
* Class used to encapsulate values for primitives. Used for nullValue, minValue, maxValue, and constants.
*/
public class PrimitiveValue
{
/**
* Representation type used for the stored value.
*/
public enum Representation
{
/**
* Value is stored in a long value.
*/
LONG,
/**
* Value is stored in a double value.
*/
DOUBLE,
/**
* Value is stored in a byte[].
*/
BYTE_ARRAY
}
/**
* Minimum value representation for a char type.
*/
public static final long MIN_VALUE_CHAR = 0x20;
/**
* Maximum value representation for a char type.
*/
public static final long MAX_VALUE_CHAR = 0x7E;
/**
* Null value representation for a char type.
*/
public static final long NULL_VALUE_CHAR = 0;
/**
* Minimum value representation for a signed 8-bit type.
*/
public static final long MIN_VALUE_INT8 = -127;
/**
* Maximum value representation for a signed 8-bit type.
*/
public static final long MAX_VALUE_INT8 = 127;
/**
* Null value representation for a signed 8-bit type.
*/
public static final long NULL_VALUE_INT8 = -128;
/**
* Minimum value representation for an unsigned 8-bit type.
*/
public static final long MIN_VALUE_UINT8 = 0;
/**
* Maximum value representation for an unsigned 8-bit type.
*/
public static final long MAX_VALUE_UINT8 = 254;
/**
* Null value representation for an unsigned 8-bit type.
*/
public static final long NULL_VALUE_UINT8 = 255;
/**
* Minimum value representation for a signed 16-bit type.
*/
public static final long MIN_VALUE_INT16 = -32767;
/**
* Maximum value representation for a signed 16-bit type.
*/
public static final long MAX_VALUE_INT16 = 32767;
/**
* Null value representation for a signed 16-bit type.
*/
public static final long NULL_VALUE_INT16 = -32768;
/**
* Minimum value representation for an unsigned 16-bit type.
*/
public static final long MIN_VALUE_UINT16 = 0;
/**
* Maximum value representation for an unsigned 16-bit type.
*/
public static final long MAX_VALUE_UINT16 = 65534;
/**
* Null value representation for an unsigned 16-bit type.
*/
public static final long NULL_VALUE_UINT16 = 65535;
/**
* Minimum value representation for a signed 32-bit type.
*/
public static final long MIN_VALUE_INT32 = -2147483647;
/**
* Maximum value representation for a signed 32-bit type.
*/
public static final long MAX_VALUE_INT32 = 2147483647;
/**
* Null value representation for a signed 32-bit type.
*/
public static final long NULL_VALUE_INT32 = -2147483648;
/**
* Minimum value representation for an unsigned 32-bit type.
*/
public static final long MIN_VALUE_UINT32 = 0;
/**
* Maximum value representation for an unsigned 32-bit type.
*/
public static final long MAX_VALUE_UINT32 = 0xFFFF_FFFFL - 1;
/**
* Null value representation for an unsigned 32-bit type.
*/
public static final long NULL_VALUE_UINT32 = 0xFFFF_FFFFL;
/**
* Minimum value representation for a signed 64-bit type.
*/
public static final long MIN_VALUE_INT64 = Long.MIN_VALUE + 1; // (-2 ^ 63) + 1
/**
* Maximum value representation for a signed 64-bit type.
*/
public static final long MAX_VALUE_INT64 = Long.MAX_VALUE; // ( 2 ^ 63) - 1
/**
* Null value representation for a signed 64-bit type.
*/
public static final long NULL_VALUE_INT64 = Long.MIN_VALUE; // (-2 ^ 63)
/**
* Minimum value representation for an unsigned 64-bit type.
*/
public static final long MIN_VALUE_UINT64 = 0;
/**
* Maximum value representation for an unsigned 64-bit type.
*/
public static final BigInteger BI_MAX_VALUE_UINT64 = new BigInteger("18446744073709551614");
/**
* Maximum value representation for an unsigned 64-bit type.
*/
public static final long MAX_VALUE_UINT64 = BI_MAX_VALUE_UINT64.longValue(); // (2 ^ 64) - 2
/**
* Null value representation for an unsigned 64-bit type.
*/
public static final BigInteger BI_NULL_VALUE_UINT64 = new BigInteger("18446744073709551615");
/**
* Null value representation for an unsigned 64-bit type.
*/
public static final long NULL_VALUE_UINT64 = BI_NULL_VALUE_UINT64.longValue(); // (2 ^ 64) - 1
/**
* Maximum value representation for a single precision 32-bit floating point type.
*/
public static final float MIN_VALUE_FLOAT = -Float.MAX_VALUE;
/**
* Maximum value representation for a single precision 32-bit floating point type.
*/
public static final float MAX_VALUE_FLOAT = Float.MAX_VALUE;
/**
* Null value representation for a single precision 32-bit floating point type.
*/
public static final float NULL_VALUE_FLOAT = Float.NaN;
/**
* Minimum value representation for a double precision 64-bit floating point type.
*/
public static final double MIN_VALUE_DOUBLE = -Double.MAX_VALUE;
/**
* Maximum value representation for a double precision 64-bit floating point type.
*/
public static final double MAX_VALUE_DOUBLE = Double.MAX_VALUE;
/**
* Null value representation for a double precision 64-bit floating point type.
*/
public static final double NULL_VALUE_DOUBLE = Double.NaN;
private final Representation representation;
private final long longValue;
private final double doubleValue;
private final byte[] bytesValue;
private final String characterEncoding;
private final int size;
private final byte[] byteArrayValueForLong = new byte[1];
/**
* Construct and fill in value as a long.
*
* @param value in long format.
* @param size of the type in bytes.
*/
public PrimitiveValue(final long value, final int size)
{
representation = Representation.LONG;
longValue = value;
doubleValue = 0.0;
bytesValue = null;
characterEncoding = null;
this.size = size;
}
/**
* Construct and fill in value as a long.
*
* @param value in long format
* @param characterEncoding of the char type.
*/
public PrimitiveValue(final byte value, final String characterEncoding)
{
representation = Representation.LONG;
longValue = value;
doubleValue = 0.0;
bytesValue = null;
this.characterEncoding = characterEncoding;
this.size = 1;
}
/**
* Construct and fill in value as a double.
*
* @param value in double format.
* @param size of the type in bytes.
*/
public PrimitiveValue(final double value, final int size)
{
representation = Representation.DOUBLE;
longValue = 0;
doubleValue = value;
bytesValue = null;
characterEncoding = null;
this.size = size;
}
/**
* Construct and fill in value as a byte array.
*
* @param value as a byte array.
* @param characterEncoding of the characters.
* @param size of string in characters.
*/
public PrimitiveValue(final byte[] value, final String characterEncoding, final int size)
{
representation = Representation.BYTE_ARRAY;
longValue = 0;
doubleValue = 0.0;
bytesValue = value;
this.characterEncoding = characterEncoding;
this.size = size;
}
/**
* Get the {@link Representation} of the value.
*
* @return the {@link Representation} of the value.
*/
public Representation representation()
{
return representation;
}
/**
* Parse constant value string and set representation based on type
*
* @param value expressed as a String.
* @param primitiveType that this is supposed to be.
* @return a new {@link PrimitiveValue} for the value.
* @throws IllegalArgumentException if parsing malformed type
*/
public static PrimitiveValue parse(final String value, final PrimitiveType primitiveType)
{
switch (primitiveType)
{
case CHAR:
if (value.length() > 1)
{
throw new IllegalArgumentException("Constant char value malformed: " + value);
}
return new PrimitiveValue(value.getBytes(US_ASCII)[0], 1);
case INT8:
return new PrimitiveValue(Byte.parseByte(value), 1);
case INT16:
return new PrimitiveValue(Short.parseShort(value), 2);
case INT32:
return new PrimitiveValue(Integer.parseInt(value), 4);
case INT64:
return new PrimitiveValue(Long.parseLong(value), 8);
case UINT8:
return new PrimitiveValue(Short.parseShort(value), 1);
case UINT16:
return new PrimitiveValue(Integer.parseInt(value), 2);
case UINT32:
return new PrimitiveValue(Long.parseLong(value), 4);
case UINT64:
final BigInteger biValue = new BigInteger(value);
if (biValue.compareTo(BI_NULL_VALUE_UINT64) > 0)
{
throw new IllegalArgumentException("Value greater than UINT64 allows: value=" + value);
}
return new PrimitiveValue(biValue.longValue(), 8);
case FLOAT:
return new PrimitiveValue(Float.parseFloat(value), 4);
case DOUBLE:
return new PrimitiveValue(Double.parseDouble(value), 8);
default:
throw new IllegalArgumentException("Unknown PrimitiveType: " + primitiveType);
}
}
/**
* Parse constant value string and set representation based on type
*
* @param value expressed as a String.
* @param primitiveType that this is supposed to be.
* @param characterEncoding of the constant value.
* @return a new {@link PrimitiveValue} for the value.
* @throws IllegalArgumentException if parsing malformed type
*/
public static PrimitiveValue parse(
final String value, final PrimitiveType primitiveType, final String characterEncoding)
{
if (PrimitiveType.CHAR != primitiveType)
{
throw new IllegalArgumentException("primitiveType must be char: " + primitiveType);
}
if (value.length() > 1)
{
throw new IllegalArgumentException("Constant char value malformed: " + value);
}
return new PrimitiveValue(value.getBytes(forName(characterEncoding))[0], characterEncoding);
}
/**
* Parse constant value string and set representation based on type, length, and characterEncoding
*
* @param value expressed as a String.
* @param length of the type.
* @param characterEncoding of the String.
* @return a new {@link PrimitiveValue} for the value.
* @throws IllegalArgumentException if parsing malformed type.
*/
public static PrimitiveValue parse(
final String value, final int length, final String characterEncoding)
{
if (value.length() > length)
{
throw new IllegalStateException("value.length=" + value.length() + " greater than length=" + length);
}
byte[] bytes = value.getBytes(forName(characterEncoding));
if (bytes.length < length)
{
bytes = Arrays.copyOf(bytes, length);
}
return new PrimitiveValue(bytes, characterEncoding, length);
}
/**
* Return long value for this PrimitiveValue.
*
* @return value expressed as a long.
* @throws IllegalStateException if not a long value representation.
*/
public long longValue()
{
if (representation != Representation.LONG)
{
throw new IllegalStateException(
"Not a long representation: representation=" + representation + " value=" + this);
}
return longValue;
}
/**
* Return double value for this PrimitiveValue.
*
* @return value expressed as a double.
* @throws IllegalStateException if not a double value representation.
*/
public double doubleValue()
{
if (representation != Representation.DOUBLE)
{
throw new IllegalStateException(
"Not a double representation: representation=" + representation + " value=" + this);
}
return doubleValue;
}
/**
* Return byte array value for this PrimitiveValue.
*
* @return value expressed as a byte array.
* @throws IllegalStateException if not a byte array value representation.
*/
public byte[] byteArrayValue()
{
if (representation != Representation.BYTE_ARRAY)
{
throw new IllegalStateException(
"Not a byte[] representation: representation=" + representation + " value=" + this);
}
return bytesValue;
}
/**
* Return byte array value for this PrimitiveValue given a particular type
*
* @param type of this value.
* @return value expressed as a byte array.
* @throws IllegalStateException if not a byte array value representation.
*/
public byte[] byteArrayValue(final PrimitiveType type)
{
if (representation == Representation.BYTE_ARRAY)
{
return bytesValue;
}
else if (representation == Representation.LONG && size == 1 && type == PrimitiveType.CHAR)
{
byteArrayValueForLong[0] = (byte)longValue;
return byteArrayValueForLong;
}
throw new IllegalStateException("PrimitiveValue is not a byte[] representation");
}
/**
* Return encodedLength for this PrimitiveValue for serialization purposes.
*
* @return encodedLength for serialization.
*/
public int size()
{
return size;
}
/**
* The character encoding of the byte array representation.
*
* @return the character encoding of te byte array representation.
*/
public String characterEncoding()
{
return characterEncoding;
}
/**
* Return String value representation of this object.
*
* @return String representing object value.
*/
public String toString()
{
if (Representation.LONG == representation)
{
return Long.toString(longValue);
}
else if (Representation.DOUBLE == representation)
{
return Double.toString(doubleValue);
}
else if (Representation.BYTE_ARRAY == representation)
{
try
{
return null == characterEncoding ? new String(bytesValue) : new String(bytesValue, characterEncoding);
}
catch (final UnsupportedEncodingException ex)
{
throw new IllegalStateException(ex);
}
}
else
{
throw new IllegalStateException("Unsupported Representation: " + representation);
}
}
/**
* Determine if two values are equivalent.
*
* @param value to compare this value with.
* @return equivalence of values.
*/
public boolean equals(final Object value)
{
if (value instanceof PrimitiveValue)
{
final PrimitiveValue rhs = (PrimitiveValue)value;
if (representation == rhs.representation)
{
switch (representation)
{
case LONG:
return longValue == rhs.longValue;
case DOUBLE:
return doubleToLongBits(doubleValue) == doubleToLongBits(rhs.doubleValue);
case BYTE_ARRAY:
return Arrays.equals(bytesValue, rhs.bytesValue);
}
}
}
return false;
}
/**
* Return hashCode for value. This is the underlying representations hashCode for the value.
*
* @return int value of the hashCode.
*/
public int hashCode()
{
final long bits;
switch (representation)
{
case LONG:
bits = longValue;
break;
case DOUBLE:
bits = doubleToLongBits(doubleValue);
break;
case BYTE_ARRAY:
return Arrays.hashCode(bytesValue);
default:
throw new IllegalStateException("Unrecognised representation: " + representation);
}
return (int)(bits ^ (bits >>> 32));
}
}