001/* 002 * Copyright (C) 2009-2011 Mathias Doenitz 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.parboiled.common; 018 019import org.parboiled.support.Characters; 020import org.parboiled.support.Chars; 021import org.parboiled.support.Chars; 022 023import java.util.Arrays; 024import java.util.Iterator; 025 026/** 027 * General utility methods for string manipulation. 028 */ 029public final class StringUtils { 030 031 private StringUtils() {} 032 033 /** 034 * Replaces carriage returns, newlines, tabs, formfeeds and the special chars defined in {@link Characters} 035 * with their respective escape sequences. 036 * 037 * @param string the string 038 * @return the escaped string 039 */ 040 public static String escape(String string) { 041 if (isEmpty(string)) return ""; 042 StringBuilder sb = new StringBuilder(); 043 char[] chars = string.toCharArray(); 044 for (int i = 0; i < chars.length; i++) { 045 if (i == chars.length - 1 || chars[i] != '\r' || chars[i + 1] != '\n') { 046 sb.append(escape(chars[i])); 047 } 048 } 049 return sb.toString(); 050 } 051 052 /** 053 * Replaces carriage returns, newlines, tabs, formfeeds and the special chars defined in {@link Characters} 054 * with their respective escape sequences. 055 * 056 * @param c the character to escape 057 * @return the escaped string 058 */ 059 public static String escape(char c) { 060 switch (c) { 061 case '\r': 062 return "\\r"; 063 case '\n': 064 return "\\n"; 065 case '\t': 066 return "\\t"; 067 case '\f': 068 return "\\f"; 069 case Chars.DEL_ERROR: 070 return "DEL_ERROR"; 071 case Chars.INS_ERROR: 072 return "INS_ERROR"; 073 case Chars.RESYNC: 074 return "RESYNC"; 075 case Chars.RESYNC_START: 076 return "RESYNC_START"; 077 case Chars.RESYNC_END: 078 return "RESYNC_END"; 079 case Chars.RESYNC_EOI: 080 return "RESYNC_EOI"; 081 case Chars.INDENT: 082 return "INDENT"; 083 case Chars.DEDENT: 084 return "DEDENT"; 085 case Chars.EOI: 086 return "EOI"; 087 default: 088 return String.valueOf(c); 089 } 090 } 091 092 /** 093 * Creates a string consisting of n times the given character. 094 * 095 * @param c the char 096 * @param n the number of times to repeat 097 * @return the string 098 */ 099 public static String repeat(char c, int n) { 100 char[] array = new char[n]; 101 Arrays.fill(array, c); 102 return String.valueOf(array); 103 } 104 105 //*********************************************************************************************** 106 //** THE FOLLOWING CODE IS A PARTIAL, VERBATIM COPY OF ** 107 //** org.apache.commons.lang.StringUtils ** 108 //** which is licensed under ASF 2.0 ** 109 //*********************************************************************************************** 110 111 /** 112 * <p>Joins the elements of the provided <code>Iterable</code> into 113 * a single String containing the provided elements.</p> 114 * <p>No delimiter is added before or after the list. 115 * A <code>null</code> separator is the same as an empty String ("").</p> 116 * 117 * @param iterable the <code>Iterable</code> of values to join together, may be null 118 * @param separator the separator character to use, null treated as "" 119 * @return the joined String, <code>null</code> if null iterator input 120 */ 121 public static String join(Iterable iterable, String separator) { 122 return iterable == null ? null : join(iterable.iterator(), separator); 123 } 124 125 /** 126 * <p>Joins the elements of the provided <code>Iterator</code> into 127 * a single String containing the provided elements.</p> 128 * <p>No delimiter is added before or after the list. 129 * A <code>null</code> separator is the same as an empty String ("").</p> 130 * 131 * @param iterator the <code>Iterator</code> of values to join together, may be null 132 * @param separator the separator character to use, null treated as "" 133 * @return the joined String, <code>null</code> if null iterator input 134 */ 135 public static String join(Iterator iterator, String separator) { 136 // handle null, zero and one elements before building a buffer 137 if (iterator == null) return null; 138 if (!iterator.hasNext()) return ""; 139 Object first = iterator.next(); 140 if (!iterator.hasNext()) return Utils.toString(first); 141 142 // two or more elements 143 StringBuilder buf = new StringBuilder(256); // Java default is 16, probably too small 144 if (first != null) buf.append(first); 145 146 while (iterator.hasNext()) { 147 if (separator != null) buf.append(separator); 148 Object obj = iterator.next(); 149 if (obj != null) buf.append(obj); 150 } 151 return buf.toString(); 152 } 153 154 /** 155 * <p>Joins the elements of the provided array into a single String 156 * containing the provided list of elements.</p> 157 * <p>No delimiter is added before or after the list. 158 * A <code>null</code> separator is the same as an empty String (""). 159 * Null objects or empty strings within the array are represented by 160 * empty strings.</p> 161 * 162 * <pre> 163 * StringUtils.join(null, *) = null 164 * StringUtils.join([], *) = "" 165 * StringUtils.join([null], *) = "" 166 * StringUtils.join(["a", "b", "c"], "--") = "a--b--c" 167 * StringUtils.join(["a", "b", "c"], null) = "abc" 168 * StringUtils.join(["a", "b", "c"], "") = "abc" 169 * StringUtils.join([null, "", "a"], ',') = ",,a" 170 * </pre> 171 * 172 * @param array the array of values to join together, may be null 173 * @param separator the separator character to use, null treated as "" 174 * @return the joined String, <code>null</code> if null array input 175 */ 176 public static String join(Object[] array, String separator) { 177 return array == null ? null : join(array, separator, 0, array.length); 178 } 179 180 /** 181 * <p>Joins the elements of the provided array into a single String 182 * containing the provided list of elements.</p> 183 * <p>No delimiter is added before or after the list. 184 * A <code>null</code> separator is the same as an empty String (""). 185 * Null objects or empty strings within the array are represented by 186 * empty strings.</p> 187 * <pre> 188 * StringUtils.join(null, *) = null 189 * StringUtils.join([], *) = "" 190 * StringUtils.join([null], *) = "" 191 * StringUtils.join(["a", "b", "c"], "--") = "a--b--c" 192 * StringUtils.join(["a", "b", "c"], null) = "abc" 193 * StringUtils.join(["a", "b", "c"], "") = "abc" 194 * StringUtils.join([null, "", "a"], ',') = ",,a" 195 * </pre> 196 * 197 * @param array the array of values to join together, may be null 198 * @param separator the separator character to use, null treated as "" 199 * @param startIndex the first index to start joining from. It is 200 * an error to pass in an end index past the end of the array 201 * @param endIndex the index to stop joining from (exclusive). It is 202 * an error to pass in an end index past the end of the array 203 * @return the joined String, <code>null</code> if null array input 204 */ 205 public static String join(Object[] array, String separator, int startIndex, int endIndex) { 206 if (array == null) return null; 207 if (separator == null) separator = ""; 208 209 // lastIndex - firstIndex > 0: Len = NofStrings *(len(firstString) + len(separator)) 210 // (Assuming that all Strings are roughly equally long) 211 int bufSize = (endIndex - startIndex); 212 if (bufSize <= 0) return ""; 213 bufSize *= ((array[startIndex] == null ? 16 : array[startIndex].toString().length()) + separator.length()); 214 StringBuilder buf = new StringBuilder(bufSize); 215 216 for (int i = startIndex; i < endIndex; i++) { 217 if (i > startIndex) buf.append(separator); 218 if (array[i] != null) buf.append(array[i]); 219 } 220 return buf.toString(); 221 } 222 223 // Empty checks 224 //----------------------------------------------------------------------- 225 226 /** 227 * <p>Checks if a String is empty ("") or null.</p> 228 * <pre> 229 * StringUtils.isEmpty(null) = true 230 * StringUtils.isEmpty("") = true 231 * StringUtils.isEmpty(" ") = false 232 * StringUtils.isEmpty("bob") = false 233 * StringUtils.isEmpty(" bob ") = false 234 * </pre> 235 * 236 * @param str the String to check, may be null 237 * @return <code>true</code> if the String is empty or null 238 */ 239 public static boolean isEmpty(String str) { 240 return str == null || str.length() == 0; 241 } 242 243 /** 244 * <p>Checks if a String is not empty ("") and not null.</p> 245 * <pre> 246 * StringUtils.isNotEmpty(null) = false 247 * StringUtils.isNotEmpty("") = false 248 * StringUtils.isNotEmpty(" ") = true 249 * StringUtils.isNotEmpty("bob") = true 250 * StringUtils.isNotEmpty(" bob ") = true 251 * </pre> 252 * 253 * @param str the String to check, may be null 254 * @return <code>true</code> if the String is not empty and not null 255 */ 256 public static boolean isNotEmpty(String str) { 257 return !isEmpty(str); 258 } 259 260 /** 261 * Gets a String's length or <code>0</code> if the String is <code>null</code>. 262 * 263 * @param str a String or <code>null</code> 264 * @return String length or <code>0</code> if the String is <code>null</code>. 265 */ 266 public static int length(String str) { 267 return str == null ? 0 : str.length(); 268 } 269 270 /** 271 * <p>Compares two Strings, returning <code>true</code> if they are equal ignoring 272 * the case.</p> 273 * <p><code>null</code>s are handled without exceptions. Two <code>null</code> 274 * references are considered equal. Comparison is case insensitive.</p> 275 * 276 * <pre> 277 * StringUtils.equalsIgnoreCase(null, null) = true 278 * StringUtils.equalsIgnoreCase(null, "abc") = false 279 * StringUtils.equalsIgnoreCase("abc", null) = false 280 * StringUtils.equalsIgnoreCase("abc", "abc") = true 281 * StringUtils.equalsIgnoreCase("abc", "ABC") = true 282 * </pre> 283 * 284 * @param str1 the first String, may be null 285 * @param str2 the second String, may be null 286 * @return <code>true</code> if the Strings are equal, case insensitive, or 287 * both <code>null</code> 288 */ 289 public static boolean equalsIgnoreCase(String str1, String str2) { 290 return str1 == null ? str2 == null : str1.equalsIgnoreCase(str2); 291 } 292 293 /** 294 * Test whether a string starts with a given prefix, handling null values without exceptions. 295 * 296 * StringUtils.startsWith(null, null) = false 297 * StringUtils.startsWith(null, "abc") = false 298 * StringUtils.startsWith("abc", null) = true 299 * StringUtils.startsWith("abc", "ab") = true 300 * StringUtils.startsWith("abc", "abc") = true 301 * 302 * @param string the string 303 * @param prefix the prefix 304 * @return true if string starts with prefix 305 */ 306 public static boolean startsWith(String string, String prefix) { 307 return string != null && (prefix == null || string.startsWith(prefix)); 308 } 309 310 /** 311 * <p>Gets a substring from the specified String avoiding exceptions.</p> 312 * <p>A negative start position can be used to start <code>n</code> 313 * characters from the end of the String.</p> 314 * <p>A <code>null</code> String will return <code>null</code>. 315 * An empty ("") String will return "".</p> 316 * <pre> 317 * StringUtils.substring(null, *) = null 318 * StringUtils.substring("", *) = "" 319 * StringUtils.substring("abc", 0) = "abc" 320 * StringUtils.substring("abc", 2) = "c" 321 * StringUtils.substring("abc", 4) = "" 322 * StringUtils.substring("abc", -2) = "bc" 323 * StringUtils.substring("abc", -4) = "abc" 324 * </pre> 325 * 326 * @param str the String to get the substring from, may be null 327 * @param start the position to start from, negative means 328 * count back from the end of the String by this many characters 329 * @return substring from start position, <code>null</code> if null String input 330 */ 331 public static String substring(String str, int start) { 332 if (str == null) { 333 return null; 334 } 335 336 // handle negatives, which means last n characters 337 if (start < 0) { 338 start = str.length() + start; // remember start is negative 339 } 340 341 if (start < 0) { 342 start = 0; 343 } 344 if (start > str.length()) { 345 return ""; 346 } 347 348 return str.substring(start); 349 } 350 351 /** 352 * <p>Gets a substring from the specified String avoiding exceptions.</p> 353 * <p>A negative start position can be used to start/end <code>n</code> 354 * characters from the end of the String.</p> 355 * <p>The returned substring starts with the character in the <code>start</code> 356 * position and ends before the <code>end</code> position. All position counting is 357 * zero-based -- i.e., to start at the beginning of the string use 358 * <code>start = 0</code>. Negative start and end positions can be used to 359 * specify offsets relative to the end of the String.</p> 360 * <p>If <code>start</code> is not strictly to the left of <code>end</code>, "" 361 * is returned.</p> 362 * <pre> 363 * StringUtils.substring(null, *, *) = null 364 * StringUtils.substring("", * , *) = ""; 365 * StringUtils.substring("abc", 0, 2) = "ab" 366 * StringUtils.substring("abc", 2, 0) = "" 367 * StringUtils.substring("abc", 2, 4) = "c" 368 * StringUtils.substring("abc", 4, 6) = "" 369 * StringUtils.substring("abc", 2, 2) = "" 370 * StringUtils.substring("abc", -2, -1) = "b" 371 * StringUtils.substring("abc", -4, 2) = "ab" 372 * </pre> 373 * 374 * @param str the String to get the substring from, may be null 375 * @param start the position to start from, negative means 376 * count back from the end of the String by this many characters 377 * @param end the position to end at (exclusive), negative means 378 * count back from the end of the String by this many characters 379 * @return substring from start position to end positon, 380 * <code>null</code> if null String input 381 */ 382 public static String substring(String str, int start, int end) { 383 if (str == null) { 384 return null; 385 } 386 387 // handle negatives 388 if (end < 0) { 389 end = str.length() + end; // remember end is negative 390 } 391 if (start < 0) { 392 start = str.length() + start; // remember start is negative 393 } 394 395 // check length next 396 if (end > str.length()) { 397 end = str.length(); 398 } 399 400 // if start is greater than end, return "" 401 if (start > end) { 402 return ""; 403 } 404 405 if (start < 0) { 406 start = 0; 407 } 408 if (end < 0) { 409 end = 0; 410 } 411 412 return str.substring(start, end); 413 } 414 415 // Left/Right/Mid 416 //----------------------------------------------------------------------- 417 418 /** 419 * <p>Gets the leftmost <code>len</code> characters of a String.</p> 420 * <p>If <code>len</code> characters are not available, or the 421 * String is <code>null</code>, the String will be returned without 422 * an exception. An exception is thrown if len is negative.</p> 423 * <pre> 424 * StringUtils.left(null, *) = null 425 * StringUtils.left(*, -ve) = "" 426 * StringUtils.left("", *) = "" 427 * StringUtils.left("abc", 0) = "" 428 * StringUtils.left("abc", 2) = "ab" 429 * StringUtils.left("abc", 4) = "abc" 430 * </pre> 431 * 432 * @param str the String to get the leftmost characters from, may be null 433 * @param len the length of the required String, must be zero or positive 434 * @return the leftmost characters, <code>null</code> if null String input 435 */ 436 public static String left(String str, int len) { 437 if (str == null) { 438 return null; 439 } 440 if (len < 0) { 441 return ""; 442 } 443 if (str.length() <= len) { 444 return str; 445 } 446 return str.substring(0, len); 447 } 448 449 /** 450 * <p>Gets the rightmost <code>len</code> characters of a String.</p> 451 * <p>If <code>len</code> characters are not available, or the String 452 * is <code>null</code>, the String will be returned without an 453 * an exception. An exception is thrown if len is negative.</p> 454 * <pre> 455 * StringUtils.right(null, *) = null 456 * StringUtils.right(*, -ve) = "" 457 * StringUtils.right("", *) = "" 458 * StringUtils.right("abc", 0) = "" 459 * StringUtils.right("abc", 2) = "bc" 460 * StringUtils.right("abc", 4) = "abc" 461 * </pre> 462 * 463 * @param str the String to get the rightmost characters from, may be null 464 * @param len the length of the required String, must be zero or positive 465 * @return the rightmost characters, <code>null</code> if null String input 466 */ 467 public static String right(String str, int len) { 468 if (str == null) { 469 return null; 470 } 471 if (len < 0) { 472 return ""; 473 } 474 if (str.length() <= len) { 475 return str; 476 } 477 return str.substring(str.length() - len); 478 } 479 480 /** 481 * <p>Gets <code>len</code> characters from the middle of a String.</p> 482 * <p>If <code>len</code> characters are not available, the remainder 483 * of the String will be returned without an exception. If the 484 * String is <code>null</code>, <code>null</code> will be returned. 485 * An exception is thrown if len is negative.</p> 486 * <pre> 487 * StringUtils.mid(null, *, *) = null 488 * StringUtils.mid(*, *, -ve) = "" 489 * StringUtils.mid("", 0, *) = "" 490 * StringUtils.mid("abc", 0, 2) = "ab" 491 * StringUtils.mid("abc", 0, 4) = "abc" 492 * StringUtils.mid("abc", 2, 4) = "c" 493 * StringUtils.mid("abc", 4, 2) = "" 494 * StringUtils.mid("abc", -2, 2) = "ab" 495 * </pre> 496 * 497 * @param str the String to get the characters from, may be null 498 * @param pos the position to start from, negative treated as zero 499 * @param len the length of the required String, must be zero or positive 500 * @return the middle characters, <code>null</code> if null String input 501 */ 502 public static String mid(String str, int pos, int len) { 503 if (str == null) { 504 return null; 505 } 506 if (len < 0 || pos > str.length()) { 507 return ""; 508 } 509 if (pos < 0) { 510 pos = 0; 511 } 512 if (str.length() <= (pos + len)) { 513 return str.substring(pos); 514 } 515 return str.substring(pos, pos + len); 516 } 517 518}