--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007- VTT Technical Research Centre of Finland.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+/*\r
+ * Created on Jan 21, 2005\r
+ * \r
+ * Copyright Toni Kalajainen\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.simantics.utils.strings;\r
+\r
+import java.io.IOException;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.List;\r
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
+import java.util.regex.PatternSyntaxException;\r
+\r
+import org.simantics.databoard.parser.StringEscapeUtils;\r
+import org.simantics.utils.bytes.ByteArrays;\r
+\r
+\r
+/**\r
+ * Extended string functions\r
+ * Byte array <-> string conversions\r
+ *\r
+ * Length is not included\r
+ *\r
+ *\r
+ * See also {@link StringEscapeUtils}\r
+ * @author Toni Kalajainen\r
+ */\r
+public class EString {\r
+\r
+ public static final char[] HEX_VALUES =\r
+ {'0', '1', '2', '3' ,'4' ,'5', '6', '7', '8', '9' ,'A', 'B', 'C',\r
+ 'D', 'E', 'F'};\r
+\r
+\r
+ /**\r
+ * convert string to byte array\r
+ * @param s\r
+ * @return\r
+ */\r
+ public static byte[] toBytes(String s) {\r
+ int size = s.length();\r
+ byte array[] = new byte[size];\r
+ // write chars\r
+ for (int i=0; i<size; i++)\r
+ array[i] = (byte) (s.charAt(i) );\r
+ return array;\r
+ }\r
+\r
+ /**\r
+ * convert bytearray to string\r
+ * @param array\r
+ * @return\r
+ */\r
+ public static String toString(byte array[]) {\r
+ if (array==null) return null;\r
+ int size = array.length;\r
+ if (size==0) return null;\r
+ // read chars\r
+ //return new String(array, 4, size);\r
+ char chars[] = new char[size];\r
+ for (int i=0; i<size; i++)\r
+ chars[i] = (char) (array[i] & 0xff);\r
+ return new String(chars);\r
+ }\r
+\r
+ /**\r
+ * read null terminated string\r
+ * @param array\r
+ * @param offset start offset\r
+ * @return\r
+ */\r
+ public static String PChar(byte array[], int offset) {\r
+ if (array==null) return null;\r
+ int size = array.length;\r
+ int zero = offset;\r
+ while (zero<size && array[zero]!=0) zero++;\r
+ if (zero>=size) throw new IndexOutOfBoundsException();\r
+ char chars[] = new char[zero-offset];\r
+ for (int i=0; i<chars.length; i++)\r
+ chars[i] = (char) (array[i+offset] & 0xff);\r
+ return new String(chars);\r
+ }\r
+\r
+ /**\r
+ * read null terminated string\r
+ * @param array\r
+ * @param offset start offset\r
+ * @param maxLen maximum bytes to read\r
+ * @return\r
+ */\r
+ public static String PChar(byte array[], int offset, int maxLen) {\r
+ if (array==null) return null;\r
+ int size = array.length;\r
+ if (offset+maxLen<size) size = offset+maxLen;\r
+ int zero = offset;\r
+ while (zero<size && array[zero]!=0) zero++;\r
+ if (zero>=size) throw new IndexOutOfBoundsException();\r
+ char chars[] = new char[zero-offset];\r
+ for (int i=0; i<chars.length; i++)\r
+ chars[i] = (char) (array[i+offset] & 0xff);\r
+ return new String(chars);\r
+ }\r
+\r
+ /**\r
+ * Explode words into array\r
+ * @param str\r
+ * @param breaker\r
+ * @return\r
+ */\r
+ public static String[] explode(String str, String breaker) {\r
+ return str.split(breaker);\r
+ }\r
+ /**\r
+ * Explode string into lines\r
+ * @param str\r
+ * @return\r
+ */\r
+ public static String[] explode(String str) {\r
+ return str.split("\n");\r
+ }\r
+ /**\r
+ * implode array into string\r
+ * @param strings\r
+ * @param glue\r
+ * @return\r
+ */\r
+ public static String implode(Object strings[], String glue) {\r
+ if (strings.length==0) return null;\r
+ if (strings.length == 1)\r
+ return strings[0].toString();\r
+ StringBuilder sb = new StringBuilder();\r
+ sb.append(strings[0].toString());\r
+ for (int i=1; i<strings.length; i++) {\r
+ sb.append(glue);\r
+ sb.append(strings[i]);\r
+ }\r
+ return sb.toString();\r
+ }\r
+ public static String implode(Collection<?> strings) {\r
+ return implode(strings.toArray(new Object[strings.size()]));\r
+ }\r
+ public static String implode(Collection<?> strings, String glue) {\r
+ return implode(strings.toArray(new Object[strings.size()]), glue);\r
+ }\r
+ /**\r
+ * implode lines into array\r
+ * @param strings\r
+ * @return\r
+ */\r
+ public static String implode(Object strings[]) {\r
+ if (strings.length==0) return "";\r
+\r
+ String s0 = strings[0].toString();\r
+ int s0len = s0.length();\r
+ int len = s0len;\r
+ for (int i=1; i<strings.length; i++)\r
+ len += 1+strings[i].toString().length();\r
+\r
+ char data[] = new char[len];\r
+ s0.getChars(0, s0.length(), data, 0);\r
+ int pos = s0len;\r
+\r
+ for (int i=1; i<strings.length; i++) {\r
+ data[pos] = '\n';\r
+ String si = strings[i].toString();\r
+ int silen = si.length();\r
+ si.getChars(0, silen, data, pos+1);\r
+ pos += 1+silen;\r
+ }\r
+\r
+ return new String(data);\r
+ }\r
+\r
+ /**\r
+ * Add prefix to stings in array\r
+ * @param strings\r
+ * @param prefix\r
+ * @return\r
+ */\r
+ public static String[] addPrefix(String strings[], String prefix) {\r
+ String result[] = new String[strings.length];\r
+ for (int i=0; i<result.length; i++)\r
+ result[i] = prefix + strings[i];\r
+ return result;\r
+ }\r
+\r
+ /**\r
+ * add prefix to lines\r
+ * @param strings\r
+ * @param prefix\r
+ * @return\r
+ */\r
+ public static String addPrefix(String strings, String prefix) {\r
+ String result[] = explode(strings);\r
+ for (int i=0; i<result.length; i++)\r
+ result[i] = prefix + result[i];\r
+ return implode(result);\r
+ }\r
+\r
+ /**\r
+ * add prefix and suffix to lines\r
+ * @param strings\r
+ * @param prefix\r
+ * @param suffixfix\r
+ * @return\r
+ */\r
+ public static String addFix(String strings, String prefix, String suffix) {\r
+ String result[] = explode(strings);\r
+ for (int i=0; i<result.length; i++)\r
+ result[i] = prefix + result[i] + suffix;\r
+ return implode(result);\r
+ }\r
+\r
+ /**\r
+ * Big Endian hex\r
+ * @param value\r
+ * @param decimals\r
+ * @return\r
+ */\r
+ public static String intToBEHex(int value, int decimals) {\r
+ // TODO Replace with String.format("%0"+decimals+"X", value)\r
+ String result="";\r
+ for (int i=0; i<decimals; i++) {\r
+ result += EString.HEX_VALUES[(value>>4) & 0xF];\r
+ result += EString.HEX_VALUES[value & 0xF];\r
+ value = value >> 8;\r
+ }\r
+ return result;\r
+ }\r
+\r
+ /**\r
+ * splits line in a manner that is done to word wrap\r
+ * Lines are broken between spaces if possible\r
+ */\r
+ public static String wordWrap(String text, int minWidth, int maxWidth)\r
+ {\r
+ // init values\r
+ char cr = 0x0D;\r
+ String lines[] = text.replaceAll(""+cr, "").split("\n");\r
+ List<String> result = new ArrayList<String>();\r
+\r
+ // iterate lines\r
+ for (int i=0; i<lines.length; i++) {\r
+ String line = lines[i];\r
+\r
+ if (line.length() < maxWidth) {\r
+ result.add(line);\r
+ continue;\r
+ }\r
+\r
+ // Line is longer than maxwidth, split it\r
+ String words[] = lines[i].split(" ");\r
+ line = "";\r
+ for (int j=0; j<words.length; j++) {\r
+ // Nothing on the buffer\r
+ if (line.equals("")) {\r
+ line = words[j];\r
+ while (line.length() > maxWidth) {\r
+ result.add(line.substring(0, maxWidth));\r
+ line = line.substring(maxWidth);\r
+ }\r
+ continue;\r
+ }\r
+\r
+ // Add to previous line buffer\r
+ String word = words[j];\r
+\r
+ // Check if adding this word fits maxwidth\r
+ if (line.length()+1+word.length()<maxWidth) {\r
+ line = line + " " + word;\r
+ continue;\r
+ }\r
+ // Adding this word would make the line too long\r
+\r
+ // Check if this line is long enough\r
+ if (line.length()>=minWidth) {\r
+ result.add(line);\r
+ line = word;\r
+ continue;\r
+ }\r
+ // Line is not long enough with out AWord and with it\r
+ // the line is too long.\r
+\r
+ // So we need to split the line\r
+ line = line + " " + word;\r
+ while (line.length()>maxWidth) {\r
+ result.add(line.substring(0, maxWidth));\r
+ line = line.substring(maxWidth);\r
+ }\r
+ }\r
+ if (!line.equals(""))\r
+ result.add(line);\r
+ }\r
+\r
+ // Change string lines into single string\r
+ StringBuilder sb = new StringBuilder();\r
+ int rs = result.size();\r
+ if (rs > 0) {\r
+ sb.append(result.get(0));\r
+ for (int i=1; i<rs; i++)\r
+ sb.append("\n").append(result.get(i));\r
+ }\r
+ return sb.length() == 0 ? "" : sb.toString();\r
+ }\r
+\r
+\r
+ public static void printByteArray(byte array[]) {\r
+ for (int i=0; i<array.length; i++) {\r
+ System.out.print(array[i] & 0xff);\r
+ if (i<array.length-1)\r
+ System.out.print(",");\r
+ }\r
+ }\r
+\r
+ public static void saveToFile(String text, String filename)\r
+ throws IOException\r
+ {\r
+ ByteArrays.saveToFile(toBytes(text), filename);\r
+ }\r
+\r
+ /**\r
+ * Escape characters in a string.\r
+ * <p>\r
+ * eg. value=5,5 will be escaped to value\=5\,5\r
+ * with escape set =, and escape char \\r
+ * \r
+ * @param str string to escape\r
+ * @param escapeSet set of chars\r
+ * @param escapeChar escape character\r
+ * @return escaped string\r
+ */\r
+ public static String escapeString(String str, String escapeSet, char escapeChar)\r
+ {\r
+ escapeSet += escapeChar;\r
+ StringBuilder sb = new StringBuilder(str.length()*2);\r
+ for (int i=0; i<str.length(); i++)\r
+ {\r
+ char c = str.charAt(i);\r
+\r
+ for (int j=0; j<escapeSet.length(); j++)\r
+ {\r
+ char ec = escapeSet.charAt(j);\r
+ if (ec==c) {\r
+ sb.append(escapeChar);\r
+ break;\r
+ }\r
+ }\r
+\r
+ sb.append(c);\r
+ }\r
+\r
+ return sb.toString();\r
+ }\r
+\r
+ /**\r
+ * Unescape charaters in a string\r
+ * <p>\r
+ * eg. value\=5\,5 will be unescaped to value=5,5 with\r
+ * escape set =, and escape char \\r
+ * \r
+ * @param str string to unescape\r
+ * @param escapeChar\r
+ * @return unescaped string\r
+ */\r
+ public static String unescapeString(String str, char escapeChar)\r
+ {\r
+ StringBuilder sb = new StringBuilder(str.length());\r
+ boolean prevWasEscapeChar = false;\r
+ for (int i=0; i<str.length(); i++)\r
+ {\r
+ char c = str.charAt(i);\r
+\r
+ // Atmost escape every second character\r
+ if (prevWasEscapeChar || (c != escapeChar)) {\r
+ prevWasEscapeChar = false;\r
+ sb.append(c);\r
+ } else {\r
+ prevWasEscapeChar = true;\r
+ }\r
+ }\r
+\r
+ return sb.toString();\r
+ }\r
+\r
+ /**\r
+ * Scans escaped string\r
+ * e.g. key=val\,ue,key2=xx returns key=val\,ue with endMark ,\r
+ * \r
+ * @param str string to scan\r
+ * @param escapeChar escape character\r
+ * @param endMark end mark\r
+ * @return everything before endMark\r
+ */\r
+ public static String scanEscapedString(String str, char escapeChar, char endMark)\r
+ {\r
+ StringBuilder sb = new StringBuilder(str.length());\r
+ boolean prevWasEscapeChar = false;\r
+ for (int i=0; i<str.length(); i++)\r
+ {\r
+ char c = str.charAt(i);\r
+\r
+ // Atmost escape every second character\r
+ if (prevWasEscapeChar || (c != escapeChar)) {\r
+ if (!prevWasEscapeChar && c==endMark)\r
+ return sb.toString();\r
+ // the next char won't be escape char\r
+ prevWasEscapeChar = false;\r
+ } else {\r
+ // This is escape char\r
+ prevWasEscapeChar = true;\r
+ }\r
+ sb.append(c);\r
+ }\r
+\r
+ return sb.toString();\r
+ }\r
+\r
+ /**\r
+ * Compiles pattern from simple pattern. Simple pattern is normal\r
+ * wild card compare that supports * and ? wild cards.\r
+ * \r
+ * @param patternStr simple pattern\r
+ * @return Regexp pattern\r
+ */\r
+ public static Pattern compileSimplePattern(String patternStr)\r
+ throws PatternSyntaxException\r
+ {\r
+ String str ="";\r
+ for (int i=0; i<patternStr.length(); i++)\r
+ {\r
+ char c = patternStr.charAt(i);\r
+ if ( (c>='a'&&c<='z') || (c>='A'&&c<='Z') || (c>='0'&&c<='9'))\r
+ str += c;\r
+ else if ( c=='?' )\r
+ str += ".?";\r
+ else if ( c=='*' )\r
+ str += ".*";\r
+ else str += "\\"+c;\r
+ }\r
+ return Pattern.compile(str);\r
+ }\r
+\r
+ public static boolean simplePatternMatch(String str, String simplePattern)\r
+ {\r
+ try {\r
+ Pattern ptr = compileSimplePattern(simplePattern);\r
+ Matcher m = ptr.matcher(str);\r
+ return m.matches();\r
+ } catch (PatternSyntaxException pse) {\r
+ return false;\r
+ }\r
+ }\r
+\r
+ public static void main(String[] args) {\r
+ System.out.println(escapeString("value=5,\\5", ",=", '\\'));\r
+ System.out.println(unescapeString("value\\=5\\,\\\\5", '\\'));\r
+ System.out.println(scanEscapedString("val\\,ue\\=5\\,\\\\5,value2=xxx", '\\', ','));\r
+ System.out.println(scanEscapedString("\\,\\,,\\,\\,", '\\', ','));\r
+\r
+ String value = "STRING 01234"+(char)(128)+(char)(129)+(char)(255);\r
+\r
+ int X = 500;\r
+ System.out.println(X+" = "+intToBEHex(X, 4));\r
+\r
+ byte array[] = toBytes(value);\r
+ System.out.print(value);\r
+ System.out.print(" = ");\r
+ printByteArray(array);\r
+ System.out.println();\r
+\r
+ @SuppressWarnings("unused")\r
+ String str = toString(array);\r
+ System.out.print(value);\r
+ System.out.print(" = ");\r
+ printByteArray(array);\r
+ System.out.println();\r
+\r
+ String text = "Reads b.length bytes from this file into the "+\r
+ "byte array, starting at the current file pointer. This method"+\r
+ " reads repeatedly from the file until the requested number of "+\r
+ "bytes are read. This method blocks until the requested number of "+\r
+ "bytes are read, the end of the stream is detected, or an exception "+\r
+ "is thrown";\r
+ text = wordWrap(text, 20, 30);\r
+ System.out.println(text);\r
+\r
+\r
+ List<String> v = new ArrayList<String>();\r
+ v.add("jeps");\r
+ v.add("jops");\r
+ v.add("kops");\r
+ v.add("hops");\r
+ System.out.println(implode(v));\r
+ }\r
+\r
+\r
+}\r