670 lines
21 KiB
Java
670 lines
21 KiB
Java
/*
|
|
* Copyright (C) 2010 The Guava Authors
|
|
*
|
|
* Licensed 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 com.google.common.base;
|
|
|
|
import static com.google.common.base.Preconditions.checkArgument;
|
|
import static com.google.common.base.Preconditions.checkNotNull;
|
|
|
|
import javax.annotation.CheckReturnValue;
|
|
|
|
import com.google.common.annotations.Beta;
|
|
import com.google.common.annotations.GwtCompatible;
|
|
|
|
/**
|
|
* Static methods pertaining to ASCII characters (those in the range of values
|
|
* {@code 0x00} through {@code 0x7F}), and to strings containing such
|
|
* characters.
|
|
*
|
|
* <p>
|
|
* ASCII utilities also exist in other classes of this package:
|
|
* <ul>
|
|
* <!-- TODO(kevinb): how can we make this not produce a warning when building
|
|
* gwt javadoc? -->
|
|
* <li>{@link Charsets#US_ASCII} specifies the {@code Charset} of ASCII
|
|
* characters.
|
|
* <li>{@link CharMatcher#ASCII} matches ASCII characters and provides text
|
|
* processing methods which operate only on the ASCII characters of a string.
|
|
* </ul>
|
|
*
|
|
* @author Craig Berry
|
|
* @author Gregory Kick
|
|
* @since 7.0
|
|
*/
|
|
@GwtCompatible
|
|
public final class Ascii {
|
|
|
|
private Ascii() {
|
|
}
|
|
|
|
/* The ASCII control characters, per RFC 20. */
|
|
/**
|
|
* Null ('\0'): The all-zeros character which may serve to accomplish time fill
|
|
* and media fill. Normally used as a C string terminator.
|
|
* <p>
|
|
* Although RFC 20 names this as "Null", note that it is distinct from the C/C++
|
|
* "NULL" pointer.
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte NUL = 0;
|
|
|
|
/**
|
|
* Start of Heading: A communication control character used at the beginning of
|
|
* a sequence of characters which constitute a machine-sensible address or
|
|
* routing information. Such a sequence is referred to as the "heading." An STX
|
|
* character has the effect of terminating a heading.
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte SOH = 1;
|
|
|
|
/**
|
|
* Start of Text: A communication control character which precedes a sequence of
|
|
* characters that is to be treated as an entity and entirely transmitted
|
|
* through to the ultimate destination. Such a sequence is referred to as
|
|
* "text." STX may be used to terminate a sequence of characters started by SOH.
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte STX = 2;
|
|
|
|
/**
|
|
* End of Text: A communication control character used to terminate a sequence
|
|
* of characters started with STX and transmitted as an entity.
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte ETX = 3;
|
|
|
|
/**
|
|
* End of Transmission: A communication control character used to indicate the
|
|
* conclusion of a transmission, which may have contained one or more texts and
|
|
* any associated headings.
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte EOT = 4;
|
|
|
|
/**
|
|
* Enquiry: A communication control character used in data communication systems
|
|
* as a request for a response from a remote station. It may be used as a "Who
|
|
* Are You" (WRU) to obtain identification, or may be used to obtain station
|
|
* status, or both.
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte ENQ = 5;
|
|
|
|
/**
|
|
* Acknowledge: A communication control character transmitted by a receiver as
|
|
* an affirmative response to a sender.
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte ACK = 6;
|
|
|
|
/**
|
|
* Bell ('\a'): A character for use when there is a need to call for human
|
|
* attention. It may control alarm or attention devices.
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte BEL = 7;
|
|
|
|
/**
|
|
* Backspace ('\b'): A format effector which controls the movement of the
|
|
* printing position one printing space backward on the same printing line.
|
|
* (Applicable also to display devices.)
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte BS = 8;
|
|
|
|
/**
|
|
* Horizontal Tabulation ('\t'): A format effector which controls the movement
|
|
* of the printing position to the next in a series of predetermined positions
|
|
* along the printing line. (Applicable also to display devices and the skip
|
|
* function on punched cards.)
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte HT = 9;
|
|
|
|
/**
|
|
* Line Feed ('\n'): A format effector which controls the movement of the
|
|
* printing position to the next printing line. (Applicable also to display
|
|
* devices.) Where appropriate, this character may have the meaning "New Line"
|
|
* (NL), a format effector which controls the movement of the printing point to
|
|
* the first printing position on the next printing line. Use of this convention
|
|
* requires agreement between sender and recipient of data.
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte LF = 10;
|
|
|
|
/**
|
|
* Alternate name for {@link #LF}. ({@code LF} is preferred.)
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte NL = 10;
|
|
|
|
/**
|
|
* Vertical Tabulation ('\v'): A format effector which controls the movement of
|
|
* the printing position to the next in a series of predetermined printing
|
|
* lines. (Applicable also to display devices.)
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte VT = 11;
|
|
|
|
/**
|
|
* Form Feed ('\f'): A format effector which controls the movement of the
|
|
* printing position to the first pre-determined printing line on the next form
|
|
* or page. (Applicable also to display devices.)
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte FF = 12;
|
|
|
|
/**
|
|
* Carriage Return ('\r'): A format effector which controls the movement of the
|
|
* printing position to the first printing position on the same printing line.
|
|
* (Applicable also to display devices.)
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte CR = 13;
|
|
|
|
/**
|
|
* Shift Out: A control character indicating that the code combinations which
|
|
* follow shall be interpreted as outside of the character set of the standard
|
|
* code table until a Shift In character is reached.
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte SO = 14;
|
|
|
|
/**
|
|
* Shift In: A control character indicating that the code combinations which
|
|
* follow shall be interpreted according to the standard code table.
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte SI = 15;
|
|
|
|
/**
|
|
* Data Link Escape: A communication control character which will change the
|
|
* meaning of a limited number of contiguously following characters. It is used
|
|
* exclusively to provide supplementary controls in data communication networks.
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte DLE = 16;
|
|
|
|
/**
|
|
* Device Control 1. Characters for the control of ancillary devices associated
|
|
* with data processing or telecommunication systems, more especially switching
|
|
* devices "on" or "off." (If a single "stop" control is required to interrupt
|
|
* or turn off ancillary devices, DC4 is the preferred assignment.)
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte DC1 = 17; // aka XON
|
|
|
|
/**
|
|
* Transmission On: Although originally defined as DC1, this ASCII control
|
|
* character is now better known as the XON code used for software flow control
|
|
* in serial communications. The main use is restarting the transmission after
|
|
* the communication has been stopped by the XOFF control code.
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte XON = 17; // aka DC1
|
|
|
|
/**
|
|
* Device Control 2. Characters for the control of ancillary devices associated
|
|
* with data processing or telecommunication systems, more especially switching
|
|
* devices "on" or "off." (If a single "stop" control is required to interrupt
|
|
* or turn off ancillary devices, DC4 is the preferred assignment.)
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte DC2 = 18;
|
|
|
|
/**
|
|
* Device Control 3. Characters for the control of ancillary devices associated
|
|
* with data processing or telecommunication systems, more especially switching
|
|
* devices "on" or "off." (If a single "stop" control is required to interrupt
|
|
* or turn off ancillary devices, DC4 is the preferred assignment.)
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte DC3 = 19; // aka XOFF
|
|
|
|
/**
|
|
* Transmission off. See {@link #XON} for explanation.
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte XOFF = 19; // aka DC3
|
|
|
|
/**
|
|
* Device Control 4. Characters for the control of ancillary devices associated
|
|
* with data processing or telecommunication systems, more especially switching
|
|
* devices "on" or "off." (If a single "stop" control is required to interrupt
|
|
* or turn off ancillary devices, DC4 is the preferred assignment.)
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte DC4 = 20;
|
|
|
|
/**
|
|
* Negative Acknowledge: A communication control character transmitted by a
|
|
* receiver as a negative response to the sender.
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte NAK = 21;
|
|
|
|
/**
|
|
* Synchronous Idle: A communication control character used by a synchronous
|
|
* transmission system in the absence of any other character to provide a signal
|
|
* from which synchronism may be achieved or retained.
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte SYN = 22;
|
|
|
|
/**
|
|
* End of Transmission Block: A communication control character used to indicate
|
|
* the end of a block of data for communication purposes. ETB is used for
|
|
* blocking data where the block structure is not necessarily related to the
|
|
* processing format.
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte ETB = 23;
|
|
|
|
/**
|
|
* Cancel: A control character used to indicate that the data with which it is
|
|
* sent is in error or is to be disregarded.
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte CAN = 24;
|
|
|
|
/**
|
|
* End of Medium: A control character associated with the sent data which may be
|
|
* used to identify the physical end of the medium, or the end of the used, or
|
|
* wanted, portion of information recorded on a medium. (The position of this
|
|
* character does not necessarily correspond to the physical end of the medium.)
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte EM = 25;
|
|
|
|
/**
|
|
* Substitute: A character that may be substituted for a character which is
|
|
* determined to be invalid or in error.
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte SUB = 26;
|
|
|
|
/**
|
|
* Escape: A control character intended to provide code extension (supplementary
|
|
* characters) in general information interchange. The Escape character itself
|
|
* is a prefix affecting the interpretation of a limited number of contiguously
|
|
* following characters.
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte ESC = 27;
|
|
|
|
/**
|
|
* File Separator: These four information separators may be used within data in
|
|
* optional fashion, except that their hierarchical relationship shall be: FS is
|
|
* the most inclusive, then GS, then RS, and US is least inclusive. (The content
|
|
* and length of a File, Group, Record, or Unit are not specified.)
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte FS = 28;
|
|
|
|
/**
|
|
* Group Separator: These four information separators may be used within data in
|
|
* optional fashion, except that their hierarchical relationship shall be: FS is
|
|
* the most inclusive, then GS, then RS, and US is least inclusive. (The content
|
|
* and length of a File, Group, Record, or Unit are not specified.)
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte GS = 29;
|
|
|
|
/**
|
|
* Record Separator: These four information separators may be used within data
|
|
* in optional fashion, except that their hierarchical relationship shall be: FS
|
|
* is the most inclusive, then GS, then RS, and US is least inclusive. (The
|
|
* content and length of a File, Group, Record, or Unit are not specified.)
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte RS = 30;
|
|
|
|
/**
|
|
* Unit Separator: These four information separators may be used within data in
|
|
* optional fashion, except that their hierarchical relationship shall be: FS is
|
|
* the most inclusive, then GS, then RS, and US is least inclusive. (The content
|
|
* and length of a File, Group, Record, or Unit are not specified.)
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte US = 31;
|
|
|
|
/**
|
|
* Space: A normally non-printing graphic character used to separate words. It
|
|
* is also a format effector which controls the movement of the printing
|
|
* position, one printing position forward. (Applicable also to display
|
|
* devices.)
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte SP = 32;
|
|
|
|
/**
|
|
* Alternate name for {@link #SP}.
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte SPACE = 32;
|
|
|
|
/**
|
|
* Delete: This character is used primarily to "erase" or "obliterate" erroneous
|
|
* or unwanted characters in perforated tape.
|
|
*
|
|
* @since 8.0
|
|
*/
|
|
public static final byte DEL = 127;
|
|
|
|
/**
|
|
* The minimum value of an ASCII character.
|
|
*
|
|
* @since 9.0 (was type {@code int} before 12.0)
|
|
*/
|
|
public static final char MIN = 0;
|
|
|
|
/**
|
|
* The maximum value of an ASCII character.
|
|
*
|
|
* @since 9.0 (was type {@code int} before 12.0)
|
|
*/
|
|
public static final char MAX = 127;
|
|
|
|
/**
|
|
* Returns a copy of the input string in which all
|
|
* {@linkplain #isUpperCase(char) uppercase ASCII characters} have been
|
|
* converted to lowercase. All other characters are copied without modification.
|
|
*/
|
|
public static String toLowerCase(String string) {
|
|
int length = string.length();
|
|
for (int i = 0; i < length; i++) {
|
|
if (isUpperCase(string.charAt(i))) {
|
|
char[] chars = string.toCharArray();
|
|
for (; i < length; i++) {
|
|
char c = chars[i];
|
|
if (isUpperCase(c)) {
|
|
chars[i] = (char) (c ^ 0x20);
|
|
}
|
|
}
|
|
return String.valueOf(chars);
|
|
}
|
|
}
|
|
return string;
|
|
}
|
|
|
|
/**
|
|
* Returns a copy of the input character sequence in which all
|
|
* {@linkplain #isUpperCase(char) uppercase ASCII characters} have been
|
|
* converted to lowercase. All other characters are copied without modification.
|
|
*
|
|
* @since 14.0
|
|
*/
|
|
public static String toLowerCase(CharSequence chars) {
|
|
if (chars instanceof String) {
|
|
return toLowerCase((String) chars);
|
|
}
|
|
int length = chars.length();
|
|
StringBuilder builder = new StringBuilder(length);
|
|
for (int i = 0; i < length; i++) {
|
|
builder.append(toLowerCase(chars.charAt(i)));
|
|
}
|
|
return builder.toString();
|
|
}
|
|
|
|
/**
|
|
* If the argument is an {@linkplain #isUpperCase(char) uppercase ASCII
|
|
* character} returns the lowercase equivalent. Otherwise returns the argument.
|
|
*/
|
|
public static char toLowerCase(char c) {
|
|
return isUpperCase(c) ? (char) (c ^ 0x20) : c;
|
|
}
|
|
|
|
/**
|
|
* Returns a copy of the input string in which all
|
|
* {@linkplain #isLowerCase(char) lowercase ASCII characters} have been
|
|
* converted to uppercase. All other characters are copied without modification.
|
|
*/
|
|
public static String toUpperCase(String string) {
|
|
int length = string.length();
|
|
for (int i = 0; i < length; i++) {
|
|
if (isLowerCase(string.charAt(i))) {
|
|
char[] chars = string.toCharArray();
|
|
for (; i < length; i++) {
|
|
char c = chars[i];
|
|
if (isLowerCase(c)) {
|
|
chars[i] = (char) (c & 0x5f);
|
|
}
|
|
}
|
|
return String.valueOf(chars);
|
|
}
|
|
}
|
|
return string;
|
|
}
|
|
|
|
/**
|
|
* Returns a copy of the input character sequence in which all
|
|
* {@linkplain #isLowerCase(char) lowercase ASCII characters} have been
|
|
* converted to uppercase. All other characters are copied without modification.
|
|
*
|
|
* @since 14.0
|
|
*/
|
|
public static String toUpperCase(CharSequence chars) {
|
|
if (chars instanceof String) {
|
|
return toUpperCase((String) chars);
|
|
}
|
|
int length = chars.length();
|
|
StringBuilder builder = new StringBuilder(length);
|
|
for (int i = 0; i < length; i++) {
|
|
builder.append(toUpperCase(chars.charAt(i)));
|
|
}
|
|
return builder.toString();
|
|
}
|
|
|
|
/**
|
|
* If the argument is a {@linkplain #isLowerCase(char) lowercase ASCII
|
|
* character} returns the uppercase equivalent. Otherwise returns the argument.
|
|
*/
|
|
public static char toUpperCase(char c) {
|
|
return isLowerCase(c) ? (char) (c & 0x5f) : c;
|
|
}
|
|
|
|
/**
|
|
* Indicates whether {@code c} is one of the twenty-six lowercase ASCII
|
|
* alphabetic characters between {@code 'a'} and {@code 'z'} inclusive. All
|
|
* others (including non-ASCII characters) return {@code false}.
|
|
*/
|
|
public static boolean isLowerCase(char c) {
|
|
// Note: This was benchmarked against the alternate expression "(char)(c - 'a')
|
|
// < 26" (Nov '13)
|
|
// and found to perform at least as well, or better.
|
|
return (c >= 'a') && (c <= 'z');
|
|
}
|
|
|
|
/**
|
|
* Indicates whether {@code c} is one of the twenty-six uppercase ASCII
|
|
* alphabetic characters between {@code 'A'} and {@code 'Z'} inclusive. All
|
|
* others (including non-ASCII characters) return {@code false}.
|
|
*/
|
|
public static boolean isUpperCase(char c) {
|
|
return (c >= 'A') && (c <= 'Z');
|
|
}
|
|
|
|
/**
|
|
* Truncates the given character sequence to the given maximum length. If the
|
|
* length of the sequence is greater than {@code maxLength}, the returned string
|
|
* will be exactly {@code maxLength} chars in length and will end with the given
|
|
* {@code truncationIndicator}. Otherwise, the sequence will be returned as a
|
|
* string with no changes to the content.
|
|
*
|
|
* <p>
|
|
* Examples:
|
|
*
|
|
* <pre>
|
|
* {@code
|
|
* Ascii.truncate("foobar", 7, "..."); // returns "foobar"
|
|
* Ascii.truncate("foobar", 5, "..."); // returns "fo..." }
|
|
* </pre>
|
|
*
|
|
* <p>
|
|
* <b>Note:</b> This method <i>may</i> work with certain non-ASCII text but is
|
|
* not safe for use with arbitrary Unicode text. It is mostly intended for use
|
|
* with text that is known to be safe for use with it (such as all-ASCII text)
|
|
* and for simple debugging text. When using this method, consider the
|
|
* following:
|
|
*
|
|
* <ul>
|
|
* <li>it may split surrogate pairs</li>
|
|
* <li>it may split characters and combining characters</li>
|
|
* <li>it does not consider word boundaries</li>
|
|
* <li>if truncating for display to users, there are other considerations that
|
|
* must be taken into account</li>
|
|
* <li>the appropriate truncation indicator may be locale-dependent</li>
|
|
* <li>it is safe to use non-ASCII characters in the truncation indicator</li>
|
|
* </ul>
|
|
*
|
|
*
|
|
* @throws IllegalArgumentException if {@code maxLength} is less than the length
|
|
* of {@code truncationIndicator}
|
|
* @since 16.0
|
|
*/
|
|
@Beta
|
|
@CheckReturnValue
|
|
public static String truncate(CharSequence seq, int maxLength, String truncationIndicator) {
|
|
checkNotNull(seq);
|
|
|
|
// length to truncate the sequence to, not including the truncation indicator
|
|
int truncationLength = maxLength - truncationIndicator.length();
|
|
|
|
// in this worst case, this allows a maxLength equal to the length of the
|
|
// truncationIndicator,
|
|
// meaning that a string will be truncated to just the truncation indicator
|
|
// itself
|
|
checkArgument(truncationLength >= 0, "maxLength (%s) must be >= length of the truncation indicator (%s)",
|
|
maxLength, truncationIndicator.length());
|
|
|
|
if (seq.length() <= maxLength) {
|
|
String string = seq.toString();
|
|
if (string.length() <= maxLength) {
|
|
return string;
|
|
}
|
|
// if the length of the toString() result was > maxLength for some reason,
|
|
// truncate that
|
|
seq = string;
|
|
}
|
|
|
|
return new StringBuilder(maxLength).append(seq, 0, truncationLength).append(truncationIndicator).toString();
|
|
}
|
|
|
|
/**
|
|
* Indicates whether the contents of the given character sequences {@code s1}
|
|
* and {@code s2} are equal, ignoring the case of any ASCII alphabetic
|
|
* characters between {@code 'a'} and {@code 'z'} or {@code 'A'} and {@code 'Z'}
|
|
* inclusive.
|
|
*
|
|
* <p>
|
|
* This method is significantly faster than {@link String#equalsIgnoreCase} and
|
|
* should be used in preference if at least one of the parameters is known to
|
|
* contain only ASCII characters.
|
|
*
|
|
* <p>
|
|
* Note however that this method does not always behave identically to
|
|
* expressions such as:
|
|
* <ul>
|
|
* <li>{@code string.toUpperCase().equals("UPPER CASE ASCII")}
|
|
* <li>{@code string.toLowerCase().equals("lower case ascii")}
|
|
* </ul>
|
|
* <p>
|
|
* due to case-folding of some non-ASCII characters (which does not occur in
|
|
* {@link String#equalsIgnoreCase}). However in almost all cases that ASCII
|
|
* strings are used, the author probably wanted the behavior provided by this
|
|
* method rather than the subtle and sometimes surprising behavior of
|
|
* {@code toUpperCase()} and {@code toLowerCase()}.
|
|
*
|
|
* @since 16.0
|
|
*/
|
|
@Beta
|
|
public static boolean equalsIgnoreCase(CharSequence s1, CharSequence s2) {
|
|
// Calling length() is the null pointer check (so do it before we can exit
|
|
// early).
|
|
int length = s1.length();
|
|
if (s1 == s2) {
|
|
return true;
|
|
}
|
|
if (length != s2.length()) {
|
|
return false;
|
|
}
|
|
for (int i = 0; i < length; i++) {
|
|
char c1 = s1.charAt(i);
|
|
char c2 = s2.charAt(i);
|
|
if (c1 == c2) {
|
|
continue;
|
|
}
|
|
int alphaIndex = getAlphaIndex(c1);
|
|
// This was also benchmarked using '&' to avoid branching (but always evaluate
|
|
// the rhs),
|
|
// however this showed no obvious improvement.
|
|
if (alphaIndex < 26 && alphaIndex == getAlphaIndex(c2)) {
|
|
continue;
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Returns the non-negative index value of the alpha character {@code c},
|
|
* regardless of case. Ie, 'a'/'A' returns 0 and 'z'/'Z' returns 25. Non-alpha
|
|
* characters return a value of 26 or greater.
|
|
*/
|
|
private static int getAlphaIndex(char c) {
|
|
// Fold upper-case ASCII to lower-case and make zero-indexed and unsigned (by
|
|
// casting to char).
|
|
return (char) ((c | 0x20) - 'a');
|
|
}
|
|
}
|