/* * StringConvertor.java * * Created on 6 Февраль 2007 г., 19:49 * * To change this template, choose Tools | Template Manager * and open the template in the editor. */ package jimm.comm; import java.io.*; import java.util.Vector; /** * * @author vladiеmir */ public final class StringUtils { private final String name; private final String[] from; private final String[] to; private static StringUtils[] converters = new StringUtils[0]; public static final String DETRANSLITERATE = "detrans" + "literate"; public static final String MRIM2JIMM = "mrim2jimm"; public static final String JIMM2MRIM = "jimm2mrim"; public static final String JABBER2JIMM = "jabber2jimm"; public static final char DELIMITER = ' '; private static boolean systemWin1251 = true; static public String bytesToSizeString(int v, boolean force) { int size = v; if (v < 1024 || force) { return size + " B"; } size = (v + 512) / 1024; v /= 1024; if (v < 1024 * 10) { return size + " KiB"; } size = (v + 512) / 1024; v /= 1024; return size + " MiB"; } // Converts a byte array to a hex string public static String byteArrayToHexString(byte[] buf) { StringBuilder hexString = new StringBuilder(buf.length * 2); for (byte b : buf) { String hex = Integer.toHexString(b & 0x00FF); if (hex.length() < 2) { hexString.append('0'); } hexString.append(hex); } return hexString.toString(); } // Check is data array ucs2 string public static boolean isDataUCS2(byte[] array, int start, int lenght) { if ((lenght & 1) != 0) { return false; } int end = start + lenght; byte b; boolean result = true; for (int i = start; i < end; i += 2) { b = array[i]; // b == 0x04 - russian if (0 < b && b < 0x09) { return true; } // b == 0x00 - latin if (0x00 == b && array[i + 1] != 0) { return true; } if (0x20 == b && array[i + 1] >= 0x20) { result = false; } if (0x20 < b || b < 0x00) { result = false; } } return result; } // Check is data array utf-8 string public static boolean isDataUTF8(byte[] array, int start, int length) { if (0 == length) { return false; } for (int i = start, len = length; len > 0;) { byte bt = array[i++]; len--; int seqLen = 0; if ((bt & 0xE0) == 0xC0) seqLen = 1; else if ((bt & 0xF0) == 0xE0) seqLen = 2; else if ((bt & 0xF8) == 0xF0) seqLen = 3; else if ((bt & 0xFC) == 0xF8) seqLen = 4; else if ((bt & 0xFE) == 0xFC) seqLen = 5; if (0 == seqLen) { if ((bt & 0x80) == 0x80) { return false; } continue; } for (int j = 0; j < seqLen; ++j) { if (len == 0) return false; bt = array[i++]; if ((bt & 0xC0) != 0x80) return false; len--; } } return true; } // Converts an Unicode string into CP1251 byte array public static byte[] stringToByteArray1251(String s) { if (null == s) { return new byte[0]; } if (systemWin1251) { try { return s.getBytes("Windows-1251"); } catch (Exception e) { systemWin1251 = false; } } byte buf[] = new byte[s.length()]; int size = s.length(); for(int i = 0; i < size; ++i) { char ch = s.charAt(i); switch (ch) { case 1025: buf[i] = -88; break; case 1105: buf[i] = -72; break; /* Ukrainian CP1251 chars section */ case 1168: buf[i] = -91; break; case 1028: buf[i] = -86; break; case 1031: buf[i] = -81; break; case 1030: buf[i] = -78; break; case 1110: buf[i] = -77; break; case 1169: buf[i] = -76; break; case 1108: buf[i] = -70; break; case 1111: buf[i] = -65; break; /* end of section */ default: if (ch >= '\u0410' && ch <= '\u044F') { buf[i] = (byte) ((ch - 1040) + 192); } else { buf[i] = (byte)((int)ch & 0xFF); } break; } } return buf; } // Converts an CP1251 byte array into an Unicode string public static String byteArray1251ToString(byte buf[], int pos, int len) { if (systemWin1251) { try { return new String(buf, pos, len, "Windows-1251"); } catch (Exception e) { systemWin1251 = false; } } int end = pos + len; StringBuilder StringBuilder = new StringBuilder(len); for(int i = pos; i < end; ++i) { int ch = buf[i] & 0xff; switch (ch) { case 168: StringBuilder.append('\u0401'); break; case 184: StringBuilder.append('\u0451'); break; /* Ukrainian CP1251 chars section */ case 165: StringBuilder.append('\u0490'); break; case 170: StringBuilder.append('\u0404'); break; case 175: StringBuilder.append('\u0407'); break; case 178: StringBuilder.append('\u0406'); break; case 179: StringBuilder.append('\u0456'); break; case 180: StringBuilder.append('\u0491'); break; case 186: StringBuilder.append('\u0454'); break; case 191: StringBuilder.append('\u0457'); break; /* end of section */ default: try { if (ch >= 192 && ch <= 255) { StringBuilder.append((char) ((1040 + ch) - 192)); } else { StringBuilder.append((char)ch); } } catch (Exception ignored) { } break; } } return removeCr(StringBuilder.toString()); } public static String utf8beByteArrayToString(byte[] buf, int off, int len) { try { // Remove \0's at the end if ((0 < len) && (0x00 == buf[off + len - 1])) { len--; } if (0 == len) { return ""; } byte[] buf2 = new byte[len + 2]; Util.putWordBE(buf2, 0, len); System.arraycopy(buf, off, buf2, 2, len); ByteArrayInputStream bais = new ByteArrayInputStream(buf2); DataInputStream dis = new DataInputStream(bais); return removeCr(dis.readUTF()); } catch (Exception e) { // do nothing } return ""; } /** * Converts the specified string to UCS-2BE */ public static byte[] stringToUcs2beByteArray(String val) { byte[] ucs2be = new byte[val.length() * 2]; int size = val.length(); for (int i = 0; i < size; ++i) { Util.putWordBE(ucs2be, i * 2, (int) val.charAt(i)); } return ucs2be; } /** * Extract a UCS-2BE string from the specified buffer (buf) * starting at position off, ending at position off+len */ public static String ucs2beByteArrayToString(byte[] buf, int off, int len) { // Length check if ((off + len > buf.length) || (len % 2 != 0)) { return ""; } // Convert StringBuilder sb = new StringBuilder(); int end = off + len; for (int i = off; i < end; i += 2) { sb.append((char)Util.getWordBE(buf, i)); } return removeCr(sb.toString()); } // Removes all CR occurences public static String removeCr(String val) { if (val.indexOf('\r') < 0) { return val; } if (-1 == val.indexOf('\n')) { return val.replace('\r', '\n'); } StringBuilder result = new StringBuilder(); int size = val.length(); for (int i = 0; i < size; ++i) { char chr = val.charAt(i); if ((chr == 0) || (chr == '\r')) continue; result.append(chr); } return result.toString(); } // Restores CRLF sequense from LF public static String restoreCrLf(String val) { StringBuilder result = new StringBuilder(); int size = val.length(); for (int i = 0; i < size; ++i) { char chr = val.charAt(i); if (chr == '\r') continue; if (chr == '\n') { result.append("\r\n"); } else { result.append(chr); } } return result.toString(); } // Converts the specified string (val) to a byte array public static byte[] stringToByteArrayUtf8(String val) { // Write string in UTF-8 format try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); char ch; for (int i = 0; i < val.length(); ++i) { ch = val.charAt(i); if ((ch & 0x7F) == ch) { if ((0x20 <= ch) || ('\r' == ch) || ('\n' == ch) || ('\t' == ch)) { baos.write(ch); } } else if ((ch & 0x7FF) == ch) { baos.write(0xC0 | ((ch >>> 6) & 0x1F)); baos.write(0x80 | ((ch) & 0x3F)); } else if ((ch & 0xFFFF) == ch) { baos.write(0xE0 | ((ch >>> 12) & 0x0F)); baos.write(0x80 | ((ch >>> 6) & 0x3F)); baos.write(0x80 | ((ch) & 0x3F)); } } return baos.toByteArray(); } catch (Exception e) { // Do nothing } return null; } // Converts the specified string (val) to a byte array public static byte[] stringToByteArray(String val) { return isEmpty(val) ? new byte[0] : val.getBytes(); } /** * Extracts a string from the buffer (buf) starting at position off, * ending at position off+len */ public static String byteArrayToString(byte[] buf, int off, int len) { // Length check if (buf.length < off + len) { return ""; } // Remove \0's at the end while ((0 < len) && (buf[off + len - 1] == 0x00)) { len--; } if (0 == len) { return ""; } // Scaning chars for detecting encoding. if (isDataUCS2(buf, off, len)) { return ucs2beByteArrayToString(buf, off, len); } // Read string in UTF-8 format if (isDataUTF8(buf, off, len)) { return utf8beByteArrayToString(buf, off, len); } return byteArrayToWinString(buf, off, len); } public static String byteArrayToWinString(byte[] buf, int off, int len) { // Length check if (buf.length < off + len) { return ""; } // Remove \0's at the end if ((0 < len) && (0x00 == buf[off + len - 1])) { len--; } if (0 == len) { return ""; } return byteArray1251ToString(buf, off, len); } public static String byteArrayToAsciiString(byte[] buf) { return new String(buf, 0, buf.length); } public static String byteArrayToAsciiString(byte[] buf, int offset, int length) { return new String(buf, offset, length); } public static boolean stringEquals(String s1, String s2) { if (s1.length() != s2.length()) { return false; } int size = s1.length(); for (int i = 0; i < size; ++i) { if (toLowerCase(s1.charAt(i)) != toLowerCase(s2.charAt(i))) { return false; } } return true; } public static int stringCompare(String s1, String s2) { int size = Math.min(s1.length(), s2.length()); int result; for (int i = 0; i < size; ++i) { result = toLowerCase(s1.charAt(i)) - toLowerCase(s2.charAt(i)); if (result != 0) { return result; } } return s1.length() - s2.length(); } public static String toLowerCase(String s) { char[] chars = s.toCharArray(); for(int i = s.length() - 1; i >= 0; i--) { chars[i] = toLowerCase(chars[i]); } String res = new String(chars); return res.equals(s) ? s : res; } public static String toUpperCase(String s) { char[] chars = s.toCharArray(); for(int i = s.length() - 1; i >= 0; i--) { chars[i] = toUpperCase(chars[i]); } String res = new String(chars); return res.equals(s) ? s : res; } public static char toLowerCase(char c) { if (c >= 'A' && c <= 'Z' || c >= '\300' && c <= '\326' || c >= '\330' && c <= '\336' || c >= '\u0400' && c <= '\u042F') { if (c <= 'Z' || c >= '\u0410' && c <= '\u042F') { return (char)(c + 32); } if(c < '\u0410') { return (char)(c + 80); } return (char)(c + 32); } return Character.toLowerCase(c); } public static char toUpperCase(char c) { if (c >= 'a' && c <= 'z' || c >= '\337' && c <= '\366' || c >= '\370' && c <= '\377' || c >= '\u0430' && c <= '\u045F') { if (c <= 'z' || c >= '\u0430' && c <= '\u044F') { return (char)(c - 32); } if (c > '\u042F') { return (char)(c - 80); } return (char)(c - 32); } return Character.toUpperCase(c); } private boolean equalsSubstring(String s1, int pos, String s2) { if (s1.length() - pos < s2.length()) { return false; } int length = s2.length(); for (int i = 0; i < length; ++i) { if (toLowerCase(s1.charAt(i + pos)) != toLowerCase(s2.charAt(i))) { return false; } } return true; } private int convertCharIndex(String str, int pos) { for (int i = 0; i < from.length; ++i) { if (equalsSubstring(str, pos, from[i])) { return i; } } return -1; } private String convertChar(String str, int pos, int wordIndex) { char ch = str.charAt(pos); if (toLowerCase(ch) == ch) { return to[wordIndex]; } if ((1 != from[wordIndex].length()) && (1 != to[wordIndex].length())) { ch = str.charAt(pos + 1); if (toLowerCase(ch) == ch) { return toUpperCase(to[wordIndex].substring(0, 1)) + to[wordIndex].substring(1); } } return toUpperCase(to[wordIndex]); } private String convertTextCaseInsensitive(String str) { StringBuilder buf = new StringBuilder(); int pos = 0; int skipLength = -1; if (str.startsWith("/")) { skipLength = str.indexOf(' '); if (-1 == skipLength) { return str; } } if (-1 == skipLength) { for (int i = 0; i < Math.min(str.length(), 32); ++i) { char ch = str.charAt(i); if (',' == ch) { skipLength = i; break; } if (' ' == ch) { break; } } } if (-1 < skipLength) { while (pos <= skipLength) { buf.append(str.charAt(pos)); pos++; } } boolean convert = true; while (pos < str.length()) { if (convert) { int wordIndex = convertCharIndex(str, pos); if (-1 != wordIndex) { buf.append(convertChar(str, pos, wordIndex)); pos += from[wordIndex].length(); continue; } } if (str.startsWith(" ", pos)) { convert = !convert; buf.append(' '); pos += 2; continue; } buf.append(str.charAt(pos)); pos++; } return buf.toString(); } private String convertText(String text) { String result = text; for (int i = 0; i < from.length; ++i) { result = Util.replace(result, from[i], to[i]); } return result; } private StringUtils(String name, String[] from, String[] to) { this.name = name; this.from = from; this.to = to; for (int i = 0; i < from.length; ++i) { if (from[i].equals(to[i])) { from[i] = to[i]; } } } public static void load() { Vector<Config> configs = new Vector<Config>(); Config.parseIniConfig("/replaces.txt", configs); // #sijapp cond.if protocols_MRIM is "true" or protocols_JABBER is "true" # Config.parseIniConfig("/mrim-replaces.txt", configs); // #sijapp cond.end # // #sijapp cond.if protocols_JABBER is "true" # Config.parseIniConfig("/jabber-replaces.txt", configs); // #sijapp cond.end # StringUtils.converters = new StringUtils[configs.size()]; for (int i = 0; i < configs.size(); ++i) { Config config = (Config) configs.elementAt(i); StringUtils.converters[i] = new StringUtils(config.getName(), config.getKeys(), config.getValues()); } } private static StringUtils getConverter(String scheme) { for (StringUtils converter : converters) { if (scheme.equals(converter.name)) { return converter; } } return null; } public static String convert(String scheme, String str) { StringUtils convertor = getConverter(scheme); return (null == convertor) ? str : convertor.convertText(str); } public static String detransliterate(String str) { StringUtils convertor = getConverter(DETRANSLITERATE); return (null == convertor) ? str : convertor.convertTextCaseInsensitive(str); } public static boolean isEmpty(String value) { return (null == value) || (0 == value.length()); } public static String notNull(String value) { return (null == value) ? "" : value; } public static String trim(String msg) { if (StringUtils.isEmpty(msg)) { return ""; } if (-1 == "\n ".indexOf(msg.charAt(msg.length() - 1))) { return msg; } for (int i = msg.length() - 1; 0 <= i; --i) { char ch = msg.charAt(i); if (('\n' != ch) && (' ' != ch)) { return msg.substring(0, i + 1); } } return ""; } public static boolean contains(String[] base, String value) { for (String baseValue : base) { if (baseValue.equals(value)) return true; } return false; } private static int cutIndex(String str, char ch, int cutIndex, int length) { int chIndex = str.lastIndexOf(ch, length); if (-1 != chIndex) { return Math.max(cutIndex, chIndex); } return cutIndex; } public static String cut(String str, int length) { if (str.length() < length) { return str; } int cutIndex = 0; final char[] cutChars = {' ', '\n'}; for (char cutChar : cutChars) { cutIndex = cutIndex(str, cutChar, cutIndex, length); } if (0 == cutIndex) { cutIndex = length; } return str.substring(0, cutIndex) + "..."; } }