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
9 * VTT Technical Research Centre of Finland - initial API and implementation
\r
10 *******************************************************************************/
\r
12 * Created on Jan 21, 2005
\r
14 * Copyright Toni Kalajainen
\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
20 * http://www.apache.org/licenses/LICENSE-2.0
\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
28 package org.simantics.utils.strings;
\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
38 import org.simantics.databoard.parser.StringEscapeUtils;
\r
39 import org.simantics.utils.bytes.ByteArrays;
\r
43 * Extended string functions
\r
44 * Byte array <-> string conversions
\r
46 * Length is not included
\r
49 * See also {@link StringEscapeUtils}
\r
50 * @author Toni Kalajainen
\r
52 public class EString {
\r
54 public static final char[] HEX_VALUES =
\r
55 {'0', '1', '2', '3' ,'4' ,'5', '6', '7', '8', '9' ,'A', 'B', 'C',
\r
60 * convert string to byte array
\r
64 public static byte[] toBytes(String s) {
\r
65 int size = s.length();
\r
66 byte array[] = new byte[size];
\r
68 for (int i=0; i<size; i++)
\r
69 array[i] = (byte) (s.charAt(i) );
\r
74 * convert bytearray to string
\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
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
91 * read null terminated string
\r
93 * @param offset start offset
\r
96 public static String PChar(byte array[], int offset) {
\r
97 if (array==null) return null;
\r
98 int size = array.length;
\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
109 * read null terminated string
\r
111 * @param offset start offset
\r
112 * @param maxLen maximum bytes to read
\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
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
129 * Explode words into array
\r
134 public static String[] explode(String str, String breaker) {
\r
135 return str.split(breaker);
\r
138 * Explode string into lines
\r
142 public static String[] explode(String str) {
\r
143 return str.split("\n");
\r
146 * implode array into string
\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
159 sb.append(strings[i]);
\r
161 return sb.toString();
\r
163 public static String implode(Collection<?> strings) {
\r
164 return implode(strings.toArray(new Object[strings.size()]));
\r
166 public static String implode(Collection<?> strings, String glue) {
\r
167 return implode(strings.toArray(new Object[strings.size()]), glue);
\r
170 * implode lines into array
\r
174 public static String implode(Object strings[]) {
\r
175 if (strings.length==0) return "";
\r
177 String s0 = strings[0].toString();
\r
178 int s0len = s0.length();
\r
180 for (int i=1; i<strings.length; i++)
\r
181 len += 1+strings[i].toString().length();
\r
183 char data[] = new char[len];
\r
184 s0.getChars(0, s0.length(), data, 0);
\r
187 for (int i=1; i<strings.length; i++) {
\r
189 String si = strings[i].toString();
\r
190 int silen = si.length();
\r
191 si.getChars(0, silen, data, pos+1);
\r
195 return new String(data);
\r
199 * Add prefix to stings in array
\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
212 * add prefix to lines
\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
225 * add prefix and suffix to lines
\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
244 public static String intToBEHex(int value, int decimals) {
\r
245 // TODO Replace with String.format("%0"+decimals+"X", value)
\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
256 * splits line in a manner that is done to word wrap
\r
257 * Lines are broken between spaces if possible
\r
259 public static String wordWrap(String text, int minWidth, int maxWidth)
\r
263 String lines[] = text.replaceAll(""+cr, "").split("\n");
\r
264 List<String> result = new ArrayList<String>();
\r
267 for (int i=0; i<lines.length; i++) {
\r
268 String line = lines[i];
\r
270 if (line.length() < maxWidth) {
\r
275 // Line is longer than maxwidth, split it
\r
276 String words[] = lines[i].split(" ");
\r
278 for (int j=0; j<words.length; j++) {
\r
279 // Nothing on the buffer
\r
280 if (line.equals("")) {
\r
282 while (line.length() > maxWidth) {
\r
283 result.add(line.substring(0, maxWidth));
\r
284 line = line.substring(maxWidth);
\r
289 // Add to previous line buffer
\r
290 String word = words[j];
\r
292 // Check if adding this word fits maxwidth
\r
293 if (line.length()+1+word.length()<maxWidth) {
\r
294 line = line + " " + word;
\r
297 // Adding this word would make the line too long
\r
299 // Check if this line is long enough
\r
300 if (line.length()>=minWidth) {
\r
305 // Line is not long enough with out AWord and with it
\r
306 // the line is too long.
\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
315 if (!line.equals(""))
\r
319 // Change string lines into single string
\r
320 StringBuilder sb = new StringBuilder();
\r
321 int rs = result.size();
\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
327 return sb.length() == 0 ? "" : sb.toString();
\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
339 public static void saveToFile(String text, String filename)
\r
342 ByteArrays.saveToFile(toBytes(text), filename);
\r
346 * Escape characters in a string.
\r
348 * eg. value=5,5 will be escaped to value\=5\,5
\r
349 * with escape set =, and escape char \
\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
356 public static String escapeString(String str, String escapeSet, char escapeChar)
\r
358 escapeSet += escapeChar;
\r
359 StringBuilder sb = new StringBuilder(str.length()*2);
\r
360 for (int i=0; i<str.length(); i++)
\r
362 char c = str.charAt(i);
\r
364 for (int j=0; j<escapeSet.length(); j++)
\r
366 char ec = escapeSet.charAt(j);
\r
368 sb.append(escapeChar);
\r
376 return sb.toString();
\r
380 * Unescape charaters in a string
\r
382 * eg. value\=5\,5 will be unescaped to value=5,5 with
\r
383 * escape set =, and escape char \
\r
385 * @param str string to unescape
\r
386 * @param escapeChar
\r
387 * @return unescaped string
\r
389 public static String unescapeString(String str, char escapeChar)
\r
391 StringBuilder sb = new StringBuilder(str.length());
\r
392 boolean prevWasEscapeChar = false;
\r
393 for (int i=0; i<str.length(); i++)
\r
395 char c = str.charAt(i);
\r
397 // Atmost escape every second character
\r
398 if (prevWasEscapeChar || (c != escapeChar)) {
\r
399 prevWasEscapeChar = false;
\r
402 prevWasEscapeChar = true;
\r
406 return sb.toString();
\r
410 * Scans escaped string
\r
411 * e.g. key=val\,ue,key2=xx returns key=val\,ue with endMark ,
\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
418 public static String scanEscapedString(String str, char escapeChar, char endMark)
\r
420 StringBuilder sb = new StringBuilder(str.length());
\r
421 boolean prevWasEscapeChar = false;
\r
422 for (int i=0; i<str.length(); i++)
\r
424 char c = str.charAt(i);
\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
433 // This is escape char
\r
434 prevWasEscapeChar = true;
\r
439 return sb.toString();
\r
443 * Compiles pattern from simple pattern. Simple pattern is normal
\r
444 * wild card compare that supports * and ? wild cards.
\r
446 * @param patternStr simple pattern
\r
447 * @return Regexp pattern
\r
449 public static Pattern compileSimplePattern(String patternStr)
\r
450 throws PatternSyntaxException
\r
453 for (int i=0; i<patternStr.length(); i++)
\r
455 char c = patternStr.charAt(i);
\r
456 if ( (c>='a'&&c<='z') || (c>='A'&&c<='Z') || (c>='0'&&c<='9'))
\r
462 else str += "\\"+c;
\r
464 return Pattern.compile(str);
\r
467 public static boolean simplePatternMatch(String str, String simplePattern)
\r
470 Pattern ptr = compileSimplePattern(simplePattern);
\r
471 Matcher m = ptr.matcher(str);
\r
472 return m.matches();
\r
473 } catch (PatternSyntaxException pse) {
\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
484 String value = "STRING 01234"+(char)(128)+(char)(129)+(char)(255);
\r
487 System.out.println(X+" = "+intToBEHex(X, 4));
\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
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
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
508 text = wordWrap(text, 20, 30);
\r
509 System.out.println(text);
\r
512 List<String> v = new ArrayList<String>();
\r
517 System.out.println(implode(v));
\r