PageRenderTime 54ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/EQEmuJSM/mysql-connector-java-5.1.13/src/com/mysql/jdbc/StringUtils.java

http://cubbers-eqemu-utils.googlecode.com/
Java | 1699 lines | 1018 code | 307 blank | 374 comment | 465 complexity | f3db39d99c5d65cde24fc5a35f271d54 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, Apache-2.0
  1. /*
  2. Copyright 2002-2004 MySQL AB, 2008-2010 Sun Microsystems
  3. All rights reserved. Use is subject to license terms.
  4. The MySQL Connector/J is licensed under the terms of the GPL,
  5. like most MySQL Connectors. There are special exceptions to the
  6. terms and conditions of the GPL as it is applied to this software,
  7. see the FLOSS License Exception available on mysql.com.
  8. This program is free software; you can redistribute it and/or
  9. modify it under the terms of the GNU General Public License as
  10. published by the Free Software Foundation; version 2 of the
  11. License.
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  19. 02110-1301 USA
  20. */
  21. package com.mysql.jdbc;
  22. import java.io.ByteArrayOutputStream;
  23. import java.io.IOException;
  24. import java.io.StringReader;
  25. import java.io.UnsupportedEncodingException;
  26. import java.lang.reflect.InvocationTargetException;
  27. import java.lang.reflect.Method;
  28. import java.math.BigDecimal;
  29. import java.sql.SQLException;
  30. import java.util.ArrayList;
  31. import java.util.List;
  32. import java.util.StringTokenizer;
  33. /**
  34. * Various utility methods for converting to/from byte arrays in the platform
  35. * encoding
  36. *
  37. * @author Mark Matthews
  38. */
  39. public class StringUtils {
  40. private static final int BYTE_RANGE = (1 + Byte.MAX_VALUE) - Byte.MIN_VALUE;
  41. private static byte[] allBytes = new byte[BYTE_RANGE];
  42. private static char[] byteToChars = new char[BYTE_RANGE];
  43. private static Method toPlainStringMethod;
  44. static final int WILD_COMPARE_MATCH_NO_WILD = 0;
  45. static final int WILD_COMPARE_MATCH_WITH_WILD = 1;
  46. static final int WILD_COMPARE_NO_MATCH = -1;
  47. static {
  48. for (int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) {
  49. allBytes[i - Byte.MIN_VALUE] = (byte) i;
  50. }
  51. String allBytesString = new String(allBytes, 0, Byte.MAX_VALUE
  52. - Byte.MIN_VALUE);
  53. int allBytesStringLen = allBytesString.length();
  54. for (int i = 0; (i < (Byte.MAX_VALUE - Byte.MIN_VALUE))
  55. && (i < allBytesStringLen); i++) {
  56. byteToChars[i] = allBytesString.charAt(i);
  57. }
  58. try {
  59. toPlainStringMethod = BigDecimal.class.getMethod("toPlainString",
  60. new Class[0]);
  61. } catch (NoSuchMethodException nsme) {
  62. // that's okay, we fallback to .toString()
  63. }
  64. }
  65. /**
  66. * Takes care of the fact that Sun changed the output of
  67. * BigDecimal.toString() between JDK-1.4 and JDK 5
  68. *
  69. * @param decimal
  70. * the big decimal to stringify
  71. *
  72. * @return a string representation of 'decimal'
  73. */
  74. public static String consistentToString(BigDecimal decimal) {
  75. if (decimal == null) {
  76. return null;
  77. }
  78. if (toPlainStringMethod != null) {
  79. try {
  80. return (String) toPlainStringMethod.invoke(decimal, (Object[])null);
  81. } catch (InvocationTargetException invokeEx) {
  82. // that's okay, we fall-through to decimal.toString()
  83. } catch (IllegalAccessException accessEx) {
  84. // that's okay, we fall-through to decimal.toString()
  85. }
  86. }
  87. return decimal.toString();
  88. }
  89. /**
  90. * Dumps the given bytes to STDOUT as a hex dump (up to length bytes).
  91. *
  92. * @param byteBuffer
  93. * the data to print as hex
  94. * @param length
  95. * the number of bytes to print
  96. *
  97. * @return ...
  98. */
  99. public static final String dumpAsHex(byte[] byteBuffer, int length) {
  100. StringBuffer outputBuf = new StringBuffer(length * 4);
  101. int p = 0;
  102. int rows = length / 8;
  103. for (int i = 0; (i < rows) && (p < length); i++) {
  104. int ptemp = p;
  105. for (int j = 0; j < 8; j++) {
  106. String hexVal = Integer.toHexString(byteBuffer[ptemp] & 0xff);
  107. if (hexVal.length() == 1) {
  108. hexVal = "0" + hexVal; //$NON-NLS-1$
  109. }
  110. outputBuf.append(hexVal + " "); //$NON-NLS-1$
  111. ptemp++;
  112. }
  113. outputBuf.append(" "); //$NON-NLS-1$
  114. for (int j = 0; j < 8; j++) {
  115. int b = 0xff & byteBuffer[p];
  116. if (b > 32 && b < 127) {
  117. outputBuf.append((char) b + " "); //$NON-NLS-1$
  118. } else {
  119. outputBuf.append(". "); //$NON-NLS-1$
  120. }
  121. p++;
  122. }
  123. outputBuf.append("\n"); //$NON-NLS-1$
  124. }
  125. int n = 0;
  126. for (int i = p; i < length; i++) {
  127. String hexVal = Integer.toHexString(byteBuffer[i] & 0xff);
  128. if (hexVal.length() == 1) {
  129. hexVal = "0" + hexVal; //$NON-NLS-1$
  130. }
  131. outputBuf.append(hexVal + " "); //$NON-NLS-1$
  132. n++;
  133. }
  134. for (int i = n; i < 8; i++) {
  135. outputBuf.append(" "); //$NON-NLS-1$
  136. }
  137. outputBuf.append(" "); //$NON-NLS-1$
  138. for (int i = p; i < length; i++) {
  139. int b = 0xff & byteBuffer[i];
  140. if (b > 32 && b < 127) {
  141. outputBuf.append((char) b + " "); //$NON-NLS-1$
  142. } else {
  143. outputBuf.append(". "); //$NON-NLS-1$
  144. }
  145. }
  146. outputBuf.append("\n"); //$NON-NLS-1$
  147. return outputBuf.toString();
  148. }
  149. private static boolean endsWith(byte[] dataFrom, String suffix) {
  150. for (int i = 1; i <= suffix.length(); i++) {
  151. int dfOffset = dataFrom.length - i;
  152. int suffixOffset = suffix.length() - i;
  153. if (dataFrom[dfOffset] != suffix.charAt(suffixOffset)) {
  154. return false;
  155. }
  156. }
  157. return true;
  158. }
  159. /**
  160. * Unfortunately, SJIS has 0x5c as a high byte in some of its double-byte
  161. * characters, so we need to escape it.
  162. *
  163. * @param origBytes
  164. * the original bytes in SJIS format
  165. * @param origString
  166. * the string that had .getBytes() called on it
  167. * @param offset
  168. * where to start converting from
  169. * @param length
  170. * how many characters to convert.
  171. *
  172. * @return byte[] with 0x5c escaped
  173. */
  174. public static byte[] escapeEasternUnicodeByteStream(byte[] origBytes,
  175. String origString, int offset, int length) {
  176. if ((origBytes == null) || (origBytes.length == 0)) {
  177. return origBytes;
  178. }
  179. int bytesLen = origBytes.length;
  180. int bufIndex = 0;
  181. int strIndex = 0;
  182. ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(bytesLen);
  183. while (true) {
  184. if (origString.charAt(strIndex) == '\\') {
  185. // write it out as-is
  186. bytesOut.write(origBytes[bufIndex++]);
  187. // bytesOut.write(origBytes[bufIndex++]);
  188. } else {
  189. // Grab the first byte
  190. int loByte = origBytes[bufIndex];
  191. if (loByte < 0) {
  192. loByte += 256; // adjust for signedness/wrap-around
  193. }
  194. // We always write the first byte
  195. bytesOut.write(loByte);
  196. //
  197. // The codepage characters in question exist between
  198. // 0x81-0x9F and 0xE0-0xFC...
  199. //
  200. // See:
  201. //
  202. // http://www.microsoft.com/GLOBALDEV/Reference/dbcs/932.htm
  203. //
  204. // Problematic characters in GBK
  205. //
  206. // U+905C : CJK UNIFIED IDEOGRAPH
  207. //
  208. // Problematic characters in Big5
  209. //
  210. // B9F0 = U+5C62 : CJK UNIFIED IDEOGRAPH
  211. //
  212. if (loByte >= 0x80) {
  213. if (bufIndex < (bytesLen - 1)) {
  214. int hiByte = origBytes[bufIndex + 1];
  215. if (hiByte < 0) {
  216. hiByte += 256; // adjust for signedness/wrap-around
  217. }
  218. // write the high byte here, and increment the index
  219. // for the high byte
  220. bytesOut.write(hiByte);
  221. bufIndex++;
  222. // escape 0x5c if necessary
  223. if (hiByte == 0x5C) {
  224. bytesOut.write(hiByte);
  225. }
  226. }
  227. } else if (loByte == 0x5c) {
  228. if (bufIndex < (bytesLen - 1)) {
  229. int hiByte = origBytes[bufIndex + 1];
  230. if (hiByte < 0) {
  231. hiByte += 256; // adjust for signedness/wrap-around
  232. }
  233. if (hiByte == 0x62) {
  234. // we need to escape the 0x5c
  235. bytesOut.write(0x5c);
  236. bytesOut.write(0x62);
  237. bufIndex++;
  238. }
  239. }
  240. }
  241. bufIndex++;
  242. }
  243. if (bufIndex >= bytesLen) {
  244. // we're done
  245. break;
  246. }
  247. strIndex++;
  248. }
  249. return bytesOut.toByteArray();
  250. }
  251. /**
  252. * Returns the first non whitespace char, converted to upper case
  253. *
  254. * @param searchIn
  255. * the string to search in
  256. *
  257. * @return the first non-whitespace character, upper cased.
  258. */
  259. public static char firstNonWsCharUc(String searchIn) {
  260. return firstNonWsCharUc(searchIn, 0);
  261. }
  262. public static char firstNonWsCharUc(String searchIn, int startAt) {
  263. if (searchIn == null) {
  264. return 0;
  265. }
  266. int length = searchIn.length();
  267. for (int i = startAt; i < length; i++) {
  268. char c = searchIn.charAt(i);
  269. if (!Character.isWhitespace(c)) {
  270. return Character.toUpperCase(c);
  271. }
  272. }
  273. return 0;
  274. }
  275. public static char firstAlphaCharUc(String searchIn, int startAt) {
  276. if (searchIn == null) {
  277. return 0;
  278. }
  279. int length = searchIn.length();
  280. for (int i = startAt; i < length; i++) {
  281. char c = searchIn.charAt(i);
  282. if (Character.isLetter(c)) {
  283. return Character.toUpperCase(c);
  284. }
  285. }
  286. return 0;
  287. }
  288. /**
  289. * Adds '+' to decimal numbers that are positive (MySQL doesn't understand
  290. * them otherwise
  291. *
  292. * @param dString
  293. * The value as a string
  294. *
  295. * @return String the string with a '+' added (if needed)
  296. */
  297. public static final String fixDecimalExponent(String dString) {
  298. int ePos = dString.indexOf("E"); //$NON-NLS-1$
  299. if (ePos == -1) {
  300. ePos = dString.indexOf("e"); //$NON-NLS-1$
  301. }
  302. if (ePos != -1) {
  303. if (dString.length() > (ePos + 1)) {
  304. char maybeMinusChar = dString.charAt(ePos + 1);
  305. if (maybeMinusChar != '-' && maybeMinusChar != '+') {
  306. StringBuffer buf = new StringBuffer(dString.length() + 1);
  307. buf.append(dString.substring(0, ePos + 1));
  308. buf.append('+');
  309. buf.append(dString.substring(ePos + 1, dString.length()));
  310. dString = buf.toString();
  311. }
  312. }
  313. }
  314. return dString;
  315. }
  316. public static final byte[] getBytes(char[] c,
  317. SingleByteCharsetConverter converter, String encoding,
  318. String serverEncoding, boolean parserKnowsUnicode, ExceptionInterceptor exceptionInterceptor)
  319. throws SQLException {
  320. try {
  321. byte[] b = null;
  322. if (converter != null) {
  323. b = converter.toBytes(c);
  324. } else if (encoding == null) {
  325. b = new String(c).getBytes();
  326. } else {
  327. String s = new String(c);
  328. b = s.getBytes(encoding);
  329. if (!parserKnowsUnicode && (encoding.equalsIgnoreCase("SJIS") //$NON-NLS-1$
  330. || encoding.equalsIgnoreCase("BIG5") //$NON-NLS-1$
  331. || encoding.equalsIgnoreCase("GBK"))) { //$NON-NLS-1$
  332. if (!encoding.equalsIgnoreCase(serverEncoding)) {
  333. b = escapeEasternUnicodeByteStream(b, s, 0, s.length());
  334. }
  335. }
  336. }
  337. return b;
  338. } catch (UnsupportedEncodingException uee) {
  339. throw SQLError.createSQLException(Messages.getString("StringUtils.5") //$NON-NLS-1$
  340. + encoding + Messages.getString("StringUtils.6"),
  341. SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); //$NON-NLS-1$
  342. }
  343. }
  344. public static final byte[] getBytes(char[] c,
  345. SingleByteCharsetConverter converter, String encoding,
  346. String serverEncoding, int offset, int length,
  347. boolean parserKnowsUnicode, ExceptionInterceptor exceptionInterceptor) throws SQLException {
  348. try {
  349. byte[] b = null;
  350. if (converter != null) {
  351. b = converter.toBytes(c, offset, length);
  352. } else if (encoding == null) {
  353. byte[] temp = new String(c, offset, length).getBytes();
  354. length = temp.length;
  355. b = new byte[length];
  356. System.arraycopy(temp, 0, b, 0, length);
  357. } else {
  358. String s = new String(c, offset, length);
  359. byte[] temp = s.getBytes(encoding);
  360. length = temp.length;
  361. b = new byte[length];
  362. System.arraycopy(temp, 0, b, 0, length);
  363. if (!parserKnowsUnicode && (encoding.equalsIgnoreCase("SJIS") //$NON-NLS-1$
  364. || encoding.equalsIgnoreCase("BIG5") //$NON-NLS-1$
  365. || encoding.equalsIgnoreCase("GBK"))) { //$NON-NLS-1$
  366. if (!encoding.equalsIgnoreCase(serverEncoding)) {
  367. b = escapeEasternUnicodeByteStream(b, s, offset, length);
  368. }
  369. }
  370. }
  371. return b;
  372. } catch (UnsupportedEncodingException uee) {
  373. throw SQLError.createSQLException(Messages.getString("StringUtils.10") //$NON-NLS-1$
  374. + encoding + Messages.getString("StringUtils.11"),
  375. SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); //$NON-NLS-1$
  376. }
  377. }
  378. public static final byte[] getBytes(char[] c, String encoding,
  379. String serverEncoding, boolean parserKnowsUnicode,
  380. MySQLConnection conn, ExceptionInterceptor exceptionInterceptor)
  381. throws SQLException {
  382. try {
  383. SingleByteCharsetConverter converter = null;
  384. if (conn != null) {
  385. converter = conn.getCharsetConverter(encoding);
  386. } else {
  387. converter = SingleByteCharsetConverter.getInstance(encoding, null);
  388. }
  389. return getBytes(c, converter, encoding, serverEncoding,
  390. parserKnowsUnicode, exceptionInterceptor);
  391. } catch (UnsupportedEncodingException uee) {
  392. throw SQLError.createSQLException(Messages.getString("StringUtils.0") //$NON-NLS-1$
  393. + encoding + Messages.getString("StringUtils.1"),
  394. SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); //$NON-NLS-1$
  395. }
  396. }
  397. /**
  398. * Returns the byte[] representation of the given string (re)using the given
  399. * charset converter, and the given encoding.
  400. *
  401. * @param s
  402. * the string to convert
  403. * @param converter
  404. * the converter to reuse
  405. * @param encoding
  406. * the character encoding to use
  407. * @param serverEncoding
  408. * DOCUMENT ME!
  409. * @param parserKnowsUnicode
  410. * DOCUMENT ME!
  411. *
  412. * @return byte[] representation of the string
  413. *
  414. * @throws SQLException
  415. * if an encoding unsupported by the JVM is supplied.
  416. */
  417. public static final byte[] getBytes(String s,
  418. SingleByteCharsetConverter converter, String encoding,
  419. String serverEncoding, boolean parserKnowsUnicode, ExceptionInterceptor exceptionInterceptor)
  420. throws SQLException {
  421. try {
  422. byte[] b = null;
  423. if (converter != null) {
  424. b = converter.toBytes(s);
  425. } else if (encoding == null) {
  426. b = s.getBytes();
  427. } else {
  428. b = s.getBytes(encoding);
  429. if (!parserKnowsUnicode && (encoding.equalsIgnoreCase("SJIS") //$NON-NLS-1$
  430. || encoding.equalsIgnoreCase("BIG5") //$NON-NLS-1$
  431. || encoding.equalsIgnoreCase("GBK"))) { //$NON-NLS-1$
  432. if (!encoding.equalsIgnoreCase(serverEncoding)) {
  433. b = escapeEasternUnicodeByteStream(b, s, 0, s.length());
  434. }
  435. }
  436. }
  437. return b;
  438. } catch (UnsupportedEncodingException uee) {
  439. throw SQLError.createSQLException(Messages.getString("StringUtils.5") //$NON-NLS-1$
  440. + encoding + Messages.getString("StringUtils.6"),
  441. SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); //$NON-NLS-1$
  442. }
  443. }
  444. public static final byte[] getBytesWrapped(String s, char beginWrap, char endWrap,
  445. SingleByteCharsetConverter converter, String encoding,
  446. String serverEncoding, boolean parserKnowsUnicode, ExceptionInterceptor exceptionInterceptor)
  447. throws SQLException {
  448. try {
  449. byte[] b = null;
  450. if (converter != null) {
  451. b = converter.toBytesWrapped(s, beginWrap, endWrap);
  452. } else if (encoding == null) {
  453. StringBuffer buf = new StringBuffer(s.length() + 2);
  454. buf.append(beginWrap);
  455. buf.append(s);
  456. buf.append(endWrap);
  457. b = buf.toString().getBytes();
  458. } else {
  459. StringBuffer buf = new StringBuffer(s.length() + 2);
  460. buf.append(beginWrap);
  461. buf.append(s);
  462. buf.append(endWrap);
  463. b = buf.toString().getBytes(encoding);
  464. if (!parserKnowsUnicode && (encoding.equalsIgnoreCase("SJIS") //$NON-NLS-1$
  465. || encoding.equalsIgnoreCase("BIG5") //$NON-NLS-1$
  466. || encoding.equalsIgnoreCase("GBK"))) { //$NON-NLS-1$
  467. if (!encoding.equalsIgnoreCase(serverEncoding)) {
  468. b = escapeEasternUnicodeByteStream(b, s, 0, s.length());
  469. }
  470. }
  471. }
  472. return b;
  473. } catch (UnsupportedEncodingException uee) {
  474. throw SQLError.createSQLException(Messages.getString("StringUtils.5") //$NON-NLS-1$
  475. + encoding + Messages.getString("StringUtils.6"),
  476. SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); //$NON-NLS-1$
  477. }
  478. }
  479. /**
  480. * DOCUMENT ME!
  481. *
  482. * @param s
  483. * DOCUMENT ME!
  484. * @param converter
  485. * DOCUMENT ME!
  486. * @param encoding
  487. * DOCUMENT ME!
  488. * @param serverEncoding
  489. * DOCUMENT ME!
  490. * @param offset
  491. * DOCUMENT ME!
  492. * @param length
  493. * DOCUMENT ME!
  494. * @param parserKnowsUnicode
  495. * DOCUMENT ME!
  496. *
  497. * @return DOCUMENT ME!
  498. *
  499. * @throws SQLException
  500. * DOCUMENT ME!
  501. */
  502. public static final byte[] getBytes(String s,
  503. SingleByteCharsetConverter converter, String encoding,
  504. String serverEncoding, int offset, int length,
  505. boolean parserKnowsUnicode, ExceptionInterceptor exceptionInterceptor) throws SQLException {
  506. try {
  507. byte[] b = null;
  508. if (converter != null) {
  509. b = converter.toBytes(s, offset, length);
  510. } else if (encoding == null) {
  511. byte[] temp = s.substring(offset, offset + length).getBytes();
  512. length = temp.length;
  513. b = new byte[length];
  514. System.arraycopy(temp, 0, b, 0, length);
  515. } else {
  516. byte[] temp = s.substring(offset, offset + length)
  517. .getBytes(encoding);
  518. length = temp.length;
  519. b = new byte[length];
  520. System.arraycopy(temp, 0, b, 0, length);
  521. if (!parserKnowsUnicode && (encoding.equalsIgnoreCase("SJIS") //$NON-NLS-1$
  522. || encoding.equalsIgnoreCase("BIG5") //$NON-NLS-1$
  523. || encoding.equalsIgnoreCase("GBK"))) { //$NON-NLS-1$
  524. if (!encoding.equalsIgnoreCase(serverEncoding)) {
  525. b = escapeEasternUnicodeByteStream(b, s, offset, length);
  526. }
  527. }
  528. }
  529. return b;
  530. } catch (UnsupportedEncodingException uee) {
  531. throw SQLError.createSQLException(Messages.getString("StringUtils.10") //$NON-NLS-1$
  532. + encoding + Messages.getString("StringUtils.11"),
  533. SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); //$NON-NLS-1$
  534. }
  535. }
  536. /**
  537. * Returns the byte[] representation of the given string using given
  538. * encoding.
  539. *
  540. * @param s
  541. * the string to convert
  542. * @param encoding
  543. * the character encoding to use
  544. * @param parserKnowsUnicode
  545. * DOCUMENT ME!
  546. *
  547. * @return byte[] representation of the string
  548. *
  549. * @throws SQLException
  550. * if an encoding unsupported by the JVM is supplied.
  551. */
  552. public static final byte[] getBytes(String s, String encoding,
  553. String serverEncoding, boolean parserKnowsUnicode,
  554. MySQLConnection conn, ExceptionInterceptor exceptionInterceptor)
  555. throws SQLException {
  556. try {
  557. SingleByteCharsetConverter converter = null;
  558. if (conn != null) {
  559. converter = conn.getCharsetConverter(encoding);
  560. } else {
  561. converter = SingleByteCharsetConverter.getInstance(encoding, null);
  562. }
  563. return getBytes(s, converter, encoding, serverEncoding,
  564. parserKnowsUnicode, exceptionInterceptor);
  565. } catch (UnsupportedEncodingException uee) {
  566. throw SQLError.createSQLException(Messages.getString("StringUtils.0") //$NON-NLS-1$
  567. + encoding + Messages.getString("StringUtils.1"),
  568. SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); //$NON-NLS-1$
  569. }
  570. }
  571. public static int getInt(byte[] buf, int offset, int endPos) throws NumberFormatException {
  572. int base = 10;
  573. int s = offset;
  574. /* Skip white space. */
  575. while (Character.isWhitespace((char) buf[s]) && (s < endPos)) {
  576. ++s;
  577. }
  578. if (s == endPos) {
  579. throw new NumberFormatException(new String(buf));
  580. }
  581. /* Check for a sign. */
  582. boolean negative = false;
  583. if ((char) buf[s] == '-') {
  584. negative = true;
  585. ++s;
  586. } else if ((char) buf[s] == '+') {
  587. ++s;
  588. }
  589. /* Save the pointer so we can check later if anything happened. */
  590. int save = s;
  591. int cutoff = Integer.MAX_VALUE / base;
  592. int cutlim = (Integer.MAX_VALUE % base);
  593. if (negative) {
  594. cutlim++;
  595. }
  596. boolean overflow = false;
  597. int i = 0;
  598. for (; s < endPos; s++) {
  599. char c = (char) buf[s];
  600. if (Character.isDigit(c)) {
  601. c -= '0';
  602. } else if (Character.isLetter(c)) {
  603. c = (char) (Character.toUpperCase(c) - 'A' + 10);
  604. } else {
  605. break;
  606. }
  607. if (c >= base) {
  608. break;
  609. }
  610. /* Check for overflow. */
  611. if ((i > cutoff) || ((i == cutoff) && (c > cutlim))) {
  612. overflow = true;
  613. } else {
  614. i *= base;
  615. i += c;
  616. }
  617. }
  618. if (s == save) {
  619. throw new NumberFormatException(new String(buf));
  620. }
  621. if (overflow) {
  622. throw new NumberFormatException(new String(buf));
  623. }
  624. /* Return the result of the appropriate sign. */
  625. return (negative ? (-i) : i);
  626. }
  627. public static int getInt(byte[] buf) throws NumberFormatException {
  628. return getInt(buf, 0, buf.length);
  629. }
  630. public static long getLong(byte[] buf) throws NumberFormatException {
  631. return getLong(buf, 0, buf.length);
  632. }
  633. public static long getLong(byte[] buf, int offset, int endpos) throws NumberFormatException {
  634. int base = 10;
  635. int s = offset;
  636. /* Skip white space. */
  637. while (Character.isWhitespace((char) buf[s]) && (s < endpos)) {
  638. ++s;
  639. }
  640. if (s == endpos) {
  641. throw new NumberFormatException(new String(buf));
  642. }
  643. /* Check for a sign. */
  644. boolean negative = false;
  645. if ((char) buf[s] == '-') {
  646. negative = true;
  647. ++s;
  648. } else if ((char) buf[s] == '+') {
  649. ++s;
  650. }
  651. /* Save the pointer so we can check later if anything happened. */
  652. int save = s;
  653. long cutoff = Long.MAX_VALUE / base;
  654. long cutlim = (int) (Long.MAX_VALUE % base);
  655. if (negative) {
  656. cutlim++;
  657. }
  658. boolean overflow = false;
  659. long i = 0;
  660. for (; s < endpos; s++) {
  661. char c = (char) buf[s];
  662. if (Character.isDigit(c)) {
  663. c -= '0';
  664. } else if (Character.isLetter(c)) {
  665. c = (char) (Character.toUpperCase(c) - 'A' + 10);
  666. } else {
  667. break;
  668. }
  669. if (c >= base) {
  670. break;
  671. }
  672. /* Check for overflow. */
  673. if ((i > cutoff) || ((i == cutoff) && (c > cutlim))) {
  674. overflow = true;
  675. } else {
  676. i *= base;
  677. i += c;
  678. }
  679. }
  680. if (s == save) {
  681. throw new NumberFormatException(new String(buf));
  682. }
  683. if (overflow) {
  684. throw new NumberFormatException(new String(buf));
  685. }
  686. /* Return the result of the appropriate sign. */
  687. return (negative ? (-i) : i);
  688. }
  689. public static short getShort(byte[] buf) throws NumberFormatException {
  690. short base = 10;
  691. int s = 0;
  692. /* Skip white space. */
  693. while (Character.isWhitespace((char) buf[s]) && (s < buf.length)) {
  694. ++s;
  695. }
  696. if (s == buf.length) {
  697. throw new NumberFormatException(new String(buf));
  698. }
  699. /* Check for a sign. */
  700. boolean negative = false;
  701. if ((char) buf[s] == '-') {
  702. negative = true;
  703. ++s;
  704. } else if ((char) buf[s] == '+') {
  705. ++s;
  706. }
  707. /* Save the pointer so we can check later if anything happened. */
  708. int save = s;
  709. short cutoff = (short) (Short.MAX_VALUE / base);
  710. short cutlim = (short) (Short.MAX_VALUE % base);
  711. if (negative) {
  712. cutlim++;
  713. }
  714. boolean overflow = false;
  715. short i = 0;
  716. for (; s < buf.length; s++) {
  717. char c = (char) buf[s];
  718. if (Character.isDigit(c)) {
  719. c -= '0';
  720. } else if (Character.isLetter(c)) {
  721. c = (char) (Character.toUpperCase(c) - 'A' + 10);
  722. } else {
  723. break;
  724. }
  725. if (c >= base) {
  726. break;
  727. }
  728. /* Check for overflow. */
  729. if ((i > cutoff) || ((i == cutoff) && (c > cutlim))) {
  730. overflow = true;
  731. } else {
  732. i *= base;
  733. i += c;
  734. }
  735. }
  736. if (s == save) {
  737. throw new NumberFormatException(new String(buf));
  738. }
  739. if (overflow) {
  740. throw new NumberFormatException(new String(buf));
  741. }
  742. /* Return the result of the appropriate sign. */
  743. return (negative ? (short) -i : (short) i);
  744. }
  745. public final static int indexOfIgnoreCase(int startingPosition,
  746. String searchIn, String searchFor) {
  747. if ((searchIn == null) || (searchFor == null)
  748. || startingPosition > searchIn.length()) {
  749. return -1;
  750. }
  751. int patternLength = searchFor.length();
  752. int stringLength = searchIn.length();
  753. int stopSearchingAt = stringLength - patternLength;
  754. if (patternLength == 0) {
  755. return -1;
  756. }
  757. // Brute force string pattern matching
  758. // Some locales don't follow upper-case rule, so need to check both
  759. char firstCharOfPatternUc = Character.toUpperCase(searchFor.charAt(0));
  760. char firstCharOfPatternLc = Character.toLowerCase(searchFor.charAt(0));
  761. // note, this also catches the case where patternLength > stringLength
  762. for (int i = startingPosition; i <= stopSearchingAt; i++) {
  763. if (isNotEqualIgnoreCharCase(searchIn, firstCharOfPatternUc,
  764. firstCharOfPatternLc, i)) {
  765. // find the first occurrence of the first character of searchFor in searchIn
  766. while (++i <= stopSearchingAt && (isNotEqualIgnoreCharCase(searchIn, firstCharOfPatternUc,
  767. firstCharOfPatternLc, i)));
  768. }
  769. if (i <= stopSearchingAt /* searchFor might be one character long! */) {
  770. // walk searchIn and searchFor in lock-step starting just past the first match,bail out if not
  771. // a match, or we've hit the end of searchFor...
  772. int j = i + 1;
  773. int end = j + patternLength - 1;
  774. for (int k = 1; j < end && (Character.toLowerCase(searchIn.charAt(j)) ==
  775. Character.toLowerCase(searchFor.charAt(k)) || Character.toUpperCase(searchIn.charAt(j)) ==
  776. Character.toUpperCase(searchFor.charAt(k))); j++, k++);
  777. if (j == end) {
  778. return i;
  779. }
  780. }
  781. }
  782. return -1;
  783. }
  784. private final static boolean isNotEqualIgnoreCharCase(String searchIn,
  785. char firstCharOfPatternUc, char firstCharOfPatternLc, int i) {
  786. return Character.toLowerCase(searchIn.charAt(i)) != firstCharOfPatternLc && Character.toUpperCase(searchIn.charAt(i)) != firstCharOfPatternUc;
  787. }
  788. /**
  789. * DOCUMENT ME!
  790. *
  791. * @param searchIn
  792. * DOCUMENT ME!
  793. * @param searchFor
  794. * DOCUMENT ME!
  795. *
  796. * @return DOCUMENT ME!
  797. */
  798. public final static int indexOfIgnoreCase(String searchIn, String searchFor) {
  799. return indexOfIgnoreCase(0, searchIn, searchFor);
  800. }
  801. public static int indexOfIgnoreCaseRespectMarker(int startAt, String src,
  802. String target, String marker, String markerCloses,
  803. boolean allowBackslashEscapes) {
  804. char contextMarker = Character.MIN_VALUE;
  805. boolean escaped = false;
  806. int markerTypeFound = 0;
  807. int srcLength = src.length();
  808. int ind = 0;
  809. for (int i = startAt; i < srcLength; i++) {
  810. char c = src.charAt(i);
  811. if (allowBackslashEscapes && c == '\\') {
  812. escaped = !escaped;
  813. } else if (c == markerCloses.charAt(markerTypeFound) && !escaped) {
  814. contextMarker = Character.MIN_VALUE;
  815. } else if ((ind = marker.indexOf(c)) != -1 && !escaped
  816. && contextMarker == Character.MIN_VALUE) {
  817. markerTypeFound = ind;
  818. contextMarker = c;
  819. } else if ((Character.toUpperCase(c) == Character.toUpperCase(target.charAt(0)) ||
  820. Character.toLowerCase(c) == Character.toLowerCase(target.charAt(0))) && !escaped
  821. && contextMarker == Character.MIN_VALUE) {
  822. if (startsWithIgnoreCase(src, i, target))
  823. return i;
  824. }
  825. }
  826. return -1;
  827. }
  828. public static int indexOfIgnoreCaseRespectQuotes(int startAt, String src,
  829. String target, char quoteChar, boolean allowBackslashEscapes) {
  830. char contextMarker = Character.MIN_VALUE;
  831. boolean escaped = false;
  832. int srcLength = src.length();
  833. for (int i = startAt; i < srcLength; i++) {
  834. char c = src.charAt(i);
  835. if (allowBackslashEscapes && c == '\\') {
  836. escaped = !escaped;
  837. } else if (c == contextMarker && !escaped) {
  838. contextMarker = Character.MIN_VALUE;
  839. } else if (c == quoteChar && !escaped
  840. && contextMarker == Character.MIN_VALUE) {
  841. contextMarker = c;
  842. // This test looks complex, but remember that in certain locales, upper case
  843. // of two different codepoints coverts to same codepoint, and vice-versa.
  844. } else if ((Character.toUpperCase(c) == Character.toUpperCase(target.charAt(0)) ||
  845. Character.toLowerCase(c) == Character.toLowerCase(target.charAt(0))) && !escaped
  846. && contextMarker == Character.MIN_VALUE) {
  847. if (startsWithIgnoreCase(src, i, target))
  848. return i;
  849. }
  850. }
  851. return -1;
  852. }
  853. /**
  854. * Splits stringToSplit into a list, using the given delimitter
  855. *
  856. * @param stringToSplit
  857. * the string to split
  858. * @param delimitter
  859. * the string to split on
  860. * @param trim
  861. * should the split strings be whitespace trimmed?
  862. *
  863. * @return the list of strings, split by delimitter
  864. *
  865. * @throws IllegalArgumentException
  866. * DOCUMENT ME!
  867. */
  868. public static final List split(String stringToSplit, String delimitter,
  869. boolean trim) {
  870. if (stringToSplit == null) {
  871. return new ArrayList();
  872. }
  873. if (delimitter == null) {
  874. throw new IllegalArgumentException();
  875. }
  876. StringTokenizer tokenizer = new StringTokenizer(stringToSplit,
  877. delimitter, false);
  878. List splitTokens = new ArrayList(tokenizer.countTokens());
  879. while (tokenizer.hasMoreTokens()) {
  880. String token = tokenizer.nextToken();
  881. if (trim) {
  882. token = token.trim();
  883. }
  884. splitTokens.add(token);
  885. }
  886. return splitTokens;
  887. }
  888. /**
  889. * Splits stringToSplit into a list, using the given delimitter
  890. *
  891. * @param stringToSplit
  892. * the string to split
  893. * @param delimitter
  894. * the string to split on
  895. * @param trim
  896. * should the split strings be whitespace trimmed?
  897. *
  898. * @return the list of strings, split by delimiter
  899. *
  900. * @throws IllegalArgumentException
  901. * DOCUMENT ME!
  902. */
  903. public static final List split(String stringToSplit, String delimiter,
  904. String markers, String markerCloses, boolean trim) {
  905. if (stringToSplit == null) {
  906. return new ArrayList();
  907. }
  908. if (delimiter == null) {
  909. throw new IllegalArgumentException();
  910. }
  911. int delimPos = 0;
  912. int currentPos = 0;
  913. List splitTokens = new ArrayList();
  914. while ((delimPos = indexOfIgnoreCaseRespectMarker(currentPos,
  915. stringToSplit, delimiter, markers, markerCloses, false)) != -1) {
  916. String token = stringToSplit.substring(currentPos, delimPos);
  917. if (trim) {
  918. token = token.trim();
  919. }
  920. splitTokens.add(token);
  921. currentPos = delimPos + 1;
  922. }
  923. if (currentPos < stringToSplit.length()) {
  924. String token = stringToSplit.substring(currentPos);
  925. if (trim) {
  926. token = token.trim();
  927. }
  928. splitTokens.add(token);
  929. }
  930. return splitTokens;
  931. }
  932. private static boolean startsWith(byte[] dataFrom, String chars) {
  933. for (int i = 0; i < chars.length(); i++) {
  934. if (dataFrom[i] != chars.charAt(i)) {
  935. return false;
  936. }
  937. }
  938. return true;
  939. }
  940. /**
  941. * Determines whether or not the string 'searchIn' contains the string
  942. * 'searchFor', dis-regarding case starting at 'startAt' Shorthand for a
  943. * String.regionMatch(...)
  944. *
  945. * @param searchIn
  946. * the string to search in
  947. * @param startAt
  948. * the position to start at
  949. * @param searchFor
  950. * the string to search for
  951. *
  952. * @return whether searchIn starts with searchFor, ignoring case
  953. */
  954. public static boolean startsWithIgnoreCase(String searchIn, int startAt,
  955. String searchFor) {
  956. return searchIn.regionMatches(true, startAt, searchFor, 0, searchFor
  957. .length());
  958. }
  959. /**
  960. * Determines whether or not the string 'searchIn' contains the string
  961. * 'searchFor', dis-regarding case. Shorthand for a String.regionMatch(...)
  962. *
  963. * @param searchIn
  964. * the string to search in
  965. * @param searchFor
  966. * the string to search for
  967. *
  968. * @return whether searchIn starts with searchFor, ignoring case
  969. */
  970. public static boolean startsWithIgnoreCase(String searchIn, String searchFor) {
  971. return startsWithIgnoreCase(searchIn, 0, searchFor);
  972. }
  973. /**
  974. * Determines whether or not the sting 'searchIn' contains the string
  975. * 'searchFor', disregarding case,leading whitespace and non-alphanumeric
  976. * characters.
  977. *
  978. * @param searchIn
  979. * the string to search in
  980. * @param searchFor
  981. * the string to search for
  982. *
  983. * @return true if the string starts with 'searchFor' ignoring whitespace
  984. */
  985. public static boolean startsWithIgnoreCaseAndNonAlphaNumeric(
  986. String searchIn, String searchFor) {
  987. if (searchIn == null) {
  988. return searchFor == null;
  989. }
  990. int beginPos = 0;
  991. int inLength = searchIn.length();
  992. for (beginPos = 0; beginPos < inLength; beginPos++) {
  993. char c = searchIn.charAt(beginPos);
  994. if (Character.isLetterOrDigit(c)) {
  995. break;
  996. }
  997. }
  998. return startsWithIgnoreCase(searchIn, beginPos, searchFor);
  999. }
  1000. /**
  1001. * Determines whether or not the sting 'searchIn' contains the string
  1002. * 'searchFor', disregarding case and leading whitespace
  1003. *
  1004. * @param searchIn
  1005. * the string to search in
  1006. * @param searchFor
  1007. * the string to search for
  1008. *
  1009. * @return true if the string starts with 'searchFor' ignoring whitespace
  1010. */
  1011. public static boolean startsWithIgnoreCaseAndWs(String searchIn,
  1012. String searchFor) {
  1013. return startsWithIgnoreCaseAndWs(searchIn, searchFor, 0);
  1014. }
  1015. /**
  1016. * Determines whether or not the sting 'searchIn' contains the string
  1017. * 'searchFor', disregarding case and leading whitespace
  1018. *
  1019. * @param searchIn
  1020. * the string to search in
  1021. * @param searchFor
  1022. * the string to search for
  1023. * @param beginPos
  1024. * where to start searching
  1025. *
  1026. * @return true if the string starts with 'searchFor' ignoring whitespace
  1027. */
  1028. public static boolean startsWithIgnoreCaseAndWs(String searchIn,
  1029. String searchFor, int beginPos) {
  1030. if (searchIn == null) {
  1031. return searchFor == null;
  1032. }
  1033. int inLength = searchIn.length();
  1034. for (; beginPos < inLength; beginPos++) {
  1035. if (!Character.isWhitespace(searchIn.charAt(beginPos))) {
  1036. break;
  1037. }
  1038. }
  1039. return startsWithIgnoreCase(searchIn, beginPos, searchFor);
  1040. }
  1041. /**
  1042. * @param bytesToStrip
  1043. * @param prefix
  1044. * @param suffix
  1045. * @return
  1046. */
  1047. public static byte[] stripEnclosure(byte[] source, String prefix,
  1048. String suffix) {
  1049. if (source.length >= prefix.length() + suffix.length()
  1050. && startsWith(source, prefix) && endsWith(source, suffix)) {
  1051. int totalToStrip = prefix.length() + suffix.length();
  1052. int enclosedLength = source.length - totalToStrip;
  1053. byte[] enclosed = new byte[enclosedLength];
  1054. int startPos = prefix.length();
  1055. int numToCopy = enclosed.length;
  1056. System.arraycopy(source, startPos, enclosed, 0, numToCopy);
  1057. return enclosed;
  1058. }
  1059. return source;
  1060. }
  1061. /**
  1062. * Returns the bytes as an ASCII String.
  1063. *
  1064. * @param buffer
  1065. * the bytes representing the string
  1066. *
  1067. * @return The ASCII String.
  1068. */
  1069. public static final String toAsciiString(byte[] buffer) {
  1070. return toAsciiString(buffer, 0, buffer.length);
  1071. }
  1072. /**
  1073. * Returns the bytes as an ASCII String.
  1074. *
  1075. * @param buffer
  1076. * the bytes to convert
  1077. * @param startPos
  1078. * the position to start converting
  1079. * @param length
  1080. * the length of the string to convert
  1081. *
  1082. * @return the ASCII string
  1083. */
  1084. public static final String toAsciiString(byte[] buffer, int startPos,
  1085. int length) {
  1086. char[] charArray = new char[length];
  1087. int readpoint = startPos;
  1088. for (int i = 0; i < length; i++) {
  1089. charArray[i] = (char) buffer[readpoint];
  1090. readpoint++;
  1091. }
  1092. return new String(charArray);
  1093. }
  1094. /**
  1095. * Compares searchIn against searchForWildcard with wildcards (heavily
  1096. * borrowed from strings/ctype-simple.c in the server sources)
  1097. *
  1098. * @param searchIn
  1099. * the string to search in
  1100. * @param searchForWildcard
  1101. * the string to search for, using the 'standard' SQL wildcard
  1102. * chars of '%' and '_'
  1103. *
  1104. * @return WILD_COMPARE_MATCH_NO_WILD if matched, WILD_COMPARE_NO_MATCH if
  1105. * not matched with wildcard, WILD_COMPARE_MATCH_WITH_WILD if
  1106. * matched with wildcard
  1107. */
  1108. public static int wildCompare(String searchIn, String searchForWildcard) {
  1109. if ((searchIn == null) || (searchForWildcard == null)) {
  1110. return WILD_COMPARE_NO_MATCH;
  1111. }
  1112. if (searchForWildcard.equals("%")) { //$NON-NLS-1$
  1113. return WILD_COMPARE_MATCH_WITH_WILD;
  1114. }
  1115. int result = WILD_COMPARE_NO_MATCH; /* Not found, using wildcards */
  1116. char wildcardMany = '%';
  1117. char wildcardOne = '_';
  1118. char wildcardEscape = '\\';
  1119. int searchForPos = 0;
  1120. int searchForEnd = searchForWildcard.length();
  1121. int searchInPos = 0;
  1122. int searchInEnd = searchIn.length();
  1123. while (searchForPos != searchForEnd) {
  1124. char wildstrChar = searchForWildcard.charAt(searchForPos);
  1125. while ((searchForWildcard.charAt(searchForPos) != wildcardMany)
  1126. && (wildstrChar != wildcardOne)) {
  1127. if ((searchForWildcard.charAt(searchForPos) == wildcardEscape)
  1128. && ((searchForPos + 1) != searchForEnd)) {
  1129. searchForPos++;
  1130. }
  1131. if ((searchInPos == searchInEnd)
  1132. || (Character.toUpperCase(searchForWildcard
  1133. .charAt(searchForPos++)) != Character
  1134. .toUpperCase(searchIn.charAt(searchInPos++)))) {
  1135. return WILD_COMPARE_MATCH_WITH_WILD; /* No match */
  1136. }
  1137. if (searchForPos == searchForEnd) {
  1138. return ((searchInPos != searchInEnd) ? WILD_COMPARE_MATCH_WITH_WILD
  1139. : WILD_COMPARE_MATCH_NO_WILD); /*
  1140. * Match if both are
  1141. * at end
  1142. */
  1143. }
  1144. result = WILD_COMPARE_MATCH_WITH_WILD; /* Found an anchor char */
  1145. }
  1146. if (searchForWildcard.charAt(searchForPos) == wildcardOne) {
  1147. do {
  1148. if (searchInPos == searchInEnd) { /*
  1149. * Skip one char if
  1150. * possible
  1151. */
  1152. return (result);
  1153. }
  1154. searchInPos++;
  1155. } while ((++searchForPos < searchForEnd)
  1156. && (searchForWildcard.charAt(searchForPos) == wildcardOne));
  1157. if (searchForPos == searchForEnd) {
  1158. break;
  1159. }
  1160. }
  1161. if (searchForWildcard.charAt(searchForPos) == wildcardMany) { /*
  1162. * Found
  1163. * w_many
  1164. */
  1165. char cmp;
  1166. searchForPos++;
  1167. /* Remove any '%' and '_' from the wild search string */
  1168. for (; searchForPos != searchForEnd; searchForPos++) {
  1169. if (searchForWildcard.charAt(searchForPos) == wildcardMany) {
  1170. continue;
  1171. }
  1172. if (searchForWildcard.charAt(searchForPos) == wildcardOne) {
  1173. if (searchInPos == searchInEnd) {
  1174. return (WILD_COMPARE_NO_MATCH);
  1175. }
  1176. searchInPos++;
  1177. continue;
  1178. }
  1179. break; /* Not a wild character */
  1180. }
  1181. if (searchForPos == searchForEnd) {
  1182. return WILD_COMPARE_MATCH_NO_WILD; /* Ok if w_many is last */
  1183. }
  1184. if (searchInPos == searchInEnd) {
  1185. return WILD_COMPARE_NO_MATCH;
  1186. }
  1187. if (((cmp = searchForWildcard.charAt(searchForPos)) == wildcardEscape)
  1188. && ((searchForPos + 1) != searchForEnd)) {
  1189. cmp = searchForWildcard.charAt(++searchForPos);
  1190. }
  1191. searchForPos++;
  1192. do {
  1193. while ((searchInPos != searchInEnd)
  1194. && (Character.toUpperCase(searchIn
  1195. .charAt(searchInPos)) != Character
  1196. .toUpperCase(cmp)))
  1197. searchInPos++;
  1198. if (searchInPos++ == searchInEnd) {
  1199. return WILD_COMPARE_NO_MATCH;
  1200. }
  1201. {
  1202. int tmp = wildCompare(searchIn, searchForWildcard);
  1203. if (tmp <= 0) {
  1204. return (tmp);
  1205. }
  1206. }
  1207. } while ((searchInPos != searchInEnd)
  1208. && (searchForWildcard.charAt(0) != wildcardMany));
  1209. return WILD_COMPARE_NO_MATCH;
  1210. }
  1211. }
  1212. return ((searchInPos != searchInEnd) ? WILD_COMPARE_MATCH_WITH_WILD
  1213. : WILD_COMPARE_MATCH_NO_WILD);
  1214. }
  1215. static byte[] s2b(String s, MySQLConnection conn) throws SQLException {
  1216. if (s == null) {
  1217. return null;
  1218. }
  1219. if ((conn != null) && conn.getUseUnicode()) {
  1220. try {
  1221. String encoding = conn.getEncoding();
  1222. if (encoding == null) {
  1223. return s.getBytes();
  1224. }
  1225. SingleByteCharsetConverter converter = conn
  1226. .getCharsetConverter(encoding);
  1227. if (converter != null) {
  1228. return converter.toBytes(s);
  1229. }
  1230. return s.getBytes(encoding);
  1231. } catch (java.io.UnsupportedEncodingException E) {
  1232. return s.getBytes();
  1233. }
  1234. }
  1235. return s.getBytes();
  1236. }
  1237. public static int lastIndexOf(byte[] s, char c) {
  1238. if (s == null) {
  1239. return -1;
  1240. }
  1241. for (int i = s.length - 1; i >= 0; i--) {
  1242. if (s[i] == c) {
  1243. return i;
  1244. }
  1245. }
  1246. return -1;
  1247. }
  1248. public static int indexOf(byte[] s, char c) {
  1249. if (s == null) {
  1250. return -1;
  1251. }
  1252. int length = s.length;
  1253. for (int i = 0; i < length; i++) {
  1254. if (s[i] == c) {
  1255. return i;
  1256. }
  1257. }
  1258. return -1;
  1259. }
  1260. public static boolean isNullOrEmpty(String toTest) {
  1261. return (toTest == null || toTest.length() == 0);
  1262. }
  1263. /**
  1264. * Returns the given string, with comments removed
  1265. *
  1266. * @param src
  1267. * the source string
  1268. * @param stringOpens
  1269. * characters which delimit the "open" of a string
  1270. * @param stringCloses
  1271. * characters which delimit the "close" of a string, in
  1272. * counterpart order to <code>stringOpens</code>
  1273. * @param slashStarComments
  1274. * strip slash-star type "C" style comments
  1275. * @param slashSlashComments
  1276. * strip slash-slash C++ style comments to end-of-line
  1277. * @param hashComments
  1278. * strip #-style comments to end-of-line
  1279. * @param dashDashComments
  1280. * strip "--" style comments to end-of-line
  1281. * @return the input string with all comment-delimited data removed
  1282. */
  1283. public static String stripComments(String src, String stringOpens,
  1284. String stringCloses, boolean slashStarComments,
  1285. boolean slashSlashComments, boolean hashComments,
  1286. boolean dashDashComments) {
  1287. if (src == null) {
  1288. return null;
  1289. }
  1290. StringBuffer buf = new StringBuffer(src.length());
  1291. // It's just more natural to deal with this as a stream
  1292. // when parsing..This code is currently only called when
  1293. // parsing the kind of metadata that developers are strongly
  1294. // recommended to cache anyways, so we're not worried
  1295. // about the _1_ extra object allocation if it cleans
  1296. // up the code
  1297. StringReader sourceReader = new StringReader(src);
  1298. int contextMarker = Character.MIN_VALUE;
  1299. boolean escaped = false;
  1300. int markerTypeFound = -1;
  1301. int ind = 0;
  1302. int currentChar = 0;
  1303. try {
  1304. while ((currentChar = sourceReader.read()) != -1) {
  1305. if (false && currentChar == '\\') {
  1306. escaped = !escaped;
  1307. } else if (markerTypeFound != -1 && currentChar == stringCloses.charAt(markerTypeFound)
  1308. && !escaped) {
  1309. contextMarker = Character.MIN_VALUE;
  1310. markerTypeFound = -1;
  1311. } else if ((ind = stringOpens.indexOf(currentChar)) != -1
  1312. && !escaped && contextMarker == Character.MIN_VALUE) {
  1313. markerTypeFound = ind;
  1314. contextMarker = currentChar;
  1315. }
  1316. if (contextMarker == Character.MIN_VALUE && currentChar == '/'
  1317. && (slashSlashComments || slashStarComments)) {
  1318. currentChar = sourceReader.read();
  1319. if (currentChar == '*' && slashStarComments) {
  1320. int prevChar = 0;
  1321. while ((currentChar = sourceReader.read()) != '/'
  1322. || prevChar != '*') {
  1323. if (currentChar == '\r') {
  1324. currentChar = sourceReader.read();
  1325. if (currentChar == '\n') {
  1326. currentChar = sourceReader.read();
  1327. }
  1328. } else {
  1329. if (currentChar == '\n') {
  1330. currentChar = sourceReader.read();
  1331. }
  1332. }
  1333. if (currentChar < 0)
  1334. break;
  1335. prevChar = currentChar;
  1336. }
  1337. continue;
  1338. } else if (currentChar == '/' && slashSlashComments) {
  1339. while ((currentChar = sourceReader.read()) != '\n'
  1340. && currentChar != '\r' && currentChar >= 0)
  1341. ;
  1342. }
  1343. } else if (contextMarker == Character.MIN_VALUE
  1344. && currentChar == '#' && hashComments) {
  1345. // Slurp up everything until the newline
  1346. while ((currentChar = sourceReader.read()) != '\n'
  1347. && currentChar != '\r' && currentChar >= 0)
  1348. ;
  1349. } else if (contextMarker == Character.MIN_VALUE
  1350. && currentChar == '-' && dashDashComments) {
  1351. currentChar = sourceReader.read();
  1352. if (currentChar == -1 || currentChar != '-') {
  1353. buf.append('-');
  1354. if (currentChar != -1) {
  1355. buf.append(currentChar);
  1356. }
  1357. continue;
  1358. }
  1359. // Slurp up everything until the newline
  1360. while ((currentChar = sourceReader.read()) != '\n'
  1361. && currentChar != '\r' && currentChar >= 0)
  1362. ;
  1363. }
  1364. if (currentChar != -1) {
  1365. buf.append((char) currentChar);
  1366. }
  1367. }
  1368. } catch (IOException ioEx) {
  1369. // we'll never see this from a StringReader
  1370. }
  1371. return buf.toString();
  1372. }
  1373. public static final boolean isEmptyOrWhitespaceOnly(String str) {
  1374. if (str == null || str.length() == 0) {
  1375. return true;
  1376. }
  1377. int length = str.length();
  1378. for (int i = 0; i < length; i++) {
  1379. if (!Character.isWhitespace(str.charAt(i))) {
  1380. return false;
  1381. }
  1382. }
  1383. return true;
  1384. }
  1385. }