org.apache.datasketches.common.ArrayOfNumbersSerDe Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of datasketches-java Show documentation
Show all versions of datasketches-java Show documentation
Core sketch algorithms used alone and by other Java repositories in the DataSketches library.
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.datasketches.common;
import static org.apache.datasketches.common.ByteArrayUtil.copyBytes;
import static org.apache.datasketches.common.ByteArrayUtil.putDoubleLE;
import static org.apache.datasketches.common.ByteArrayUtil.putFloatLE;
import static org.apache.datasketches.common.ByteArrayUtil.putIntLE;
import static org.apache.datasketches.common.ByteArrayUtil.putLongLE;
import static org.apache.datasketches.common.ByteArrayUtil.putShortLE;
import java.util.Objects;
import org.apache.datasketches.memory.Memory;
/**
* Methods of serializing and deserializing arrays of the object version of primitive types of
* Number. The array can be a mix of primitive object types.
*
* This class serializes numbers with a leading byte (ASCII character) indicating the type.
* The class keeps the values byte aligned, even though only 3 bits are strictly necessary to
* encode one of the 6 different primitives with object types that extend Number.
*
* Classes handled are: Long
, Integer
, Short
,
* Byte
, Double
, and Float
.
*
* @author Jon Malkin
*/
public class ArrayOfNumbersSerDe extends ArrayOfItemsSerDe {
// values selected to enable backwards compatibility
private static final byte LONG_INDICATOR = 12;
private static final byte INTEGER_INDICATOR = 9;
private static final byte SHORT_INDICATOR = 3;
private static final byte BYTE_INDICATOR = 2;
private static final byte DOUBLE_INDICATOR = 4;
private static final byte FLOAT_INDICATOR = 6;
@Override
public byte[] serializeToByteArray(final Number item) {
Objects.requireNonNull(item, "Item must not be null");
final byte[] byteArr;
if (item instanceof Long) {
byteArr = new byte[Long.BYTES + 1];
byteArr[0] = LONG_INDICATOR;
putLongLE(byteArr, 1, (Long)item);
} else if (item instanceof Integer) {
byteArr = new byte[Integer.BYTES + 1];
byteArr[0] = INTEGER_INDICATOR;
putIntLE(byteArr, 1, (Integer)item);
} else if (item instanceof Short) {
byteArr = new byte[Short.BYTES + 1];
byteArr[0] = SHORT_INDICATOR;
putShortLE(byteArr, 1, (Short)item);
} else if (item instanceof Byte) {
byteArr = new byte[Byte.BYTES + 1];
byteArr[0] = BYTE_INDICATOR;
byteArr[1] = (byte)item;
} else if (item instanceof Double) {
byteArr = new byte[Double.BYTES + 1];
byteArr[0] = DOUBLE_INDICATOR;
putDoubleLE(byteArr, 1, (Double)item);
} else if (item instanceof Float) {
byteArr = new byte[Float.BYTES + 1];
byteArr[0] = FLOAT_INDICATOR;
putFloatLE(byteArr, 1, (Float)item);
} else {
throw new SketchesArgumentException(
"Item must be one of: Long, Integer, Short, Byte, Double, Float. "
+ "item: " + item.toString());
}
return byteArr;
}
@Override
public byte[] serializeToByteArray(final Number[] items) {
Objects.requireNonNull(items, "Items must not be null");
final int numItems = items.length;
int totalBytes = 0;
final byte[][] serialized2DArray = new byte[numItems][];
for (int i = 0; i < numItems; i++) {
serialized2DArray[i] = serializeToByteArray(items[i]);
totalBytes += serialized2DArray[i].length;
}
final byte[] out = new byte[totalBytes];
int offset = 0;
for (int i = 0; i < numItems; i++) {
final int itemLen = serialized2DArray[i].length;
copyBytes(serialized2DArray[i], 0, out, offset, itemLen);
offset += itemLen;
}
return out;
}
@Override
@Deprecated
public Number[] deserializeFromMemory(final Memory mem, final int numItems) {
return deserializeFromMemory(mem, 0, numItems);
}
@Override
public Number[] deserializeFromMemory(final Memory mem, final long offsetBytes, final int numItems) {
Objects.requireNonNull(mem, "Memory must not be null");
if (numItems <= 0) { return new Number[0]; }
final Number[] array = new Number[numItems];
long offset = offsetBytes;
for (int i = 0; i < numItems; i++) {
Util.checkBounds(offset, Byte.BYTES, mem.getCapacity());
final byte typeId = mem.getByte(offset);
offset += Byte.BYTES;
switch (typeId) {
case LONG_INDICATOR:
Util.checkBounds(offset, Long.BYTES, mem.getCapacity());
array[i] = mem.getLong(offset);
offset += Long.BYTES;
break;
case INTEGER_INDICATOR:
Util.checkBounds(offset, Integer.BYTES, mem.getCapacity());
array[i] = mem.getInt(offset);
offset += Integer.BYTES;
break;
case SHORT_INDICATOR:
Util.checkBounds(offset, Short.BYTES, mem.getCapacity());
array[i] = mem.getShort(offset);
offset += Short.BYTES;
break;
case BYTE_INDICATOR:
Util.checkBounds(offset, Byte.BYTES, mem.getCapacity());
array[i] = mem.getByte(offset);
offset += Byte.BYTES;
break;
case DOUBLE_INDICATOR:
Util.checkBounds(offset, Double.BYTES, mem.getCapacity());
array[i] = mem.getDouble(offset);
offset += Double.BYTES;
break;
case FLOAT_INDICATOR:
Util.checkBounds(offset, Float.BYTES, mem.getCapacity());
array[i] = mem.getFloat(offset);
offset += Float.BYTES;
break;
default:
throw new SketchesArgumentException(
"Item must be one of: Long, Integer, Short, Byte, Double, Float. "
+ "index: " + i + ", typeId: " + typeId);
}
}
return array;
}
@Override
public int sizeOf(final Number item) {
Objects.requireNonNull(item, "Item must not be null");
if ( item instanceof Long) { return Byte.BYTES + Long.BYTES; }
else if ( item instanceof Integer) { return Byte.BYTES + Integer.BYTES; }
else if ( item instanceof Short) { return Byte.BYTES + Short.BYTES; }
else if ( item instanceof Byte) { return Byte.BYTES + Byte.BYTES; }
else if ( item instanceof Double) { return Byte.BYTES + Double.BYTES; }
else if ( item instanceof Float) { return Byte.BYTES + Float.BYTES; }
else { throw new SketchesArgumentException(
"Item must be one of: Long, Integer, Short, Byte, Double, Float. "
+ "item: " + item.toString()); }
}
@Override
public int sizeOf(final Number[] items) {
Objects.requireNonNull(items, "Items must not be null");
int totalBytes = 0;
for (final Number item : items) {
totalBytes += sizeOf(item);
}
return totalBytes;
}
@Override
public int sizeOf(final Memory mem, final long offsetBytes, final int numItems) {
Objects.requireNonNull(mem, "Memory must not be null");
long offset = offsetBytes;
for (int i = 0; i < numItems; i++) {
Util.checkBounds(offset, Byte.BYTES, mem.getCapacity());
final byte typeId = mem.getByte(offset);
offset += Byte.BYTES;
switch (typeId) {
case LONG_INDICATOR:
Util.checkBounds(offset, Long.BYTES, mem.getCapacity());
offset += Long.BYTES;
break;
case INTEGER_INDICATOR:
Util.checkBounds(offset, Integer.BYTES, mem.getCapacity());
offset += Integer.BYTES;
break;
case SHORT_INDICATOR:
Util.checkBounds(offset, Short.BYTES, mem.getCapacity());
offset += Short.BYTES;
break;
case BYTE_INDICATOR:
Util.checkBounds(offset, Byte.BYTES, mem.getCapacity());
offset += Byte.BYTES;
break;
case DOUBLE_INDICATOR:
Util.checkBounds(offset, Double.BYTES, mem.getCapacity());
offset += Double.BYTES;
break;
case FLOAT_INDICATOR:
Util.checkBounds(offset, Float.BYTES, mem.getCapacity());
offset += Float.BYTES;
break;
default:
throw new SketchesArgumentException(
"Item must be one of: Long, Integer, Short, Byte, Double, Float. "
+ "index: " + i + ", typeId: " + typeId);
}
}
return (int)(offset - offsetBytes);
}
@Override
public String toString(final Number item) {
if (item == null) { return "null"; }
return item.toString();
}
@Override
public Class getClassOfT() { return Number.class; }
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy