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