1508 |
public static final char MAX_LOW_SURROGATE = '\udfff'; |
public static final char MAX_LOW_SURROGATE = '\udfff'; |
1509 |
|
|
1510 |
/** |
/** |
1511 |
|
* Minimum surrogate code in UTF-16 encoding. |
1512 |
|
* |
1513 |
|
* @since 1.5 |
1514 |
|
*/ |
1515 |
|
public static final char MIN_SURROGATE = MIN_HIGH_SURROGATE; |
1516 |
|
|
1517 |
|
/** |
1518 |
|
* Maximum low surrogate code in UTF-16 encoding. |
1519 |
|
* |
1520 |
|
* @since 1.5 |
1521 |
|
*/ |
1522 |
|
public static final char MAX_SURROGATE = MAX_LOW_SURROGATE; |
1523 |
|
|
1524 |
|
/** |
1525 |
* Grabs an attribute offset from the Unicode attribute database. The lower |
* Grabs an attribute offset from the Unicode attribute database. The lower |
1526 |
* 5 bits are the character type, the next 2 bits are flags, and the top |
* 5 bits are the character type, the next 2 bits are flags, and the top |
1527 |
* 9 bits are the offset into the attribute tables. |
* 9 bits are the offset into the attribute tables. |
2429 |
{ |
{ |
2430 |
return codePoint >= MIN_CODE_POINT && codePoint <= MAX_CODE_POINT; |
return codePoint >= MIN_CODE_POINT && codePoint <= MAX_CODE_POINT; |
2431 |
} |
} |
2432 |
|
|
2433 |
|
/** |
2434 |
|
* Return true if the given character is a high surrogate. |
2435 |
|
* @param ch the character |
2436 |
|
* @return true if the character is a high surrogate character |
2437 |
|
* |
2438 |
|
* @since 1.5 |
2439 |
|
*/ |
2440 |
|
public static boolean isHighSurrogate(char ch) |
2441 |
|
{ |
2442 |
|
return ch >= MIN_HIGH_SURROGATE && ch <= MAX_HIGH_SURROGATE; |
2443 |
|
} |
2444 |
|
|
2445 |
|
/** |
2446 |
|
* Return true if the given character is a low surrogate. |
2447 |
|
* @param ch the character |
2448 |
|
* @return true if the character is a low surrogate character |
2449 |
|
* |
2450 |
|
* @since 1.5 |
2451 |
|
*/ |
2452 |
|
public static boolean isLowSurrogate(char ch) |
2453 |
|
{ |
2454 |
|
return ch >= MIN_LOW_SURROGATE && ch <= MAX_LOW_SURROGATE; |
2455 |
|
} |
2456 |
|
|
2457 |
|
/** |
2458 |
|
* Return true if the given characters compose a surrogate pair. |
2459 |
|
* This is true if the first character is a high surrogate and the |
2460 |
|
* second character is a low surrogate. |
2461 |
|
* @param ch1 the first character |
2462 |
|
* @param ch2 the first character |
2463 |
|
* @return true if the characters compose a surrogate pair |
2464 |
|
* |
2465 |
|
* @since 1.5 |
2466 |
|
*/ |
2467 |
|
public static boolean isSurrogatePair(char ch1, char ch2) |
2468 |
|
{ |
2469 |
|
return isHighSurrogate(ch1) && isLowSurrogate(ch2); |
2470 |
|
} |
2471 |
|
|
2472 |
|
/** |
2473 |
|
* Given a valid surrogate pair, this returns the corresponding |
2474 |
|
* code point. |
2475 |
|
* @param high the high character of the pair |
2476 |
|
* @param low the low character of the pair |
2477 |
|
* @return the corresponding code point |
2478 |
|
* |
2479 |
|
* @since 1.5 |
2480 |
|
*/ |
2481 |
|
public static int toCodePoint(char high, char low) |
2482 |
|
{ |
2483 |
|
return ((high - MIN_HIGH_SURROGATE) << 10) + (low - MIN_LOW_SURROGATE); |
2484 |
|
} |
2485 |
|
|
2486 |
|
/** |
2487 |
|
* Get the code point at the specified index in the CharSequence. |
2488 |
|
* This is like CharSequence#charAt(int), but if the character is |
2489 |
|
* the start of a surrogate pair, and there is a following |
2490 |
|
* character, and this character completes the pair, then the |
2491 |
|
* corresponding supplementary code point is returned. Otherwise, |
2492 |
|
* the character at the index is returned. |
2493 |
|
* |
2494 |
|
* @param sequence the CharSequence |
2495 |
|
* @param index the index of the codepoint to get, starting at 0 |
2496 |
|
* @return the codepoint at the specified index |
2497 |
|
* @throws IndexOutOfBoundsException if index is negative or >= length() |
2498 |
|
* @since 1.5 |
2499 |
|
*/ |
2500 |
|
public static int codePointAt(CharSequence sequence, int index) |
2501 |
|
{ |
2502 |
|
int len = sequence.length(); |
2503 |
|
if (index < 0 || index >= len) |
2504 |
|
throw new IndexOutOfBoundsException(); |
2505 |
|
char high = sequence.charAt(index); |
2506 |
|
if (! isHighSurrogate(high) || ++index >= len) |
2507 |
|
return high; |
2508 |
|
char low = sequence.charAt(index); |
2509 |
|
if (! isLowSurrogate(low)) |
2510 |
|
return high; |
2511 |
|
return toCodePoint(high, low); |
2512 |
|
} |
2513 |
|
|
2514 |
|
/** |
2515 |
|
* Get the code point at the specified index in the CharSequence. |
2516 |
|
* If the character is the start of a surrogate pair, and there is a |
2517 |
|
* following character, and this character completes the pair, then |
2518 |
|
* the corresponding supplementary code point is returned. |
2519 |
|
* Otherwise, the character at the index is returned. |
2520 |
|
* |
2521 |
|
* @param chars the character array in which to look |
2522 |
|
* @param index the index of the codepoint to get, starting at 0 |
2523 |
|
* @return the codepoint at the specified index |
2524 |
|
* @throws IndexOutOfBoundsException if index is negative or >= length() |
2525 |
|
* @since 1.5 |
2526 |
|
*/ |
2527 |
|
public static int codePointAt(char[] chars, int index) |
2528 |
|
{ |
2529 |
|
return codePointAt(chars, index, chars.length); |
2530 |
|
} |
2531 |
|
|
2532 |
|
/** |
2533 |
|
* Get the code point at the specified index in the CharSequence. |
2534 |
|
* If the character is the start of a surrogate pair, and there is a |
2535 |
|
* following character within the specified range, and this |
2536 |
|
* character completes the pair, then the corresponding |
2537 |
|
* supplementary code point is returned. Otherwise, the character |
2538 |
|
* at the index is returned. |
2539 |
|
* |
2540 |
|
* @param chars the character array in which to look |
2541 |
|
* @param index the index of the codepoint to get, starting at 0 |
2542 |
|
* @param limit the limit past which characters should not be examined |
2543 |
|
* @return the codepoint at the specified index |
2544 |
|
* @throws IndexOutOfBoundsException if index is negative or >= |
2545 |
|
* limit, or if limit is negative or >= the length of the array |
2546 |
|
* @since 1.5 |
2547 |
|
*/ |
2548 |
|
public static int codePointAt(char[] chars, int index, int limit) |
2549 |
|
{ |
2550 |
|
if (index < 0 || index >= limit || limit < 0 || limit >= chars.length) |
2551 |
|
throw new IndexOutOfBoundsException(); |
2552 |
|
char high = chars[index]; |
2553 |
|
if (! isHighSurrogate(high) || ++index >= limit) |
2554 |
|
return high; |
2555 |
|
char low = chars[index]; |
2556 |
|
if (! isLowSurrogate(low)) |
2557 |
|
return high; |
2558 |
|
return toCodePoint(high, low); |
2559 |
|
} |
2560 |
|
|
2561 |
|
/** |
2562 |
|
* Get the code point before the specified index. This is like |
2563 |
|
* #codePointAt(char[], int), but checks the characters at |
2564 |
|
* <code>index-1</code> and <code>index-2</code> to see if they form |
2565 |
|
* a supplementary code point. If they do not, the character at |
2566 |
|
* <code>index-1</code> is returned. |
2567 |
|
* |
2568 |
|
* @param chars the character array |
2569 |
|
* @param index the index just past the codepoint to get, starting at 0 |
2570 |
|
* @return the codepoint at the specified index |
2571 |
|
* @throws IndexOutOfBoundsException if index is negative or >= length() |
2572 |
|
* @since 1.5 |
2573 |
|
*/ |
2574 |
|
public static int codePointBefore(char[] chars, int index) |
2575 |
|
{ |
2576 |
|
return codePointBefore(chars, index, 1); |
2577 |
|
} |
2578 |
|
|
2579 |
|
/** |
2580 |
|
* Get the code point before the specified index. This is like |
2581 |
|
* #codePointAt(char[], int), but checks the characters at |
2582 |
|
* <code>index-1</code> and <code>index-2</code> to see if they form |
2583 |
|
* a supplementary code point. If they do not, the character at |
2584 |
|
* <code>index-1</code> is returned. The start parameter is used to |
2585 |
|
* limit the range of the array which may be examined. |
2586 |
|
* |
2587 |
|
* @param chars the character array |
2588 |
|
* @param index the index just past the codepoint to get, starting at 0 |
2589 |
|
* @param start the index before which characters should not be examined |
2590 |
|
* @return the codepoint at the specified index |
2591 |
|
* @throws IndexOutOfBoundsException if index is > start or > |
2592 |
|
* the length of the array, or if limit is negative or >= the |
2593 |
|
* length of the array |
2594 |
|
* @since 1.5 |
2595 |
|
*/ |
2596 |
|
public static int codePointBefore(char[] chars, int index, int start) |
2597 |
|
{ |
2598 |
|
if (index < start || index > chars.length |
2599 |
|
|| start < 0 || start >= chars.length) |
2600 |
|
throw new IndexOutOfBoundsException(); |
2601 |
|
--index; |
2602 |
|
char low = chars[index]; |
2603 |
|
if (! isLowSurrogate(low) || --index < start) |
2604 |
|
return low; |
2605 |
|
char high = chars[index]; |
2606 |
|
if (! isHighSurrogate(high)) |
2607 |
|
return low; |
2608 |
|
return toCodePoint(high, low); |
2609 |
|
} |
2610 |
|
|
2611 |
|
/** |
2612 |
|
* Get the code point before the specified index. This is like |
2613 |
|
* #codePointAt(CharSequence, int), but checks the characters at |
2614 |
|
* <code>index-1</code> and <code>index-2</code> to see if they form |
2615 |
|
* a supplementary code point. If they do not, the character at |
2616 |
|
* <code>index-1</code> is returned. |
2617 |
|
* |
2618 |
|
* @param sequence the CharSequence |
2619 |
|
* @param index the index just past the codepoint to get, starting at 0 |
2620 |
|
* @return the codepoint at the specified index |
2621 |
|
* @throws IndexOutOfBoundsException if index is negative or >= length() |
2622 |
|
* @since 1.5 |
2623 |
|
*/ |
2624 |
|
public static int codePointBefore(CharSequence sequence, int index) |
2625 |
|
{ |
2626 |
|
int len = sequence.length(); |
2627 |
|
if (index < 1 || index > len) |
2628 |
|
throw new IndexOutOfBoundsException(); |
2629 |
|
--index; |
2630 |
|
char low = sequence.charAt(index); |
2631 |
|
if (! isLowSurrogate(low) || --index < 0) |
2632 |
|
return low; |
2633 |
|
char high = sequence.charAt(index); |
2634 |
|
if (! isHighSurrogate(high)) |
2635 |
|
return low; |
2636 |
|
return toCodePoint(high, low); |
2637 |
|
} |
2638 |
} // class Character |
} // class Character |