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