/** Override default prototype construct with value implementation. */ @Override public Class<?> getVarArgsComponentType() { return Types.arrayElementType(getVarArgsType()); }
/** Repeat the contents of an array a number of times. * @param arr the array object to repeat * @param times number of repetitions * @return a new array instance with repeated contents */ public static Object repeat(Object arr, int times) { Class<?> toType = Types.arrayElementType(arr.getClass()); if ( times < 1 ) return Array.newInstance(toType, 0); int[] dims = dimensions(arr); int length = dims[0]; dims[0] *= times; int i = 0, total = dims[0]; Object toArray = Array.newInstance(toType, dims); while ( i < total ) { System.arraycopy(arr, 0, toArray, i, length); i += length; } return toArray; }
/** Slice the supplied array for range and step. * @param arr to slice * @param from start index inclusive * @param to to index exclusive * @param step size of step or 0 if no step * @return a new array instance sliced */ public static Object slice(Object arr, int from, int to, int step) { Class<?> toType = Types.arrayElementType(arr.getClass()); int length = Array.getLength(arr); if ( to > length ) to = length; if ( 0 > from ) from = 0; length = to - from; if ( 0 >= length ) return Array.newInstance(toType, 0); if ( step == 0 || step == 1 ) { Object toArray = Array.newInstance(toType, length); System.arraycopy(arr, from, toArray, 0, length); return toArray; } Object[] tmp = new Object[(int)Math.ceil((0.0+length)/Math.abs(step))]; for ( int i = 0, j = 0; i < length; i++ ) if ( i % step == 0 ) tmp[j++] = Array.get(arr, step < 0 ? length-1-i : i+from); Object toArray = Array.newInstance(toType, tmp.length); copy(toType, toArray, (Object)tmp); return toArray; }
/** Get object from array or list at index. * @param array to retrieve from * @param index of the element to retrieve * @return Array.get for array or List.get for list * @throws UtilTargetError wrapped Index out of bounds */ public static Object getIndex(Object array, int index) throws UtilTargetError { Interpreter.debug("getIndex: ", array, ", index=", index); try { if ( array instanceof List ) return ((List<?>) array).get(index); Object val = Array.get(array, index); return Primitive.wrap( val, Types.arrayElementType(array.getClass()) ); } catch( IndexOutOfBoundsException e1 ) { int len = array instanceof List ? ((List<?>) array).size() : Array.getLength(array); throw new UtilTargetError("Index " + index + " out-of-bounds for length " + len, e1); } }
/** Fill boxed numeric types with default numbers instead of nulls. * @param arr the array to fill. */ private void arrayFillDefaultValue(Object arr) { if (null == arr) return; Class<?> clas = arr.getClass(); Class<?> comp = Types.arrayElementType(clas); if ( !comp.isPrimitive() ) if ( Types.arrayDimensions(clas) > 1 ) for ( int i = 0; i < Array.getLength(arr); i++ ) arrayFillDefaultValue(Array.get(arr, i)); else Arrays.fill((Object[]) arr, Primitive.unwrap( Primitive.getDefaultValue(comp))); } }
/** Concatenate two arrays. * @param lhs 1st array * @param rhs 2nd array * @return a new array instance of concatenated contents. * @throws UtilEvalError for inconsistent dimensions. */ public static Object concat(Object lhs, Object rhs) throws UtilEvalError { Class<?> lhsType = lhs.getClass(); Class<?> rhsType = rhs.getClass(); if ( Types.arrayDimensions(lhsType) != Types.arrayDimensions(rhsType) ) throw new UtilEvalError("Cannot concat arrays with inconsistent dimensions." + " Attempting to concat array of type " + StringUtil.typeString(lhs) + " with array of type " + StringUtil.typeString(rhs) + "."); Class<?> toType = Types.getCommonType( Types.arrayElementType(lhsType), Types.arrayElementType(rhsType)); int[] dims = dimensions(lhs); dims[0] = Array.getLength(lhs) + Array.getLength(rhs); Object toArray = Array.newInstance(toType, dims); copy(toType, toArray, lhs, rhs); return toArray; }
if ( Types.isJavaAssignable(Entry.class, Types.arrayElementType(fromType)) ) return mapOfEntries((Entry[]) fromValue); if ( Types.isJavaAssignable(toType, LinkedHashMap.class) ) { toType = Types.arrayElementType(toType); int[] dims = dimensions(fromValue); Object toArray = Array.newInstance(toType, dims);
/** Helper class for type suffixes. */ public static class Suffix { private static final Map<String, Class<?>> m = Collections.unmodifiableMap(new HashMap<String, Class<?>>() { private static final long serialVersionUID = 1L; { put("O", Byte.TYPE); put("S", Short.TYPE); put("I", Integer.TYPE); put("L", Long.TYPE); put("W", BigInteger.class); put("w", BigDecimal.class); put("d", Double.TYPE); put("f", Float.TYPE); } }); private static String toUpperKey(Character key) { return key.toString().toUpperCase(); } private static String toLowerKey(Character key) { return key.toString().toLowerCase(); } public static boolean isIntegral(Character key) { return m.containsKey(toUpperKey(key)); } public static Class<?> getIntegralType(Character key) { return m.get(toUpperKey(key));
if ( object.getClass().isArray() && val != null ) try { val = Types.castObject( val, Types.arrayElementType(object.getClass()), Types.ASSIGNMENT); } catch (Exception e) { /* ignore cast exceptions */ }
/** Helper function to traverse array dimensions to find the common type. * Recursive calling for each element in an array initializer or finds the * common type relative to a value cell. * @param common the current common type * @param node the node to query * @param callstack the evaluation call stack * @param interpreter the evaluation interpreter * @return the common type for all cells * @throws EvalError thrown at node evaluation */ private Class<?> inferCommonType(Class<?> common, Node node, CallStack callstack, Interpreter interpreter ) throws EvalError { // Object is already the most common type and maps are typed LHS.MapEntry if ( Object.class == common || LHS.MapEntry.class == common ) return common; // inspect value elements for common type if ( !(node instanceof BSHArrayInitializer) ) { Object value = ((SimpleNode) node).eval(callstack, interpreter); Class<?> type = Types.getType(value, Primitive.isWrapperType(common)); return Types.getCommonType(common, Types.arrayElementType(type)); } // avoid traversing maps as arrays when nested in array if ( isMapInArray((BSHArrayInitializer) node) ) return Types.getCommonType(common, Map.class); // recurse through nested array initializer nodes int count = node.jjtGetNumChildren(); for ( int i = 0; i < count; i++ ) common = this.inferCommonType(common, node.jjtGetChild(i), callstack, interpreter); return common; }