1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.lang3;
18
19 import java.util.Objects;
20
21 /**
22 * Operations on char primitives and Character objects.
23 *
24 * <p>This class tries to handle {@code null} input gracefully.
25 * An exception will not be thrown for a {@code null} input.
26 * Each method documents its behavior in more detail.</p>
27 *
28 * <p>#ThreadSafe#</p>
29 *
30 * @since 2.1
31 */
32 public class CharUtils {
33
34 private static final String[] CHAR_STRING_ARRAY = ArrayUtils.setAll(new String[128], i -> String.valueOf((char) i));
35
36 private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
37
38 /**
39 * Linefeed character LF ({@code '\n'}, Unicode 000a).
40 *
41 * @see <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences
42 * for Character and String Literals</a>
43 * @since 2.2
44 */
45 public static final char LF = '\n';
46
47 /**
48 * Carriage return character CR ('\r', Unicode 000d).
49 *
50 * @see <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences
51 * for Character and String Literals</a>
52 * @since 2.2
53 */
54 public static final char CR = '\r';
55
56 /**
57 * {@code \u0000} null control character ('\0'), abbreviated NUL.
58 *
59 * @since 3.6
60 */
61 public static final char NUL = '\0';
62
63 /**
64 * Compares two {@code char} values numerically. This is the same functionality as provided in Java 7.
65 *
66 * @param x the first {@code char} to compare
67 * @param y the second {@code char} to compare
68 * @return the value {@code 0} if {@code x == y};
69 * a value less than {@code 0} if {@code x < y}; and
70 * a value greater than {@code 0} if {@code x > y}
71 * @since 3.4
72 */
73 public static int compare(final char x, final char y) {
74 return x - y;
75 }
76
77 /**
78 * Tests whether the character is ASCII 7 bit.
79 *
80 * <pre>
81 * CharUtils.isAscii('a') = true
82 * CharUtils.isAscii('A') = true
83 * CharUtils.isAscii('3') = true
84 * CharUtils.isAscii('-') = true
85 * CharUtils.isAscii('\n') = true
86 * CharUtils.isAscii('©') = false
87 * </pre>
88 *
89 * @param ch the character to check
90 * @return true if less than 128
91 */
92 public static boolean isAscii(final char ch) {
93 return ch < 128;
94 }
95
96 /**
97 * Tests whether the character is ASCII 7 bit alphabetic.
98 *
99 * <pre>
100 * CharUtils.isAsciiAlpha('a') = true
101 * CharUtils.isAsciiAlpha('A') = true
102 * CharUtils.isAsciiAlpha('3') = false
103 * CharUtils.isAsciiAlpha('-') = false
104 * CharUtils.isAsciiAlpha('\n') = false
105 * CharUtils.isAsciiAlpha('©') = false
106 * </pre>
107 *
108 * @param ch the character to check
109 * @return true if between 65 and 90 or 97 and 122 inclusive
110 */
111 public static boolean isAsciiAlpha(final char ch) {
112 return isAsciiAlphaUpper(ch) || isAsciiAlphaLower(ch);
113 }
114
115 /**
116 * Tests whether the character is ASCII 7 bit alphabetic lower case.
117 *
118 * <pre>
119 * CharUtils.isAsciiAlphaLower('a') = true
120 * CharUtils.isAsciiAlphaLower('A') = false
121 * CharUtils.isAsciiAlphaLower('3') = false
122 * CharUtils.isAsciiAlphaLower('-') = false
123 * CharUtils.isAsciiAlphaLower('\n') = false
124 * CharUtils.isAsciiAlphaLower('©') = false
125 * </pre>
126 *
127 * @param ch the character to check
128 * @return true if between 97 and 122 inclusive
129 */
130 public static boolean isAsciiAlphaLower(final char ch) {
131 return ch >= 'a' && ch <= 'z';
132 }
133
134 /**
135 * Tests whether the character is ASCII 7 bit alphanumeric character.
136 *
137 * <pre>
138 * CharUtils.isAsciiAlphanumeric('a') = true
139 * CharUtils.isAsciiAlphanumeric('A') = true
140 * CharUtils.isAsciiAlphanumeric('3') = true
141 * CharUtils.isAsciiAlphanumeric('-') = false
142 * CharUtils.isAsciiAlphanumeric('\n') = false
143 * CharUtils.isAsciiAlphanumeric('©') = false
144 * </pre>
145 *
146 * @param ch the character to check
147 * @return true if between 48 and 57 or 65 and 90 or 97 and 122 inclusive
148 */
149 public static boolean isAsciiAlphanumeric(final char ch) {
150 return isAsciiAlpha(ch) || isAsciiNumeric(ch);
151 }
152
153 /**
154 * Tests whether the character is ASCII 7 bit alphabetic upper case.
155 *
156 * <pre>
157 * CharUtils.isAsciiAlphaUpper('a') = false
158 * CharUtils.isAsciiAlphaUpper('A') = true
159 * CharUtils.isAsciiAlphaUpper('3') = false
160 * CharUtils.isAsciiAlphaUpper('-') = false
161 * CharUtils.isAsciiAlphaUpper('\n') = false
162 * CharUtils.isAsciiAlphaUpper('©') = false
163 * </pre>
164 *
165 * @param ch the character to check
166 * @return true if between 65 and 90 inclusive
167 */
168 public static boolean isAsciiAlphaUpper(final char ch) {
169 return ch >= 'A' && ch <= 'Z';
170 }
171
172 /**
173 * Tests whether the character is ASCII 7 bit control.
174 *
175 * <pre>
176 * CharUtils.isAsciiControl('a') = false
177 * CharUtils.isAsciiControl('A') = false
178 * CharUtils.isAsciiControl('3') = false
179 * CharUtils.isAsciiControl('-') = false
180 * CharUtils.isAsciiControl('\n') = true
181 * CharUtils.isAsciiControl('©') = false
182 * </pre>
183 *
184 * @param ch the character to check
185 * @return true if less than 32 or equals 127
186 */
187 public static boolean isAsciiControl(final char ch) {
188 return ch < 32 || ch == 127;
189 }
190
191 /**
192 * Tests whether the character is ASCII 7 bit numeric.
193 *
194 * <pre>
195 * CharUtils.isAsciiNumeric('a') = false
196 * CharUtils.isAsciiNumeric('A') = false
197 * CharUtils.isAsciiNumeric('3') = true
198 * CharUtils.isAsciiNumeric('-') = false
199 * CharUtils.isAsciiNumeric('\n') = false
200 * CharUtils.isAsciiNumeric('©') = false
201 * </pre>
202 *
203 * @param ch the character to check
204 * @return true if between 48 and 57 inclusive
205 */
206 public static boolean isAsciiNumeric(final char ch) {
207 return ch >= '0' && ch <= '9';
208 }
209
210 /**
211 * Tests whether the character is ASCII 7 bit printable.
212 *
213 * <pre>
214 * CharUtils.isAsciiPrintable('a') = true
215 * CharUtils.isAsciiPrintable('A') = true
216 * CharUtils.isAsciiPrintable('3') = true
217 * CharUtils.isAsciiPrintable('-') = true
218 * CharUtils.isAsciiPrintable('\n') = false
219 * CharUtils.isAsciiPrintable('©') = false
220 * </pre>
221 *
222 * @param ch the character to check
223 * @return true if between 32 and 126 inclusive
224 */
225 public static boolean isAsciiPrintable(final char ch) {
226 return ch >= 32 && ch < 127;
227 }
228
229 /**
230 * Tests whether a character is a hexadecimal character.
231 *
232 * <pre>
233 * CharUtils.isHex('0') = true
234 * CharUtils.isHex('3') = true
235 * CharUtils.isHex('9') = true
236 * CharUtils.isHex('a') = true
237 * CharUtils.isHex('f') = true
238 * CharUtils.isHex('g') = false
239 * CharUtils.isHex('A') = true
240 * CharUtils.isHex('F') = true
241 * CharUtils.isHex('G') = false
242 * CharUtils.isHex('#') = false
243 * CharUtils.isHex('-') = false
244 * CharUtils.isHex('\n') = false
245 * CharUtils.isHex('©') = false
246 * </pre>
247 *
248 * @param ch the character to test.
249 * @return true if character is a hexadecimal character.
250 * @since 3.18.0
251 */
252 public static boolean isHex(final char ch) {
253 return isAsciiNumeric(ch) || ch >= 'a' && ch <= 'f' || ch >= 'A' && ch <= 'F';
254 }
255
256 /**
257 * Tests if the given char is an octal digit. Octal digits are the character representations of the digits 0 to 7.
258 *
259 * @param ch the char to check
260 * @return true if the given char is the character representation of one of the digits from 0 to 7
261 * @since 3.18.0
262 */
263 public static boolean isOctal(final char ch) {
264 return ch >= '0' && ch <= '7';
265 }
266
267 /**
268 * Converts the Character to a char throwing an exception for {@code null}.
269 *
270 * <pre>
271 * CharUtils.toChar(' ') = ' '
272 * CharUtils.toChar('A') = 'A'
273 * CharUtils.toChar(null) throws NullPointerException
274 * </pre>
275 *
276 * @param ch the character to convert
277 * @return the char value of the Character
278 * @throws NullPointerException if the Character is null
279 */
280 public static char toChar(final Character ch) {
281 return Objects.requireNonNull(ch, "ch").charValue();
282 }
283
284 /**
285 * Converts the Character to a char handling {@code null}.
286 *
287 * <pre>
288 * CharUtils.toChar(null, 'X') = 'X'
289 * CharUtils.toChar(' ', 'X') = ' '
290 * CharUtils.toChar('A', 'X') = 'A'
291 * </pre>
292 *
293 * @param ch the character to convert
294 * @param defaultValue the value to use if the Character is null
295 * @return the char value of the Character or the default if null
296 */
297 public static char toChar(final Character ch, final char defaultValue) {
298 return ch != null ? ch.charValue() : defaultValue;
299 }
300
301 /**
302 * Converts the String to a char using the first character, throwing
303 * an exception on empty Strings.
304 *
305 * <pre>
306 * CharUtils.toChar("A") = 'A'
307 * CharUtils.toChar("BA") = 'B'
308 * CharUtils.toChar(null) throws NullPointerException
309 * CharUtils.toChar("") throws IllegalArgumentException
310 * </pre>
311 *
312 * @param str the character to convert
313 * @return the char value of the first letter of the String
314 * @throws NullPointerException if the string is null
315 * @throws IllegalArgumentException if the String is empty
316 */
317 public static char toChar(final String str) {
318 Validate.notEmpty(str, "The String must not be empty");
319 return str.charAt(0);
320 }
321
322 /**
323 * Converts the String to a char using the first character, defaulting
324 * the value on empty Strings.
325 *
326 * <pre>
327 * CharUtils.toChar(null, 'X') = 'X'
328 * CharUtils.toChar("", 'X') = 'X'
329 * CharUtils.toChar("A", 'X') = 'A'
330 * CharUtils.toChar("BA", 'X') = 'B'
331 * </pre>
332 *
333 * @param str the character to convert
334 * @param defaultValue the value to use if the Character is null
335 * @return the char value of the first letter of the String or the default if null
336 */
337 public static char toChar(final String str, final char defaultValue) {
338 return StringUtils.isEmpty(str) ? defaultValue : str.charAt(0);
339 }
340
341 /**
342 * Delegates to {@link Character#valueOf(char)}.
343 *
344 * @param c the character to convert
345 * @return a {@code Character} representing {@code c}.
346 * @deprecated Use {@link Character#valueOf(char)}.
347 */
348 @Deprecated
349 public static Character toCharacterObject(final char c) {
350 return Character.valueOf(c);
351 }
352
353 /**
354 * Converts the String to a Character using the first character, returning
355 * null for empty Strings.
356 *
357 * <p>For ASCII 7 bit characters, this uses a cache that will return the
358 * same Character object each time.</p>
359 *
360 * <pre>
361 * CharUtils.toCharacterObject(null) = null
362 * CharUtils.toCharacterObject("") = null
363 * CharUtils.toCharacterObject("A") = 'A'
364 * CharUtils.toCharacterObject("BA") = 'B'
365 * </pre>
366 *
367 * @param str the character to convert
368 * @return the Character value of the first letter of the String
369 */
370 public static Character toCharacterObject(final String str) {
371 return StringUtils.isEmpty(str) ? null : Character.valueOf(str.charAt(0));
372 }
373
374 /**
375 * Converts the character to the Integer it represents, throwing an
376 * exception if the character is not numeric.
377 *
378 * <p>This method converts the char '1' to the int 1 and so on.</p>
379 *
380 * <pre>
381 * CharUtils.toIntValue('3') = 3
382 * CharUtils.toIntValue('A') throws IllegalArgumentException
383 * </pre>
384 *
385 * @param ch the character to convert
386 * @return the int value of the character
387 * @throws IllegalArgumentException if the character is not ASCII numeric
388 */
389 public static int toIntValue(final char ch) {
390 if (!isAsciiNumeric(ch)) {
391 throw new IllegalArgumentException("The character " + ch + " is not in the range '0' - '9'");
392 }
393 return ch - 48;
394 }
395
396 /**
397 * Converts the character to the Integer it represents, throwing an
398 * exception if the character is not numeric.
399 *
400 * <p>This method converts the char '1' to the int 1 and so on.</p>
401 *
402 * <pre>
403 * CharUtils.toIntValue('3', -1) = 3
404 * CharUtils.toIntValue('A', -1) = -1
405 * </pre>
406 *
407 * @param ch the character to convert
408 * @param defaultValue the default value to use if the character is not numeric
409 * @return the int value of the character
410 */
411 public static int toIntValue(final char ch, final int defaultValue) {
412 return isAsciiNumeric(ch) ? ch - 48 : defaultValue;
413 }
414
415 /**
416 * Converts the character to the Integer it represents, throwing an
417 * exception if the character is not numeric.
418 *
419 * <p>This method converts the char '1' to the int 1 and so on.</p>
420 *
421 * <pre>
422 * CharUtils.toIntValue('3') = 3
423 * CharUtils.toIntValue(null) throws NullPointerException
424 * CharUtils.toIntValue('A') throws IllegalArgumentException
425 * </pre>
426 *
427 * @param ch the character to convert, not null
428 * @return the int value of the character
429 * @throws NullPointerException if the Character is null
430 * @throws IllegalArgumentException if the Character is not ASCII numeric
431 */
432 public static int toIntValue(final Character ch) {
433 return toIntValue(toChar(ch));
434 }
435
436 /**
437 * Converts the character to the Integer it represents, throwing an
438 * exception if the character is not numeric.
439 *
440 * <p>This method converts the char '1' to the int 1 and so on.</p>
441 *
442 * <pre>
443 * CharUtils.toIntValue(null, -1) = -1
444 * CharUtils.toIntValue('3', -1) = 3
445 * CharUtils.toIntValue('A', -1) = -1
446 * </pre>
447 *
448 * @param ch the character to convert
449 * @param defaultValue the default value to use if the character is not numeric
450 * @return the int value of the character
451 */
452 public static int toIntValue(final Character ch, final int defaultValue) {
453 return ch != null ? toIntValue(ch.charValue(), defaultValue) : defaultValue;
454 }
455
456 /**
457 * Converts the character to a String that contains the one character.
458 *
459 * <p>For ASCII 7 bit characters, this uses a cache that will return the
460 * same String object each time.</p>
461 *
462 * <pre>
463 * CharUtils.toString(' ') = " "
464 * CharUtils.toString('A') = "A"
465 * </pre>
466 *
467 * @param ch the character to convert
468 * @return a String containing the one specified character
469 */
470 public static String toString(final char ch) {
471 if (ch < CHAR_STRING_ARRAY.length) {
472 return CHAR_STRING_ARRAY[ch];
473 }
474 return String.valueOf(ch);
475 }
476
477 /**
478 * Converts the character to a String that contains the one character.
479 *
480 * <p>For ASCII 7 bit characters, this uses a cache that will return the
481 * same String object each time.</p>
482 *
483 * <p>If {@code null} is passed in, {@code null} will be returned.</p>
484 *
485 * <pre>
486 * CharUtils.toString(null) = null
487 * CharUtils.toString(' ') = " "
488 * CharUtils.toString('A') = "A"
489 * </pre>
490 *
491 * @param ch the character to convert
492 * @return a String containing the one specified character
493 */
494 public static String toString(final Character ch) {
495 return ch != null ? toString(ch.charValue()) : null;
496 }
497
498 /**
499 * Converts the string to the Unicode format '\u0020'.
500 *
501 * <p>This format is the Java source code format.</p>
502 *
503 * <pre>
504 * CharUtils.unicodeEscaped(' ') = "\u0020"
505 * CharUtils.unicodeEscaped('A') = "\u0041"
506 * </pre>
507 *
508 * @param ch the character to convert
509 * @return the escaped Unicode string
510 */
511 public static String unicodeEscaped(final char ch) {
512 return "\\u" +
513 HEX_DIGITS[ch >> 12 & 15] +
514 HEX_DIGITS[ch >> 8 & 15] +
515 HEX_DIGITS[ch >> 4 & 15] +
516 HEX_DIGITS[ch & 15];
517 }
518
519 /**
520 * Converts the string to the Unicode format '\u0020'.
521 *
522 * <p>This format is the Java source code format.</p>
523 *
524 * <p>If {@code null} is passed in, {@code null} will be returned.</p>
525 *
526 * <pre>
527 * CharUtils.unicodeEscaped(null) = null
528 * CharUtils.unicodeEscaped(' ') = "\u0020"
529 * CharUtils.unicodeEscaped('A') = "\u0041"
530 * </pre>
531 *
532 * @param ch the character to convert, may be null
533 * @return the escaped Unicode string, null if null input
534 */
535 public static String unicodeEscaped(final Character ch) {
536 return ch != null ? unicodeEscaped(ch.charValue()) : null;
537 }
538
539 /**
540 * {@link CharUtils} instances should NOT be constructed in standard programming.
541 * Instead, the class should be used as {@code CharUtils.toString('c');}.
542 *
543 * <p>This constructor is public to permit tools that require a JavaBean instance
544 * to operate.</p>
545 *
546 * @deprecated TODO Make private in 4.0.
547 */
548 @Deprecated
549 public CharUtils() {
550 // empty
551 }
552 }