Path: blob/master/src/java.base/share/classes/jdk/internal/util/Preconditions.java
41159 views
/*1* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24package jdk.internal.util;2526import jdk.internal.vm.annotation.IntrinsicCandidate;2728import java.util.List;29import java.util.function.BiFunction;30import java.util.function.Function;3132/**33* Utility methods to check if state or arguments are correct.34*35*/36public class Preconditions {3738/**39* Maps out-of-bounds values to a runtime exception.40*41* @param checkKind the kind of bounds check, whose name may correspond42* to the name of one of the range check methods, checkIndex,43* checkFromToIndex, checkFromIndexSize44* @param args the out-of-bounds arguments that failed the range check.45* If the checkKind corresponds a the name of a range check method46* then the bounds arguments are those that can be passed in order47* to the method.48* @param oobef the exception formatter that when applied with a checkKind49* and a list out-of-bounds arguments returns a runtime exception.50* If {@code null} then, it is as if an exception formatter was51* supplied that returns {@link IndexOutOfBoundsException} for any52* given arguments.53* @return the runtime exception54*/55private static RuntimeException outOfBounds(56BiFunction<String, List<Number>, ? extends RuntimeException> oobef,57String checkKind,58Number... args) {59List<Number> largs = List.of(args);60RuntimeException e = oobef == null61? null : oobef.apply(checkKind, largs);62return e == null63? new IndexOutOfBoundsException(outOfBoundsMessage(checkKind, largs)) : e;64}6566private static RuntimeException outOfBoundsCheckIndex(67BiFunction<String, List<Number>, ? extends RuntimeException> oobe,68int index, int length) {69return outOfBounds(oobe, "checkIndex", index, length);70}7172private static RuntimeException outOfBoundsCheckFromToIndex(73BiFunction<String, List<Number>, ? extends RuntimeException> oobe,74int fromIndex, int toIndex, int length) {75return outOfBounds(oobe, "checkFromToIndex", fromIndex, toIndex, length);76}7778private static RuntimeException outOfBoundsCheckFromIndexSize(79BiFunction<String, List<Number>, ? extends RuntimeException> oobe,80int fromIndex, int size, int length) {81return outOfBounds(oobe, "checkFromIndexSize", fromIndex, size, length);82}8384private static RuntimeException outOfBoundsCheckIndex(85BiFunction<String, List<Number>, ? extends RuntimeException> oobe,86long index, long length) {87return outOfBounds(oobe, "checkIndex", index, length);88}8990private static RuntimeException outOfBoundsCheckFromToIndex(91BiFunction<String, List<Number>, ? extends RuntimeException> oobe,92long fromIndex, long toIndex, long length) {93return outOfBounds(oobe, "checkFromToIndex", fromIndex, toIndex, length);94}9596private static RuntimeException outOfBoundsCheckFromIndexSize(97BiFunction<String, List<Number>, ? extends RuntimeException> oobe,98long fromIndex, long size, long length) {99return outOfBounds(oobe, "checkFromIndexSize", fromIndex, size, length);100}101102/**103* Returns an out-of-bounds exception formatter from an given exception104* factory. The exception formatter is a function that formats an105* out-of-bounds message from its arguments and applies that message to the106* given exception factory to produce and relay an exception.107*108* <p>The exception formatter accepts two arguments: a {@code String}109* describing the out-of-bounds range check that failed, referred to as the110* <em>check kind</em>; and a {@code List<Number>} containing the111* out-of-bound integral values that failed the check. The list of112* out-of-bound values is not modified.113*114* <p>Three check kinds are supported {@code checkIndex},115* {@code checkFromToIndex} and {@code checkFromIndexSize} corresponding116* respectively to the specified application of an exception formatter as an117* argument to the out-of-bounds range check methods118* {@link #checkIndex(int, int, BiFunction) checkIndex},119* {@link #checkFromToIndex(int, int, int, BiFunction) checkFromToIndex}, and120* {@link #checkFromIndexSize(int, int, int, BiFunction) checkFromIndexSize}.121* Thus a supported check kind corresponds to a method name and the122* out-of-bound integral values correspond to method argument values, in123* order, preceding the exception formatter argument (similar in many124* respects to the form of arguments required for a reflective invocation of125* such a range check method).126*127* <p>Formatter arguments conforming to such supported check kinds will128* produce specific exception messages describing failed out-of-bounds129* checks. Otherwise, more generic exception messages will be produced in130* any of the following cases: the check kind is supported but fewer131* or more out-of-bounds values are supplied, the check kind is not132* supported, the check kind is {@code null}, or the list of out-of-bound133* values is {@code null}.134*135* @apiNote136* This method produces an out-of-bounds exception formatter that can be137* passed as an argument to any of the supported out-of-bounds range check138* methods declared by {@code Objects}. For example, a formatter producing139* an {@code ArrayIndexOutOfBoundsException} may be produced and stored on a140* {@code static final} field as follows:141* <pre>{@code142* static final143* BiFunction<String, List<Number>, ArrayIndexOutOfBoundsException> AIOOBEF =144* outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new);145* }</pre>146* The formatter instance {@code AIOOBEF} may be passed as an argument to an147* out-of-bounds range check method, such as checking if an {@code index}148* is within the bounds of a {@code limit}:149* <pre>{@code150* checkIndex(index, limit, AIOOBEF);151* }</pre>152* If the bounds check fails then the range check method will throw an153* {@code ArrayIndexOutOfBoundsException} with an appropriate exception154* message that is a produced from {@code AIOOBEF} as follows:155* <pre>{@code156* AIOOBEF.apply("checkIndex", List.of(index, limit));157* }</pre>158*159* @param f the exception factory, that produces an exception from a message160* where the message is produced and formatted by the returned161* exception formatter. If this factory is stateless and side-effect162* free then so is the returned formatter.163* Exceptions thrown by the factory are relayed to the caller164* of the returned formatter.165* @param <X> the type of runtime exception to be returned by the given166* exception factory and relayed by the exception formatter167* @return the out-of-bounds exception formatter168*/169public static <X extends RuntimeException>170BiFunction<String, List<Number>, X> outOfBoundsExceptionFormatter(Function<String, X> f) {171// Use anonymous class to avoid bootstrap issues if this method is172// used early in startup173return new BiFunction<String, List<Number>, X>() {174@Override175public X apply(String checkKind, List<Number> args) {176return f.apply(outOfBoundsMessage(checkKind, args));177}178};179}180181private static String outOfBoundsMessage(String checkKind, List<? extends Number> args) {182if (checkKind == null && args == null) {183return String.format("Range check failed");184} else if (checkKind == null) {185return String.format("Range check failed: %s", args);186} else if (args == null) {187return String.format("Range check failed: %s", checkKind);188}189190int argSize = 0;191switch (checkKind) {192case "checkIndex":193argSize = 2;194break;195case "checkFromToIndex":196case "checkFromIndexSize":197argSize = 3;198break;199default:200}201202// Switch to default if fewer or more arguments than required are supplied203switch ((args.size() != argSize) ? "" : checkKind) {204case "checkIndex":205return String.format("Index %s out of bounds for length %s",206args.get(0), args.get(1));207case "checkFromToIndex":208return String.format("Range [%s, %s) out of bounds for length %s",209args.get(0), args.get(1), args.get(2));210case "checkFromIndexSize":211return String.format("Range [%s, %<s + %s) out of bounds for length %s",212args.get(0), args.get(1), args.get(2));213default:214return String.format("Range check failed: %s %s", checkKind, args);215}216}217218/**219* Checks if the {@code index} is within the bounds of the range from220* {@code 0} (inclusive) to {@code length} (exclusive).221*222* <p>The {@code index} is defined to be out of bounds if any of the223* following inequalities is true:224* <ul>225* <li>{@code index < 0}</li>226* <li>{@code index >= length}</li>227* <li>{@code length < 0}, which is implied from the former inequalities</li>228* </ul>229*230* <p>If the {@code index} is out of bounds, then a runtime exception is231* thrown that is the result of applying the following arguments to the232* exception formatter: the name of this method, {@code checkIndex};233* and an unmodifiable list of integers whose values are, in order, the234* out-of-bounds arguments {@code index} and {@code length}.235*236* @param <X> the type of runtime exception to throw if the arguments are237* out of bounds238* @param index the index239* @param length the upper-bound (exclusive) of the range240* @param oobef the exception formatter that when applied with this241* method name and out-of-bounds arguments returns a runtime242* exception. If {@code null} or returns {@code null} then, it is as243* if an exception formatter produced from an invocation of244* {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used245* instead (though it may be more efficient).246* Exceptions thrown by the formatter are relayed to the caller.247* @return {@code index} if it is within bounds of the range248* @throws X if the {@code index} is out of bounds and the exception249* formatter is non-{@code null}250* @throws IndexOutOfBoundsException if the {@code index} is out of bounds251* and the exception formatter is {@code null}252* @since 9253*254* @implNote255* This method is made intrinsic in optimizing compilers to guide them to256* perform unsigned comparisons of the index and length when it is known the257* length is a non-negative value (such as that of an array length or from258* the upper bound of a loop)259*/260@IntrinsicCandidate261public static <X extends RuntimeException>262int checkIndex(int index, int length,263BiFunction<String, List<Number>, X> oobef) {264if (index < 0 || index >= length)265throw outOfBoundsCheckIndex(oobef, index, length);266return index;267}268269/**270* Checks if the sub-range from {@code fromIndex} (inclusive) to271* {@code toIndex} (exclusive) is within the bounds of range from {@code 0}272* (inclusive) to {@code length} (exclusive).273*274* <p>The sub-range is defined to be out of bounds if any of the following275* inequalities is true:276* <ul>277* <li>{@code fromIndex < 0}</li>278* <li>{@code fromIndex > toIndex}</li>279* <li>{@code toIndex > length}</li>280* <li>{@code length < 0}, which is implied from the former inequalities</li>281* </ul>282*283* <p>If the sub-range is out of bounds, then a runtime exception is284* thrown that is the result of applying the following arguments to the285* exception formatter: the name of this method, {@code checkFromToIndex};286* and an unmodifiable list of integers whose values are, in order, the287* out-of-bounds arguments {@code fromIndex}, {@code toIndex}, and {@code length}.288*289* @param <X> the type of runtime exception to throw if the arguments are290* out of bounds291* @param fromIndex the lower-bound (inclusive) of the sub-range292* @param toIndex the upper-bound (exclusive) of the sub-range293* @param length the upper-bound (exclusive) the range294* @param oobef the exception formatter that when applied with this295* method name and out-of-bounds arguments returns a runtime296* exception. If {@code null} or returns {@code null} then, it is as297* if an exception formatter produced from an invocation of298* {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used299* instead (though it may be more efficient).300* Exceptions thrown by the formatter are relayed to the caller.301* @return {@code fromIndex} if the sub-range within bounds of the range302* @throws X if the sub-range is out of bounds and the exception factory303* function is non-{@code null}304* @throws IndexOutOfBoundsException if the sub-range is out of bounds and305* the exception factory function is {@code null}306* @since 9307*/308public static <X extends RuntimeException>309int checkFromToIndex(int fromIndex, int toIndex, int length,310BiFunction<String, List<Number>, X> oobef) {311if (fromIndex < 0 || fromIndex > toIndex || toIndex > length)312throw outOfBoundsCheckFromToIndex(oobef, fromIndex, toIndex, length);313return fromIndex;314}315316/**317* Checks if the sub-range from {@code fromIndex} (inclusive) to318* {@code fromIndex + size} (exclusive) is within the bounds of range from319* {@code 0} (inclusive) to {@code length} (exclusive).320*321* <p>The sub-range is defined to be out of bounds if any of the following322* inequalities is true:323* <ul>324* <li>{@code fromIndex < 0}</li>325* <li>{@code size < 0}</li>326* <li>{@code fromIndex + size > length}, taking into account integer overflow</li>327* <li>{@code length < 0}, which is implied from the former inequalities</li>328* </ul>329*330* <p>If the sub-range is out of bounds, then a runtime exception is331* thrown that is the result of applying the following arguments to the332* exception formatter: the name of this method, {@code checkFromIndexSize};333* and an unmodifiable list of integers whose values are, in order, the334* out-of-bounds arguments {@code fromIndex}, {@code size}, and335* {@code length}.336*337* @param <X> the type of runtime exception to throw if the arguments are338* out of bounds339* @param fromIndex the lower-bound (inclusive) of the sub-interval340* @param size the size of the sub-range341* @param length the upper-bound (exclusive) of the range342* @param oobef the exception formatter that when applied with this343* method name and out-of-bounds arguments returns a runtime344* exception. If {@code null} or returns {@code null} then, it is as345* if an exception formatter produced from an invocation of346* {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used347* instead (though it may be more efficient).348* Exceptions thrown by the formatter are relayed to the caller.349* @return {@code fromIndex} if the sub-range within bounds of the range350* @throws X if the sub-range is out of bounds and the exception factory351* function is non-{@code null}352* @throws IndexOutOfBoundsException if the sub-range is out of bounds and353* the exception factory function is {@code null}354* @since 9355*/356public static <X extends RuntimeException>357int checkFromIndexSize(int fromIndex, int size, int length,358BiFunction<String, List<Number>, X> oobef) {359if ((length | fromIndex | size) < 0 || size > length - fromIndex)360throw outOfBoundsCheckFromIndexSize(oobef, fromIndex, size, length);361return fromIndex;362}363364/**365* Checks if the {@code index} is within the bounds of the range from366* {@code 0} (inclusive) to {@code length} (exclusive).367*368* <p>The {@code index} is defined to be out of bounds if any of the369* following inequalities is true:370* <ul>371* <li>{@code index < 0}</li>372* <li>{@code index >= length}</li>373* <li>{@code length < 0}, which is implied from the former inequalities</li>374* </ul>375*376* <p>If the {@code index} is out of bounds, then a runtime exception is377* thrown that is the result of applying the following arguments to the378* exception formatter: the name of this method, {@code checkIndex};379* and an unmodifiable list of longs whose values are, in order, the380* out-of-bounds arguments {@code index} and {@code length}.381*382* @param <X> the type of runtime exception to throw if the arguments are383* out of bounds384* @param index the index385* @param length the upper-bound (exclusive) of the range386* @param oobef the exception formatter that when applied with this387* method name and out-of-bounds arguments returns a runtime388* exception. If {@code null} or returns {@code null} then, it is as389* if an exception formatter produced from an invocation of390* {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used391* instead (though it may be more efficient).392* Exceptions thrown by the formatter are relayed to the caller.393* @return {@code index} if it is within bounds of the range394* @throws X if the {@code index} is out of bounds and the exception395* formatter is non-{@code null}396* @throws IndexOutOfBoundsException if the {@code index} is out of bounds397* and the exception formatter is {@code null}398* @since 16399*400* @implNote401* This method is made intrinsic in optimizing compilers to guide them to402* perform unsigned comparisons of the index and length when it is known the403* length is a non-negative value (such as that of an array length or from404* the upper bound of a loop)405*/406@IntrinsicCandidate407public static <X extends RuntimeException>408long checkIndex(long index, long length,409BiFunction<String, List<Number>, X> oobef) {410if (index < 0 || index >= length)411throw outOfBoundsCheckIndex(oobef, index, length);412return index;413}414415/**416* Checks if the sub-range from {@code fromIndex} (inclusive) to417* {@code toIndex} (exclusive) is within the bounds of range from {@code 0}418* (inclusive) to {@code length} (exclusive).419*420* <p>The sub-range is defined to be out of bounds if any of the following421* inequalities is true:422* <ul>423* <li>{@code fromIndex < 0}</li>424* <li>{@code fromIndex > toIndex}</li>425* <li>{@code toIndex > length}</li>426* <li>{@code length < 0}, which is implied from the former inequalities</li>427* </ul>428*429* <p>If the sub-range is out of bounds, then a runtime exception is430* thrown that is the result of applying the following arguments to the431* exception formatter: the name of this method, {@code checkFromToIndex};432* and an unmodifiable list of longs whose values are, in order, the433* out-of-bounds arguments {@code fromIndex}, {@code toIndex}, and {@code length}.434*435* @param <X> the type of runtime exception to throw if the arguments are436* out of bounds437* @param fromIndex the lower-bound (inclusive) of the sub-range438* @param toIndex the upper-bound (exclusive) of the sub-range439* @param length the upper-bound (exclusive) the range440* @param oobef the exception formatter that when applied with this441* method name and out-of-bounds arguments returns a runtime442* exception. If {@code null} or returns {@code null} then, it is as443* if an exception formatter produced from an invocation of444* {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used445* instead (though it may be more efficient).446* Exceptions thrown by the formatter are relayed to the caller.447* @return {@code fromIndex} if the sub-range within bounds of the range448* @throws X if the sub-range is out of bounds and the exception factory449* function is non-{@code null}450* @throws IndexOutOfBoundsException if the sub-range is out of bounds and451* the exception factory function is {@code null}452* @since 16453*/454public static <X extends RuntimeException>455long checkFromToIndex(long fromIndex, long toIndex, long length,456BiFunction<String, List<Number>, X> oobef) {457if (fromIndex < 0 || fromIndex > toIndex || toIndex > length)458throw outOfBoundsCheckFromToIndex(oobef, fromIndex, toIndex, length);459return fromIndex;460}461462/**463* Checks if the sub-range from {@code fromIndex} (inclusive) to464* {@code fromIndex + size} (exclusive) is within the bounds of range from465* {@code 0} (inclusive) to {@code length} (exclusive).466*467* <p>The sub-range is defined to be out of bounds if any of the following468* inequalities is true:469* <ul>470* <li>{@code fromIndex < 0}</li>471* <li>{@code size < 0}</li>472* <li>{@code fromIndex + size > length}, taking into account integer overflow</li>473* <li>{@code length < 0}, which is implied from the former inequalities</li>474* </ul>475*476* <p>If the sub-range is out of bounds, then a runtime exception is477* thrown that is the result of applying the following arguments to the478* exception formatter: the name of this method, {@code checkFromIndexSize};479* and an unmodifiable list of longs whose values are, in order, the480* out-of-bounds arguments {@code fromIndex}, {@code size}, and481* {@code length}.482*483* @param <X> the type of runtime exception to throw if the arguments are484* out of bounds485* @param fromIndex the lower-bound (inclusive) of the sub-interval486* @param size the size of the sub-range487* @param length the upper-bound (exclusive) of the range488* @param oobef the exception formatter that when applied with this489* method name and out-of-bounds arguments returns a runtime490* exception. If {@code null} or returns {@code null} then, it is as491* if an exception formatter produced from an invocation of492* {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used493* instead (though it may be more efficient).494* Exceptions thrown by the formatter are relayed to the caller.495* @return {@code fromIndex} if the sub-range within bounds of the range496* @throws X if the sub-range is out of bounds and the exception factory497* function is non-{@code null}498* @throws IndexOutOfBoundsException if the sub-range is out of bounds and499* the exception factory function is {@code null}500* @since 16501*/502public static <X extends RuntimeException>503long checkFromIndexSize(long fromIndex, long size, long length,504BiFunction<String, List<Number>, X> oobef) {505if ((length | fromIndex | size) < 0 || size > length - fromIndex)506throw outOfBoundsCheckFromIndexSize(oobef, fromIndex, size, length);507return fromIndex;508}509}510511512