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     */
017    package 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 1158279 2011-08-16 14:06:45Z ggregory $
029     */
030    public 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://java.sun.com/docs/books/jls/third_edition/html/lexical.html#101089">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://java.sun.com/docs/books/jls/third_edition/html/lexical.html#101089">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(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(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(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(Character ch, 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(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(String str, 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(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(char ch, 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(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(Character ch, 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(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(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(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(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(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(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(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(char ch) {
460            return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
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(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(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(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(char ch) {
536            return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9');
537        }
538        
539    }