/* 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.escape; import xbn.XBNObject; import xbn.AssertException; import xbn.string.StringOrBuffer; import xbn.string.UtilString; import xbn.string.UtilStringBuffer; /**

Base class for escaping or unescaping characters in a string.

Source code:  EscapeUnescapeString.java

@version 0.9b @author Jeff Epstein, http://sourceforge.net/projects/xbnjava. **/ public abstract class EscapeUnescapeString extends XBNObject { private UtilString uStr = new UtilString(); private UtilStringBuffer uSB = new UtilStringBuffer(); private ESConfig esc = null; /**

Create an EscapeUnescapeString.

@param es_config The configuration. May not be null. **/ public EscapeUnescapeString(ESConfig es_config) { throwAXIfNull(es_config, "es_config", sCNSTR); esc = es_config; } /**

Create a full copy of the provided EscapeUnescapeString.

@param escape_unescapeString The object to copy. May not be null. **/ public EscapeUnescapeString(EscapeUnescapeString escape_unescapeString) { try { esc = new ESConfig(escape_unescapeString.esc); } catch(AssertException ax) { throwAX("constructor: escape_unescapeString is null. Original error: " + ax.toString()); } } /**

Get the ESConfig for direct manipulation.

@return es_config Exactly as provided to the constructor. **/ public final ESConfig getESConfig() { return esc; } /**

Is the character at the requested array index preceded by the escape character?

@return isEscaped([UtilString].getSOBSB(s_tr, "isEscaped"), i_dx) **/ public final boolean isEscaped(String s_tr, int i_dx) { return isEscaped(uStr.getSOBS(s_tr, "isEscaped"), i_dx); } /**

Is the character at the requested array index preceded by the escape character?

@return isEscaped([UtilStringBuffer].getSOBSB(str_buffer, "isEscaped"), i_dx) **/ public final boolean isEscaped(StringBuffer str_buffer, int i_dx) { return isEscaped(uSB.getSOBSB(str_buffer, "isEscaped"), i_dx); } /**

Is the character at the requested array index preceded by the escape character?

Note that this function does not care if the character is one that should be escaped, just that it is preceded by the escape character.

Also, take special care when analyzing a character in a string that is being unescaped on the fly. It is easily possible to confuse things. For example:

@param str_orBfr The string to analyze. May not be null or zero characters in length. @param i_dx The array index of the character to analyze for escaped-ness. Must be between zero and (str_orBfr.length() - 1), inclusive. @return true If an odd number of escape characters immediately precede str_orBfr.charAt(i_dx).
false If an even number (including zero) of escape characters immediately precede str_orBfr.charAt(i_dx). **/ public final boolean isEscaped(StringOrBuffer str_orBfr, int i_dx) { if(i_dx == 0) { //No matter what, the first character is not escaped. return false; } char cThis = ' '; try { cThis = str_orBfr.charAt(i_dx); } catch(IndexOutOfBoundsException ioobx) { throwAX("isEscaped: i_dx (" + i_dx + ") is invalid. str_orBfr.length()=" + str_orBfr.length() + "."); } //Must be initialized to false. boolean bSheLovesMe = false; //bSheLovesMe == "is escaped" int i = (i_dx - 1); while(i > -1) { if(str_orBfr.charAt(i) == getESConfig().getEscapeChar()) { bSheLovesMe = !bSheLovesMe; //If this is the first one found, then it's set to true (false //is the initial value, !false is true). Therefore it is escaped. //If this is the second, then it's false. It's not escaped. //If this is the third, then it's true. It is escaped. //If this is the fourth, then it's false. It's not escaped. //If this is the fifth, then it's true. It is escaped. //... // //An odd number of escape characters before this one means //this one is escaped. An even number of escape characters //before this one means this one is not escaped. i--; } else { break; } } return bSheLovesMe; //bSheLovesMe == "is escaped" } private static final String sGI1U2BE = "getIdx1stUnesc2BEsc"; /**

Get the array index of the first character that should be escaped, but is not.

@return getIdx1stUnesc2BEsc([UtilString].getSOBSB(s_tr, "getIdx1stUnesc2BEsc")) **/ public final int getIdx1stUnesc2BEsc(String s_tr) { return getIdx1stUnesc2BEsc(uStr.getSOBSB(s_tr, sGI1U2BE)); } /**

Get the array index of the first character that should be escaped, but is not.

@return getIdx1stUnesc2BEsc([UtilString].getSOBSB(s_tr, "getIdx1stUnesc2BEsc"), i_idxStart) **/ public final int getIdx1stUnesc2BEsc(String s_tr, int i_idxStart) { return getIdx1stUnesc2BEsc(uStr.getSOBSB(s_tr, sGI1U2BE), i_idxStart); } /**

Get the array index of the first character that should be escaped, but is not.

@return getIdx1stUnesc2BEsc([UtilString].getSOBSB(s_tr, "getIdx1stUnesc2BEsc"), i_idxStart, i_idxEnd) **/ public final int getIdx1stUnesc2BEsc(String s_tr, int i_idxStart, int i_idxEnd) { return getIdx1stUnesc2BEsc(uStr.getSOBSB(s_tr, sGI1U2BE), i_idxStart, i_idxEnd); } /**

Get the array index of the first character that should be escaped, but is not.

@return getIdx1stUnesc2BEsc([UtilStringBuffer].getSOBSB(s_tr, "getIdx1stUnesc2BEsc")) **/ public final int getIdx1stUnesc2BEsc(StringBuffer str_buffer) { return getIdx1stUnesc2BEsc(uSB.getSOBSB(str_buffer, sGI1U2BE)); } /**

Get the array index of the first character that should be escaped, but is not.

@return getIdx1stUnesc2BEsc([UtilStringBuffer].getSOBSB(str_buffer, "getIdx1stUnesc2BEsc"), i_idxStart) **/ public final int getIdx1stUnesc2BEsc(StringBuffer str_buffer, int i_idxStart) { return getIdx1stUnesc2BEsc(uSB.getSOBSB(str_buffer, sGI1U2BE), i_idxStart); } /**

Get the array index of the first character that should be escaped, but is not.

@return getIdx1stUnesc2BEsc([UtilStringBuffer].getSOBSB(str_buffer, "getIdx1stUnesc2BEsc"), i_idxStart, i_idxEnd) **/ public final int getIdx1stUnesc2BEsc(StringBuffer str_buffer, int i_idxStart, int i_idxEnd) { return getIdx1stUnesc2BEsc(uSB.getSOBSB(str_buffer, sGI1U2BE), i_idxStart, i_idxEnd); } /**

Get the array index of the first character that should be escaped, but is not.

@return getIdx1stUnesc2BEsc(str_orBfr, 0) **/ public final int getIdx1stUnesc2BEsc(StringOrBuffer str_orBfr) { return getIdx1stUnesc2BEsc(str_orBfr, 0); } /**

Get the array index of the first character that should be escaped, but is not.

@param str_orBfr The StringOrBuffer to analyze. May not be null. @return getIdx1stUnesc2BEsc(str_orBfr, i_idxStart, (str_orBfr.length() - 1)) **/ public final int getIdx1stUnesc2BEsc(StringOrBuffer str_orBfr, int i_idxStart) { try { return getIdx1stUnesc2BEsc(str_orBfr, i_idxStart, (str_orBfr.length() - 1)); } catch(NullPointerException npx) { throwAX("getIdx1stUnesc2BEsc: str_orBfr is null."); } //Never reached. Required for compile. return -1; } /**

Get the array index of the first character that should be escaped, but is not.

Note: Be careful that the value of i_idxStart/i_idxEnd (whichever is lower/smaller/more-to-the-left) is the index of a character that is not escaped. Otherwise, this function will give you inaccurate results.

@param str_orBfr The StringBuffer to analyze. May not be null or zero characters in length. @param i_idxStart The first array index to analyze. Must be between zero and (str_orBfr.length() - 1), inclusive. Note that this may be greater than i_idxEnd, should you want to analyze right to left. @param i_idxEnd The last array index to analyze. Must be between zero and (str_orBfr.length() - 1), inclusive. @return The index of the first char found, starting with i_idxStart, that should be escaped, but is not. If every character that should be escaped, is escaped (or no to-be-escaped characters exist in the line), then -1 is returned. **/ public final int getIdx1stUnesc2BEsc(StringOrBuffer str_orBfr, int i_idxStart, int i_idxEnd) { try { int i = i_idxStart; if(i_idxStart > i_idxEnd) { for(; i >= i_idxEnd; i--) { char c = str_orBfr.charAt(i); if(getESConfig().isToBeEscaped(c) && !isEscaped(str_orBfr, i)) { return i; } } } else { for(; i <= i_idxEnd; i++) { char c = str_orBfr.charAt(i); if(getESConfig().isToBeEscaped(c) && !isEscaped(str_orBfr, i)) { return i; } } } } catch(NullPointerException npx) { throwAX("getIdx1stUnesc2BEsc: str_orBfr is null."); } catch(IndexOutOfBoundsException ioobx) { if(str_orBfr.length() < 1) { throwAX("getIdx1stUnesc2BEsc: str_orBfr is zero characters in length."); } throwAX("getIdx1stUnesc2BEsc: str_orBfr is " + str_orBfr.length() + " characters in length, i_idxStart (" + i_idxStart + ") and/or i_idxEnd (" + i_idxEnd + ") are invalid array index bounds. str_orBfr.length()=" + str_orBfr.length() + "."); } return -1; } }