/******************************************************************************* * Copyright © 2011, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * *******************************************************************************/ package org.eclipse.edt.runtime.java.eglx.lang; import java.math.BigDecimal; import java.math.BigInteger; import org.eclipse.edt.javart.AnyBoxedObject; import org.eclipse.edt.javart.Constants; import org.eclipse.edt.javart.messages.Message; import org.eclipse.edt.javart.util.NumericUtil; import eglx.lang.*; public class EBytes extends AnyBoxedObject<byte[]> { private static final long serialVersionUID = Constants.SERIAL_VERSION_UID; private int maxLength; public int getLength() { return maxLength; } private EBytes(byte[] value) { super(value); maxLength = -1; } private EBytes(byte[] value, int length) { super(value); maxLength = length; } public static EBytes ezeBox(byte[] value) { return new EBytes(value); } public static EBytes ezeBox(byte[] value, int length) { return new EBytes(value, length); } public static byte[] ezeCast(Object value, Integer... args) throws AnyException { return (byte[]) EAny.ezeCast(value, "asBytes", EBytes.class, new Class[] { Integer[].class }, args); } public static boolean ezeIsa(Object value, Integer... length) { boolean isa = (value instanceof EBytes && ((EBytes) value).ezeUnbox() != null); if (isa) { if (length.length != 0) isa = ((EBytes) value).getLength() == length[0]; } else { isa = value instanceof byte[]; } return isa; } public static byte[] ezeAssignToLonger( byte[] target, int targetLength, byte[] source ) { if ( source == null ) { return null; } if ( target == null ) { target = new byte[ targetLength ]; System.arraycopy( source, 0, target, 0, source.length ); } else { System.arraycopy( source, 0, target, 0, source.length ); } return target; } /** * Called by the code generated from "bytes(x) = any". */ public static byte[] ezeAssignFromAny( byte[] target, int targetLength, byte[] source ) { if ( source == null ) { return null; } if ( target == null ) { target = new byte[ targetLength ]; } System.arraycopy( source, 0, target, 0, Math.min( targetLength, source.length ) ); return target; } /** * Called by the code generated from "bytes = any". */ public static byte[] ezeAssignFromAny( byte[] target, byte[] source ) { if ( source == null ) { return null; } if ( target == null ) { target = new byte[ source.length ]; } System.arraycopy( source, 0, target, 0, Math.min( target.length, source.length ) ); return target; } public static byte[] asBytes( Short value, Integer... length ) { if ( length.length > 0 && length[ 0 ] != 2 ) { throwTypeCastException( "smallint", value, length ); } if ( value == null ) { return null; } short bValue = value; byte[] bytes = new byte[ 2 ]; bytes[ 0 ] = (byte)(bValue >> 8); bytes[ 1 ] = (byte)bValue; return bytes; } public static byte[] asBytes(ESmallint value, Integer... length) { if (value == null) return null; return asBytes(value.ezeUnbox(), length); } public static byte[] asBytes( Integer value, Integer... length ) { if ( length.length > 0 && length[ 0 ] != 4 ) { throwTypeCastException( "int", value, length ); } if ( value == null ) { return null; } int bValue = value; byte[] bytes = new byte[ 4 ]; bytes[ 0 ] = (byte)(bValue >> 24); bytes[ 1 ] = (byte)(bValue >> 16); bytes[ 2 ] = (byte)(bValue >> 8); bytes[ 3 ] = (byte)bValue; return bytes; } public static byte[] asBytes(EInt value, Integer... length) { if (value == null) return null; return asBytes(value.ezeUnbox(), length); } public static byte[] asBytes( Long value, Integer... length ) { if ( length.length > 0 && length[ 0 ] != 8 ) { throwTypeCastException( "bigint", value, length ); } if ( value == null ) { return null; } long bValue = value; byte[] bytes = new byte[ 8 ]; bytes[ 0 ] = (byte)(bValue >> 56); bytes[ 1 ] = (byte)(bValue >> 48); bytes[ 2 ] = (byte)(bValue >> 40); bytes[ 3 ] = (byte)(bValue >> 32); bytes[ 4 ] = (byte)(bValue >> 24); bytes[ 5 ] = (byte)(bValue >> 16); bytes[ 6 ] = (byte)(bValue >> 8); bytes[ 7 ] = (byte)bValue; return bytes; } public static byte[] asBytes(EBigint value, Integer... length) { if (value == null) return null; return asBytes(value.ezeUnbox(), length); } public static byte[] asBytes( Float value, Integer... length ) { if ( length.length > 0 && length[ 0 ] != 4 ) { throwTypeCastException( "smallfloat", value, length ); } if ( value == null ) { return null; } int bValue = Float.floatToIntBits( value ); byte[] bytes = new byte[ 4 ]; bytes[ 0 ] = (byte)(bValue >> 24); bytes[ 1 ] = (byte)(bValue >> 16); bytes[ 2 ] = (byte)(bValue >> 8); bytes[ 3 ] = (byte)bValue; return bytes; } public static byte[] asBytes(ESmallfloat value, Integer... length) { if (value == null) return null; return asBytes(value.ezeUnbox(), length); } public static byte[] asBytes( Double value, Integer... length ) { if ( length.length > 0 && length[ 0 ] != 8 ) { throwTypeCastException( "float", value, length ); } if ( value == null ) { return null; } long bValue = Double.doubleToRawLongBits( value ); byte[] bytes = new byte[ 8 ]; bytes[ 0 ] = (byte)(bValue >> 56); bytes[ 1 ] = (byte)(bValue >> 48); bytes[ 2 ] = (byte)(bValue >> 40); bytes[ 3 ] = (byte)(bValue >> 32); bytes[ 4 ] = (byte)(bValue >> 24); bytes[ 5 ] = (byte)(bValue >> 16); bytes[ 6 ] = (byte)(bValue >> 8); bytes[ 7 ] = (byte)bValue; return bytes; } public static byte[] asBytes(EFloat value, Integer... length) { if (value == null) return null; return asBytes(value.ezeUnbox(), length); } public static byte[] asBytes(BigDecimal value, Integer... attrs) { if (value == null) return null; // attrs[0] is the bytes's length // attrs[1] is the decimal's precision if ( attrs.length > 1 && attrs[ 0 ] != attrs[ 1 ] / 2 + 1 ) { throwTypeCastException( "decimal(" + attrs[ 1 ] + ')', value, attrs ); } return asBytes(value.unscaledValue(), attrs); } public static byte[] asBytes(EDecimal value, Integer... length) { if (value == null) return null; return asBytes(value.ezeUnbox(), length.length > 0 ? new Integer[] { length[ 0 ], value.getPrecision() } : length ); } public static byte[] asBytes(BigInteger value, Integer... length) { if (value == null) return null; int digits = digits( value ); byte[] bytes = new byte[ digits / 2 + 1 ]; if ( length.length > 0 && length[ 0 ] != bytes.length ) { throwTypeCastException( "decimal(" + digits + ')', value, length ); } if ( digits < 18 ) { NumericUtil.toDecimal( value.longValue(), bytes, 0, digits, bytes.length, (byte)0x0C ); } else { NumericUtil.toDecimal( value, bytes, 0, digits, bytes.length, (byte)0x0C ); } return bytes; } /** * @return the number of digits in the given BigInteger. */ private static int digits( BigInteger bi ) { int bitLength = bi.bitLength(); if ( bitLength < 4 ) { return 1; } else if ( bitLength < 63 ) { double log10 = Math.log10( Math.abs( bi.longValue() ) ); int digits = (int)Math.ceil( log10 ); if ( log10 == (int)log10 ) { // Add one for powers of 10. digits++; } return digits; } else { return new BigDecimal( bi ).precision(); } } public static byte[] asBytes(Number value, Integer... length) { if (value == null) return null; if ( value instanceof Integer ) { return asBytes( (Integer)value, length ); } else if ( value instanceof Short ) { return asBytes( (Short)value, length ); } else if ( value instanceof Long ) { return asBytes( (Long)value, length ); } else if ( value instanceof BigInteger ) { return asBytes( (BigInteger)value, length ); } else if ( value instanceof BigDecimal ) { return asBytes( (BigDecimal)value, length ); } else if ( value instanceof Double ) { return asBytes( (Double)value, length ); } else if ( value instanceof Float ) { return asBytes( (Float)value, length ); } throwTypeCastException( "number", value, length ); return null; // This is dead code but necessary for the method to compile. } public static byte[] asBytes(eglx.lang.ENumber value, Integer... length) { if (value == null) return null; return asBytes(value.ezeUnbox(), length); } public static byte[] asBytes(byte[] value, Integer... length) { if (value == null) return null; if (length.length != 0 && value.length > length[0]) { byte[] bytes = new byte[length[0]]; if (bytes.length > 0) { for (int i = 0; i < bytes.length; i++) bytes[i] = value[i]; } return bytes; } return value; } public static byte[] asBytes(EBytes value, Integer... length) { if (value == null) return null; return asBytes(value.ezeUnbox(), length); } private static void throwTypeCastException( String actualTypeName, Object value, Integer... length ) throws TypeCastException { TypeCastException tcx = new TypeCastException(); if ( length.length > 0 ) { tcx.castToName = "bytes(" + length[ 0 ] + ')'; } else { tcx.castToName = "bytes"; } tcx.actualTypeName = actualTypeName; throw tcx.fillInMessage( Message.CONVERSION_ERROR, value, tcx.actualTypeName, tcx.castToName ); } public static byte[] plus(byte[] op1, byte[] op2) throws AnyException { return concat(op1, op2); } public static byte[] concat(byte[] op1, byte[] op2) throws AnyException { int op1Length = (op1 == null ? 0 : op1.length); int op2Length = (op2 == null ? 0 : op2.length); byte[] bytes = new byte[ op1Length + op2Length ]; int i = 0; while ( i < op1Length ) { bytes[i] = op1[i]; i++; } for ( int j = 0; j < op2Length; j++ ) { bytes[i] = op2[j]; i++; } return bytes; } public static byte[] concatNull(byte[] op1, byte[] op2) { if (op1 == null || op2 == null) return null; byte[] bytes = new byte[op1.length + op2.length]; int i = 0; while (i < op1.length) { bytes[i] = op1[i]; i++; } for ( int j = 0; j < op2.length; j++ ) { bytes[i] = op2[j]; i++; } return bytes; } public static boolean equals(byte[] op1, byte[] op2) throws AnyException { if (op1 == op2) return true; if (op1 == null || op2 == null || op1.length != op2.length) return false; for ( int i = 0; i < op1.length; i++ ) { if ( op1[i] != op2[i] ) { return false; } } return true; } public static boolean notEquals(byte[] op1, byte[] op2) throws AnyException { return !equals(op1, op2); } public static int compareTo( byte[] op1, byte[] op2 ) throws AnyException { if ( op1.length == op2.length ) { for ( int i = 0; i < op1.length; i++ ) { if ( op1[i] != op2[i] ) { return (op1[i] & 0xFF) < (op2[i] & 0xFF) ? -1 : 1; } } } else if ( op1.length > op2.length ) { int i = 0; while ( i < op2.length ) { if ( op1[i] != op2[i] ) { return (op1[i] & 0xFF) < (op2[i] & 0xFF) ? -1 : 1; } i++; } while ( i < op1.length ) { if ( op1[i] != 0 ) { return 1; } i++; } } else { int i = 0; while ( i < op1.length ) { if ( op1[i] != op2[i] ) { return (op1[i] & 0xFF) < (op2[i] & 0xFF) ? -1 : 1; } i++; } while ( i < op2.length ) { if ( op2[i] != 0 ) { return -1; } i++; } } return 0; } public static byte[] substring(byte[] value, int start, int end) throws AnyException { if (value == null) { throw new NullValueException().fillInMessage(Message.NULL_NOT_ALLOWED); } int max = value.length; if (start < 1 || start > max) { InvalidIndexException ex = new InvalidIndexException(); ex.index = start; throw ex.fillInMessage(Message.INVALID_SUBSTRING_INDEX, start, end); } else if (end < start || end < 1 || end > max) { InvalidIndexException ex = new InvalidIndexException(); ex.index = end; throw ex.fillInMessage(Message.INVALID_SUBSTRING_INDEX, start, end); } byte[] bytes = new byte[end - start + 1]; if (bytes.length > 0) { for (int i = 0; i < bytes.length; i++) bytes[i] = value[i + start - 1]; } return bytes; } /** * Returns the length of the bytes value. */ public static int length(byte[] source) { return source.length; } }