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