0001: /*
0002: Copyright (C) 2002-2004 MySQL AB
0003:
0004: This program is free software; you can redistribute it and/or modify
0005: it under the terms of version 2 of the GNU General Public License as
0006: published by the Free Software Foundation.
0007:
0008: There are special exceptions to the terms and conditions of the GPL
0009: as it is applied to this software. View the full text of the
0010: exception in file EXCEPTIONS-CONNECTOR-J in the directory of this
0011: software distribution.
0012:
0013: This program is distributed in the hope that it will be useful,
0014: but WITHOUT ANY WARRANTY; without even the implied warranty of
0015: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0016: GNU General Public License for more details.
0017:
0018: You should have received a copy of the GNU General Public License
0019: along with this program; if not, write to the Free Software
0020: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0021:
0022:
0023:
0024: */
0025: package com.mysql.jdbc;
0026:
0027: import java.io.ByteArrayOutputStream;
0028: import java.io.IOException;
0029: import java.io.StringReader;
0030: import java.io.UnsupportedEncodingException;
0031: import java.lang.reflect.InvocationTargetException;
0032: import java.lang.reflect.Method;
0033: import java.math.BigDecimal;
0034:
0035: import java.sql.SQLException;
0036:
0037: import java.util.ArrayList;
0038: import java.util.List;
0039: import java.util.StringTokenizer;
0040:
0041: /**
0042: * Various utility methods for converting to/from byte arrays in the platform
0043: * encoding
0044: *
0045: * @author Mark Matthews
0046: */
0047: public class StringUtils {
0048:
0049: private static final int BYTE_RANGE = (1 + Byte.MAX_VALUE)
0050: - Byte.MIN_VALUE;
0051:
0052: private static byte[] allBytes = new byte[BYTE_RANGE];
0053:
0054: private static char[] byteToChars = new char[BYTE_RANGE];
0055:
0056: private static Method toPlainStringMethod;
0057:
0058: static final int WILD_COMPARE_MATCH_NO_WILD = 0;
0059:
0060: static final int WILD_COMPARE_MATCH_WITH_WILD = 1;
0061:
0062: static final int WILD_COMPARE_NO_MATCH = -1;
0063:
0064: static {
0065: for (int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) {
0066: allBytes[i - Byte.MIN_VALUE] = (byte) i;
0067: }
0068:
0069: String allBytesString = new String(allBytes, 0, Byte.MAX_VALUE
0070: - Byte.MIN_VALUE);
0071:
0072: int allBytesStringLen = allBytesString.length();
0073:
0074: for (int i = 0; (i < (Byte.MAX_VALUE - Byte.MIN_VALUE))
0075: && (i < allBytesStringLen); i++) {
0076: byteToChars[i] = allBytesString.charAt(i);
0077: }
0078:
0079: try {
0080: toPlainStringMethod = BigDecimal.class.getMethod(
0081: "toPlainString", new Class[0]);
0082: } catch (NoSuchMethodException nsme) {
0083: // that's okay, we fallback to .toString()
0084: }
0085: }
0086:
0087: /**
0088: * Takes care of the fact that Sun changed the output of
0089: * BigDecimal.toString() between JDK-1.4 and JDK 5
0090: *
0091: * @param decimal
0092: * the big decimal to stringify
0093: *
0094: * @return a string representation of 'decimal'
0095: */
0096: public static String consistentToString(BigDecimal decimal) {
0097: if (decimal == null) {
0098: return null;
0099: }
0100:
0101: if (toPlainStringMethod != null) {
0102: try {
0103: return (String) toPlainStringMethod.invoke(decimal,
0104: null);
0105: } catch (InvocationTargetException invokeEx) {
0106: // that's okay, we fall-through to decimal.toString()
0107: } catch (IllegalAccessException accessEx) {
0108: // that's okay, we fall-through to decimal.toString()
0109: }
0110: }
0111:
0112: return decimal.toString();
0113: }
0114:
0115: /**
0116: * Dumps the given bytes to STDOUT as a hex dump (up to length bytes).
0117: *
0118: * @param byteBuffer
0119: * the data to print as hex
0120: * @param length
0121: * the number of bytes to print
0122: *
0123: * @return ...
0124: */
0125: public static final String dumpAsHex(byte[] byteBuffer, int length) {
0126: StringBuffer outputBuf = new StringBuffer(length * 4);
0127:
0128: int p = 0;
0129: int rows = length / 8;
0130:
0131: for (int i = 0; (i < rows) && (p < length); i++) {
0132: int ptemp = p;
0133:
0134: for (int j = 0; j < 8; j++) {
0135: String hexVal = Integer
0136: .toHexString(byteBuffer[ptemp] & 0xff);
0137:
0138: if (hexVal.length() == 1) {
0139: hexVal = "0" + hexVal; //$NON-NLS-1$
0140: }
0141:
0142: outputBuf.append(hexVal + " "); //$NON-NLS-1$
0143: ptemp++;
0144: }
0145:
0146: outputBuf.append(" "); //$NON-NLS-1$
0147:
0148: for (int j = 0; j < 8; j++) {
0149: int b = 0xff & byteBuffer[p];
0150:
0151: if (b > 32 && b < 127) {
0152: outputBuf.append((char) b + " "); //$NON-NLS-1$
0153: } else {
0154: outputBuf.append(". "); //$NON-NLS-1$
0155: }
0156:
0157: p++;
0158: }
0159:
0160: outputBuf.append("\n"); //$NON-NLS-1$
0161: }
0162:
0163: int n = 0;
0164:
0165: for (int i = p; i < length; i++) {
0166: String hexVal = Integer.toHexString(byteBuffer[i] & 0xff);
0167:
0168: if (hexVal.length() == 1) {
0169: hexVal = "0" + hexVal; //$NON-NLS-1$
0170: }
0171:
0172: outputBuf.append(hexVal + " "); //$NON-NLS-1$
0173: n++;
0174: }
0175:
0176: for (int i = n; i < 8; i++) {
0177: outputBuf.append(" "); //$NON-NLS-1$
0178: }
0179:
0180: outputBuf.append(" "); //$NON-NLS-1$
0181:
0182: for (int i = p; i < length; i++) {
0183: int b = 0xff & byteBuffer[i];
0184:
0185: if (b > 32 && b < 127) {
0186: outputBuf.append((char) b + " "); //$NON-NLS-1$
0187: } else {
0188: outputBuf.append(". "); //$NON-NLS-1$
0189: }
0190: }
0191:
0192: outputBuf.append("\n"); //$NON-NLS-1$
0193:
0194: return outputBuf.toString();
0195: }
0196:
0197: private static boolean endsWith(byte[] dataFrom, String suffix) {
0198: for (int i = 1; i <= suffix.length(); i++) {
0199: int dfOffset = dataFrom.length - i;
0200: int suffixOffset = suffix.length() - i;
0201: if (dataFrom[dfOffset] != suffix.charAt(suffixOffset)) {
0202: return false;
0203: }
0204: }
0205: return true;
0206: }
0207:
0208: /**
0209: * Unfortunately, SJIS has 0x5c as a high byte in some of its double-byte
0210: * characters, so we need to escape it.
0211: *
0212: * @param origBytes
0213: * the original bytes in SJIS format
0214: * @param origString
0215: * the string that had .getBytes() called on it
0216: * @param offset
0217: * where to start converting from
0218: * @param length
0219: * how many characters to convert.
0220: *
0221: * @return byte[] with 0x5c escaped
0222: */
0223: public static byte[] escapeEasternUnicodeByteStream(
0224: byte[] origBytes, String origString, int offset, int length) {
0225: if ((origBytes == null) || (origBytes.length == 0)) {
0226: return origBytes;
0227: }
0228:
0229: int bytesLen = origBytes.length;
0230: int bufIndex = 0;
0231: int strIndex = 0;
0232:
0233: ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(
0234: bytesLen);
0235:
0236: while (true) {
0237: if (origString.charAt(strIndex) == '\\') {
0238: // write it out as-is
0239: bytesOut.write(origBytes[bufIndex++]);
0240:
0241: // bytesOut.write(origBytes[bufIndex++]);
0242: } else {
0243: // Grab the first byte
0244: int loByte = origBytes[bufIndex];
0245:
0246: if (loByte < 0) {
0247: loByte += 256; // adjust for signedness/wrap-around
0248: }
0249:
0250: // We always write the first byte
0251: bytesOut.write(loByte);
0252:
0253: //
0254: // The codepage characters in question exist between
0255: // 0x81-0x9F and 0xE0-0xFC...
0256: //
0257: // See:
0258: //
0259: // http://www.microsoft.com/GLOBALDEV/Reference/dbcs/932.htm
0260: //
0261: // Problematic characters in GBK
0262: //
0263: // U+905C : CJK UNIFIED IDEOGRAPH
0264: //
0265: // Problematic characters in Big5
0266: //
0267: // B9F0 = U+5C62 : CJK UNIFIED IDEOGRAPH
0268: //
0269: if (loByte >= 0x80) {
0270: if (bufIndex < (bytesLen - 1)) {
0271: int hiByte = origBytes[bufIndex + 1];
0272:
0273: if (hiByte < 0) {
0274: hiByte += 256; // adjust for signedness/wrap-around
0275: }
0276:
0277: // write the high byte here, and increment the index
0278: // for the high byte
0279: bytesOut.write(hiByte);
0280: bufIndex++;
0281:
0282: // escape 0x5c if necessary
0283: if (hiByte == 0x5C) {
0284: bytesOut.write(hiByte);
0285: }
0286: }
0287: } else if (loByte == 0x5c) {
0288: if (bufIndex < (bytesLen - 1)) {
0289: int hiByte = origBytes[bufIndex + 1];
0290:
0291: if (hiByte < 0) {
0292: hiByte += 256; // adjust for signedness/wrap-around
0293: }
0294:
0295: if (hiByte == 0x62) {
0296: // we need to escape the 0x5c
0297: bytesOut.write(0x5c);
0298: bytesOut.write(0x62);
0299: bufIndex++;
0300: }
0301: }
0302: }
0303:
0304: bufIndex++;
0305: }
0306:
0307: if (bufIndex >= bytesLen) {
0308: // we're done
0309: break;
0310: }
0311:
0312: strIndex++;
0313: }
0314:
0315: return bytesOut.toByteArray();
0316: }
0317:
0318: /**
0319: * Returns the first non whitespace char, converted to upper case
0320: *
0321: * @param searchIn
0322: * the string to search in
0323: *
0324: * @return the first non-whitespace character, upper cased.
0325: */
0326: public static char firstNonWsCharUc(String searchIn) {
0327: return firstNonWsCharUc(searchIn, 0);
0328: }
0329:
0330: public static char firstNonWsCharUc(String searchIn, int startAt) {
0331: if (searchIn == null) {
0332: return 0;
0333: }
0334:
0335: int length = searchIn.length();
0336:
0337: for (int i = startAt; i < length; i++) {
0338: char c = searchIn.charAt(i);
0339:
0340: if (!Character.isWhitespace(c)) {
0341: return Character.toUpperCase(c);
0342: }
0343: }
0344:
0345: return 0;
0346: }
0347:
0348: /**
0349: * Adds '+' to decimal numbers that are positive (MySQL doesn't understand
0350: * them otherwise
0351: *
0352: * @param dString
0353: * The value as a string
0354: *
0355: * @return String the string with a '+' added (if needed)
0356: */
0357: public static final String fixDecimalExponent(String dString) {
0358: int ePos = dString.indexOf("E"); //$NON-NLS-1$
0359:
0360: if (ePos == -1) {
0361: ePos = dString.indexOf("e"); //$NON-NLS-1$
0362: }
0363:
0364: if (ePos != -1) {
0365: if (dString.length() > (ePos + 1)) {
0366: char maybeMinusChar = dString.charAt(ePos + 1);
0367:
0368: if (maybeMinusChar != '-' && maybeMinusChar != '+') {
0369: StringBuffer buf = new StringBuffer(dString
0370: .length() + 1);
0371: buf.append(dString.substring(0, ePos + 1));
0372: buf.append('+');
0373: buf.append(dString.substring(ePos + 1, dString
0374: .length()));
0375: dString = buf.toString();
0376: }
0377: }
0378: }
0379:
0380: return dString;
0381: }
0382:
0383: public static final byte[] getBytes(char[] c,
0384: SingleByteCharsetConverter converter, String encoding,
0385: String serverEncoding, boolean parserKnowsUnicode)
0386: throws SQLException {
0387: try {
0388: byte[] b = null;
0389:
0390: if (converter != null) {
0391: b = converter.toBytes(c);
0392: } else if (encoding == null) {
0393: b = new String(c).getBytes();
0394: } else {
0395: String s = new String(c);
0396:
0397: b = s.getBytes(encoding);
0398:
0399: if (!parserKnowsUnicode
0400: && (encoding.equalsIgnoreCase("SJIS") //$NON-NLS-1$
0401: || encoding.equalsIgnoreCase("BIG5") //$NON-NLS-1$
0402: || encoding.equalsIgnoreCase("GBK"))) { //$NON-NLS-1$
0403:
0404: if (!encoding.equalsIgnoreCase(serverEncoding)) {
0405: b = escapeEasternUnicodeByteStream(b, s, 0, s
0406: .length());
0407: }
0408: }
0409: }
0410:
0411: return b;
0412: } catch (UnsupportedEncodingException uee) {
0413: throw SQLError.createSQLException(Messages
0414: .getString("StringUtils.5") //$NON-NLS-1$
0415: + encoding + Messages.getString("StringUtils.6"),
0416: SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
0417: }
0418: }
0419:
0420: public static final byte[] getBytes(char[] c,
0421: SingleByteCharsetConverter converter, String encoding,
0422: String serverEncoding, int offset, int length,
0423: boolean parserKnowsUnicode) throws SQLException {
0424: try {
0425: byte[] b = null;
0426:
0427: if (converter != null) {
0428: b = converter.toBytes(c, offset, length);
0429: } else if (encoding == null) {
0430: byte[] temp = new String(c, offset, length).getBytes();
0431:
0432: length = temp.length;
0433:
0434: b = new byte[length];
0435: System.arraycopy(temp, 0, b, 0, length);
0436: } else {
0437: String s = new String(c, offset, length);
0438:
0439: byte[] temp = s.getBytes(encoding);
0440:
0441: length = temp.length;
0442:
0443: b = new byte[length];
0444: System.arraycopy(temp, 0, b, 0, length);
0445:
0446: if (!parserKnowsUnicode
0447: && (encoding.equalsIgnoreCase("SJIS") //$NON-NLS-1$
0448: || encoding.equalsIgnoreCase("BIG5") //$NON-NLS-1$
0449: || encoding.equalsIgnoreCase("GBK"))) { //$NON-NLS-1$
0450:
0451: if (!encoding.equalsIgnoreCase(serverEncoding)) {
0452: b = escapeEasternUnicodeByteStream(b, s,
0453: offset, length);
0454: }
0455: }
0456: }
0457:
0458: return b;
0459: } catch (UnsupportedEncodingException uee) {
0460: throw SQLError.createSQLException(Messages
0461: .getString("StringUtils.10") //$NON-NLS-1$
0462: + encoding + Messages.getString("StringUtils.11"),
0463: SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
0464: }
0465: }
0466:
0467: public static final byte[] getBytes(char[] c, String encoding,
0468: String serverEncoding, boolean parserKnowsUnicode,
0469: ConnectionImpl conn) throws SQLException {
0470: try {
0471:
0472: SingleByteCharsetConverter converter = null;
0473:
0474: if (conn != null) {
0475: converter = conn.getCharsetConverter(encoding);
0476: } else {
0477: converter = SingleByteCharsetConverter.getInstance(
0478: encoding, null);
0479: }
0480:
0481: return getBytes(c, converter, encoding, serverEncoding,
0482: parserKnowsUnicode);
0483: } catch (UnsupportedEncodingException uee) {
0484: throw SQLError.createSQLException(Messages
0485: .getString("StringUtils.0") //$NON-NLS-1$
0486: + encoding + Messages.getString("StringUtils.1"),
0487: SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
0488: }
0489: }
0490:
0491: /**
0492: * Returns the byte[] representation of the given string (re)using the given
0493: * charset converter, and the given encoding.
0494: *
0495: * @param s
0496: * the string to convert
0497: * @param converter
0498: * the converter to reuse
0499: * @param encoding
0500: * the character encoding to use
0501: * @param serverEncoding
0502: * DOCUMENT ME!
0503: * @param parserKnowsUnicode
0504: * DOCUMENT ME!
0505: *
0506: * @return byte[] representation of the string
0507: *
0508: * @throws SQLException
0509: * if an encoding unsupported by the JVM is supplied.
0510: */
0511: public static final byte[] getBytes(String s,
0512: SingleByteCharsetConverter converter, String encoding,
0513: String serverEncoding, boolean parserKnowsUnicode)
0514: throws SQLException {
0515: try {
0516: byte[] b = null;
0517:
0518: if (converter != null) {
0519: b = converter.toBytes(s);
0520: } else if (encoding == null) {
0521: b = s.getBytes();
0522: } else {
0523: b = s.getBytes(encoding);
0524:
0525: if (!parserKnowsUnicode
0526: && (encoding.equalsIgnoreCase("SJIS") //$NON-NLS-1$
0527: || encoding.equalsIgnoreCase("BIG5") //$NON-NLS-1$
0528: || encoding.equalsIgnoreCase("GBK"))) { //$NON-NLS-1$
0529:
0530: if (!encoding.equalsIgnoreCase(serverEncoding)) {
0531: b = escapeEasternUnicodeByteStream(b, s, 0, s
0532: .length());
0533: }
0534: }
0535: }
0536:
0537: return b;
0538: } catch (UnsupportedEncodingException uee) {
0539: throw SQLError.createSQLException(Messages
0540: .getString("StringUtils.5") //$NON-NLS-1$
0541: + encoding + Messages.getString("StringUtils.6"),
0542: SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
0543: }
0544: }
0545:
0546: public static final byte[] getBytesWrapped(String s,
0547: char beginWrap, char endWrap,
0548: SingleByteCharsetConverter converter, String encoding,
0549: String serverEncoding, boolean parserKnowsUnicode)
0550: throws SQLException {
0551: try {
0552: byte[] b = null;
0553:
0554: if (converter != null) {
0555: b = converter.toBytesWrapped(s, beginWrap, endWrap);
0556: } else if (encoding == null) {
0557: StringBuffer buf = new StringBuffer(s.length() + 2);
0558: buf.append(beginWrap);
0559: buf.append(s);
0560: buf.append(endWrap);
0561:
0562: b = buf.toString().getBytes();
0563: } else {
0564: StringBuffer buf = new StringBuffer(s.length() + 2);
0565: buf.append(beginWrap);
0566: buf.append(s);
0567: buf.append(endWrap);
0568:
0569: b = buf.toString().getBytes(encoding);
0570:
0571: if (!parserKnowsUnicode
0572: && (encoding.equalsIgnoreCase("SJIS") //$NON-NLS-1$
0573: || encoding.equalsIgnoreCase("BIG5") //$NON-NLS-1$
0574: || encoding.equalsIgnoreCase("GBK"))) { //$NON-NLS-1$
0575:
0576: if (!encoding.equalsIgnoreCase(serverEncoding)) {
0577: b = escapeEasternUnicodeByteStream(b, s, 0, s
0578: .length());
0579: }
0580: }
0581: }
0582:
0583: return b;
0584: } catch (UnsupportedEncodingException uee) {
0585: throw SQLError.createSQLException(Messages
0586: .getString("StringUtils.5") //$NON-NLS-1$
0587: + encoding + Messages.getString("StringUtils.6"),
0588: SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
0589: }
0590: }
0591:
0592: /**
0593: * DOCUMENT ME!
0594: *
0595: * @param s
0596: * DOCUMENT ME!
0597: * @param converter
0598: * DOCUMENT ME!
0599: * @param encoding
0600: * DOCUMENT ME!
0601: * @param serverEncoding
0602: * DOCUMENT ME!
0603: * @param offset
0604: * DOCUMENT ME!
0605: * @param length
0606: * DOCUMENT ME!
0607: * @param parserKnowsUnicode
0608: * DOCUMENT ME!
0609: *
0610: * @return DOCUMENT ME!
0611: *
0612: * @throws SQLException
0613: * DOCUMENT ME!
0614: */
0615: public static final byte[] getBytes(String s,
0616: SingleByteCharsetConverter converter, String encoding,
0617: String serverEncoding, int offset, int length,
0618: boolean parserKnowsUnicode) throws SQLException {
0619: try {
0620: byte[] b = null;
0621:
0622: if (converter != null) {
0623: b = converter.toBytes(s, offset, length);
0624: } else if (encoding == null) {
0625: byte[] temp = s.substring(offset, offset + length)
0626: .getBytes();
0627:
0628: length = temp.length;
0629:
0630: b = new byte[length];
0631: System.arraycopy(temp, 0, b, 0, length);
0632: } else {
0633:
0634: byte[] temp = s.substring(offset, offset + length)
0635: .getBytes(encoding);
0636:
0637: length = temp.length;
0638:
0639: b = new byte[length];
0640: System.arraycopy(temp, 0, b, 0, length);
0641:
0642: if (!parserKnowsUnicode
0643: && (encoding.equalsIgnoreCase("SJIS") //$NON-NLS-1$
0644: || encoding.equalsIgnoreCase("BIG5") //$NON-NLS-1$
0645: || encoding.equalsIgnoreCase("GBK"))) { //$NON-NLS-1$
0646:
0647: if (!encoding.equalsIgnoreCase(serverEncoding)) {
0648: b = escapeEasternUnicodeByteStream(b, s,
0649: offset, length);
0650: }
0651: }
0652: }
0653:
0654: return b;
0655: } catch (UnsupportedEncodingException uee) {
0656: throw SQLError.createSQLException(Messages
0657: .getString("StringUtils.10") //$NON-NLS-1$
0658: + encoding + Messages.getString("StringUtils.11"),
0659: SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
0660: }
0661: }
0662:
0663: /**
0664: * Returns the byte[] representation of the given string using given
0665: * encoding.
0666: *
0667: * @param s
0668: * the string to convert
0669: * @param encoding
0670: * the character encoding to use
0671: * @param parserKnowsUnicode
0672: * DOCUMENT ME!
0673: *
0674: * @return byte[] representation of the string
0675: *
0676: * @throws SQLException
0677: * if an encoding unsupported by the JVM is supplied.
0678: */
0679: public static final byte[] getBytes(String s, String encoding,
0680: String serverEncoding, boolean parserKnowsUnicode,
0681: ConnectionImpl conn) throws SQLException {
0682: try {
0683: SingleByteCharsetConverter converter = null;
0684:
0685: if (conn != null) {
0686: converter = conn.getCharsetConverter(encoding);
0687: } else {
0688: converter = SingleByteCharsetConverter.getInstance(
0689: encoding, null);
0690: }
0691:
0692: return getBytes(s, converter, encoding, serverEncoding,
0693: parserKnowsUnicode);
0694: } catch (UnsupportedEncodingException uee) {
0695: throw SQLError.createSQLException(Messages
0696: .getString("StringUtils.0") //$NON-NLS-1$
0697: + encoding + Messages.getString("StringUtils.1"),
0698: SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
0699: }
0700: }
0701:
0702: public static int getInt(byte[] buf, int offset, int endPos)
0703: throws NumberFormatException {
0704: int base = 10;
0705:
0706: int s = offset;
0707:
0708: /* Skip white space. */
0709: while (Character.isWhitespace((char) buf[s]) && (s < endPos)) {
0710: ++s;
0711: }
0712:
0713: if (s == endPos) {
0714: throw new NumberFormatException(new String(buf));
0715: }
0716:
0717: /* Check for a sign. */
0718: boolean negative = false;
0719:
0720: if ((char) buf[s] == '-') {
0721: negative = true;
0722: ++s;
0723: } else if ((char) buf[s] == '+') {
0724: ++s;
0725: }
0726:
0727: /* Save the pointer so we can check later if anything happened. */
0728: int save = s;
0729:
0730: int cutoff = Integer.MAX_VALUE / base;
0731: int cutlim = (Integer.MAX_VALUE % base);
0732:
0733: if (negative) {
0734: cutlim++;
0735: }
0736:
0737: boolean overflow = false;
0738:
0739: int i = 0;
0740:
0741: for (; s < endPos; s++) {
0742: char c = (char) buf[s];
0743:
0744: if (Character.isDigit(c)) {
0745: c -= '0';
0746: } else if (Character.isLetter(c)) {
0747: c = (char) (Character.toUpperCase(c) - 'A' + 10);
0748: } else {
0749: break;
0750: }
0751:
0752: if (c >= base) {
0753: break;
0754: }
0755:
0756: /* Check for overflow. */
0757: if ((i > cutoff) || ((i == cutoff) && (c > cutlim))) {
0758: overflow = true;
0759: } else {
0760: i *= base;
0761: i += c;
0762: }
0763: }
0764:
0765: if (s == save) {
0766: throw new NumberFormatException(new String(buf));
0767: }
0768:
0769: if (overflow) {
0770: throw new NumberFormatException(new String(buf));
0771: }
0772:
0773: /* Return the result of the appropriate sign. */
0774: return (negative ? (-i) : i);
0775: }
0776:
0777: public static int getInt(byte[] buf) throws NumberFormatException {
0778: return getInt(buf, 0, buf.length);
0779: }
0780:
0781: public static long getLong(byte[] buf) throws NumberFormatException {
0782: return getLong(buf, 0, buf.length);
0783: }
0784:
0785: public static long getLong(byte[] buf, int offset, int endpos)
0786: throws NumberFormatException {
0787: int base = 10;
0788:
0789: int s = offset;
0790:
0791: /* Skip white space. */
0792: while (Character.isWhitespace((char) buf[s]) && (s < endpos)) {
0793: ++s;
0794: }
0795:
0796: if (s == endpos) {
0797: throw new NumberFormatException(new String(buf));
0798: }
0799:
0800: /* Check for a sign. */
0801: boolean negative = false;
0802:
0803: if ((char) buf[s] == '-') {
0804: negative = true;
0805: ++s;
0806: } else if ((char) buf[s] == '+') {
0807: ++s;
0808: }
0809:
0810: /* Save the pointer so we can check later if anything happened. */
0811: int save = s;
0812:
0813: long cutoff = Long.MAX_VALUE / base;
0814: long cutlim = (int) (Long.MAX_VALUE % base);
0815:
0816: if (negative) {
0817: cutlim++;
0818: }
0819:
0820: boolean overflow = false;
0821: long i = 0;
0822:
0823: for (; s < endpos; s++) {
0824: char c = (char) buf[s];
0825:
0826: if (Character.isDigit(c)) {
0827: c -= '0';
0828: } else if (Character.isLetter(c)) {
0829: c = (char) (Character.toUpperCase(c) - 'A' + 10);
0830: } else {
0831: break;
0832: }
0833:
0834: if (c >= base) {
0835: break;
0836: }
0837:
0838: /* Check for overflow. */
0839: if ((i > cutoff) || ((i == cutoff) && (c > cutlim))) {
0840: overflow = true;
0841: } else {
0842: i *= base;
0843: i += c;
0844: }
0845: }
0846:
0847: if (s == save) {
0848: throw new NumberFormatException(new String(buf));
0849: }
0850:
0851: if (overflow) {
0852: throw new NumberFormatException(new String(buf));
0853: }
0854:
0855: /* Return the result of the appropriate sign. */
0856: return (negative ? (-i) : i);
0857: }
0858:
0859: public static short getShort(byte[] buf)
0860: throws NumberFormatException {
0861: short base = 10;
0862:
0863: int s = 0;
0864:
0865: /* Skip white space. */
0866: while (Character.isWhitespace((char) buf[s])
0867: && (s < buf.length)) {
0868: ++s;
0869: }
0870:
0871: if (s == buf.length) {
0872: throw new NumberFormatException(new String(buf));
0873: }
0874:
0875: /* Check for a sign. */
0876: boolean negative = false;
0877:
0878: if ((char) buf[s] == '-') {
0879: negative = true;
0880: ++s;
0881: } else if ((char) buf[s] == '+') {
0882: ++s;
0883: }
0884:
0885: /* Save the pointer so we can check later if anything happened. */
0886: int save = s;
0887:
0888: short cutoff = (short) (Short.MAX_VALUE / base);
0889: short cutlim = (short) (Short.MAX_VALUE % base);
0890:
0891: if (negative) {
0892: cutlim++;
0893: }
0894:
0895: boolean overflow = false;
0896: short i = 0;
0897:
0898: for (; s < buf.length; s++) {
0899: char c = (char) buf[s];
0900:
0901: if (Character.isDigit(c)) {
0902: c -= '0';
0903: } else if (Character.isLetter(c)) {
0904: c = (char) (Character.toUpperCase(c) - 'A' + 10);
0905: } else {
0906: break;
0907: }
0908:
0909: if (c >= base) {
0910: break;
0911: }
0912:
0913: /* Check for overflow. */
0914: if ((i > cutoff) || ((i == cutoff) && (c > cutlim))) {
0915: overflow = true;
0916: } else {
0917: i *= base;
0918: i += c;
0919: }
0920: }
0921:
0922: if (s == save) {
0923: throw new NumberFormatException(new String(buf));
0924: }
0925:
0926: if (overflow) {
0927: throw new NumberFormatException(new String(buf));
0928: }
0929:
0930: /* Return the result of the appropriate sign. */
0931: return (negative ? (short) -i : (short) i);
0932: }
0933:
0934: public final static int indexOfIgnoreCase(int startingPosition,
0935: String searchIn, String searchFor) {
0936: if ((searchIn == null) || (searchFor == null)
0937: || startingPosition > searchIn.length()) {
0938: return -1;
0939: }
0940:
0941: int patternLength = searchFor.length();
0942: int stringLength = searchIn.length();
0943: int stopSearchingAt = stringLength - patternLength;
0944:
0945: int i = startingPosition;
0946:
0947: if (patternLength == 0) {
0948: return -1;
0949: }
0950:
0951: // Brute force string pattern matching
0952: // Some locales don't follow upper-case rule, so need to check both
0953: char firstCharOfPatternUc = Character.toUpperCase(searchFor
0954: .charAt(0));
0955: char firstCharOfPatternLc = Character.toLowerCase(searchFor
0956: .charAt(0));
0957:
0958: lookForFirstChar: while (true) {
0959: while ((i < stopSearchingAt)
0960: && (Character.toUpperCase(searchIn.charAt(i)) != firstCharOfPatternUc)
0961: && Character.toLowerCase(searchIn.charAt(i)) != firstCharOfPatternLc) {
0962: i++;
0963: }
0964:
0965: if (i > stopSearchingAt) {
0966: return -1;
0967: }
0968:
0969: int j = i + 1;
0970: int end = (j + patternLength) - 1;
0971:
0972: int k = 1; // start at second char of pattern
0973:
0974: while (j < end) {
0975: int searchInPos = j++;
0976: int searchForPos = k++;
0977:
0978: if (Character.toUpperCase(searchIn.charAt(searchInPos)) != Character
0979: .toUpperCase(searchFor.charAt(searchForPos))) {
0980: i++;
0981:
0982: // start over
0983: continue lookForFirstChar;
0984: }
0985:
0986: // Georgian and Turkish locales don't have same convention, so
0987: // need to check lowercase
0988: // too!
0989: if (Character.toLowerCase(searchIn.charAt(searchInPos)) != Character
0990: .toLowerCase(searchFor.charAt(searchForPos))) {
0991: i++;
0992:
0993: // start over
0994: continue lookForFirstChar;
0995: }
0996: }
0997:
0998: return i; // found entire pattern
0999: }
1000: }
1001:
1002: /**
1003: * DOCUMENT ME!
1004: *
1005: * @param searchIn
1006: * DOCUMENT ME!
1007: * @param searchFor
1008: * DOCUMENT ME!
1009: *
1010: * @return DOCUMENT ME!
1011: */
1012: public final static int indexOfIgnoreCase(String searchIn,
1013: String searchFor) {
1014: return indexOfIgnoreCase(0, searchIn, searchFor);
1015: }
1016:
1017: public static int indexOfIgnoreCaseRespectMarker(int startAt,
1018: String src, String target, String marker,
1019: String markerCloses, boolean allowBackslashEscapes) {
1020: char contextMarker = Character.MIN_VALUE;
1021: boolean escaped = false;
1022: int markerTypeFound = 0;
1023: int srcLength = src.length();
1024: int ind = 0;
1025:
1026: for (int i = startAt; i < srcLength; i++) {
1027: char c = src.charAt(i);
1028:
1029: if (allowBackslashEscapes && c == '\\') {
1030: escaped = !escaped;
1031: } else if (c == markerCloses.charAt(markerTypeFound)
1032: && !escaped) {
1033: contextMarker = Character.MIN_VALUE;
1034: } else if ((ind = marker.indexOf(c)) != -1 && !escaped
1035: && contextMarker == Character.MIN_VALUE) {
1036: markerTypeFound = ind;
1037: contextMarker = c;
1038: } else if (c == target.charAt(0) && !escaped
1039: && contextMarker == Character.MIN_VALUE) {
1040: if (indexOfIgnoreCase(i, src, target) != -1)
1041: return i;
1042: }
1043: }
1044:
1045: return -1;
1046:
1047: }
1048:
1049: public static int indexOfIgnoreCaseRespectQuotes(int startAt,
1050: String src, String target, char quoteChar,
1051: boolean allowBackslashEscapes) {
1052: char contextMarker = Character.MIN_VALUE;
1053: boolean escaped = false;
1054:
1055: int srcLength = src.length();
1056:
1057: for (int i = startAt; i < srcLength; i++) {
1058: char c = src.charAt(i);
1059:
1060: if (allowBackslashEscapes && c == '\\') {
1061: escaped = !escaped;
1062: } else if (c == contextMarker && !escaped) {
1063: contextMarker = Character.MIN_VALUE;
1064: } else if (c == quoteChar && !escaped
1065: && contextMarker == Character.MIN_VALUE) {
1066: contextMarker = c;
1067: // This test looks complex, but remember that in certain locales, upper case
1068: // of two different codepoints coverts to same codepoint, and vice-versa.
1069: } else if ((Character.toUpperCase(c) == Character
1070: .toUpperCase(target.charAt(0)) || Character
1071: .toLowerCase(c) == Character.toLowerCase(target
1072: .charAt(0)))
1073: && !escaped && contextMarker == Character.MIN_VALUE) {
1074: if (startsWithIgnoreCase(src, i, target))
1075: return i;
1076: }
1077: }
1078:
1079: return -1;
1080:
1081: }
1082:
1083: /**
1084: * Splits stringToSplit into a list, using the given delimitter
1085: *
1086: * @param stringToSplit
1087: * the string to split
1088: * @param delimitter
1089: * the string to split on
1090: * @param trim
1091: * should the split strings be whitespace trimmed?
1092: *
1093: * @return the list of strings, split by delimitter
1094: *
1095: * @throws IllegalArgumentException
1096: * DOCUMENT ME!
1097: */
1098: public static final List split(String stringToSplit,
1099: String delimitter, boolean trim) {
1100: if (stringToSplit == null) {
1101: return new ArrayList();
1102: }
1103:
1104: if (delimitter == null) {
1105: throw new IllegalArgumentException();
1106: }
1107:
1108: StringTokenizer tokenizer = new StringTokenizer(stringToSplit,
1109: delimitter, false);
1110:
1111: List splitTokens = new ArrayList(tokenizer.countTokens());
1112:
1113: while (tokenizer.hasMoreTokens()) {
1114: String token = tokenizer.nextToken();
1115:
1116: if (trim) {
1117: token = token.trim();
1118: }
1119:
1120: splitTokens.add(token);
1121: }
1122:
1123: return splitTokens;
1124: }
1125:
1126: /**
1127: * Splits stringToSplit into a list, using the given delimitter
1128: *
1129: * @param stringToSplit
1130: * the string to split
1131: * @param delimitter
1132: * the string to split on
1133: * @param trim
1134: * should the split strings be whitespace trimmed?
1135: *
1136: * @return the list of strings, split by delimiter
1137: *
1138: * @throws IllegalArgumentException
1139: * DOCUMENT ME!
1140: */
1141: public static final List split(String stringToSplit,
1142: String delimiter, String markers, String markerCloses,
1143: boolean trim) {
1144: if (stringToSplit == null) {
1145: return new ArrayList();
1146: }
1147:
1148: if (delimiter == null) {
1149: throw new IllegalArgumentException();
1150: }
1151:
1152: int delimPos = 0;
1153: int currentPos = 0;
1154:
1155: List splitTokens = new ArrayList();
1156:
1157: while ((delimPos = indexOfIgnoreCaseRespectMarker(currentPos,
1158: stringToSplit, delimiter, markers, markerCloses, false)) != -1) {
1159: String token = stringToSplit
1160: .substring(currentPos, delimPos);
1161:
1162: if (trim) {
1163: token = token.trim();
1164: }
1165:
1166: splitTokens.add(token);
1167: currentPos = delimPos + 1;
1168: }
1169:
1170: if (currentPos < stringToSplit.length()) {
1171: String token = stringToSplit.substring(currentPos);
1172:
1173: if (trim) {
1174: token = token.trim();
1175: }
1176:
1177: splitTokens.add(token);
1178: }
1179:
1180: return splitTokens;
1181: }
1182:
1183: private static boolean startsWith(byte[] dataFrom, String chars) {
1184: for (int i = 0; i < chars.length(); i++) {
1185: if (dataFrom[i] != chars.charAt(i)) {
1186: return false;
1187: }
1188: }
1189: return true;
1190: }
1191:
1192: /**
1193: * Determines whether or not the string 'searchIn' contains the string
1194: * 'searchFor', dis-regarding case starting at 'startAt' Shorthand for a
1195: * String.regionMatch(...)
1196: *
1197: * @param searchIn
1198: * the string to search in
1199: * @param startAt
1200: * the position to start at
1201: * @param searchFor
1202: * the string to search for
1203: *
1204: * @return whether searchIn starts with searchFor, ignoring case
1205: */
1206: public static boolean startsWithIgnoreCase(String searchIn,
1207: int startAt, String searchFor) {
1208: return searchIn.regionMatches(true, startAt, searchFor, 0,
1209: searchFor.length());
1210: }
1211:
1212: /**
1213: * Determines whether or not the string 'searchIn' contains the string
1214: * 'searchFor', dis-regarding case. Shorthand for a String.regionMatch(...)
1215: *
1216: * @param searchIn
1217: * the string to search in
1218: * @param searchFor
1219: * the string to search for
1220: *
1221: * @return whether searchIn starts with searchFor, ignoring case
1222: */
1223: public static boolean startsWithIgnoreCase(String searchIn,
1224: String searchFor) {
1225: return startsWithIgnoreCase(searchIn, 0, searchFor);
1226: }
1227:
1228: /**
1229: * Determines whether or not the sting 'searchIn' contains the string
1230: * 'searchFor', disregarding case,leading whitespace and non-alphanumeric
1231: * characters.
1232: *
1233: * @param searchIn
1234: * the string to search in
1235: * @param searchFor
1236: * the string to search for
1237: *
1238: * @return true if the string starts with 'searchFor' ignoring whitespace
1239: */
1240: public static boolean startsWithIgnoreCaseAndNonAlphaNumeric(
1241: String searchIn, String searchFor) {
1242: if (searchIn == null) {
1243: return searchFor == null;
1244: }
1245:
1246: int beginPos = 0;
1247:
1248: int inLength = searchIn.length();
1249:
1250: for (beginPos = 0; beginPos < inLength; beginPos++) {
1251: char c = searchIn.charAt(beginPos);
1252:
1253: if (Character.isLetterOrDigit(c)) {
1254: break;
1255: }
1256: }
1257:
1258: return startsWithIgnoreCase(searchIn, beginPos, searchFor);
1259: }
1260:
1261: /**
1262: * Determines whether or not the sting 'searchIn' contains the string
1263: * 'searchFor', disregarding case and leading whitespace
1264: *
1265: * @param searchIn
1266: * the string to search in
1267: * @param searchFor
1268: * the string to search for
1269: *
1270: * @return true if the string starts with 'searchFor' ignoring whitespace
1271: */
1272: public static boolean startsWithIgnoreCaseAndWs(String searchIn,
1273: String searchFor) {
1274: return startsWithIgnoreCaseAndWs(searchIn, searchFor, 0);
1275: }
1276:
1277: /**
1278: * Determines whether or not the sting 'searchIn' contains the string
1279: * 'searchFor', disregarding case and leading whitespace
1280: *
1281: * @param searchIn
1282: * the string to search in
1283: * @param searchFor
1284: * the string to search for
1285: * @param beginPos
1286: * where to start searching
1287: *
1288: * @return true if the string starts with 'searchFor' ignoring whitespace
1289: */
1290:
1291: public static boolean startsWithIgnoreCaseAndWs(String searchIn,
1292: String searchFor, int beginPos) {
1293: if (searchIn == null) {
1294: return searchFor == null;
1295: }
1296:
1297: int inLength = searchIn.length();
1298:
1299: for (; beginPos < inLength; beginPos++) {
1300: if (!Character.isWhitespace(searchIn.charAt(beginPos))) {
1301: break;
1302: }
1303: }
1304:
1305: return startsWithIgnoreCase(searchIn, beginPos, searchFor);
1306: }
1307:
1308: /**
1309: * @param bytesToStrip
1310: * @param prefix
1311: * @param suffix
1312: * @return
1313: */
1314: public static byte[] stripEnclosure(byte[] source, String prefix,
1315: String suffix) {
1316: if (source.length >= prefix.length() + suffix.length()
1317: && startsWith(source, prefix)
1318: && endsWith(source, suffix)) {
1319:
1320: int totalToStrip = prefix.length() + suffix.length();
1321: int enclosedLength = source.length - totalToStrip;
1322: byte[] enclosed = new byte[enclosedLength];
1323:
1324: int startPos = prefix.length();
1325: int numToCopy = enclosed.length;
1326: System.arraycopy(source, startPos, enclosed, 0, numToCopy);
1327:
1328: return enclosed;
1329: }
1330: return source;
1331: }
1332:
1333: /**
1334: * Returns the bytes as an ASCII String.
1335: *
1336: * @param buffer
1337: * the bytes representing the string
1338: *
1339: * @return The ASCII String.
1340: */
1341: public static final String toAsciiString(byte[] buffer) {
1342: return toAsciiString(buffer, 0, buffer.length);
1343: }
1344:
1345: /**
1346: * Returns the bytes as an ASCII String.
1347: *
1348: * @param buffer
1349: * the bytes to convert
1350: * @param startPos
1351: * the position to start converting
1352: * @param length
1353: * the length of the string to convert
1354: *
1355: * @return the ASCII string
1356: */
1357: public static final String toAsciiString(byte[] buffer,
1358: int startPos, int length) {
1359: char[] charArray = new char[length];
1360: int readpoint = startPos;
1361:
1362: for (int i = 0; i < length; i++) {
1363: charArray[i] = (char) buffer[readpoint];
1364: readpoint++;
1365: }
1366:
1367: return new String(charArray);
1368: }
1369:
1370: /**
1371: * Compares searchIn against searchForWildcard with wildcards (heavily
1372: * borrowed from strings/ctype-simple.c in the server sources)
1373: *
1374: * @param searchIn
1375: * the string to search in
1376: * @param searchForWildcard
1377: * the string to search for, using the 'standard' SQL wildcard
1378: * chars of '%' and '_'
1379: *
1380: * @return WILD_COMPARE_MATCH_NO_WILD if matched, WILD_COMPARE_NO_MATCH if
1381: * not matched with wildcard, WILD_COMPARE_MATCH_WITH_WILD if
1382: * matched with wildcard
1383: */
1384: public static int wildCompare(String searchIn,
1385: String searchForWildcard) {
1386: if ((searchIn == null) || (searchForWildcard == null)) {
1387: return WILD_COMPARE_NO_MATCH;
1388: }
1389:
1390: if (searchForWildcard.equals("%")) { //$NON-NLS-1$
1391:
1392: return WILD_COMPARE_MATCH_WITH_WILD;
1393: }
1394:
1395: int result = WILD_COMPARE_NO_MATCH; /* Not found, using wildcards */
1396:
1397: char wildcardMany = '%';
1398: char wildcardOne = '_';
1399: char wildcardEscape = '\\';
1400:
1401: int searchForPos = 0;
1402: int searchForEnd = searchForWildcard.length();
1403:
1404: int searchInPos = 0;
1405: int searchInEnd = searchIn.length();
1406:
1407: while (searchForPos != searchForEnd) {
1408: char wildstrChar = searchForWildcard.charAt(searchForPos);
1409:
1410: while ((searchForWildcard.charAt(searchForPos) != wildcardMany)
1411: && (wildstrChar != wildcardOne)) {
1412: if ((searchForWildcard.charAt(searchForPos) == wildcardEscape)
1413: && ((searchForPos + 1) != searchForEnd)) {
1414: searchForPos++;
1415: }
1416:
1417: if ((searchInPos == searchInEnd)
1418: || (Character.toUpperCase(searchForWildcard
1419: .charAt(searchForPos++)) != Character
1420: .toUpperCase(searchIn
1421: .charAt(searchInPos++)))) {
1422: return WILD_COMPARE_MATCH_WITH_WILD; /* No match */
1423: }
1424:
1425: if (searchForPos == searchForEnd) {
1426: return ((searchInPos != searchInEnd) ? WILD_COMPARE_MATCH_WITH_WILD
1427: : WILD_COMPARE_MATCH_NO_WILD); /*
1428: * Match if both are
1429: * at end
1430: */
1431: }
1432:
1433: result = WILD_COMPARE_MATCH_WITH_WILD; /* Found an anchor char */
1434: }
1435:
1436: if (searchForWildcard.charAt(searchForPos) == wildcardOne) {
1437: do {
1438: if (searchInPos == searchInEnd) { /*
1439: * Skip one char if
1440: * possible
1441: */
1442:
1443: return (result);
1444: }
1445:
1446: searchInPos++;
1447: } while ((++searchForPos < searchForEnd)
1448: && (searchForWildcard.charAt(searchForPos) == wildcardOne));
1449:
1450: if (searchForPos == searchForEnd) {
1451: break;
1452: }
1453: }
1454:
1455: if (searchForWildcard.charAt(searchForPos) == wildcardMany) { /*
1456: * Found
1457: * w_many
1458: */
1459:
1460: char cmp;
1461:
1462: searchForPos++;
1463:
1464: /* Remove any '%' and '_' from the wild search string */
1465: for (; searchForPos != searchForEnd; searchForPos++) {
1466: if (searchForWildcard.charAt(searchForPos) == wildcardMany) {
1467: continue;
1468: }
1469:
1470: if (searchForWildcard.charAt(searchForPos) == wildcardOne) {
1471: if (searchInPos == searchInEnd) {
1472: return (WILD_COMPARE_NO_MATCH);
1473: }
1474:
1475: searchInPos++;
1476:
1477: continue;
1478: }
1479:
1480: break; /* Not a wild character */
1481: }
1482:
1483: if (searchForPos == searchForEnd) {
1484: return WILD_COMPARE_MATCH_NO_WILD; /* Ok if w_many is last */
1485: }
1486:
1487: if (searchInPos == searchInEnd) {
1488: return WILD_COMPARE_NO_MATCH;
1489: }
1490:
1491: if (((cmp = searchForWildcard.charAt(searchForPos)) == wildcardEscape)
1492: && ((searchForPos + 1) != searchForEnd)) {
1493: cmp = searchForWildcard.charAt(++searchForPos);
1494: }
1495:
1496: searchForPos++;
1497:
1498: do {
1499: while ((searchInPos != searchInEnd)
1500: && (Character.toUpperCase(searchIn
1501: .charAt(searchInPos)) != Character
1502: .toUpperCase(cmp)))
1503: searchInPos++;
1504:
1505: if (searchInPos++ == searchInEnd) {
1506: return WILD_COMPARE_NO_MATCH;
1507: }
1508:
1509: {
1510: int tmp = wildCompare(searchIn,
1511: searchForWildcard);
1512:
1513: if (tmp <= 0) {
1514: return (tmp);
1515: }
1516: }
1517: } while ((searchInPos != searchInEnd)
1518: && (searchForWildcard.charAt(0) != wildcardMany));
1519:
1520: return WILD_COMPARE_NO_MATCH;
1521: }
1522: }
1523:
1524: return ((searchInPos != searchInEnd) ? WILD_COMPARE_MATCH_WITH_WILD
1525: : WILD_COMPARE_MATCH_NO_WILD);
1526: }
1527:
1528: static byte[] s2b(String s, ConnectionImpl conn)
1529: throws SQLException {
1530: if (s == null) {
1531: return null;
1532: }
1533:
1534: if ((conn != null) && conn.getUseUnicode()) {
1535: try {
1536: String encoding = conn.getEncoding();
1537:
1538: if (encoding == null) {
1539: return s.getBytes();
1540: }
1541:
1542: SingleByteCharsetConverter converter = conn
1543: .getCharsetConverter(encoding);
1544:
1545: if (converter != null) {
1546: return converter.toBytes(s);
1547: }
1548:
1549: return s.getBytes(encoding);
1550: } catch (java.io.UnsupportedEncodingException E) {
1551: return s.getBytes();
1552: }
1553: }
1554:
1555: return s.getBytes();
1556: }
1557:
1558: public static int lastIndexOf(byte[] s, char c) {
1559: if (s == null) {
1560: return -1;
1561: }
1562:
1563: for (int i = s.length - 1; i >= 0; i--) {
1564: if (s[i] == c) {
1565: return i;
1566: }
1567: }
1568:
1569: return -1;
1570: }
1571:
1572: public static int indexOf(byte[] s, char c) {
1573: if (s == null) {
1574: return -1;
1575: }
1576:
1577: int length = s.length;
1578:
1579: for (int i = 0; i < length; i++) {
1580: if (s[i] == c) {
1581: return i;
1582: }
1583: }
1584:
1585: return -1;
1586: }
1587:
1588: public static boolean isNullOrEmpty(String toTest) {
1589: return (toTest == null || toTest.length() == 0);
1590: }
1591:
1592: /**
1593: * Returns the given string, with comments removed
1594: *
1595: * @param src
1596: * the source string
1597: * @param stringOpens
1598: * characters which delimit the "open" of a string
1599: * @param stringCloses
1600: * characters which delimit the "close" of a string, in
1601: * counterpart order to <code>stringOpens</code>
1602: * @param slashStarComments
1603: * strip slash-star type "C" style comments
1604: * @param slashSlashComments
1605: * strip slash-slash C++ style comments to end-of-line
1606: * @param hashComments
1607: * strip #-style comments to end-of-line
1608: * @param dashDashComments
1609: * strip "--" style comments to end-of-line
1610: * @return the input string with all comment-delimited data removed
1611: */
1612: public static String stripComments(String src, String stringOpens,
1613: String stringCloses, boolean slashStarComments,
1614: boolean slashSlashComments, boolean hashComments,
1615: boolean dashDashComments) {
1616: if (src == null) {
1617: return null;
1618: }
1619:
1620: StringBuffer buf = new StringBuffer(src.length());
1621:
1622: // It's just more natural to deal with this as a stream
1623: // when parsing..This code is currently only called when
1624: // parsing the kind of metadata that developers are strongly
1625: // recommended to cache anyways, so we're not worried
1626: // about the _1_ extra object allocation if it cleans
1627: // up the code
1628:
1629: StringReader sourceReader = new StringReader(src);
1630:
1631: int contextMarker = Character.MIN_VALUE;
1632: boolean escaped = false;
1633: int markerTypeFound = -1;
1634:
1635: int ind = 0;
1636:
1637: int currentChar = 0;
1638:
1639: try {
1640: while ((currentChar = sourceReader.read()) != -1) {
1641:
1642: if (false && currentChar == '\\') {
1643: escaped = !escaped;
1644: } else if (markerTypeFound != -1
1645: && currentChar == stringCloses
1646: .charAt(markerTypeFound) && !escaped) {
1647: contextMarker = Character.MIN_VALUE;
1648: markerTypeFound = -1;
1649: } else if ((ind = stringOpens.indexOf(currentChar)) != -1
1650: && !escaped
1651: && contextMarker == Character.MIN_VALUE) {
1652: markerTypeFound = ind;
1653: contextMarker = currentChar;
1654: }
1655:
1656: if (contextMarker == Character.MIN_VALUE
1657: && currentChar == '/'
1658: && (slashSlashComments || slashStarComments)) {
1659: currentChar = sourceReader.read();
1660: if (currentChar == '*' && slashStarComments) {
1661: int prevChar = 0;
1662: while ((currentChar = sourceReader.read()) != '/'
1663: || prevChar != '*') {
1664: if (currentChar == '\r') {
1665:
1666: currentChar = sourceReader.read();
1667: if (currentChar == '\n') {
1668: currentChar = sourceReader.read();
1669: }
1670: } else {
1671: if (currentChar == '\n') {
1672:
1673: currentChar = sourceReader.read();
1674: }
1675: }
1676: if (currentChar < 0)
1677: break;
1678: prevChar = currentChar;
1679: }
1680: continue;
1681: } else if (currentChar == '/' && slashSlashComments) {
1682: while ((currentChar = sourceReader.read()) != '\n'
1683: && currentChar != '\r'
1684: && currentChar >= 0)
1685: ;
1686: }
1687: } else if (contextMarker == Character.MIN_VALUE
1688: && currentChar == '#' && hashComments) {
1689: // Slurp up everything until the newline
1690: while ((currentChar = sourceReader.read()) != '\n'
1691: && currentChar != '\r' && currentChar >= 0)
1692: ;
1693: } else if (contextMarker == Character.MIN_VALUE
1694: && currentChar == '-' && dashDashComments) {
1695: currentChar = sourceReader.read();
1696:
1697: if (currentChar == -1 || currentChar != '-') {
1698: buf.append('-');
1699:
1700: if (currentChar != -1) {
1701: buf.append(currentChar);
1702: }
1703:
1704: continue;
1705: }
1706:
1707: // Slurp up everything until the newline
1708:
1709: while ((currentChar = sourceReader.read()) != '\n'
1710: && currentChar != '\r' && currentChar >= 0)
1711: ;
1712: }
1713:
1714: if (currentChar != -1) {
1715: buf.append((char) currentChar);
1716: }
1717: }
1718: } catch (IOException ioEx) {
1719: // we'll never see this from a StringReader
1720: }
1721:
1722: return buf.toString();
1723: }
1724:
1725: public static final boolean isEmptyOrWhitespaceOnly(String str) {
1726: if (str == null || str.length() == 0) {
1727: return true;
1728: }
1729:
1730: int length = str.length();
1731:
1732: for (int i = 0; i < length; i++) {
1733: if (!Character.isWhitespace(str.charAt(i))) {
1734: return false;
1735: }
1736: }
1737:
1738: return true;
1739: }
1740: }
|