View Javadoc

1   package com.sharkysoft.string;
2   
3   import com.sharkysoft.util.UnreachableCodeException;
4   
5   /***
6    * Miscellaneous string functions.
7    *
8    * <p><b>Details:</b> <code>StringToolbox</code> is a miscellaneous collection
9    * of functions for manipulating strings.</p>
10   *
11   * @author Sharky
12   */
13  public final class StringToolbox
14  {
15  
16  	private StringToolbox()
17  	{
18  		throw new UnreachableCodeException();
19  	}
20  
21  //  /***
22  //   * Determines whether a string contains a character.
23  //   *
24  //   * <p><b>Details:</b>  <code>contains</code> determines whether <var>c</var>
25  //   * is contained within <var>string</var>, returning <code>true</code> if it
26  //   * is, <code>false</code> otherwise.</p>
27  //   *
28  //   * @param string the string
29  //   * @param c the character
30  //   * @return true iff the string contains the substring
31  //   *
32  //   * @since 2001.03.09
33  //   */
34  //  public static boolean contains(String string, char c)
35  //  {
36  //    return string.indexOf(c) >= 0;
37  //  }
38  //
39  //  /***
40  //   * Determines whether a string contains a substring.
41  //   *
42  //   * <p><b>Details:</b>  <code>contains</code> determines whether
43  //   * <var>substring</var> is contained within <var>string</var>, returning
44  //   * <code>true</code> if it is, <code>false</code> if it is not.</p>
45  //   *
46  //   * @param string the string
47  //   * @param substring the substring
48  //   * @return true iff the string contains the substring
49  //   *
50  //   * @since 1999.04.16
51  //   */
52  //  public static boolean contains(String string, String substring)
53  //  {
54  //    return string.indexOf(substring) >= 0;
55  //  }
56  //
57  //  /***
58  //   * Counts character occurrences.
59  //   *
60  //   * <p><b>Details:</b> <code>count</code> determines the number of occurrences
61  //   * of a character in a string.</p>
62  //   *
63  //   * @param string the string to search
64  //   * @param c the character
65  //   * @return the number of occurrences
66  //   */
67  //  public static final int count(String string, char c)
68  //  {
69  //    int string_len = string.length();
70  //    int count = 0;
71  //    for (int i = 0; i < string_len; ++ i)
72  //      if (string.charAt(i) == c)
73  //        ++ count;
74  //    return count;
75  //  }
76  //
77  //  /***
78  //   * Counts substring occurences.
79  //   *
80  //   * <p><b>Details:</b> <code>count</code> determines the number of occurrences
81  //   * of a substring string inside another string.  Overlapping substrings are
82  //   * counted.  For example, the call</p>
83  //   *
84  //   * <blockquote><code>
85  //   *   count("banana", "ana")
86  //   * </code></blockquote>
87  //   *
88  //   * <p>returns 2.</p>
89  //   *
90  //   * @param string the string to search
91  //   * @param substring the substring
92  //   * @return the number of occurrences
93  //   */
94  //  public static final int count(String string, String substring)
95  //  {
96  //    int string_len = string.length();
97  //    int count = 0;
98  //    int i = 0;
99  //    while (true)
100 //    {
101 //      i = string.indexOf(substring, i);
102 //      if (i < 0)
103 //        break;
104 //      ++ count;
105 //      ++ i;
106 //    }
107 //    return count;
108 //  }
109 //
110 //  /***
111 //   * Finds first difference.
112 //   *
113 //   * <p><b>Details:</b>  findDifference compares two strings, character for
114 //   * character, starting with the first character, and scanning until a
115 //   * character mismatch is encountered, or until the shorter string has run out
116 //   * of characters.  If a mismatch is encountered, the index of the mismatch is
117 //   * returned.  If no mismatches are found but the strings have unequal lengths,
118 //   * the length of the shorter string is returned.  If no mismatch is found and
119 //   * the strings have equal length, then the strings are identical and -1 is
120 //   * returned.</p>
121 //   *
122 //   * @param s1 the first string
123 //   * @param s2 the second string
124 //   * @return the index of mismatch
125 //   *
126 //   * @since 2000.02.16
127 //   */
128 //  public static final int findDifference (String s1, String s2)
129 //  {
130 //    int l1 = s1 . length ();
131 //    int l2 = s2 . length ();
132 //    int lmin = Math.min (l1, l2);
133 //    int p;
134 //    for (p = 0; p < lmin; ++ p)
135 //    {
136 //      if (s1 . charAt (p) != s2 . charAt (p))
137 //        return p;
138 //    }
139 //    if (l1 == l2)
140 //      return -1;
141 //    return lmin;
142 //  }
143 //
144 //  /***
145 //   * Determines common suffix.
146 //   *
147 //   * <p><b>Details:</b>  getCommonSuffix returns the longest string that is a
148 //   * suffix to both given strings.</p>
149 //   *
150 //   * @param s1 the first string
151 //   * @param s2 the second string
152 //   * @return the suffix
153 //   *
154 //   * @since 2001.03.09
155 //   */
156 //  public static final String getCommonSuffix(String s1, String s2)
157 //  {
158 //    int l1 = s1.length();
159 //    int l2 = s2.length();
160 //    int lmin = Math.min(l1, l2);
161 //    int p;
162 //    for (p = 0; p < lmin; ++ p)
163 //      if (s1.charAt(l1 - 1 - p) != s2.charAt(l2 - 1 - p))
164 //        break;
165 //    return s1.substring(l1 - p);
166 //  }
167 //
168 //  /***
169 //   * Returns left portion of string.
170 //   *
171 //   * <p><b>Details:</b> <code>left</code> returns a prefix of the given string
172 //   * of the requested length.  If the requested length is greater than the
173 //   * length of the original string, the original string is returned.</p>
174 //   *
175 //   * @param s the string whose prefix is desired
176 //   * @param len the length of the prefix
177 //   * @return the prefix
178 //   */
179 //  public static String left(String s, int len)
180 //  {
181 //    if (s.length() <= len)
182 //      return s;
183 //    return s.substring(0, len);
184 //  }
185 //
186 //  /***
187 //   * Removes excess spaces.
188 //   *
189 //   * <p><b>Details:</b> <code>minimizeSpaces</code> removes excess white spaces
190 //   * from the ends and middle of the given string.  Space characters are
191 //   * identified in the same manner as they are identified by
192 //   * <code>java.util.StringTokenizer</code> when an instance is created without
193 //   * delimeters.  A space is considered excess if any of the following
194 //   * conditions regarding that space are true:</p>
195 //   *
196 //   * <ul>
197 //   *   <li>It is at the beginning of the string.</li>
198 //   *   <li>It is at the end of the string.</li>
199 //   *   <li>It is preceded by another white space.</li>
200 //   * </ul>
201 //   *
202 //   * <p>After all excess spaces are removed, all remaining spaces are converted
203 //   * into normal spaces, and the resulting string is returned.</p>
204 //   *
205 //   * @param s the string to process
206 //   * @return the processed string
207 //   */
208 //  public static String minimizeSpaces(String s)
209 //  {
210 //    StringBuffer buff = new StringBuffer(s.length());
211 //    StringTokenizer toks = new StringTokenizer(s);
212 //    int count = toks.countTokens();
213 //    for (int i = 0; i < count; ++ i)
214 //    {
215 //      if (i > 0)
216 //        buff.append(' ');
217 //      buff.append(toks.nextToken());
218 //    }
219 //    return buff.toString();
220 //  }
221 
222 	/***
223 	 * Creates string by repeating character.
224 	 *
225 	 * <p><b>Details:</b> <code>repeat</code> creates a new string by repeating a
226 	 * character.  For example, the call</p>
227 	 *
228 	 * <blockquote><code>
229 	 *   repeat('#', 3)
230 	 * </code></blockquote>
231 	 *
232 	 * <p>produces the string "<tt>###</tt>".  A zero-<wbr>length string is
233 	 * returned if the repeat count is less than 1.</p>
234 	 *
235 	 * @param icChar the character to repeat
236 	 * @param inCount the repeat count
237 	 * @return the new string containing repeated characters
238 	 */
239 	public static String repeat(char icChar, int inCount)
240 	{
241 		StringBuffer buff = new StringBuffer(inCount);
242 		for (int i = 0; i < inCount; ++i)
243 			buff.append(icChar);
244 		return buff.toString();
245 	}
246 
247 //  /***
248 //   * Creates string by repeating string.
249 //   *
250 //   * <p><b>Details:</b> <code>repeat</code> creates a new <code>String</code> by
251 //   * repeating and concatenating the contents of another <code>String</code>
252 //   * (<var>s</var>).  For example, the call</p>
253 //   *
254 //   * <blockquote><code>
255 //   *   repeat ("Hello", 3)
256 //   * </code></blockquote>
257 //   *
258 //   * <p>produces the string "<tt>HelloHelloHello</tt>".  <code>repeat</code>
259 //   * returns a zero-length string if the repeat count (<var>n</var>) is less
260 //   * than 1.</p>
261 //   *
262 //   * @param s the string to repeat
263 //   * @param n the repeat count
264 //   * @return the new string containing repeated substrings
265 //   */
266 //  public static String repeat(String s, int n)
267 //  {
268 //    StringBuffer buff = new StringBuffer(s.length() * n);
269 //    for (int i = 0; i < n; ++ i)
270 //      buff.append(s);
271 //    return buff.toString();
272 //  }
273 //
274 //  /***
275 //   * Search and replace.
276 //   *
277 //   * <p><b>Details:</b>  <code>replace</code> scans <var>source</var> for
278 //   * substrings matching <var>before</var>, from left to right, and replaces all
279 //   * occurrences found with <var>after</var>.  If a matching substring is found,
280 //   * the replacement is made and then the scan picks up after the last character
281 //   * of the substring.  The result is returned in a new string.  If no
282 //   * replacements were made, the original <code>String</code> instance is
283 //   * returned.</p>
284 //   *
285 //   * @param source the source string
286 //   * @param before the substring to search for
287 //   * @param after what to replace <var>before</var> with
288 //   * @return the new string
289 //   *
290 //   * @since 2000.01.30
291 //   */
292 //
293 //  public static String replace(String source, String before, String after)
294 //  {
295 //    StringBuffer dest = new StringBuffer();
296 //    final int srclen = source.length();
297 //    final int beflen = before.length();
298 //    if (beflen == 0)
299 //      throw new IllegalArgumentException("before cannot be empty");
300 //    boolean changed = false;
301 //    int i = 0;
302 //    while(true)
303 //    {
304 //      int j = source.indexOf(before, i);
305 //      if (j < 0)
306 //      {
307 //        if (! changed)
308 //          return source;
309 //        dest.append(source.substring(i));
310 //        break;
311 //      }
312 //      changed = true;
313 //      dest.append(source.substring(i, j));
314 //      dest.append(after);
315 //      i = j + beflen;
316 //      if (i >= srclen)
317 //        break;
318 //    }
319 //    if (! changed)
320 //      return source;
321 //    return dest.toString();
322 //  }
323 //
324 //  /***
325 //   * Returns suffix of string.
326 //   *
327 //   * <p><b>Details:</b> <code>right</code> returns a suffix of the given string
328 //   * of the requested length.  If the requested length is greater than the
329 //   * length of the original string, the original string is returned.</p>
330 //   *
331 //   * @param s the string whose suffix is desired
332 //   * @param len length of desired suffix
333 //   * @return the suffix
334 //   */
335 //  public static String right(String s, int len)
336 //  {
337 //    int maxlen = s.length();
338 //    if (maxlen < len)
339 //      return s;
340 //    return s.substring(maxlen - len);
341 //  }
342 //
343 //  /***
344 //   * Divides string into tokens.
345 //   *
346 //   * <p><b>Details:</b> <code>splitString</code> breaks a string (<var>s</var>)
347 //   * into an array of substrings with the delimeters removed.  The delimeter
348 //   * characters are listed in a separate string (<var>d</var>).</p>
349 //   *
350 //   * <p><code>java.util.StringTokenizer</code> offers similar functionality.
351 //   * This implementation differs by the fact that it returns all of the tokens
352 //   * at once, using a <code>String</code> array, and does not require the
353 //   * explicit creation of a tokenizer object or enumeration handling.</p>
354 //   *
355 //   * @param s the string to split
356 //   * @param d the delimeters
357 //   * @return the substrings of s
358 //   */
359 //  public static String[] splitString(String s, String d)
360 //  {
361 //    final StringTokenizer tokenizer = new StringTokenizer(s, d);
362 //    final int vnCount = tokenizer.countTokens();
363 //    final String[] toks = new String[vnCount];
364 //    for (int i = 0; i < vnCount; ++ i)
365 //      toks[i] = tokenizer.nextToken();
366 //    return toks;
367 //  }
368 //
369 //  /***
370 //   * Converts string to "title" case.
371 //   *
372 //   * <p><b>Details:</b>  This method converts the first character of every run
373 //   * of letters in the given string (<var>s</var>) to upper case, making the
374 //   * string appear in "title" format.  For the purposes of conversion,
375 //   * apostrophes occuring immediately after letters are also treated as letters.
376 //   * This method may not be appropriate for some strings, particularly those
377 //   * containing Roman numerals and other words where more than one character
378 //   * should be capitalized.</p>
379 //   *
380 //   * <p>Examples:</p>
381 //   *
382 //   * <table>
383 //   *   <tr>
384 //   *     <td>MacDonald's</td>
385 //   *     <td>Macdonald's</td>
386 //   *   </tr>
387 //   *   <tr>
388 //   *     <td>yo-yos</td>
389 //   *     <td>Yo-Yos</td>
390 //   *   </tr>
391 //   *   <tr>
392 //   *     <td>part</td>
393 //   *     <td>Part</td>
394 //   *   </tr>
395 //   *   <tr>
396 //   *     <td>III</td>
397 //   *     <td>Iii</td>
398 //   *   </tr>
399 //   * </table>
400 //   *
401 //   * @param s the string to convert
402 //   * @return the converted string
403 //   *
404 //   * @since 2000.01.15
405 //   */
406 //  public static String toInitialCaps(String s)
407 //  {
408 //    StringBuffer buff = new StringBuffer();
409 //    boolean space = true;
410 //    int length = s.length();
411 //    for (int i = 0; i < length; ++ i)
412 //    {
413 //      char c = s.charAt(i);
414 //      if (space)
415 //        c = Character.toUpperCase(c);
416 //      else
417 //        c = Character.toLowerCase(c);
418 //      switch (c)
419 //      {
420 //        case '\'':
421 //          break;
422 //        default:
423 //          space = ! Character.isLetter(c);
424 //      }
425 //      buff.append(c);
426 //    }
427 //    return buff.toString();
428 //  }
429 //
430 //  /***
431 //   * Trims characters from both ends of string.
432 //   *
433 //   * <p><b>Details:</b> <code>trim</code> removes the given character
434 //   * (<var>c</var>) from both ends of the given string (<var>s</var>).  For
435 //   * example, the call</p>
436 //   *
437 //   * <blockquote><code>
438 //   *   trimTrailing ("sizes", 's')
439 //   * </code></blockquote>
440 //   *
441 //   * <p>returns the string "<tt>ize</tt>".</p>
442 //   *
443 //   * @param s the string to edit
444 //   * @param n the character to trim
445 //   * @return the trimmed string
446 //   */
447 //  public static String trim(String s, char c)
448 //  {
449 //    final int length = s.length();
450 //    int start;
451 //    for (start = 0; start < length; ++ start)
452 //      if (s.charAt(start) != c)
453 //        break;
454 //    int stop;
455 //    for (stop = length; stop > start; -- stop)
456 //      if (s.charAt(stop - 1) != c)
457 //        break;
458 //    return s.substring(start, stop);
459 //  }
460 //
461 //  /***
462 //   * Trims trailing characters.
463 //   *
464 //   * <p><b>Details:</b> <code>trimTrailing</code> trims the specified character
465 //   * (<var>c</var>) from the end of the given string (<var>s</var>) if the
466 //   * string ends with one or more repetitions of that character.  For example,
467 //   * the call</p>
468 //   *
469 //   * <blockquote><code>
470 //   *   removeTrailing("Tennessee", 'e')
471 //   * </code></blockquote>
472 //   *
473 //   * <p>returns the string "<tt>Tenness</tt>".</p>
474 //   *
475 //   * @param s the string to edit
476 //   * @param c the trailing character to remove
477 //   * @return a new string with the trailing characters removed
478 //   */
479 //  public static String trimTrailing(String s, char c)
480 //  {
481 //    int i;
482 //    for (i = s.length(); i > 0; -- i)
483 //      if (s.charAt(i - 1) != c)
484 //        break;
485 //    return s.substring(0, i);
486 //  }
487 //
488 //  /***
489 //   * Trims leading characters.
490 //   *
491 //   * <p><b>Details:</b> <code>trimLeading</code> trims occurances of the
492 //   * specified character (<var>ic</var>) from the beginning of the given string
493 //   * (<var>is</var>) if the string begins with one or more repetitions of that
494 //   * character.  For example, the call</p>
495 //   *
496 //   * <blockquote><code>
497 //   *   removeLeading ("eery", 'e')
498 //   * </code></blockquote>
499 //   *
500 //   * <p>returns the string "<tt>ry</tt>".</p>
501 //   *
502 //   * @param is the string to edit
503 //   * @param ic the leading character to remove
504 //   * @return a new string with the leading characters removed
505 //   *
506 //   * @since 2001.09.08
507 //   */
508 //  public static String trimLeading(String is, char ic)
509 //  {
510 //    int vnI;
511 //    final int vnL = is.length();
512 //    for (vnI = 0; vnI < vnL; ++ vnI)
513 //    {
514 //      if (is.charAt(vnI) != ic)
515 //        break;
516 //    }
517 //    return is.substring(vnI);
518 //  }
519 //
520 //  /***
521 //   * Determines if string looks like an email address.
522 //   *
523 //   * <p><b>Details:</b>  <code>looksLikeAnEmailAddress</code> analyzes the given
524 //   * string (<var>s</var>) and determines whether it looks like an email
525 //   * address.  If it does, <code>looksLikeAnEmailAddress</code> returns
526 //   * <code>true</code>, <code>false</code> otherwise.</p>
527 //   *
528 //   * <p>See {@link com.sharkysoft.io.StreamParser#tryEmailAddress()
529 //   * <code>com.sharkysoft.io.StreamParser.tryEmailAddress</code>} for more
530 //   * information on the forms of email addresses accepted by this function.</p>
531 //   *
532 //   * @param s the string to test
533 //   * @return true iff s looks like an email address
534 //   *
535 //   * @since 2000.12.21
536 //   */
537 //  public static boolean looksLikeAnEmailAddress(String s)
538 //  {
539 //    UnlimitedPushbackReader upr = null;
540 //    try
541 //    {
542 //      upr = new UnlimitedPushbackReader(new StringReader(s));
543 //      return s.equals(StreamParser.tryEmailAddress(upr));
544 //    }
545 //    catch (IOException e)
546 //    {
547 //      throw new UnreachableCodeException("looksLikeAnEmailAddress puked with s=" + s);
548 //    }
549 //    finally
550 //    {
551 //      IoCloser.close(upr);
552 //    }
553 //  }
554 
555 }
556