1 /*
2  * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 package jdk.internal.util;
26 
27 import jdk.internal.vm.annotation.IntrinsicCandidate;
28 
29 import java.util.List;
30 import java.util.function.BiFunction;
31 import java.util.function.Function;
32 
33 /**
34  * Utility methods to check if state or arguments are correct.
35  *
36  */
37 public class Preconditions {
38 
39     /**
40      * Maps out-of-bounds values to a runtime exception.
41      *
42      * @param checkKind the kind of bounds check, whose name may correspond
43      *        to the name of one of the range check methods, checkIndex,
44      *        checkFromToIndex, checkFromIndexSize
45      * @param args the out-of-bounds arguments that failed the range check.
46      *        If the checkKind corresponds a the name of a range check method
47      *        then the bounds arguments are those that can be passed in order
48      *        to the method.
49      * @param oobef the exception formatter that when applied with a checkKind
50      *        and a list out-of-bounds arguments returns a runtime exception.
51      *        If {@code null} then, it is as if an exception formatter was
52      *        supplied that returns {@link IndexOutOfBoundsException} for any
53      *        given arguments.
54      * @return the runtime exception
55      */
outOfBounds( BiFunction<String, List<Number>, ? extends RuntimeException> oobef, String checkKind, Number... args)56     private static RuntimeException outOfBounds(
57             BiFunction<String, List<Number>, ? extends RuntimeException> oobef,
58             String checkKind,
59             Number... args) {
60         List<Number> largs = List.of(args);
61         RuntimeException e = oobef == null
62                              ? null : oobef.apply(checkKind, largs);
63         return e == null
64                ? new IndexOutOfBoundsException(outOfBoundsMessage(checkKind, largs)) : e;
65     }
66 
outOfBoundsCheckIndex( BiFunction<String, List<Number>, ? extends RuntimeException> oobe, int index, int length)67     private static RuntimeException outOfBoundsCheckIndex(
68             BiFunction<String, List<Number>, ? extends RuntimeException> oobe,
69             int index, int length) {
70         return outOfBounds(oobe, "checkIndex", index, length);
71     }
72 
outOfBoundsCheckFromToIndex( BiFunction<String, List<Number>, ? extends RuntimeException> oobe, int fromIndex, int toIndex, int length)73     private static RuntimeException outOfBoundsCheckFromToIndex(
74             BiFunction<String, List<Number>, ? extends RuntimeException> oobe,
75             int fromIndex, int toIndex, int length) {
76         return outOfBounds(oobe, "checkFromToIndex", fromIndex, toIndex, length);
77     }
78 
outOfBoundsCheckFromIndexSize( BiFunction<String, List<Number>, ? extends RuntimeException> oobe, int fromIndex, int size, int length)79     private static RuntimeException outOfBoundsCheckFromIndexSize(
80             BiFunction<String, List<Number>, ? extends RuntimeException> oobe,
81             int fromIndex, int size, int length) {
82         return outOfBounds(oobe, "checkFromIndexSize", fromIndex, size, length);
83     }
84 
outOfBoundsCheckIndex( BiFunction<String, List<Number>, ? extends RuntimeException> oobe, long index, long length)85     private static RuntimeException outOfBoundsCheckIndex(
86             BiFunction<String, List<Number>, ? extends RuntimeException> oobe,
87             long index, long length) {
88         return outOfBounds(oobe, "checkIndex", index, length);
89     }
90 
outOfBoundsCheckFromToIndex( BiFunction<String, List<Number>, ? extends RuntimeException> oobe, long fromIndex, long toIndex, long length)91     private static RuntimeException outOfBoundsCheckFromToIndex(
92             BiFunction<String, List<Number>, ? extends RuntimeException> oobe,
93             long fromIndex, long toIndex, long length) {
94         return outOfBounds(oobe, "checkFromToIndex", fromIndex, toIndex, length);
95     }
96 
outOfBoundsCheckFromIndexSize( BiFunction<String, List<Number>, ? extends RuntimeException> oobe, long fromIndex, long size, long length)97     private static RuntimeException outOfBoundsCheckFromIndexSize(
98             BiFunction<String, List<Number>, ? extends RuntimeException> oobe,
99             long fromIndex, long size, long length) {
100         return outOfBounds(oobe, "checkFromIndexSize", fromIndex, size, length);
101     }
102 
103     /**
104      * Returns an out-of-bounds exception formatter from an given exception
105      * factory.  The exception formatter is a function that formats an
106      * out-of-bounds message from its arguments and applies that message to the
107      * given exception factory to produce and relay an exception.
108      *
109      * <p>The exception formatter accepts two arguments: a {@code String}
110      * describing the out-of-bounds range check that failed, referred to as the
111      * <em>check kind</em>; and a {@code List<Number>} containing the
112      * out-of-bound integral values that failed the check.  The list of
113      * out-of-bound values is not modified.
114      *
115      * <p>Three check kinds are supported {@code checkIndex},
116      * {@code checkFromToIndex} and {@code checkFromIndexSize} corresponding
117      * respectively to the specified application of an exception formatter as an
118      * argument to the out-of-bounds range check methods
119      * {@link #checkIndex(int, int, BiFunction) checkIndex},
120      * {@link #checkFromToIndex(int, int, int, BiFunction) checkFromToIndex}, and
121      * {@link #checkFromIndexSize(int, int, int, BiFunction) checkFromIndexSize}.
122      * Thus a supported check kind corresponds to a method name and the
123      * out-of-bound integral values correspond to method argument values, in
124      * order, preceding the exception formatter argument (similar in many
125      * respects to the form of arguments required for a reflective invocation of
126      * such a range check method).
127      *
128      * <p>Formatter arguments conforming to such supported check kinds will
129      * produce specific exception messages describing failed out-of-bounds
130      * checks.  Otherwise, more generic exception messages will be produced in
131      * any of the following cases: the check kind is supported but fewer
132      * or more out-of-bounds values are supplied, the check kind is not
133      * supported, the check kind is {@code null}, or the list of out-of-bound
134      * values is {@code null}.
135      *
136      * @apiNote
137      * This method produces an out-of-bounds exception formatter that can be
138      * passed as an argument to any of the supported out-of-bounds range check
139      * methods declared by {@code Objects}.  For example, a formatter producing
140      * an {@code ArrayIndexOutOfBoundsException} may be produced and stored on a
141      * {@code static final} field as follows:
142      * <pre>{@code
143      * static final
144      * BiFunction<String, List<Number>, ArrayIndexOutOfBoundsException> AIOOBEF =
145      *     outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new);
146      * }</pre>
147      * The formatter instance {@code AIOOBEF} may be passed as an argument to an
148      * out-of-bounds range check method, such as checking if an {@code index}
149      * is within the bounds of a {@code limit}:
150      * <pre>{@code
151      * checkIndex(index, limit, AIOOBEF);
152      * }</pre>
153      * If the bounds check fails then the range check method will throw an
154      * {@code ArrayIndexOutOfBoundsException} with an appropriate exception
155      * message that is a produced from {@code AIOOBEF} as follows:
156      * <pre>{@code
157      * AIOOBEF.apply("checkIndex", List.of(index, limit));
158      * }</pre>
159      *
160      * @param f the exception factory, that produces an exception from a message
161      *        where the message is produced and formatted by the returned
162      *        exception formatter.  If this factory is stateless and side-effect
163      *        free then so is the returned formatter.
164      *        Exceptions thrown by the factory are relayed to the caller
165      *        of the returned formatter.
166      * @param <X> the type of runtime exception to be returned by the given
167      *        exception factory and relayed by the exception formatter
168      * @return the out-of-bounds exception formatter
169      */
170     public static <X extends RuntimeException>
outOfBoundsExceptionFormatter(Function<String, X> f)171     BiFunction<String, List<Number>, X> outOfBoundsExceptionFormatter(Function<String, X> f) {
172         // Use anonymous class to avoid bootstrap issues if this method is
173         // used early in startup
174         return new BiFunction<String, List<Number>, X>() {
175             @Override
176             public X apply(String checkKind, List<Number> args) {
177                 return f.apply(outOfBoundsMessage(checkKind, args));
178             }
179         };
180     }
181 
182     private static String outOfBoundsMessage(String checkKind, List<? extends Number> args) {
183         if (checkKind == null && args == null) {
184             return String.format("Range check failed");
185         } else if (checkKind == null) {
186             return String.format("Range check failed: %s", args);
187         } else if (args == null) {
188             return String.format("Range check failed: %s", checkKind);
189         }
190 
191         int argSize = 0;
192         switch (checkKind) {
193             case "checkIndex":
194                 argSize = 2;
195                 break;
196             case "checkFromToIndex":
197             case "checkFromIndexSize":
198                 argSize = 3;
199                 break;
200             default:
201         }
202 
203         // Switch to default if fewer or more arguments than required are supplied
204         switch ((args.size() != argSize) ? "" : checkKind) {
205             case "checkIndex":
206                 return String.format("Index %s out of bounds for length %s",
207                                      args.get(0), args.get(1));
208             case "checkFromToIndex":
209                 return String.format("Range [%s, %s) out of bounds for length %s",
210                                      args.get(0), args.get(1), args.get(2));
211             case "checkFromIndexSize":
212                 return String.format("Range [%s, %<s + %s) out of bounds for length %s",
213                                      args.get(0), args.get(1), args.get(2));
214             default:
215                 return String.format("Range check failed: %s %s", checkKind, args);
216         }
217     }
218 
219     /**
220      * Checks if the {@code index} is within the bounds of the range from
221      * {@code 0} (inclusive) to {@code length} (exclusive).
222      *
223      * <p>The {@code index} is defined to be out of bounds if any of the
224      * following inequalities is true:
225      * <ul>
226      *  <li>{@code index < 0}</li>
227      *  <li>{@code index >= length}</li>
228      *  <li>{@code length < 0}, which is implied from the former inequalities</li>
229      * </ul>
230      *
231      * <p>If the {@code index} is out of bounds, then a runtime exception is
232      * thrown that is the result of applying the following arguments to the
233      * exception formatter: the name of this method, {@code checkIndex};
234      * and an unmodifiable list of integers whose values are, in order, the
235      * out-of-bounds arguments {@code index} and {@code length}.
236      *
237      * @param <X> the type of runtime exception to throw if the arguments are
238      *        out of bounds
239      * @param index the index
240      * @param length the upper-bound (exclusive) of the range
241      * @param oobef the exception formatter that when applied with this
242      *        method name and out-of-bounds arguments returns a runtime
243      *        exception.  If {@code null} or returns {@code null} then, it is as
244      *        if an exception formatter produced from an invocation of
245      *        {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used
246      *        instead (though it may be more efficient).
247      *        Exceptions thrown by the formatter are relayed to the caller.
248      * @return {@code index} if it is within bounds of the range
249      * @throws X if the {@code index} is out of bounds and the exception
250      *         formatter is non-{@code null}
251      * @throws IndexOutOfBoundsException if the {@code index} is out of bounds
252      *         and the exception formatter is {@code null}
253      * @since 9
254      *
255      * @implNote
256      * This method is made intrinsic in optimizing compilers to guide them to
257      * perform unsigned comparisons of the index and length when it is known the
258      * length is a non-negative value (such as that of an array length or from
259      * the upper bound of a loop)
260      */
261     @IntrinsicCandidate
262     public static <X extends RuntimeException>
263     int checkIndex(int index, int length,
264                    BiFunction<String, List<Number>, X> oobef) {
265         if (index < 0 || index >= length)
266             throw outOfBoundsCheckIndex(oobef, index, length);
267         return index;
268     }
269 
270     /**
271      * Checks if the sub-range from {@code fromIndex} (inclusive) to
272      * {@code toIndex} (exclusive) is within the bounds of range from {@code 0}
273      * (inclusive) to {@code length} (exclusive).
274      *
275      * <p>The sub-range is defined to be out of bounds if any of the following
276      * inequalities is true:
277      * <ul>
278      *  <li>{@code fromIndex < 0}</li>
279      *  <li>{@code fromIndex > toIndex}</li>
280      *  <li>{@code toIndex > length}</li>
281      *  <li>{@code length < 0}, which is implied from the former inequalities</li>
282      * </ul>
283      *
284      * <p>If the sub-range is out of bounds, then a runtime exception is
285      * thrown that is the result of applying the following arguments to the
286      * exception formatter: the name of this method, {@code checkFromToIndex};
287      * and an unmodifiable list of integers whose values are, in order, the
288      * out-of-bounds arguments {@code fromIndex}, {@code toIndex}, and {@code length}.
289      *
290      * @param <X> the type of runtime exception to throw if the arguments are
291      *        out of bounds
292      * @param fromIndex the lower-bound (inclusive) of the sub-range
293      * @param toIndex the upper-bound (exclusive) of the sub-range
294      * @param length the upper-bound (exclusive) the range
295      * @param oobef the exception formatter that when applied with this
296      *        method name and out-of-bounds arguments returns a runtime
297      *        exception.  If {@code null} or returns {@code null} then, it is as
298      *        if an exception formatter produced from an invocation of
299      *        {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used
300      *        instead (though it may be more efficient).
301      *        Exceptions thrown by the formatter are relayed to the caller.
302      * @return {@code fromIndex} if the sub-range within bounds of the range
303      * @throws X if the sub-range is out of bounds and the exception factory
304      *         function is non-{@code null}
305      * @throws IndexOutOfBoundsException if the sub-range is out of bounds and
306      *         the exception factory function is {@code null}
307      * @since 9
308      */
309     public static <X extends RuntimeException>
310     int checkFromToIndex(int fromIndex, int toIndex, int length,
311                          BiFunction<String, List<Number>, X> oobef) {
312         if (fromIndex < 0 || fromIndex > toIndex || toIndex > length)
313             throw outOfBoundsCheckFromToIndex(oobef, fromIndex, toIndex, length);
314         return fromIndex;
315     }
316 
317     /**
318      * Checks if the sub-range from {@code fromIndex} (inclusive) to
319      * {@code fromIndex + size} (exclusive) is within the bounds of range from
320      * {@code 0} (inclusive) to {@code length} (exclusive).
321      *
322      * <p>The sub-range is defined to be out of bounds if any of the following
323      * inequalities is true:
324      * <ul>
325      *  <li>{@code fromIndex < 0}</li>
326      *  <li>{@code size < 0}</li>
327      *  <li>{@code fromIndex + size > length}, taking into account integer overflow</li>
328      *  <li>{@code length < 0}, which is implied from the former inequalities</li>
329      * </ul>
330      *
331      * <p>If the sub-range is out of bounds, then a runtime exception is
332      * thrown that is the result of applying the following arguments to the
333      * exception formatter: the name of this method, {@code checkFromIndexSize};
334      * and an unmodifiable list of integers whose values are, in order, the
335      * out-of-bounds arguments {@code fromIndex}, {@code size}, and
336      * {@code length}.
337      *
338      * @param <X> the type of runtime exception to throw if the arguments are
339      *        out of bounds
340      * @param fromIndex the lower-bound (inclusive) of the sub-interval
341      * @param size the size of the sub-range
342      * @param length the upper-bound (exclusive) of the range
343      * @param oobef the exception formatter that when applied with this
344      *        method name and out-of-bounds arguments returns a runtime
345      *        exception.  If {@code null} or returns {@code null} then, it is as
346      *        if an exception formatter produced from an invocation of
347      *        {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used
348      *        instead (though it may be more efficient).
349      *        Exceptions thrown by the formatter are relayed to the caller.
350      * @return {@code fromIndex} if the sub-range within bounds of the range
351      * @throws X if the sub-range is out of bounds and the exception factory
352      *         function is non-{@code null}
353      * @throws IndexOutOfBoundsException if the sub-range is out of bounds and
354      *         the exception factory function is {@code null}
355      * @since 9
356      */
357     public static <X extends RuntimeException>
358     int checkFromIndexSize(int fromIndex, int size, int length,
359                            BiFunction<String, List<Number>, X> oobef) {
360         if ((length | fromIndex | size) < 0 || size > length - fromIndex)
361             throw outOfBoundsCheckFromIndexSize(oobef, fromIndex, size, length);
362         return fromIndex;
363     }
364 
365     /**
366      * Checks if the {@code index} is within the bounds of the range from
367      * {@code 0} (inclusive) to {@code length} (exclusive).
368      *
369      * <p>The {@code index} is defined to be out of bounds if any of the
370      * following inequalities is true:
371      * <ul>
372      *  <li>{@code index < 0}</li>
373      *  <li>{@code index >= length}</li>
374      *  <li>{@code length < 0}, which is implied from the former inequalities</li>
375      * </ul>
376      *
377      * <p>If the {@code index} is out of bounds, then a runtime exception is
378      * thrown that is the result of applying the following arguments to the
379      * exception formatter: the name of this method, {@code checkIndex};
380      * and an unmodifiable list of longs whose values are, in order, the
381      * out-of-bounds arguments {@code index} and {@code length}.
382      *
383      * @param <X> the type of runtime exception to throw if the arguments are
384      *        out of bounds
385      * @param index the index
386      * @param length the upper-bound (exclusive) of the range
387      * @param oobef the exception formatter that when applied with this
388      *        method name and out-of-bounds arguments returns a runtime
389      *        exception.  If {@code null} or returns {@code null} then, it is as
390      *        if an exception formatter produced from an invocation of
391      *        {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used
392      *        instead (though it may be more efficient).
393      *        Exceptions thrown by the formatter are relayed to the caller.
394      * @return {@code index} if it is within bounds of the range
395      * @throws X if the {@code index} is out of bounds and the exception
396      *         formatter is non-{@code null}
397      * @throws IndexOutOfBoundsException if the {@code index} is out of bounds
398      *         and the exception formatter is {@code null}
399      * @since 16
400      *
401      * @implNote
402      * This method is made intrinsic in optimizing compilers to guide them to
403      * perform unsigned comparisons of the index and length when it is known the
404      * length is a non-negative value (such as that of an array length or from
405      * the upper bound of a loop)
406      */
407     // Android-removed: @IntrinsicCandidate is not present in Android.
408     //@IntrinsicCandidate
409     public static <X extends RuntimeException>
410     long checkIndex(long index, long length,
411                     BiFunction<String, List<Number>, X> oobef) {
412         if (index < 0 || index >= length)
413             throw outOfBoundsCheckIndex(oobef, index, length);
414         return index;
415     }
416 
417     /**
418      * Checks if the sub-range from {@code fromIndex} (inclusive) to
419      * {@code toIndex} (exclusive) is within the bounds of range from {@code 0}
420      * (inclusive) to {@code length} (exclusive).
421      *
422      * <p>The sub-range is defined to be out of bounds if any of the following
423      * inequalities is true:
424      * <ul>
425      *  <li>{@code fromIndex < 0}</li>
426      *  <li>{@code fromIndex > toIndex}</li>
427      *  <li>{@code toIndex > length}</li>
428      *  <li>{@code length < 0}, which is implied from the former inequalities</li>
429      * </ul>
430      *
431      * <p>If the sub-range is out of bounds, then a runtime exception is
432      * thrown that is the result of applying the following arguments to the
433      * exception formatter: the name of this method, {@code checkFromToIndex};
434      * and an unmodifiable list of longs whose values are, in order, the
435      * out-of-bounds arguments {@code fromIndex}, {@code toIndex}, and {@code length}.
436      *
437      * @param <X> the type of runtime exception to throw if the arguments are
438      *        out of bounds
439      * @param fromIndex the lower-bound (inclusive) of the sub-range
440      * @param toIndex the upper-bound (exclusive) of the sub-range
441      * @param length the upper-bound (exclusive) the range
442      * @param oobef the exception formatter that when applied with this
443      *        method name and out-of-bounds arguments returns a runtime
444      *        exception.  If {@code null} or returns {@code null} then, it is as
445      *        if an exception formatter produced from an invocation of
446      *        {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used
447      *        instead (though it may be more efficient).
448      *        Exceptions thrown by the formatter are relayed to the caller.
449      * @return {@code fromIndex} if the sub-range within bounds of the range
450      * @throws X if the sub-range is out of bounds and the exception factory
451      *         function is non-{@code null}
452      * @throws IndexOutOfBoundsException if the sub-range is out of bounds and
453      *         the exception factory function is {@code null}
454      * @since 16
455      */
456     public static <X extends RuntimeException>
457     long checkFromToIndex(long fromIndex, long toIndex, long length,
458                           BiFunction<String, List<Number>, X> oobef) {
459         if (fromIndex < 0 || fromIndex > toIndex || toIndex > length)
460             throw outOfBoundsCheckFromToIndex(oobef, fromIndex, toIndex, length);
461         return fromIndex;
462     }
463 
464     /**
465      * Checks if the sub-range from {@code fromIndex} (inclusive) to
466      * {@code fromIndex + size} (exclusive) is within the bounds of range from
467      * {@code 0} (inclusive) to {@code length} (exclusive).
468      *
469      * <p>The sub-range is defined to be out of bounds if any of the following
470      * inequalities is true:
471      * <ul>
472      *  <li>{@code fromIndex < 0}</li>
473      *  <li>{@code size < 0}</li>
474      *  <li>{@code fromIndex + size > length}, taking into account integer overflow</li>
475      *  <li>{@code length < 0}, which is implied from the former inequalities</li>
476      * </ul>
477      *
478      * <p>If the sub-range is out of bounds, then a runtime exception is
479      * thrown that is the result of applying the following arguments to the
480      * exception formatter: the name of this method, {@code checkFromIndexSize};
481      * and an unmodifiable list of longs whose values are, in order, the
482      * out-of-bounds arguments {@code fromIndex}, {@code size}, and
483      * {@code length}.
484      *
485      * @param <X> the type of runtime exception to throw if the arguments are
486      *        out of bounds
487      * @param fromIndex the lower-bound (inclusive) of the sub-interval
488      * @param size the size of the sub-range
489      * @param length the upper-bound (exclusive) of the range
490      * @param oobef the exception formatter that when applied with this
491      *        method name and out-of-bounds arguments returns a runtime
492      *        exception.  If {@code null} or returns {@code null} then, it is as
493      *        if an exception formatter produced from an invocation of
494      *        {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used
495      *        instead (though it may be more efficient).
496      *        Exceptions thrown by the formatter are relayed to the caller.
497      * @return {@code fromIndex} if the sub-range within bounds of the range
498      * @throws X if the sub-range is out of bounds and the exception factory
499      *         function is non-{@code null}
500      * @throws IndexOutOfBoundsException if the sub-range is out of bounds and
501      *         the exception factory function is {@code null}
502      * @since 16
503      */
504     public static <X extends RuntimeException>
505     long checkFromIndexSize(long fromIndex, long size, long length,
506                             BiFunction<String, List<Number>, X> oobef) {
507         if ((length | fromIndex | size) < 0 || size > length - fromIndex)
508             throw outOfBoundsCheckFromIndexSize(oobef, fromIndex, size, length);
509         return fromIndex;
510     }
511 }
512