/*
GNU LESSER GENERAL PUBLIC LICENSE
Copyright (C) 2006 The Lobo Project
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Contact info: lobochief@users.sourceforge.net
*/
package org.lobobrowser.util;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
public class Strings {
private static final MessageDigest MESSAGE_DIGEST;
public static final String[] EMPTY_ARRAY = new String[0];
static {
MessageDigest md;
try {
md = MessageDigest.getInstance("MD5");
} catch (final NoSuchAlgorithmException err) {
throw new IllegalStateException();
}
MESSAGE_DIGEST = md;
}
private Strings() {
}
public static int compareVersions(final String version1, final String version2, final boolean startsWithDigits) {
if (version1 == null) {
return version2 == null ? 0 : -1;
} else if (version2 == null) {
return +1;
}
if (startsWithDigits) {
final String v1prefix = leadingDigits(version1);
final String v2prefix = leadingDigits(version2);
if (v1prefix.length() == 0) {
if (v2prefix.length() == 0) {
return 0;
}
return -1;
} else if (v2prefix.length() == 0) {
return +1;
}
int diff;
try {
diff = Integer.parseInt(v1prefix) - Integer.parseInt(v2prefix);
} catch (final NumberFormatException nfe) {
diff = 0;
}
if (diff == 0) {
return compareVersions(version1.substring(v1prefix.length()), version2.substring(v2prefix.length()), false);
}
return diff;
} else {
final String v1prefix = leadingNonDigits(version1);
final String v2prefix = leadingNonDigits(version2);
if (v1prefix.length() == 0) {
if (v2prefix.length() == 0) {
return 0;
}
return -1;
} else if (v2prefix.length() == 0) {
return +1;
}
final int diff = v1prefix.compareTo(v2prefix);
if (diff == 0) {
return compareVersions(version1.substring(v1prefix.length()), version2.substring(v2prefix.length()), true);
}
return diff;
}
}
public static String leadingDigits(final String text) {
final int length = text.length();
StringBuffer buffer = null;
for (int i = 0; i < length; i++) {
final char ch = text.charAt(i);
if (!Character.isDigit(ch)) {
break;
}
if (buffer == null) {
buffer = new StringBuffer(3);
}
buffer.append(ch);
}
return buffer == null ? "" : buffer.toString();
}
public static String leadingNonDigits(final String text) {
final int length = text.length();
StringBuffer buffer = null;
for (int i = 0; i < length; i++) {
final char ch = text.charAt(i);
if (Character.isDigit(ch)) {
break;
}
if (buffer == null) {
buffer = new StringBuffer(3);
}
buffer.append(ch);
}
return buffer == null ? "" : buffer.toString();
}
public static boolean isBlank(final String text) {
return (text == null) || "".equals(text);
}
public static int countLines(final String text) {
int startIdx = 0;
int lineCount = 1;
for (;;) {
final int lbIdx = text.indexOf('\n', startIdx);
if (lbIdx == -1) {
break;
}
lineCount++;
startIdx = lbIdx + 1;
}
return lineCount;
}
public static boolean isJavaIdentifier(final String id) {
if (id == null) {
return false;
}
final int len = id.length();
if (len == 0) {
return false;
}
if (!Character.isJavaIdentifierStart(id.charAt(0))) {
return false;
}
for (int i = 1; i < len; i++) {
if (!Character.isJavaIdentifierPart(id.charAt(i))) {
return false;
}
}
return true;
}
public static String getJavaStringLiteral(final String text) {
final StringBuffer buf = new StringBuffer();
buf.append('"');
final int len = text.length();
for (int i = 0; i < len; i++) {
final char ch = text.charAt(i);
switch (ch) {
case '\\':
buf.append("\\\\");
break;
case '\n':
buf.append("\\n");
break;
case '\r':
buf.append("\\r");
break;
case '\t':
buf.append("\\t");
break;
case '"':
buf.append("\\\"");
break;
default:
buf.append(ch);
break;
}
}
buf.append('"');
return buf.toString();
}
public static String getJavaIdentifier(final String candidateID) {
final int len = candidateID.length();
final StringBuffer buf = new StringBuffer();
for (int i = 0; i < len; i++) {
final char ch = candidateID.charAt(i);
final boolean good = i == 0 ? Character.isJavaIdentifierStart(ch) : Character.isJavaIdentifierPart(ch);
if (good) {
buf.append(ch);
} else {
buf.append('_');
}
}
return buf.toString();
}
private static final String HEX_CHARS = "0123456789ABCDEF";
public static String getMD5(final String source) {
byte[] bytes;
try {
bytes = source.getBytes("UTF-8");
} catch (final java.io.UnsupportedEncodingException ue) {
throw new IllegalStateException(ue);
}
byte[] result;
synchronized (MESSAGE_DIGEST) {
MESSAGE_DIGEST.update(bytes);
result = MESSAGE_DIGEST.digest();
}
final char[] resChars = new char[32];
final int len = result.length;
for (int i = 0; i < len; i++) {
final byte b = result[i];
final int lo4 = b & 0x0F;
final int hi4 = (b & 0xF0) >> 4;
resChars[i * 2] = HEX_CHARS.charAt(hi4);
resChars[(i * 2) + 1] = HEX_CHARS.charAt(lo4);
}
return new String(resChars);
}
public static String getHash32(final String source) throws UnsupportedEncodingException {
final String md5 = getMD5(source);
return md5.substring(0, 8);
}
public static String getHash64(final String source) throws UnsupportedEncodingException {
final String md5 = getMD5(source);
return md5.substring(0, 16);
}
public static int countChars(final String text, final char ch) {
final int len = text.length();
int count = 0;
for (int i = 0; i < len; i++) {
if (ch == text.charAt(i)) {
count++;
}
}
return count;
}
// public static boolean isTrimmable(char ch) {
// switch(ch) {
// case ' ':
// case '\t':
// case '\r':
// case '\n':
// return true;
// }
// return false;
// }
//
// /**
// * Trims blanks, line breaks and tabs.
// * @param text
// * @return
// */
// public static String trim(String text) {
// int len = text.length();
// int startIdx;
// for(startIdx = 0; startIdx < len; startIdx++) {
// char ch = text.charAt(startIdx);
// if(!isTrimmable(ch)) {
// break;
// }
// }
// int endIdx;
// for(endIdx = len; --endIdx > startIdx; ) {
// char ch = text.charAt(endIdx);
// if(!isTrimmable(ch)) {
// break;
// }
// }
// return text.substring(startIdx, endIdx + 1);
// }
/**
* Removes the double-quotes at the beginning and end of a string. If input
* string doesn't have the double-quote character at beginning or end, it is
* returned unchanged.
*/
public static String unquote(final String text) {
final int length = text.length();
if (length >= 2) {
if ((text.charAt(0) == '"') && (text.charAt(length - 1) == '"')) {
return text.substring(1, length - 1);
}
}
return text;
}
/**
* Removes the single-quotes at the beginning and end of a string. If input
* string doesn't have the single-quote character at beginning or end, it is
* returned unchanged.
*/
public static String unquoteSingle(final String text) {
final int length = text.length();
if (length >= 2) {
if ((text.charAt(0) == '\'') && (text.charAt(length - 1) == '\'')) {
return text.substring(1, length - 1);
}
}
return text;
}
public static String[] split(final String phrase) {
final int length = phrase.length();
final ArrayList<String> wordList = new ArrayList<>();
StringBuffer word = null;
for (int i = 0; i < length; i++) {
final char ch = phrase.charAt(i);
switch (ch) {
case ' ':
case '\t':
case '\r':
case '\n':
if (word != null) {
wordList.add(word.toString());
word = null;
}
break;
default:
if (word == null) {
word = new StringBuffer();
}
word.append(ch);
}
}
if (word != null) {
wordList.add(word.toString());
}
return wordList.toArray(EMPTY_ARRAY);
}
public static String truncate(final String text, final int maxLength) {
if (text == null) {
return null;
}
if (text.length() <= maxLength) {
return text;
}
return text.substring(0, Math.max(maxLength - 3, 0)) + "...";
}
public static String strictHtmlEncode(final String rawText, final boolean quotes) {
final StringBuffer output = new StringBuffer();
final int length = rawText.length();
for (int i = 0; i < length; i++) {
final char ch = rawText.charAt(i);
switch (ch) {
case '&':
output.append("&");
break;
case '"':
if (quotes) {
output.append(""");
} else {
output.append(ch);
}
break;
case '<':
output.append("<");
break;
case '>':
output.append(">");
break;
default:
output.append(ch);
}
}
return output.toString();
}
public static String trimForAlphaNumDash(final String rawText) {
final int length = rawText.length();
for (int i = 0; i < length; i++) {
final char ch = rawText.charAt(i);
if (((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) || ((ch >= '0') && (ch <= '9')) || (ch == '-')) {
continue;
}
return rawText.substring(0, i);
}
return rawText;
}
public static String getCRLFString(final String original) {
if (original == null) {
return null;
}
final int length = original.length();
final StringBuffer buffer = new StringBuffer();
boolean lastSlashR = false;
for (int i = 0; i < length; i++) {
final char ch = original.charAt(i);
switch (ch) {
case '\r':
lastSlashR = true;
break;
case '\n':
lastSlashR = false;
buffer.append("\r\n");
break;
default:
if (lastSlashR) {
lastSlashR = false;
buffer.append("\r\n");
}
buffer.append(ch);
break;
}
}
return buffer.toString();
}
}