Java tutorial
/* * Copyright (C) 1995-2016Dal Solutions, Inc. * All Rights Reserved * Inquire at License@dal-solutions.com */ package com.dal.vv.type; import com.dal.a.type.Size; import java.io.UnsupportedEncodingException; import java.util.Arrays; import java.util.List; import com.dal.a.type.ValueType; import com.dal.a.model.dictionary.Value; import com.dal.vv.cfg.ConfigurationFactory; import com.dal.vv.cfg.def.VoxelSettings; import org.apache.commons.configuration.Configuration; /** * * @author Dan Adams */ abstract class AbstractValue implements Value { static final Configuration cfg = ConfigurationFactory.getConfiguration(); protected final Size size; protected byte[] value; public abstract ValueType getType(); AbstractValue(Size bits) { size = bits; value = new byte[size.getBytes()]; } AbstractValue(String sequence) { String charSet = cfg.getString(VoxelSettings.CHAR_SET); try { value = sequence.getBytes(charSet); size = Size.variable; } catch (UnsupportedEncodingException ex) { throw new RuntimeException("Fatal error mapping " + charSet, ex); } } AbstractValue(List<? extends Value> list) { size = Size.variable; } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final AbstractValue other = (AbstractValue) obj; return Arrays.equals(this.value, other.value); } @Override public int hashCode() { int hash = 7; hash = 83 * hash + Arrays.hashCode(this.value); return hash; } @Override public String toString() { try { return asString(); } catch (InvalidConversionException | OverflowException x) { } return null; } @Override public boolean asBoolean() { for (byte b : value) { if (0 < b) { return true; } } return false; } @Override public byte asByte() { byte result = 0; switch (size) { case variable: case sixtyfour: case thirtytwo: case sixteen: throw new OverflowException("Data loss mapping to 8 bits"); case eight: case four: case one: result += value[0]; } return result; } @Override public double asDouble() { return Double.longBitsToDouble(asLong()); } @Override public float asFloat() { return Float.intBitsToFloat(asInt()); } @Override @SuppressWarnings("fallthrough") public int asInt() { int result = 0; switch (size) { case variable: case sixtyfour: throw new OverflowException("Data loss mapping to 32 bits"); case thirtytwo: result += ((int) (0xFF & value[3]) << 24); result += ((int) (0xFF & value[2]) << 16); case sixteen: result += ((int) (0xFF & value[1]) << 8); case eight: case four: case one: result += ((int) (0xFF & value[0])); } return result; } @Override @SuppressWarnings("fallthrough") public long asLong() { long result = 0l; switch (size) { case variable: throw new OverflowException("Data loss mapping to 64 bits"); case sixtyfour: result += ((long) (0xFF & value[4]) << 32); result += ((long) (0xFF & value[5]) << 40); result += ((long) (0xFF & value[6]) << 48); result += ((long) (0xFF & value[7]) << 56); case thirtytwo: result += ((long) (0xFF & value[3]) << 24); result += ((long) (0xFF & value[2]) << 16); case sixteen: result += ((long) (0xFF & value[1]) << 8); case eight: case four: case one: result += (long) (0xFF & value[0]); } return result; } @Override @SuppressWarnings("fallthrough") public short asShort() { short result = 0; switch (size) { case variable: case sixtyfour: case thirtytwo: throw new OverflowException("Data loss mapping to 16 bits"); case sixteen: result += ((short) 0xFF & value[1]) << 8; case eight: case four: case one: result += ((short) 0xFF & value[0]); } return result; } @Override public Value clear() { for (int index = 0; index < value.length; ++index) { value[index] = 0; } return this; } @Override public byte[] getBytes() { return Arrays.copyOf(value, value.length); } @Override public int getByteSize() { return size.getBytes(); } @Override public int getBitSize() { return size.getBits(); } @Override public Value load(byte data) { return loadNumber(data); } @Override public Value load(boolean data) { clear(); if (Size.variable == size) { value = new byte[1]; } value[0] = (data ? (byte) 1 : 0); return this; } @Override public Value load(short data) { return loadNumber(data); } @Override public Value load(int data) { return loadNumber(data); } @Override public Value load(byte[] data) { clear(); int dataLength = data.length; int valueLength = size.getBytes(); if (0 != valueLength && dataLength > valueLength) { throw new OverflowException("Unable to load byte array, potential data loss at byte " + valueLength); } if (Size.variable == size) { value = new byte[dataLength]; } for (int index = 0; index < dataLength; ++index) { value[index] = data[index]; } return this; } @Override public Value load(long data) { Value result; result = loadNumber(data); return result; } @Override public Value load(float data) { return load(Float.floatToRawIntBits(data)); } @Override public Value load(double data) { return load(Double.doubleToRawLongBits(data)); } @Override public Value load(String data) throws InvalidConversionException { Value result = null; try { result = load(data.getBytes(cfg.getString(VoxelSettings.CHAR_SET))); } catch (UnsupportedEncodingException x) { throw new InvalidConversionException("Failure encoding String data", x); } return result; } @SuppressWarnings("fallthrough") private Value loadNumber(long data) { clear(); int actualSize = 64 - Long.numberOfLeadingZeros(Math.abs(data)) - (data < 0 ? 1 : 0); int availableBits = size.getBits(); if (actualSize > availableBits) { if (Size.variable == size) { value = new byte[(1 + actualSize) / 8]; } else { throw new OverflowException("Unable to load[" + data + "] " + actualSize + " bits only " + availableBits + " available"); } } int avail = size.getBytes(); if (Size.variable == size) { avail = value.length; } switch (avail) { case 8: value[7] = (byte) ((data >> 56) & 0xFF); value[6] = (byte) ((data >> 48) & 0xFF); value[5] = (byte) ((data >> 40) & 0xFF); value[4] = (byte) ((data >> 32) & 0xFF); case 7: case 6: case 5: case 4: value[3] = (byte) ((data >> 24) & 0xFF); value[2] = (byte) ((data >> 16) & 0xFF); case 3: case 2: value[1] = (byte) ((data >> 8) & 0xFF); case 1: value[0] = (byte) (data & 0xFF); default: } return this; } protected static byte[] longBytes(long data) { byte[] result = new byte[8]; result[7] = (byte) ((data >> 56) & 0xFF); result[6] = (byte) ((data >> 48) & 0xFF); result[5] = (byte) ((data >> 40) & 0xFF); result[4] = (byte) ((data >> 32) & 0xFF); result[3] = (byte) ((data >> 24) & 0xFF); result[2] = (byte) ((data >> 16) & 0xFF); result[1] = (byte) ((data >> 8) & 0xFF); result[0] = (byte) (data & 0xFF); return result; } protected static byte[] intBytes(long data) { byte[] result = new byte[4]; result[3] = (byte) ((data >> 24) & 0xFF); result[2] = (byte) ((data >> 16) & 0xFF); result[1] = (byte) ((data >> 8) & 0xFF); result[0] = (byte) (data & 0xFF); return result; } protected static byte[] shortBytes(short data) { byte[] result = new byte[2]; result[1] = (byte) ((data >> 8) & 0xFF); result[0] = (byte) (data & 0xFF); return result; } }