/* XBN Java: Generically useful, non-GUI Java code. http://sourceforge.net/projects/xbnjava Copyright (C) 1997-2003, Jeff Epstein All rights reserved. Modifications: No Redistribution in binary form, with or without modifications, are permitted provided that the following conditions are met: * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * If modifications are made to source code then this license should indicate that fact in the "Modifications" section above. * Neither the author, nor the contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. [NOTE: This license contains NO advertising clause.] */ package xbn.string; import xbn.XBNObject; import xbn.array.primitive.PACChar; import xbn.array.primitive.PARCStrict; import xbn.array.primitive.PAROrderDir; import java.util.Arrays; /**

Random functions for analyzing and manipulating chars.

Source code:  UtilChar.java.  Unit tests:  xbn_junit.string.JUTUtilChar.java.

@version 0.9b @author Jeff Epstein, http://sourceforge.net/projects/xbnjava. **/ public class UtilChar extends XBNObject { /**

Create a UtilChar.

This constructor does nothing.

**/ public UtilChar() { } /**

Is the provided char whitespace?

@return isIn(c_har, getAOCInvisible(), true) **/ public final boolean isInvisible(char c_har) { return isIn(c_har, getAOCInvisible(), true); } /**

Is the provided char a hex digit?

@return isDigitOrIn(c_har, getAOCHexLetters(), true) **/ public final boolean isHexidecimal(char c_har) { return isDigitOrIn(c_har, getAOCHexLetters(), true); } private final static char[] hexChar = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; private final char[] acOne = new char[1]; private final char[] acTwo = new char[2]; /**

Convert a given char to a hex digit, returning it as a string. Note that all returned letters (a through f) are uppercase.

Got the main idea for this from http://mindprod.com/jglosshex.html.

@param c_har The character to translate. **/ public final String getHexDigitAsString(char c_har) { acOne[0] = c_har; byte[] ab = (new String(acOne)).getBytes(); //The high nibble acTwo[0] = new Character(hexChar [(ab[0] & 0xf0) >>> 4]).charValue(); //The low nibble acTwo[1] = new Character(hexChar[ab[0] & 0x0f]).charValue(); return new String(acTwo); } /**

Is the provided char equal to any char in the provided array?

@return isIn(c_har, ac_legal, true) **/ public final boolean isIn(char c_har, char[] ac_legal) { return isIn(c_har, ac_legal, true); } /**

Is the provided char equal to any char in the provided array?

@return isLegal(c_har, false, false, ac_legal, b_validateAOC) **/ public final boolean isIn(char c_har, char[] ac_legal, boolean b_validateAOC) { return isLegal(c_har, false, false, ac_legal, b_validateAOC); } /**

Is the provided character a letter, or other legal char?

@return isLegal(c_har, ac_legal, true) **/ public final boolean isLetterOrIn(char c_har, char[] ac_legal) { return isLetterOrIn(c_har, ac_legal, true); } /**

Is the provided character a letter, or other legal char?

@return isLegal(c_har, true, false, ac_legal, b_validateAOC) **/ public final boolean isLetterOrIn(char c_har, char[] ac_legal, boolean b_validateAOC) { return isLegal(c_har, true, false, ac_legal, b_validateAOC); } /**

Is the provided character a digit, or other legal char?

@return isDigitOrIn(c_har, ac_legal, true) **/ public final boolean isDigitOrIn(char c_har, char[] ac_legal) { return isDigitOrIn(c_har, ac_legal, true); } /**

Is the provided character a digit, or other legal char?

@return isLegal(c_har, false, true, ac_legal, b_validateAOC) **/ public final boolean isDigitOrIn(char c_har, char[] ac_legal, boolean b_validateAOC) { return isLegal(c_har, false, true, ac_legal, b_validateAOC); } /**

Is the provided character a letter, digit or other legal char?

@return isLDOrIn(c_har, ac_legal, true) **/ public final boolean isLDOrIn(char c_har, char[] ac_legal) { return isLDOrIn(c_har, ac_legal, true); } /**

Is the provided character a letter, digit or other legal char?

@return isLegal(c_har, true, true, ac_legal, b_validateAOC) **/ public final boolean isLDOrIn(char c_har, char[] ac_legal, boolean b_validateAOC) { return isLegal(c_har, true, true, ac_legal, b_validateAOC); } /**

Is the provided character an legal one?

Warning: This function will not work properly unless ac_legal conforms to all its restrictions.

@param c_har The character to analyze. @param b_letterOkOpt If true, then it is legal for c_har to be equal to any letter (a-z, A-Z). If false, then it is not checked whether or not c_har is a letter (and is therefore optional). If b_digitOkOpt is false, and ac_legal is null, then this must be true. @param b_digitOkOpt If true, then it is legal for c_har to be equal to any digit (0-9). If false, then it is not checked whether or not c_har is a digit (and is therefore optional). If b_letterOkOpt is false, and ac_legal is null, then this must be true. @param ac_legal If non-null, this is assumed to be an ordered (ascending) and unique array of characters--beyond letters and digits--that are considered legal. If null, then no characters (beyond letters and digits) are considered legal. Although it will not cause an exception, unless a subset of letters/digits are legal, it is wasteful and redundant to put letters/digits in this array. Use b_letterOkOpt/b_digitOkOpt as appropriate. If b_letterOkOpt and b_digitOkOpt are false, then this must be non-null. @param b_validateAOC If true, then it is verified that ac_legal is valid crashIfAOCNotUnqAscOrd, but only after it is determined that c_har is not a letter/digit (when b_letterOkOpt and/or b_digitOkOpt equal true). Also note that this check does not care if letters or digits exist in ac_legal. @return true If c_har meets the above requirements.
false If otherwise. **/ public final boolean isLegal(char c_har, boolean b_letterOkOpt, boolean b_digitOkOpt, char[] ac_legal, boolean b_validateAOC) { if(b_letterOkOpt && Character.isLetter(c_har)) { return true; } if(b_digitOkOpt && Character.isDigit(c_har)) { return true; } if(ac_legal == null) { //No chars--aside from potentially letters and //numbers--are legal. if(!b_letterOkOpt && !b_digitOkOpt) { //c_har is not legal, but *nothing* is legal. throwAX("isLegal: No characters considered legal. b_letterOkOpt and b_digitOkOpt both equal false, and ac_legal is null."); } //Either letters or numbers are considered legal, but //c_har does not fit the bill. return false; } else { //c_har is not a letter or digit (or if it is, we don't //care), is it any of the other legal characters? return (binarySearch(c_har, ac_legal, b_validateAOC) > -1); } } /**

Get a string to visible represent this (potentially) invisible character.

@param c_har The character to make visible. @return \\\\t If c_har equals '\\t'
\\\\n If '\\n'
\\\\f If '\\f'
\\\\r If '\\r'
(new Character(c_har)).toString() If otherwise. **/ public final String getVisible(char c_har) { if(c_har == '\t') { return "\\t"; } if(c_har == '\n') { return "\\n"; } if(c_har == '\f') { return "\\f"; } if(c_har == '\r') { return "\\r"; } return (new Character(c_har)).toString(); } /**

Is the provided character not a letter, or other illegal char?

@return isNotLetterOrIn(c_har, ac_illegal, true) **/ public final boolean isNotLetterOrIn(char c_har, char[] ac_illegal) { return isNotLetterOrIn(c_har, ac_illegal, true); } /**

Is the provided character not a letter, or other illegal char?

@return isNotIllegal(c_har, true, false, ac_illegal, b_validateAOC) **/ public final boolean isNotLetterOrIn(char c_har, char[] ac_illegal, boolean b_validateAOC) { return isNotIllegal(c_har, true, false, ac_illegal, b_validateAOC); } /**

Is the provided character not a digit, or other illegal char?

@return isNotDigitOrIn(c_har, ac_illegal, true) **/ public final boolean isNotDigitOrIn(char c_har, char[] ac_illegal) { return isNotDigitOrIn(c_har, ac_illegal, true); } /**

Is the provided character not a digit, or other illegal char?

@return isNotIllegal(c_har, false, true, ac_illegal, b_validateAOC) **/ public final boolean isNotDigitOrIn(char c_har, char[] ac_illegal, boolean b_validateAOC) { return isNotIllegal(c_har, false, true, ac_illegal, b_validateAOC); } /**

Is the provided character not a letter, digit or other illegal char?

@return isNotLDOrIn(c_har, ac_illegal, true) **/ public final boolean isNotLDOrIn(char c_har, char[] ac_illegal) { return isNotLDOrIn(c_har, ac_illegal, true); } /**

Is the provided character not a letter, digit or other illegal char?

@return isNotIllegal(c_har, true, true, ac_illegal, b_validateAOC) **/ public final boolean isNotLDOrIn(char c_har, char[] ac_illegal, boolean b_validateAOC) { return isNotIllegal(c_har, true, true, ac_illegal, b_validateAOC); } /**

Is the provided character not an illegal one?

@param c_har The character to analyze. @param b_letterBadOpt If true, then it is illegal for c_har to be equal to any letter (a-z, A-Z). If false, then it is okay (optional) for c_har to be a letter. @param b_digitBadOpt If true, then it is illegal for c_har to be equal to any digit (0-9). If false, then it is okay (optional) for c_har to be a digit. @param ac_illegal If non-null, this is an ordered (ascending) and unique array of characters--beyond letters and digits--that are considered illegal. If null, then no characters (beyond letters and digits) are considered illegal. Although it will not cause an exception, it is wasteful and redundant to put letters/digits in this array (exception: When only a subset of letters are illegal). Use b_letterBadOpt/b_digitBadOpt as appropriate. @param b_validateAOC If true, then it is verified that ac_illegal is valid crashIfAOCNotUnqAscOrd, but only after it is determined that c_har is not a letter/digit (when b_letterBadOpt/b_digitBadOpt equal true). Also note that this check does not care if letters or digits exist in ac_illegal. @return true If c_har meets the above requirements.
false If otherwise. **/ public final boolean isNotIllegal(char c_har, boolean b_letterBadOpt, boolean b_digitBadOpt, char[] ac_illegal, boolean b_validateAOC) { if(b_letterBadOpt && Character.isLetter(c_har)) { return false; } if(b_digitBadOpt && Character.isDigit(c_har)) { return false; } if(ac_illegal == null) { //No characters (beyond letters and digits) are illegal. return true; } else { return (binarySearch(c_har, ac_illegal, b_validateAOC) <= -1); } } /**

Get the array index at which the requested character exists.

@param c_har The char to search for. @param a_char The array of chars in which to search for c_har. Must be non-null, at least one element in length, and all values must be unique and ordered ascending. @param b_validateAOC If true, then a_char is analyzed to ensure it is valid. If false, it is assumed that a_char is valid. Use false with care. @return return Arrays.binarySearch(a_char, c_har) **/ public final int binarySearch(char c_har, char[] a_char, boolean b_validateAOC) { crashIfAOCNotUnqAscOrd("binarySearch", a_char, "a_char", b_validateAOC); try { return Arrays.binarySearch(a_char, c_har); } catch(NullPointerException npx) { throwAX("binarySearch: a_char is null and b_validateAOC is false. It is expected that this array is not null, at least one element in length, and all values must be unique and ordered ascending. Set b_validateAOC to true to validate a_char before comparing c_har against it."); } return -1; } /**

Verify that the provided char array is non-null, at least one element in length, unique and ordered ascending. If valid, do nothing. Otherwise throw an AssertException.

@param s_callingClsFnc The class-plus-function from which a potential error message should appear like it is being generated from. May not be null. @param a_char The array of characters to analyze. @param s_acDesc The descriptive name of a_char, for the potential error message. @param b_actuallyCheck If true then actually check a_char. If false, this function does nothing. **/ public final void crashIfAOCNotUnqAscOrd(String s_callingClsFnc, char[] a_char, String s_acDesc, boolean b_actuallyCheck) { throwAXIfNull(s_callingClsFnc, "s_callingClsFnc", "crashIfAOCNotUnqAscOrd"); if(b_actuallyCheck) { PACChar pacc = new PACChar(a_char, (new PARCStrict(new PAROrderDir(true)))); pacc.crashIfBad(s_callingClsFnc, s_acDesc); } } /**

Get an array of chars containing the tab and space characters.

See getAOCInvisible, Character.isSpace and isWhitespace.

@return (new char[] {'\\t', ' '}) **/ public static final char[] getAOCTabSpace() { return (new char[] {'\t', ' '}); } /**

Get an array of chars containing non-visible characters.

See getAOCTabSpace, Character.isSpace and isWhitespace.

@return (new char[] {'\\t', '\\n', '\\f', '\\r', ' '}) **/ public static final char[] getAOCInvisible() { return (new char[] {'\t', '\n', '\f', '\r', ' '}); } /**

Get an array of chars containing the letters used in hexidecimal numbers.

@return (new char[] {'A', 'B', 'C', 'D', 'E', 'F'}}) **/ public static final char[] getAOCHexLetters() { return (new char[] {'A', 'B', 'C', 'D', 'E', 'F'}); } }