    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *      http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017package org.apache.commons.lang3;
    018
    019/**
    020 * <p>Operations on char primitives and Character objects.</p>
    021 *
    022 * <p>This class tries to handle {@code null} input gracefully.
    023 * An exception will not be thrown for a {@code null} input.
    024 * Each method documents its behavior in more detail.</p>
    025 *
    026 * <p>#ThreadSafe#</p>
    027 * @since 2.1
    028 */
    029public class CharUtils {
    030
    031    private static final String[] CHAR_STRING_ARRAY = new String[128];
    032
    033    private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
    034
    035    /**
    036     * Linefeed character LF ({@code '\n'}, Unicode 000a).
    037     *
    038     * @see <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences
    039     *      for Character and String Literals</a>
    040     * @since 2.2
    041     */
    042    public static final char LF = '\n';
    043
    044    /**
    045     * Carriage return characterf CR ('\r', Unicode 000d).
    046     *
    047     * @see <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences
    048     *      for Character and String Literals</a>
    049     * @since 2.2
    050     */
    051    public static final char CR = '\r';
    052
    053    /**
    054     * {@code \u0000} null control character ('\0'), abbreviated NUL.
    055     *
    056     * @since 3.6
    057     */
    058    public static final char NUL = '\0';
    059
    060    static {
    061        for (char c = 0; c < CHAR_STRING_ARRAY.length; c++) {
    062            CHAR_STRING_ARRAY[c] = String.valueOf(c);
    063        }
    064    }
    065
    066    /**
    067     * <p>{@code CharUtils} instances should NOT be constructed in standard programming.
    068     * Instead, the class should be used as {@code CharUtils.toString('c');}.</p>
    069     *
    070     * <p>This constructor is public to permit tools that require a JavaBean instance
    071     * to operate.</p>
    072     */
    073    public CharUtils() {
    074      super();
    075    }
    076
    077    //-----------------------------------------------------------------------
    078    /**
    079     * <p>Converts the character to a Character.</p>
    080     *
    081     * <p>For ASCII 7 bit characters, this uses a cache that will return the
    082     * same Character object each time.</p>
    083     *
    084     * <pre>
    085     *   CharUtils.toCharacterObject(' ')  = ' '
    086     *   CharUtils.toCharacterObject('A')  = 'A'
    087     * </pre>
    088     *
    089     * @deprecated Java 5 introduced {@link Character#valueOf(char)} which caches chars 0 through 127.
    090     * @param ch  the character to convert
    091     * @return a Character of the specified character
    092     */
    093    @Deprecated
    094    public static Character toCharacterObject(final char ch) {
    095        return Character.valueOf(ch);
    096    }
    097
    098    /**
    099     * <p>Converts the String to a Character using the first character, returning
    100     * null for empty Strings.</p>
    101     *
    102     * <p>For ASCII 7 bit characters, this uses a cache that will return the
    103     * same Character object each time.</p>
    104     *
    105     * <pre>
    106     *   CharUtils.toCharacterObject(null) = null
    107     *   CharUtils.toCharacterObject("")   = null
    108     *   CharUtils.toCharacterObject("A")  = 'A'
    109     *   CharUtils.toCharacterObject("BA") = 'B'
    110     * </pre>
    111     *
    112     * @param str  the character to convert
    113     * @return the Character value of the first letter of the String
    114     */
    115    public static Character toCharacterObject(final String str) {
    116        if (StringUtils.isEmpty(str)) {
    117            return null;
    118        }
    119        return Character.valueOf(str.charAt(0));
    120    }
    121
    122    //-----------------------------------------------------------------------
    123    /**
    124     * <p>Converts the Character to a char throwing an exception for {@code null}.</p>
    125     *
    126     * <pre>
    127     *   CharUtils.toChar(' ')  = ' '
    128     *   CharUtils.toChar('A')  = 'A'
    129     *   CharUtils.toChar(null) throws IllegalArgumentException
    130     * </pre>
    131     *
    132     * @param ch  the character to convert
    133     * @return the char value of the Character
    134     * @throws NullPointerException if the Character is null
    135     */
    136    public static char toChar(final Character ch) {
    137        Validate.notNull(ch, "The Character must not be null");
    138        return ch.charValue();
    139    }
    140
    141    /**
    142     * <p>Converts the Character to a char handling {@code null}.</p>
    143     *
    144     * <pre>
    145     *   CharUtils.toChar(null, 'X') = 'X'
    146     *   CharUtils.toChar(' ', 'X')  = ' '
    147     *   CharUtils.toChar('A', 'X')  = 'A'
    148     * </pre>
    149     *
    150     * @param ch  the character to convert
    151     * @param defaultValue  the value to use if the  Character is null
    152     * @return the char value of the Character or the default if null
    153     */
    154    public static char toChar(final Character ch, final char defaultValue) {
    155        if (ch == null) {
    156            return defaultValue;
    157        }
    158        return ch.charValue();
    159    }
    160
    161    //-----------------------------------------------------------------------
    162    /**
    163     * <p>Converts the String to a char using the first character, throwing
    164     * an exception on empty Strings.</p>
    165     *
    166     * <pre>
    167     *   CharUtils.toChar("A")  = 'A'
    168     *   CharUtils.toChar("BA") = 'B'
    169     *   CharUtils.toChar(null) throws IllegalArgumentException
    170     *   CharUtils.toChar("")   throws IllegalArgumentException
    171     * </pre>
    172     *
    173     * @param str  the character to convert
    174     * @return the char value of the first letter of the String
    175     * @throws NullPointerException if the string is null
    176     * @throws IllegalArgumentException if the String is empty
    177     */
    178    public static char toChar(final String str) {
    179        Validate.notEmpty(str, "The String must not be empty");
    180        return str.charAt(0);
    181    }
    182
    183    /**
    184     * <p>Converts the String to a char using the first character, defaulting
    185     * the value on empty Strings.</p>
    186     *
    187     * <pre>
    188     *   CharUtils.toChar(null, 'X') = 'X'
    189     *   CharUtils.toChar("", 'X')   = 'X'
    190     *   CharUtils.toChar("A", 'X')  = 'A'
    191     *   CharUtils.toChar("BA", 'X') = 'B'
    192     * </pre>
    193     *
    194     * @param str  the character to convert
    195     * @param defaultValue  the value to use if the  Character is null
    196     * @return the char value of the first letter of the String or the default if null
    197     */
    198    public static char toChar(final String str, final char defaultValue) {
    199        if (StringUtils.isEmpty(str)) {
    200            return defaultValue;
    201        }
    202        return str.charAt(0);
    203    }
    204
    205    //-----------------------------------------------------------------------
    206    /**
    207     * <p>Converts the character to the Integer it represents, throwing an
    208     * exception if the character is not numeric.</p>
    209     *
    210     * <p>This method converts the char '1' to the int 1 and so on.</p>
    211     *
    212     * <pre>
    213     *   CharUtils.toIntValue('3')  = 3
    214     *   CharUtils.toIntValue('A')  throws IllegalArgumentException
    215     * </pre>
    216     *
    217     * @param ch  the character to convert
    218     * @return the int value of the character
    219     * @throws IllegalArgumentException if the character is not ASCII numeric
    220     */
    221    public static int toIntValue(final char ch) {
    222        if (!isAsciiNumeric(ch)) {
    223            throw new IllegalArgumentException("The character " + ch + " is not in the range '0' - '9'");
    224        }
    225        return ch - 48;
    226    }
    227
    228    /**
    229     * <p>Converts the character to the Integer it represents, throwing an
    230     * exception if the character is not numeric.</p>
    231     *
    232     * <p>This method converts the char '1' to the int 1 and so on.</p>
    233     *
    234     * <pre>
    235     *   CharUtils.toIntValue('3', -1)  = 3
    236     *   CharUtils.toIntValue('A', -1)  = -1
    237     * </pre>
    238     *
    239     * @param ch  the character to convert
    240     * @param defaultValue  the default value to use if the character is not numeric
    241     * @return the int value of the character
    242     */
    243    public static int toIntValue(final char ch, final int defaultValue) {
    244        if (!isAsciiNumeric(ch)) {
    245            return defaultValue;
    246        }
    247        return ch - 48;
    248    }
    249
    250    /**
    251     * <p>Converts the character to the Integer it represents, throwing an
    252     * exception if the character is not numeric.</p>
    253     *
    254     * <p>This method converts the char '1' to the int 1 and so on.</p>
    255     *
    256     * <pre>
    257     *   CharUtils.toIntValue('3')  = 3
    258     *   CharUtils.toIntValue(null) throws IllegalArgumentException
    259     *   CharUtils.toIntValue('A')  throws IllegalArgumentException
    260     * </pre>
    261     *
    262     * @param ch  the character to convert, not null
    263     * @return the int value of the character
    264     * @throws NullPointerException if the Character is null
    265     * @throws IllegalArgumentException if the Character is not ASCII numeric
    266     */
    267    public static int toIntValue(final Character ch) {
    268        Validate.notNull(ch, "The character must not be null");
    269        return toIntValue(ch.charValue());
    270    }
    271
    272    /**
    273     * <p>Converts the character to the Integer it represents, throwing an
    274     * exception if the character is not numeric.</p>
    275     *
    276     * <p>This method converts the char '1' to the int 1 and so on.</p>
    277     *
    278     * <pre>
    279     *   CharUtils.toIntValue(null, -1) = -1
    280     *   CharUtils.toIntValue('3', -1)  = 3
    281     *   CharUtils.toIntValue('A', -1)  = -1
    282     * </pre>
    283     *
    284     * @param ch  the character to convert
    285     * @param defaultValue  the default value to use if the character is not numeric
    286     * @return the int value of the character
    287     */
    288    public static int toIntValue(final Character ch, final int defaultValue) {
    289        if (ch == null) {
    290            return defaultValue;
    291        }
    292        return toIntValue(ch.charValue(), defaultValue);
    293    }
    294
    295    //-----------------------------------------------------------------------
    296    /**
    297     * <p>Converts the character to a String that contains the one character.</p>
    298     *
    299     * <p>For ASCII 7 bit characters, this uses a cache that will return the
    300     * same String object each time.</p>
    301     *
    302     * <pre>
    303     *   CharUtils.toString(' ')  = " "
    304     *   CharUtils.toString('A')  = "A"
    305     * </pre>
    306     *
    307     * @param ch  the character to convert
    308     * @return a String containing the one specified character
    309     */
    310    public static String toString(final char ch) {
    311        if (ch < 128) {
    312            return CHAR_STRING_ARRAY[ch];
    313        }
    314        return new String(new char[] {ch});
    315    }
    316
    317    /**
    318     * <p>Converts the character to a String that contains the one character.</p>
    319     *
    320     * <p>For ASCII 7 bit characters, this uses a cache that will return the
    321     * same String object each time.</p>
    322     *
    323     * <p>If {@code null} is passed in, {@code null} will be returned.</p>
    324     *
    325     * <pre>
    326     *   CharUtils.toString(null) = null
    327     *   CharUtils.toString(' ')  = " "
    328     *   CharUtils.toString('A')  = "A"
    329     * </pre>
    330     *
    331     * @param ch  the character to convert
    332     * @return a String containing the one specified character
    333     */
    334    public static String toString(final Character ch) {
    335        if (ch == null) {
    336            return null;
    337        }
    338        return toString(ch.charValue());
    339    }
    340
    341    //--------------------------------------------------------------------------
    342    /**
    343     * <p>Converts the string to the Unicode format '\u0020'.</p>
    344     *
    345     * <p>This format is the Java source code format.</p>
    346     *
    347     * <pre>
    348     *   CharUtils.unicodeEscaped(' ') = "\u0020"
    349     *   CharUtils.unicodeEscaped('A') = "\u0041"
    350     * </pre>
    351     *
    352     * @param ch  the character to convert
    353     * @return the escaped Unicode string
    354     */
    355    public static String unicodeEscaped(final char ch) {
    356        return "\\u" +
    357            HEX_DIGITS[(ch >> 12) & 15] +
    358            HEX_DIGITS[(ch >> 8) & 15] +
    359            HEX_DIGITS[(ch >> 4) & 15] +
    360            HEX_DIGITS[(ch) & 15];
    361    }
    362
    363    /**
    364     * <p>Converts the string to the Unicode format '\u0020'.</p>
    365     *
    366     * <p>This format is the Java source code format.</p>
    367     *
    368     * <p>If {@code null} is passed in, {@code null} will be returned.</p>
    369     *
    370     * <pre>
    371     *   CharUtils.unicodeEscaped(null) = null
    372     *   CharUtils.unicodeEscaped(' ')  = "\u0020"
    373     *   CharUtils.unicodeEscaped('A')  = "\u0041"
    374     * </pre>
    375     *
    376     * @param ch  the character to convert, may be null
    377     * @return the escaped Unicode string, null if null input
    378     */
    379    public static String unicodeEscaped(final Character ch) {
    380        if (ch == null) {
    381            return null;
    382        }
    383        return unicodeEscaped(ch.charValue());
    384    }
    385
    386    //--------------------------------------------------------------------------
    387    /**
    388     * <p>Checks whether the character is ASCII 7 bit.</p>
    389     *
    390     * <pre>
    391     *   CharUtils.isAscii('a')  = true
    392     *   CharUtils.isAscii('A')  = true
    393     *   CharUtils.isAscii('3')  = true
    394     *   CharUtils.isAscii('-')  = true
    395     *   CharUtils.isAscii('\n') = true
    396     *   CharUtils.isAscii('&copy;') = false
    397     * </pre>
    398     *
    399     * @param ch  the character to check
    400     * @return true if less than 128
    401     */
    402    public static boolean isAscii(final char ch) {
    403        return ch < 128;
    404    }
    405
    406    /**
    407     * <p>Checks whether the character is ASCII 7 bit printable.</p>
    408     *
    409     * <pre>
    410     *   CharUtils.isAsciiPrintable('a')  = true
    411     *   CharUtils.isAsciiPrintable('A')  = true
    412     *   CharUtils.isAsciiPrintable('3')  = true
    413     *   CharUtils.isAsciiPrintable('-')  = true
    414     *   CharUtils.isAsciiPrintable('\n') = false
    415     *   CharUtils.isAsciiPrintable('&copy;') = false
    416     * </pre>
    417     *
    418     * @param ch  the character to check
    419     * @return true if between 32 and 126 inclusive
    420     */
    421    public static boolean isAsciiPrintable(final char ch) {
    422        return ch >= 32 && ch < 127;
    423    }
    424
    425    /**
    426     * <p>Checks whether the character is ASCII 7 bit control.</p>
    427     *
    428     * <pre>
    429     *   CharUtils.isAsciiControl('a')  = false
    430     *   CharUtils.isAsciiControl('A')  = false
    431     *   CharUtils.isAsciiControl('3')  = false
    432     *   CharUtils.isAsciiControl('-')  = false
    433     *   CharUtils.isAsciiControl('\n') = true
    434     *   CharUtils.isAsciiControl('&copy;') = false
    435     * </pre>
    436     *
    437     * @param ch  the character to check
    438     * @return true if less than 32 or equals 127
    439     */
    440    public static boolean isAsciiControl(final char ch) {
    441        return ch < 32 || ch == 127;
    442    }
    443
    444    /**
    445     * <p>Checks whether the character is ASCII 7 bit alphabetic.</p>
    446     *
    447     * <pre>
    448     *   CharUtils.isAsciiAlpha('a')  = true
    449     *   CharUtils.isAsciiAlpha('A')  = true
    450     *   CharUtils.isAsciiAlpha('3')  = false
    451     *   CharUtils.isAsciiAlpha('-')  = false
    452     *   CharUtils.isAsciiAlpha('\n') = false
    453     *   CharUtils.isAsciiAlpha('&copy;') = false
    454     * </pre>
    455     *
    456     * @param ch  the character to check
    457     * @return true if between 65 and 90 or 97 and 122 inclusive
    458     */
    459    public static boolean isAsciiAlpha(final char ch) {
    460        return isAsciiAlphaUpper(ch) || isAsciiAlphaLower(ch);
    461    }
    462
    463    /**
    464     * <p>Checks whether the character is ASCII 7 bit alphabetic upper case.</p>
    465     *
    466     * <pre>
    467     *   CharUtils.isAsciiAlphaUpper('a')  = false
    468     *   CharUtils.isAsciiAlphaUpper('A')  = true
    469     *   CharUtils.isAsciiAlphaUpper('3')  = false
    470     *   CharUtils.isAsciiAlphaUpper('-')  = false
    471     *   CharUtils.isAsciiAlphaUpper('\n') = false
    472     *   CharUtils.isAsciiAlphaUpper('&copy;') = false
    473     * </pre>
    474     *
    475     * @param ch  the character to check
    476     * @return true if between 65 and 90 inclusive
    477     */
    478    public static boolean isAsciiAlphaUpper(final char ch) {
    479        return ch >= 'A' && ch <= 'Z';
    480    }
    481
    482    /**
    483     * <p>Checks whether the character is ASCII 7 bit alphabetic lower case.</p>
    484     *
    485     * <pre>
    486     *   CharUtils.isAsciiAlphaLower('a')  = true
    487     *   CharUtils.isAsciiAlphaLower('A')  = false
    488     *   CharUtils.isAsciiAlphaLower('3')  = false
    489     *   CharUtils.isAsciiAlphaLower('-')  = false
    490     *   CharUtils.isAsciiAlphaLower('\n') = false
    491     *   CharUtils.isAsciiAlphaLower('&copy;') = false
    492     * </pre>
    493     *
    494     * @param ch  the character to check
    495     * @return true if between 97 and 122 inclusive
    496     */
    497    public static boolean isAsciiAlphaLower(final char ch) {
    498        return ch >= 'a' && ch <= 'z';
    499    }
    500
    501    /**
    502     * <p>Checks whether the character is ASCII 7 bit numeric.</p>
    503     *
    504     * <pre>
    505     *   CharUtils.isAsciiNumeric('a')  = false
    506     *   CharUtils.isAsciiNumeric('A')  = false
    507     *   CharUtils.isAsciiNumeric('3')  = true
    508     *   CharUtils.isAsciiNumeric('-')  = false
    509     *   CharUtils.isAsciiNumeric('\n') = false
    510     *   CharUtils.isAsciiNumeric('&copy;') = false
    511     * </pre>
    512     *
    513     * @param ch  the character to check
    514     * @return true if between 48 and 57 inclusive
    515     */
    516    public static boolean isAsciiNumeric(final char ch) {
    517        return ch >= '0' && ch <= '9';
    518    }
    519
    520    /**
    521     * <p>Checks whether the character is ASCII 7 bit numeric.</p>
    522     *
    523     * <pre>
    524     *   CharUtils.isAsciiAlphanumeric('a')  = true
    525     *   CharUtils.isAsciiAlphanumeric('A')  = true
    526     *   CharUtils.isAsciiAlphanumeric('3')  = true
    527     *   CharUtils.isAsciiAlphanumeric('-')  = false
    528     *   CharUtils.isAsciiAlphanumeric('\n') = false
    529     *   CharUtils.isAsciiAlphanumeric('&copy;') = false
    530     * </pre>
    531     *
    532     * @param ch  the character to check
    533     * @return true if between 48 and 57 or 65 and 90 or 97 and 122 inclusive
    534     */
    535    public static boolean isAsciiAlphanumeric(final char ch) {
    536        return isAsciiAlpha(ch) || isAsciiNumeric(ch);
    537    }
    538
    539    /**
    540     * <p>Compares two {@code char} values numerically. This is the same functionality as provided in Java 7.</p>
    541     *
    542     * @param x the first {@code char} to compare
    543     * @param y the second {@code char} to compare
    544     * @return the value {@code 0} if {@code x == y};
    545     *         a value less than {@code 0} if {@code x < y}; and
    546     *         a value greater than {@code 0} if {@code x > y}
    547     * @since 3.4
    548     */
    549    public static int compare(final char x, final char y) {
    550        return x-y;
    551    }
    552}