org.apache.commons.imaging.common.Allocator Maven / Gradle / Ivy
/*
* 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.commons.imaging.common;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.function.IntFunction;
/**
* Checks inputs for meeting allocation limits and allocates arrays.
*/
public class Allocator {
private static final String CANONICAL_NAME = Allocator.class.getCanonicalName();
/** One GB. */
private static final int DEFAULT = 1_073_741_824;
private static final int LIMIT;
static {
LIMIT = Integer.getInteger(CANONICAL_NAME, DEFAULT);
}
/**
* Allocates an Object of type T of the requested size.
*
* @param The return array type
* @param request The requested size.
* @param factory The array factory.
* @return a new byte array.
* @throws AllocationRequestException Thrown when the request exceeds the limit.
* @see #check(int)
*/
public static T apply(final int request, final IntFunction factory) {
return factory.apply(check(request));
}
/**
* Allocates an array of type T of the requested size.
*
* @param The return array type
* @param request The requested size.
* @param factory The array factory.
* @param eltShallowByteSize The shallow byte size of an element.
* @return a new byte array.
* @throws AllocationRequestException Thrown when the request exceeds the limit.
* @see #check(int)
*/
public static T[] array(final int request, final IntFunction factory, final int eltShallowByteSize) {
check(request * eltShallowByteSize);
return factory.apply(request);
}
/**
* Allocates an Object array of type T of the requested size.
*
* @param The return array type
* @param request The requested size.
* @return a new byte array.
* @throws AllocationRequestException Thrown when the request exceeds the limit.
* @see #check(int)
*/
public static ArrayList arrayList(final int request) {
check(24 + request * 4); // 4 bytes per element
return apply(request, ArrayList::new);
}
/**
* Allocates a byte array of the requested size.
*
* @param request The requested size.
* @return a new byte array.
* @throws AllocationRequestException Thrown when the request exceeds the limit.
* @see #check(int, int)
*/
public static byte[] byteArray(final int request) {
return new byte[checkByteArray(request)];
}
/**
* Allocates a byte array of the requested size.
*
* @param request The requested size is cast down to an int.
* @return a new byte array.
* @throws AllocationRequestException Thrown when the request exceeds the limit.
* @see #check(int, int)
*/
public static byte[] byteArray(final long request) {
return new byte[check(request, Byte.BYTES)];
}
/**
* Allocates a char array of the requested size.
*
* @param request The requested size.
* @return a new char array.
* @throws AllocationRequestException Thrown when the request exceeds the limit.
* @see #check(int, int)
*/
public static char[] charArray(final int request) {
return new char[check(request, Character.BYTES)];
}
/**
* Checks a request for meeting allocation limits.
*
* The default limit is {@value #DEFAULT}, override with the system property "org.apache.commons.imaging.common.mylzw.AllocationChecker".
*
*
* @param request an allocation request.
* @return the request.
* @throws AllocationRequestException Thrown when the request exceeds the limit.
*/
public static int check(final int request) {
if (request > LIMIT) {
throw new AllocationRequestException(LIMIT, request);
}
return request;
}
/**
* Checks a request for meeting allocation limits.
*
* The default limit is {@value #DEFAULT}, override with the system property "org.apache.commons.imaging.common.mylzw.AllocationChecker".
*
*
* @param request an allocation request count.
* @param elementSize The element size.
* @return the request.
* @throws AllocationRequestException Thrown when the request exceeds the limit.
*/
public static int check(final int request, final int elementSize) {
int multiplyExact;
try {
multiplyExact = Math.multiplyExact(request, elementSize);
} catch (final ArithmeticException e) {
throw new AllocationRequestException(LIMIT, BigInteger.valueOf(request).multiply(BigInteger.valueOf(elementSize)), e);
}
if (multiplyExact > LIMIT) {
throw new AllocationRequestException(LIMIT, request);
}
return request;
}
/**
* Checks a request for meeting allocation limits.
*
* The default limit is {@value #DEFAULT}, override with the system property "org.apache.commons.imaging.common.mylzw.AllocationChecker".
*
*
* @param request an allocation request count is cast down to an int.
* @param elementSize The element size.
* @return the request.
* @throws AllocationRequestException Thrown when the request exceeds the limit.
*/
public static int check(final long request, final int elementSize) {
try {
return check(Math.toIntExact(request), elementSize);
} catch (final ArithmeticException e) {
throw new AllocationRequestException(LIMIT, request, e);
}
}
/**
* Checks that allocating a byte array of the requested size is within the limit.
*
* @param request The byte array size.
* @return The input request.
*/
public static int checkByteArray(final int request) {
return check(request, Byte.BYTES);
}
/**
* Allocates a double array of the requested size.
*
* @param request The requested size.
* @return a new double array.
* @throws AllocationRequestException Thrown when the request exceeds the limit.
* @see #check(int, int)
*/
public static double[] doubleArray(final int request) {
return new double[check(request, Double.BYTES)];
}
/**
* Allocates a float array of the requested size.
*
* @param request The requested size.
* @return a new float array.
* @throws AllocationRequestException Thrown when the request exceeds the limit.
* @see #check(int, int)
*/
public static float[] floatArray(final int request) {
return new float[check(request, Float.BYTES)];
}
/**
* Allocates a int array of the requested size.
*
* @param request The requested size.
* @return a new int array.
* @throws AllocationRequestException Thrown when the request exceeds the limit.
* @see #check(int, int)
*/
public static int[] intArray(final int request) {
return new int[check(request, Integer.BYTES)];
}
/**
* Allocates a long array of the requested size.
*
* @param request The requested size.
* @return a new long array.
* @throws AllocationRequestException Thrown when the request exceeds the limit.
* @see #check(int, int)
*/
public static long[] longArray(final int request) {
return new long[check(request, Long.BYTES)];
}
/**
* Allocates a short array of the requested size.
*
* @param request The requested size.
* @return a new short array.
* @throws AllocationRequestException Thrown when the request exceeds the limit.
* @see #check(int, int)
*/
public static short[] shortArray(final int request) {
return new short[check(request, Short.BYTES)];
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy