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 behaviour in more detail.</p>
025 * 
026 * <p>#ThreadSafe#</p>
027 * @since 2.1
028 * @version $Id: CharUtils.java 1531257 2013-10-11 11:25:28Z britter $
029 */
030public class CharUtils {
031    
032    private static final String[] CHAR_STRING_ARRAY = new String[128];
033    
034    /**
035     * {@code \u000a} linefeed LF ('\n').
036     * 
037     * @see <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences
038     *      for Character and String Literals</a>
039     * @since 2.2
040     */
041    public static final char LF = '\n';
042
043    /**
044     * {@code \u000d} carriage return CR ('\r').
045     * 
046     * @see <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences
047     *      for Character and String Literals</a>
048     * @since 2.2
049     */
050    public static final char CR = '\r';
051    
052
053    static {
054        for (char c = 0; c < CHAR_STRING_ARRAY.length; c++) {
055            CHAR_STRING_ARRAY[c] = String.valueOf(c);
056        }
057    }
058
059    /**
060     * <p>{@code CharUtils} instances should NOT be constructed in standard programming.
061     * Instead, the class should be used as {@code CharUtils.toString('c');}.</p>
062     *
063     * <p>This constructor is public to permit tools that require a JavaBean instance
064     * to operate.</p>
065     */
066    public CharUtils() {
067      super();
068    }
069
070    //-----------------------------------------------------------------------
071    /**
072     * <p>Converts the character to a Character.</p>
073     * 
074     * <p>For ASCII 7 bit characters, this uses a cache that will return the
075     * same Character object each time.</p>
076     *
077     * <pre>
078     *   CharUtils.toCharacterObject(' ')  = ' '
079     *   CharUtils.toCharacterObject('A')  = 'A'
080     * </pre>
081     *
082     * @deprecated Java 5 introduced {@link Character#valueOf(char)} which caches chars 0 through 127.
083     * @param ch  the character to convert
084     * @return a Character of the specified character
085     */
086    @Deprecated
087    public static Character toCharacterObject(final char ch) {
088        return Character.valueOf(ch);
089    }
090    
091    /**
092     * <p>Converts the String to a Character using the first character, returning
093     * null for empty Strings.</p>
094     * 
095     * <p>For ASCII 7 bit characters, this uses a cache that will return the
096     * same Character object each time.</p>
097     * 
098     * <pre>
099     *   CharUtils.toCharacterObject(null) = null
100     *   CharUtils.toCharacterObject("")   = null
101     *   CharUtils.toCharacterObject("A")  = 'A'
102     *   CharUtils.toCharacterObject("BA") = 'B'
103     * </pre>
104     *
105     * @param str  the character to convert
106     * @return the Character value of the first letter of the String
107     */
108    public static Character toCharacterObject(final String str) {
109        if (StringUtils.isEmpty(str)) {
110            return null;
111        }
112        return Character.valueOf(str.charAt(0));
113    }
114    
115    //-----------------------------------------------------------------------
116    /**
117     * <p>Converts the Character to a char throwing an exception for {@code null}.</p>
118     * 
119     * <pre>
120     *   CharUtils.toChar(' ')  = ' '
121     *   CharUtils.toChar('A')  = 'A'
122     *   CharUtils.toChar(null) throws IllegalArgumentException
123     * </pre>
124     *
125     * @param ch  the character to convert
126     * @return the char value of the Character
127     * @throws IllegalArgumentException if the Character is null
128     */
129    public static char toChar(final Character ch) {
130        if (ch == null) {
131            throw new IllegalArgumentException("The Character must not be null");
132        }
133        return ch.charValue();
134    }
135    
136    /**
137     * <p>Converts the Character to a char handling {@code null}.</p>
138     * 
139     * <pre>
140     *   CharUtils.toChar(null, 'X') = 'X'
141     *   CharUtils.toChar(' ', 'X')  = ' '
142     *   CharUtils.toChar('A', 'X')  = 'A'
143     * </pre>
144     *
145     * @param ch  the character to convert
146     * @param defaultValue  the value to use if the  Character is null
147     * @return the char value of the Character or the default if null
148     */
149    public static char toChar(final Character ch, final char defaultValue) {
150        if (ch == null) {
151            return defaultValue;
152        }
153        return ch.charValue();
154    }
155    
156    //-----------------------------------------------------------------------
157    /**
158     * <p>Converts the String to a char using the first character, throwing
159     * an exception on empty Strings.</p>
160     * 
161     * <pre>
162     *   CharUtils.toChar("A")  = 'A'
163     *   CharUtils.toChar("BA") = 'B'
164     *   CharUtils.toChar(null) throws IllegalArgumentException
165     *   CharUtils.toChar("")   throws IllegalArgumentException
166     * </pre>
167     *
168     * @param str  the character to convert
169     * @return the char value of the first letter of the String
170     * @throws IllegalArgumentException if the String is empty
171     */
172    public static char toChar(final String str) {
173        if (StringUtils.isEmpty(str)) {
174            throw new IllegalArgumentException("The String must not be empty");
175        }
176        return str.charAt(0);
177    }
178    
179    /**
180     * <p>Converts the String to a char using the first character, defaulting
181     * the value on empty Strings.</p>
182     * 
183     * <pre>
184     *   CharUtils.toChar(null, 'X') = 'X'
185     *   CharUtils.toChar("", 'X')   = 'X'
186     *   CharUtils.toChar("A", 'X')  = 'A'
187     *   CharUtils.toChar("BA", 'X') = 'B'
188     * </pre>
189     *
190     * @param str  the character to convert
191     * @param defaultValue  the value to use if the  Character is null
192     * @return the char value of the first letter of the String or the default if null
193     */
194    public static char toChar(final String str, final char defaultValue) {
195        if (StringUtils.isEmpty(str)) {
196            return defaultValue;
197        }
198        return str.charAt(0);
199    }
200    
201    //-----------------------------------------------------------------------
202    /**
203     * <p>Converts the character to the Integer it represents, throwing an
204     * exception if the character is not numeric.</p>
205     * 
206     * <p>This method coverts the char '1' to the int 1 and so on.</p>
207     *
208     * <pre>
209     *   CharUtils.toIntValue('3')  = 3
210     *   CharUtils.toIntValue('A')  throws IllegalArgumentException
211     * </pre>
212     *
213     * @param ch  the character to convert
214     * @return the int value of the character
215     * @throws IllegalArgumentException if the character is not ASCII numeric
216     */
217    public static int toIntValue(final char ch) {
218        if (isAsciiNumeric(ch) == false) {
219            throw new IllegalArgumentException("The character " + ch + " is not in the range '0' - '9'");
220        }
221        return ch - 48;
222    }
223    
224    /**
225     * <p>Converts the character to the Integer it represents, throwing an
226     * exception if the character is not numeric.</p>
227     * 
228     * <p>This method coverts the char '1' to the int 1 and so on.</p>
229     *
230     * <pre>
231     *   CharUtils.toIntValue('3', -1)  = 3
232     *   CharUtils.toIntValue('A', -1)  = -1
233     * </pre>
234     *
235     * @param ch  the character to convert
236     * @param defaultValue  the default value to use if the character is not numeric
237     * @return the int value of the character
238     */
239    public static int toIntValue(final char ch, final int defaultValue) {
240        if (isAsciiNumeric(ch) == false) {
241            return defaultValue;
242        }
243        return ch - 48;
244    }
245    
246    /**
247     * <p>Converts the character to the Integer it represents, throwing an
248     * exception if the character is not numeric.</p>
249     * 
250     * <p>This method coverts the char '1' to the int 1 and so on.</p>
251     *
252     * <pre>
253     *   CharUtils.toIntValue('3')  = 3
254     *   CharUtils.toIntValue(null) throws IllegalArgumentException
255     *   CharUtils.toIntValue('A')  throws IllegalArgumentException
256     * </pre>
257     *
258     * @param ch  the character to convert, not null
259     * @return the int value of the character
260     * @throws IllegalArgumentException if the Character is not ASCII numeric or is null
261     */
262    public static int toIntValue(final Character ch) {
263        if (ch == null) {
264            throw new IllegalArgumentException("The character must not be null");
265        }
266        return toIntValue(ch.charValue());
267    }
268    
269    /**
270     * <p>Converts the character to the Integer it represents, throwing an
271     * exception if the character is not numeric.</p>
272     * 
273     * <p>This method coverts the char '1' to the int 1 and so on.</p>
274     *
275     * <pre>
276     *   CharUtils.toIntValue(null, -1) = -1
277     *   CharUtils.toIntValue('3', -1)  = 3
278     *   CharUtils.toIntValue('A', -1)  = -1
279     * </pre>
280     *
281     * @param ch  the character to convert
282     * @param defaultValue  the default value to use if the character is not numeric
283     * @return the int value of the character
284     */
285    public static int toIntValue(final Character ch, final int defaultValue) {
286        if (ch == null) {
287            return defaultValue;
288        }
289        return toIntValue(ch.charValue(), defaultValue);
290    }
291    
292    //-----------------------------------------------------------------------
293    /**
294     * <p>Converts the character to a String that contains the one character.</p>
295     * 
296     * <p>For ASCII 7 bit characters, this uses a cache that will return the
297     * same String object each time.</p>
298     *
299     * <pre>
300     *   CharUtils.toString(' ')  = " "
301     *   CharUtils.toString('A')  = "A"
302     * </pre>
303     *
304     * @param ch  the character to convert
305     * @return a String containing the one specified character
306     */
307    public static String toString(final char ch) {
308        if (ch < 128) {
309            return CHAR_STRING_ARRAY[ch];
310        }
311        return new String(new char[] {ch});
312    }
313    
314    /**
315     * <p>Converts the character to a String that contains the one character.</p>
316     * 
317     * <p>For ASCII 7 bit characters, this uses a cache that will return the
318     * same String object each time.</p>
319     * 
320     * <p>If {@code null} is passed in, {@code null} will be returned.</p>
321     *
322     * <pre>
323     *   CharUtils.toString(null) = null
324     *   CharUtils.toString(' ')  = " "
325     *   CharUtils.toString('A')  = "A"
326     * </pre>
327     *
328     * @param ch  the character to convert
329     * @return a String containing the one specified character
330     */
331    public static String toString(final Character ch) {
332        if (ch == null) {
333            return null;
334        }
335        return toString(ch.charValue());
336    }
337    
338    //--------------------------------------------------------------------------
339    /**
340     * <p>Converts the string to the Unicode format '\u0020'.</p>
341     * 
342     * <p>This format is the Java source code format.</p>
343     *
344     * <pre>
345     *   CharUtils.unicodeEscaped(' ') = "\u0020"
346     *   CharUtils.unicodeEscaped('A') = "\u0041"
347     * </pre>
348     * 
349     * @param ch  the character to convert
350     * @return the escaped Unicode string
351     */
352    public static String unicodeEscaped(final char ch) {
353        if (ch < 0x10) {
354            return "\\u000" + Integer.toHexString(ch);
355        } else if (ch < 0x100) {
356            return "\\u00" + Integer.toHexString(ch);
357        } else if (ch < 0x1000) {
358            return "\\u0" + Integer.toHexString(ch);
359        }
360        return "\\u" + Integer.toHexString(ch);
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}