]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.utils/src/org/simantics/utils/strings/EString.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.utils / src / org / simantics / utils / strings / EString.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007- VTT Technical Research Centre of Finland.\r
3  * All rights reserved. This program and the accompanying materials\r
4  * are made available under the terms of the Eclipse Public License v1.0\r
5  * which accompanies this distribution, and is available at\r
6  * http://www.eclipse.org/legal/epl-v10.html\r
7  *\r
8  * Contributors:\r
9  *     VTT Technical Research Centre of Finland - initial API and implementation\r
10  *******************************************************************************/\r
11 /*\r
12  * Created on Jan 21, 2005\r
13  * \r
14  * Copyright Toni Kalajainen\r
15  * \r
16  * Licensed under the Apache License, Version 2.0 (the "License");\r
17  * you may not use this file except in compliance with the License.\r
18  * You may obtain a copy of the License at\r
19  *\r
20  *     http://www.apache.org/licenses/LICENSE-2.0\r
21  *\r
22  * Unless required by applicable law or agreed to in writing, software\r
23  * distributed under the License is distributed on an "AS IS" BASIS,\r
24  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
25  * See the License for the specific language governing permissions and\r
26  * limitations under the License.\r
27  */\r
28 package org.simantics.utils.strings;\r
29 \r
30 import java.io.IOException;\r
31 import java.util.ArrayList;\r
32 import java.util.Collection;\r
33 import java.util.List;\r
34 import java.util.regex.Matcher;\r
35 import java.util.regex.Pattern;\r
36 import java.util.regex.PatternSyntaxException;\r
37 \r
38 import org.simantics.databoard.parser.StringEscapeUtils;\r
39 import org.simantics.utils.bytes.ByteArrays;\r
40 \r
41 \r
42 /**\r
43  * Extended string functions\r
44  * Byte array <-> string conversions\r
45  *\r
46  *  Length is not included\r
47  *\r
48  *\r
49  * See also {@link StringEscapeUtils}\r
50  * @author Toni Kalajainen\r
51  */\r
52 public class EString {\r
53 \r
54     public static final char[] HEX_VALUES =\r
55     {'0', '1', '2', '3' ,'4' ,'5', '6', '7', '8', '9' ,'A', 'B', 'C',\r
56         'D', 'E', 'F'};\r
57 \r
58 \r
59     /**\r
60      * convert string to byte array\r
61      * @param s\r
62      * @return\r
63      */\r
64     public static byte[] toBytes(String s) {\r
65         int size = s.length();\r
66         byte array[] = new byte[size];\r
67         // write chars\r
68         for (int i=0; i<size; i++)\r
69             array[i] = (byte) (s.charAt(i) );\r
70         return array;\r
71     }\r
72 \r
73     /**\r
74      * convert bytearray to string\r
75      * @param array\r
76      * @return\r
77      */\r
78     public static String toString(byte array[]) {\r
79         if (array==null) return null;\r
80         int size = array.length;\r
81         if (size==0) return null;\r
82         // read chars\r
83         //return new String(array, 4, size);\r
84         char chars[] = new char[size];\r
85         for (int i=0; i<size; i++)\r
86             chars[i] = (char) (array[i] & 0xff);\r
87         return new String(chars);\r
88     }\r
89 \r
90     /**\r
91      * read null terminated string\r
92      * @param array\r
93      * @param offset start offset\r
94      * @return\r
95      */\r
96     public static String PChar(byte array[], int offset) {\r
97         if (array==null) return null;\r
98         int size = array.length;\r
99         int zero = offset;\r
100         while (zero<size && array[zero]!=0) zero++;\r
101         if (zero>=size) throw new IndexOutOfBoundsException();\r
102         char chars[] = new char[zero-offset];\r
103         for (int i=0; i<chars.length; i++)\r
104             chars[i] = (char) (array[i+offset] & 0xff);\r
105         return new String(chars);\r
106     }\r
107 \r
108     /**\r
109      * read null terminated string\r
110      * @param array\r
111      * @param offset start offset\r
112      * @param maxLen maximum bytes to read\r
113      * @return\r
114      */\r
115     public static String PChar(byte array[], int offset, int maxLen) {\r
116         if (array==null) return null;\r
117         int size = array.length;\r
118         if (offset+maxLen<size) size = offset+maxLen;\r
119         int zero = offset;\r
120         while (zero<size && array[zero]!=0) zero++;\r
121         if (zero>=size) throw new IndexOutOfBoundsException();\r
122         char chars[] = new char[zero-offset];\r
123         for (int i=0; i<chars.length; i++)\r
124             chars[i] = (char) (array[i+offset] & 0xff);\r
125         return new String(chars);\r
126     }\r
127 \r
128     /**\r
129      * Explode words into array\r
130      * @param str\r
131      * @param breaker\r
132      * @return\r
133      */\r
134     public static String[] explode(String str, String breaker) {\r
135         return str.split(breaker);\r
136     }\r
137     /**\r
138      * Explode string into lines\r
139      * @param str\r
140      * @return\r
141      */\r
142     public static String[] explode(String str) {\r
143         return str.split("\n");\r
144     }\r
145     /**\r
146      * implode array into string\r
147      * @param strings\r
148      * @param glue\r
149      * @return\r
150      */\r
151     public static String implode(Object strings[], String glue) {\r
152         if (strings.length==0) return null;\r
153         if (strings.length == 1)\r
154             return strings[0].toString();\r
155         StringBuilder sb = new StringBuilder();\r
156         sb.append(strings[0].toString());\r
157         for (int i=1; i<strings.length; i++) {\r
158             sb.append(glue);\r
159             sb.append(strings[i]);\r
160         }\r
161         return sb.toString();\r
162     }\r
163     public static String implode(Collection<?> strings) {\r
164         return implode(strings.toArray(new Object[strings.size()]));\r
165     }\r
166     public static String implode(Collection<?> strings, String glue) {\r
167         return implode(strings.toArray(new Object[strings.size()]), glue);\r
168     }\r
169     /**\r
170      * implode lines into array\r
171      * @param strings\r
172      * @return\r
173      */\r
174     public static String implode(Object strings[]) {\r
175         if (strings.length==0) return "";\r
176 \r
177         String s0 = strings[0].toString();\r
178         int s0len = s0.length();\r
179         int len = s0len;\r
180         for (int i=1; i<strings.length; i++)\r
181             len += 1+strings[i].toString().length();\r
182 \r
183         char data[] = new char[len];\r
184         s0.getChars(0, s0.length(), data, 0);\r
185         int pos = s0len;\r
186 \r
187         for (int i=1; i<strings.length; i++) {\r
188             data[pos] = '\n';\r
189             String si = strings[i].toString();\r
190             int silen = si.length();\r
191             si.getChars(0, silen, data, pos+1);\r
192             pos += 1+silen;\r
193         }\r
194 \r
195         return new String(data);\r
196     }\r
197 \r
198     /**\r
199      * Add prefix to stings in array\r
200      * @param strings\r
201      * @param prefix\r
202      * @return\r
203      */\r
204     public static String[] addPrefix(String strings[], String prefix) {\r
205         String result[] = new String[strings.length];\r
206         for (int i=0; i<result.length; i++)\r
207             result[i] = prefix + strings[i];\r
208         return result;\r
209     }\r
210 \r
211     /**\r
212      * add prefix to lines\r
213      * @param strings\r
214      * @param prefix\r
215      * @return\r
216      */\r
217     public static String addPrefix(String strings, String prefix) {\r
218         String result[] = explode(strings);\r
219         for (int i=0; i<result.length; i++)\r
220             result[i] = prefix + result[i];\r
221         return implode(result);\r
222     }\r
223 \r
224     /**\r
225      * add prefix and suffix to lines\r
226      * @param strings\r
227      * @param prefix\r
228      * @param suffixfix\r
229      * @return\r
230      */\r
231     public static String addFix(String strings, String prefix, String suffix) {\r
232         String result[] = explode(strings);\r
233         for (int i=0; i<result.length; i++)\r
234             result[i] = prefix + result[i] + suffix;\r
235         return implode(result);\r
236     }\r
237 \r
238     /**\r
239      * Big Endian hex\r
240      * @param value\r
241      * @param decimals\r
242      * @return\r
243      */\r
244     public static String intToBEHex(int value, int decimals) {\r
245         // TODO Replace with String.format("%0"+decimals+"X", value)\r
246         String result="";\r
247         for (int i=0; i<decimals; i++) {\r
248             result += EString.HEX_VALUES[(value>>4) & 0xF];\r
249             result += EString.HEX_VALUES[value & 0xF];\r
250             value = value >> 8;\r
251         }\r
252         return result;\r
253     }\r
254 \r
255     /**\r
256      * splits line in a manner that is done to word wrap\r
257      * Lines are broken between spaces if possible\r
258      */\r
259     public static String wordWrap(String text, int minWidth, int maxWidth)\r
260     {\r
261         // init values\r
262         char cr = 0x0D;\r
263         String lines[] = text.replaceAll(""+cr, "").split("\n");\r
264         List<String> result = new ArrayList<String>();\r
265 \r
266         // iterate lines\r
267         for (int i=0; i<lines.length; i++) {\r
268             String line = lines[i];\r
269 \r
270             if (line.length() < maxWidth) {\r
271                 result.add(line);\r
272                 continue;\r
273             }\r
274 \r
275             // Line is longer than maxwidth, split it\r
276             String words[] = lines[i].split(" ");\r
277             line = "";\r
278             for (int j=0; j<words.length; j++) {\r
279                 // Nothing on the buffer\r
280                 if (line.equals("")) {\r
281                     line = words[j];\r
282                     while (line.length() > maxWidth) {\r
283                         result.add(line.substring(0, maxWidth));\r
284                         line = line.substring(maxWidth);\r
285                     }\r
286                     continue;\r
287                 }\r
288 \r
289                 // Add to previous line buffer\r
290                 String word = words[j];\r
291 \r
292                 // Check if adding this word fits maxwidth\r
293                 if (line.length()+1+word.length()<maxWidth) {\r
294                     line = line + " " + word;\r
295                     continue;\r
296                 }\r
297                 // Adding this word would make the line too long\r
298 \r
299                 // Check if this line is long enough\r
300                 if (line.length()>=minWidth) {\r
301                     result.add(line);\r
302                     line = word;\r
303                     continue;\r
304                 }\r
305                 // Line is not long enough with out AWord and with it\r
306                 // the line is too long.\r
307 \r
308                 // So we need to split the line\r
309                 line = line + " " + word;\r
310                 while (line.length()>maxWidth) {\r
311                     result.add(line.substring(0, maxWidth));\r
312                     line = line.substring(maxWidth);\r
313                 }\r
314             }\r
315             if (!line.equals(""))\r
316                 result.add(line);\r
317         }\r
318 \r
319         // Change string lines into single string\r
320         StringBuilder sb = new StringBuilder();\r
321         int rs = result.size();\r
322         if (rs > 0) {\r
323             sb.append(result.get(0));\r
324             for (int i=1; i<rs; i++)\r
325                 sb.append("\n").append(result.get(i));\r
326         }\r
327         return sb.length() == 0 ? "" : sb.toString();\r
328     }\r
329 \r
330 \r
331     public static void printByteArray(byte array[]) {\r
332         for (int i=0; i<array.length; i++) {\r
333             System.out.print(array[i] & 0xff);\r
334             if (i<array.length-1)\r
335                 System.out.print(",");\r
336         }\r
337     }\r
338 \r
339     public static void saveToFile(String text, String filename)\r
340     throws IOException\r
341     {\r
342         ByteArrays.saveToFile(toBytes(text), filename);\r
343     }\r
344 \r
345     /**\r
346      * Escape characters in a string.\r
347      * <p>\r
348      * eg. value=5,5 will be escaped to value\=5\,5\r
349      * with escape set =, and escape char \\r
350      * \r
351      * @param str string to escape\r
352      * @param escapeSet set of chars\r
353      * @param escapeChar escape character\r
354      * @return escaped string\r
355      */\r
356     public static String escapeString(String str, String escapeSet, char escapeChar)\r
357     {\r
358         escapeSet += escapeChar;\r
359         StringBuilder sb = new StringBuilder(str.length()*2);\r
360         for (int i=0; i<str.length(); i++)\r
361         {\r
362             char c = str.charAt(i);\r
363 \r
364             for (int j=0; j<escapeSet.length(); j++)\r
365             {\r
366                 char ec = escapeSet.charAt(j);\r
367                 if (ec==c) {\r
368                     sb.append(escapeChar);\r
369                     break;\r
370                 }\r
371             }\r
372 \r
373             sb.append(c);\r
374         }\r
375 \r
376         return sb.toString();\r
377     }\r
378 \r
379     /**\r
380      * Unescape charaters in a string\r
381      * <p>\r
382      * eg. value\=5\,5 will be unescaped to value=5,5 with\r
383      * escape set =, and escape char \\r
384      * \r
385      * @param str string to unescape\r
386      * @param escapeChar\r
387      * @return unescaped string\r
388      */\r
389     public static String unescapeString(String str, char escapeChar)\r
390     {\r
391         StringBuilder sb = new StringBuilder(str.length());\r
392         boolean prevWasEscapeChar = false;\r
393         for (int i=0; i<str.length(); i++)\r
394         {\r
395             char c = str.charAt(i);\r
396 \r
397             // Atmost escape every second character\r
398             if (prevWasEscapeChar || (c != escapeChar)) {\r
399                 prevWasEscapeChar = false;\r
400                 sb.append(c);\r
401             } else {\r
402                 prevWasEscapeChar = true;\r
403             }\r
404         }\r
405 \r
406         return sb.toString();\r
407     }\r
408 \r
409     /**\r
410      * Scans escaped string\r
411      * e.g. key=val\,ue,key2=xx returns key=val\,ue with endMark ,\r
412      * \r
413      * @param str string to scan\r
414      * @param escapeChar escape character\r
415      * @param endMark end mark\r
416      * @return everything before endMark\r
417      */\r
418     public static String scanEscapedString(String str, char escapeChar, char endMark)\r
419     {\r
420         StringBuilder sb = new StringBuilder(str.length());\r
421         boolean prevWasEscapeChar = false;\r
422         for (int i=0; i<str.length(); i++)\r
423         {\r
424             char c = str.charAt(i);\r
425 \r
426             // Atmost escape every second character\r
427             if (prevWasEscapeChar || (c != escapeChar)) {\r
428                 if (!prevWasEscapeChar && c==endMark)\r
429                     return sb.toString();\r
430                 // the next char won't be escape char\r
431                 prevWasEscapeChar = false;\r
432             } else {\r
433                 // This is escape char\r
434                 prevWasEscapeChar = true;\r
435             }\r
436             sb.append(c);\r
437         }\r
438 \r
439         return sb.toString();\r
440     }\r
441 \r
442     /**\r
443      * Compiles pattern from simple pattern. Simple pattern is normal\r
444      * wild card compare that supports * and ? wild cards.\r
445      * \r
446      * @param patternStr simple pattern\r
447      * @return Regexp pattern\r
448      */\r
449     public static Pattern compileSimplePattern(String patternStr)\r
450     throws PatternSyntaxException\r
451     {\r
452         String str ="";\r
453         for (int i=0; i<patternStr.length(); i++)\r
454         {\r
455             char c = patternStr.charAt(i);\r
456             if ( (c>='a'&&c<='z') || (c>='A'&&c<='Z') || (c>='0'&&c<='9'))\r
457                 str += c;\r
458             else if ( c=='?' )\r
459                 str += ".?";\r
460             else if ( c=='*' )\r
461                 str += ".*";\r
462             else str += "\\"+c;\r
463         }\r
464         return Pattern.compile(str);\r
465     }\r
466 \r
467     public static boolean simplePatternMatch(String str, String simplePattern)\r
468     {\r
469         try {\r
470             Pattern ptr = compileSimplePattern(simplePattern);\r
471             Matcher m = ptr.matcher(str);\r
472             return m.matches();\r
473         } catch (PatternSyntaxException pse) {\r
474             return false;\r
475         }\r
476     }\r
477 \r
478     public static void main(String[] args) {\r
479         System.out.println(escapeString("value=5,\\5", ",=", '\\'));\r
480         System.out.println(unescapeString("value\\=5\\,\\\\5", '\\'));\r
481         System.out.println(scanEscapedString("val\\,ue\\=5\\,\\\\5,value2=xxx", '\\', ','));\r
482         System.out.println(scanEscapedString("\\,\\,,\\,\\,", '\\', ','));\r
483 \r
484         String value = "STRING 01234"+(char)(128)+(char)(129)+(char)(255);\r
485 \r
486         int X = 500;\r
487         System.out.println(X+" = "+intToBEHex(X, 4));\r
488 \r
489         byte array[] = toBytes(value);\r
490         System.out.print(value);\r
491         System.out.print(" = ");\r
492         printByteArray(array);\r
493         System.out.println();\r
494 \r
495         @SuppressWarnings("unused")\r
496         String str = toString(array);\r
497         System.out.print(value);\r
498         System.out.print(" = ");\r
499         printByteArray(array);\r
500         System.out.println();\r
501 \r
502         String text = "Reads b.length bytes from this file into the "+\r
503         "byte array, starting at the current file pointer. This method"+\r
504         " reads repeatedly from the file until the requested number of "+\r
505         "bytes are read. This method blocks until the requested number of "+\r
506         "bytes are read, the end of the stream is detected, or an exception "+\r
507         "is thrown";\r
508         text = wordWrap(text, 20, 30);\r
509         System.out.println(text);\r
510 \r
511 \r
512         List<String> v = new ArrayList<String>();\r
513         v.add("jeps");\r
514         v.add("jops");\r
515         v.add("kops");\r
516         v.add("hops");\r
517         System.out.println(implode(v));\r
518     }\r
519 \r
520 \r
521 }\r