package com.sharkysoft.string;

import com.sharkysoft.util.UnreachableCodeException;

/**
 * Miscellaneous string functions.
 *
 * <p><b>Details:</b> <code>StringToolbox</code> is a miscellaneous collection
 * of functions for manipulating strings.</p>
 *
 * @author Sharky
 */
public final class StringToolbox
{

	private StringToolbox()
	{
		throw new UnreachableCodeException();
	}

//  /**
//   * Determines whether a string contains a character.
//   *
//   * <p><b>Details:</b>  <code>contains</code> determines whether <var>c</var>
//   * is contained within <var>string</var>, returning <code>true</code> if it
//   * is, <code>false</code> otherwise.</p>
//   *
//   * @param string the string
//   * @param c the character
//   * @return true iff the string contains the substring
//   *
//   * @since 2001.03.09
//   */
//  public static boolean contains(String string, char c)
//  {
//    return string.indexOf(c) >= 0;
//  }
//
//  /**
//   * Determines whether a string contains a substring.
//   *
//   * <p><b>Details:</b>  <code>contains</code> determines whether
//   * <var>substring</var> is contained within <var>string</var>, returning
//   * <code>true</code> if it is, <code>false</code> if it is not.</p>
//   *
//   * @param string the string
//   * @param substring the substring
//   * @return true iff the string contains the substring
//   *
//   * @since 1999.04.16
//   */
//  public static boolean contains(String string, String substring)
//  {
//    return string.indexOf(substring) >= 0;
//  }
//
//  /**
//   * Counts character occurrences.
//   *
//   * <p><b>Details:</b> <code>count</code> determines the number of occurrences
//   * of a character in a string.</p>
//   *
//   * @param string the string to search
//   * @param c the character
//   * @return the number of occurrences
//   */
//  public static final int count(String string, char c)
//  {
//    int string_len = string.length();
//    int count = 0;
//    for (int i = 0; i < string_len; ++ i)
//      if (string.charAt(i) == c)
//        ++ count;
//    return count;
//  }
//
//  /**
//   * Counts substring occurences.
//   *
//   * <p><b>Details:</b> <code>count</code> determines the number of occurrences
//   * of a substring string inside another string.  Overlapping substrings are
//   * counted.  For example, the call</p>
//   *
//   * <blockquote><code>
//   *   count("banana", "ana")
//   * </code></blockquote>
//   *
//   * <p>returns 2.</p>
//   *
//   * @param string the string to search
//   * @param substring the substring
//   * @return the number of occurrences
//   */
//  public static final int count(String string, String substring)
//  {
//    int string_len = string.length();
//    int count = 0;
//    int i = 0;
//    while (true)
//    {
//      i = string.indexOf(substring, i);
//      if (i < 0)
//        break;
//      ++ count;
//      ++ i;
//    }
//    return count;
//  }
//
//  /**
//   * Finds first difference.
//   *
//   * <p><b>Details:</b>  findDifference compares two strings, character for
//   * character, starting with the first character, and scanning until a
//   * character mismatch is encountered, or until the shorter string has run out
//   * of characters.  If a mismatch is encountered, the index of the mismatch is
//   * returned.  If no mismatches are found but the strings have unequal lengths,
//   * the length of the shorter string is returned.  If no mismatch is found and
//   * the strings have equal length, then the strings are identical and -1 is
//   * returned.</p>
//   *
//   * @param s1 the first string
//   * @param s2 the second string
//   * @return the index of mismatch
//   *
//   * @since 2000.02.16
//   */
//  public static final int findDifference (String s1, String s2)
//  {
//    int l1 = s1 . length ();
//    int l2 = s2 . length ();
//    int lmin = Math.min (l1, l2);
//    int p;
//    for (p = 0; p < lmin; ++ p)
//    {
//      if (s1 . charAt (p) != s2 . charAt (p))
//        return p;
//    }
//    if (l1 == l2)
//      return -1;
//    return lmin;
//  }
//
//  /**
//   * Determines common suffix.
//   *
//   * <p><b>Details:</b>  getCommonSuffix returns the longest string that is a
//   * suffix to both given strings.</p>
//   *
//   * @param s1 the first string
//   * @param s2 the second string
//   * @return the suffix
//   *
//   * @since 2001.03.09
//   */
//  public static final String getCommonSuffix(String s1, String s2)
//  {
//    int l1 = s1.length();
//    int l2 = s2.length();
//    int lmin = Math.min(l1, l2);
//    int p;
//    for (p = 0; p < lmin; ++ p)
//      if (s1.charAt(l1 - 1 - p) != s2.charAt(l2 - 1 - p))
//        break;
//    return s1.substring(l1 - p);
//  }
//
//  /**
//   * Returns left portion of string.
//   *
//   * <p><b>Details:</b> <code>left</code> returns a prefix of the given string
//   * of the requested length.  If the requested length is greater than the
//   * length of the original string, the original string is returned.</p>
//   *
//   * @param s the string whose prefix is desired
//   * @param len the length of the prefix
//   * @return the prefix
//   */
//  public static String left(String s, int len)
//  {
//    if (s.length() <= len)
//      return s;
//    return s.substring(0, len);
//  }
//
//  /**
//   * Removes excess spaces.
//   *
//   * <p><b>Details:</b> <code>minimizeSpaces</code> removes excess white spaces
//   * from the ends and middle of the given string.  Space characters are
//   * identified in the same manner as they are identified by
//   * <code>java.util.StringTokenizer</code> when an instance is created without
//   * delimeters.  A space is considered excess if any of the following
//   * conditions regarding that space are true:</p>
//   *
//   * <ul>
//   *   <li>It is at the beginning of the string.</li>
//   *   <li>It is at the end of the string.</li>
//   *   <li>It is preceded by another white space.</li>
//   * </ul>
//   *
//   * <p>After all excess spaces are removed, all remaining spaces are converted
//   * into normal spaces, and the resulting string is returned.</p>
//   *
//   * @param s the string to process
//   * @return the processed string
//   */
//  public static String minimizeSpaces(String s)
//  {
//    StringBuffer buff = new StringBuffer(s.length());
//    StringTokenizer toks = new StringTokenizer(s);
//    int count = toks.countTokens();
//    for (int i = 0; i < count; ++ i)
//    {
//      if (i > 0)
//        buff.append(' ');
//      buff.append(toks.nextToken());
//    }
//    return buff.toString();
//  }

	/**
	 * Creates string by repeating character.
	 *
	 * <p><b>Details:</b> <code>repeat</code> creates a new string by repeating a
	 * character.  For example, the call</p>
	 *
	 * <blockquote><code>
	 *   repeat('#', 3)
	 * </code></blockquote>
	 *
	 * <p>produces the string "<tt>###</tt>".  A zero-<wbr>length string is
	 * returned if the repeat count is less than 1.</p>
	 *
	 * @param icChar the character to repeat
	 * @param inCount the repeat count
	 * @return the new string containing repeated characters
	 */
	public static String repeat(char icChar, int inCount)
	{
		StringBuffer buff = new StringBuffer(inCount);
		for (int i = 0; i < inCount; ++i)
			buff.append(icChar);
		return buff.toString();
	}

//  /**
//   * Creates string by repeating string.
//   *
//   * <p><b>Details:</b> <code>repeat</code> creates a new <code>String</code> by
//   * repeating and concatenating the contents of another <code>String</code>
//   * (<var>s</var>).  For example, the call</p>
//   *
//   * <blockquote><code>
//   *   repeat ("Hello", 3)
//   * </code></blockquote>
//   *
//   * <p>produces the string "<tt>HelloHelloHello</tt>".  <code>repeat</code>
//   * returns a zero-length string if the repeat count (<var>n</var>) is less
//   * than 1.</p>
//   *
//   * @param s the string to repeat
//   * @param n the repeat count
//   * @return the new string containing repeated substrings
//   */
//  public static String repeat(String s, int n)
//  {
//    StringBuffer buff = new StringBuffer(s.length() * n);
//    for (int i = 0; i < n; ++ i)
//      buff.append(s);
//    return buff.toString();
//  }
//
//  /**
//   * Search and replace.
//   *
//   * <p><b>Details:</b>  <code>replace</code> scans <var>source</var> for
//   * substrings matching <var>before</var>, from left to right, and replaces all
//   * occurrences found with <var>after</var>.  If a matching substring is found,
//   * the replacement is made and then the scan picks up after the last character
//   * of the substring.  The result is returned in a new string.  If no
//   * replacements were made, the original <code>String</code> instance is
//   * returned.</p>
//   *
//   * @param source the source string
//   * @param before the substring to search for
//   * @param after what to replace <var>before</var> with
//   * @return the new string
//   *
//   * @since 2000.01.30
//   */
//
//  public static String replace(String source, String before, String after)
//  {
//    StringBuffer dest = new StringBuffer();
//    final int srclen = source.length();
//    final int beflen = before.length();
//    if (beflen == 0)
//      throw new IllegalArgumentException("before cannot be empty");
//    boolean changed = false;
//    int i = 0;
//    while(true)
//    {
//      int j = source.indexOf(before, i);
//      if (j < 0)
//      {
//        if (! changed)
//          return source;
//        dest.append(source.substring(i));
//        break;
//      }
//      changed = true;
//      dest.append(source.substring(i, j));
//      dest.append(after);
//      i = j + beflen;
//      if (i >= srclen)
//        break;
//    }
//    if (! changed)
//      return source;
//    return dest.toString();
//  }
//
//  /**
//   * Returns suffix of string.
//   *
//   * <p><b>Details:</b> <code>right</code> returns a suffix of the given string
//   * of the requested length.  If the requested length is greater than the
//   * length of the original string, the original string is returned.</p>
//   *
//   * @param s the string whose suffix is desired
//   * @param len length of desired suffix
//   * @return the suffix
//   */
//  public static String right(String s, int len)
//  {
//    int maxlen = s.length();
//    if (maxlen < len)
//      return s;
//    return s.substring(maxlen - len);
//  }
//
//  /**
//   * Divides string into tokens.
//   *
//   * <p><b>Details:</b> <code>splitString</code> breaks a string (<var>s</var>)
//   * into an array of substrings with the delimeters removed.  The delimeter
//   * characters are listed in a separate string (<var>d</var>).</p>
//   *
//   * <p><code>java.util.StringTokenizer</code> offers similar functionality.
//   * This implementation differs by the fact that it returns all of the tokens
//   * at once, using a <code>String</code> array, and does not require the
//   * explicit creation of a tokenizer object or enumeration handling.</p>
//   *
//   * @param s the string to split
//   * @param d the delimeters
//   * @return the substrings of s
//   */
//  public static String[] splitString(String s, String d)
//  {
//    final StringTokenizer tokenizer = new StringTokenizer(s, d);
//    final int vnCount = tokenizer.countTokens();
//    final String[] toks = new String[vnCount];
//    for (int i = 0; i < vnCount; ++ i)
//      toks[i] = tokenizer.nextToken();
//    return toks;
//  }
//
//  /**
//   * Converts string to "title" case.
//   *
//   * <p><b>Details:</b>  This method converts the first character of every run
//   * of letters in the given string (<var>s</var>) to upper case, making the
//   * string appear in "title" format.  For the purposes of conversion,
//   * apostrophes occuring immediately after letters are also treated as letters.
//   * This method may not be appropriate for some strings, particularly those
//   * containing Roman numerals and other words where more than one character
//   * should be capitalized.</p>
//   *
//   * <p>Examples:</p>
//   *
//   * <table>
//   *   <tr>
//   *     <td>MacDonald's</td>
//   *     <td>Macdonald's</td>
//   *   </tr>
//   *   <tr>
//   *     <td>yo-yos</td>
//   *     <td>Yo-Yos</td>
//   *   </tr>
//   *   <tr>
//   *     <td>part</td>
//   *     <td>Part</td>
//   *   </tr>
//   *   <tr>
//   *     <td>III</td>
//   *     <td>Iii</td>
//   *   </tr>
//   * </table>
//   *
//   * @param s the string to convert
//   * @return the converted string
//   *
//   * @since 2000.01.15
//   */
//  public static String toInitialCaps(String s)
//  {
//    StringBuffer buff = new StringBuffer();
//    boolean space = true;
//    int length = s.length();
//    for (int i = 0; i < length; ++ i)
//    {
//      char c = s.charAt(i);
//      if (space)
//        c = Character.toUpperCase(c);
//      else
//        c = Character.toLowerCase(c);
//      switch (c)
//      {
//        case '\'':
//          break;
//        default:
//          space = ! Character.isLetter(c);
//      }
//      buff.append(c);
//    }
//    return buff.toString();
//  }
//
//  /**
//   * Trims characters from both ends of string.
//   *
//   * <p><b>Details:</b> <code>trim</code> removes the given character
//   * (<var>c</var>) from both ends of the given string (<var>s</var>).  For
//   * example, the call</p>
//   *
//   * <blockquote><code>
//   *   trimTrailing ("sizes", 's')
//   * </code></blockquote>
//   *
//   * <p>returns the string "<tt>ize</tt>".</p>
//   *
//   * @param s the string to edit
//   * @param n the character to trim
//   * @return the trimmed string
//   */
//  public static String trim(String s, char c)
//  {
//    final int length = s.length();
//    int start;
//    for (start = 0; start < length; ++ start)
//      if (s.charAt(start) != c)
//        break;
//    int stop;
//    for (stop = length; stop > start; -- stop)
//      if (s.charAt(stop - 1) != c)
//        break;
//    return s.substring(start, stop);
//  }
//
//  /**
//   * Trims trailing characters.
//   *
//   * <p><b>Details:</b> <code>trimTrailing</code> trims the specified character
//   * (<var>c</var>) from the end of the given string (<var>s</var>) if the
//   * string ends with one or more repetitions of that character.  For example,
//   * the call</p>
//   *
//   * <blockquote><code>
//   *   removeTrailing("Tennessee", 'e')
//   * </code></blockquote>
//   *
//   * <p>returns the string "<tt>Tenness</tt>".</p>
//   *
//   * @param s the string to edit
//   * @param c the trailing character to remove
//   * @return a new string with the trailing characters removed
//   */
//  public static String trimTrailing(String s, char c)
//  {
//    int i;
//    for (i = s.length(); i > 0; -- i)
//      if (s.charAt(i - 1) != c)
//        break;
//    return s.substring(0, i);
//  }
//
//  /**
//   * Trims leading characters.
//   *
//   * <p><b>Details:</b> <code>trimLeading</code> trims occurances of the
//   * specified character (<var>ic</var>) from the beginning of the given string
//   * (<var>is</var>) if the string begins with one or more repetitions of that
//   * character.  For example, the call</p>
//   *
//   * <blockquote><code>
//   *   removeLeading ("eery", 'e')
//   * </code></blockquote>
//   *
//   * <p>returns the string "<tt>ry</tt>".</p>
//   *
//   * @param is the string to edit
//   * @param ic the leading character to remove
//   * @return a new string with the leading characters removed
//   *
//   * @since 2001.09.08
//   */
//  public static String trimLeading(String is, char ic)
//  {
//    int vnI;
//    final int vnL = is.length();
//    for (vnI = 0; vnI < vnL; ++ vnI)
//    {
//      if (is.charAt(vnI) != ic)
//        break;
//    }
//    return is.substring(vnI);
//  }
//
//  /**
//   * Determines if string looks like an email address.
//   *
//   * <p><b>Details:</b>  <code>looksLikeAnEmailAddress</code> analyzes the given
//   * string (<var>s</var>) and determines whether it looks like an email
//   * address.  If it does, <code>looksLikeAnEmailAddress</code> returns
//   * <code>true</code>, <code>false</code> otherwise.</p>
//   *
//   * <p>See {@link com.sharkysoft.io.StreamParser#tryEmailAddress()
//   * <code>com.sharkysoft.io.StreamParser.tryEmailAddress</code>} for more
//   * information on the forms of email addresses accepted by this function.</p>
//   *
//   * @param s the string to test
//   * @return true iff s looks like an email address
//   *
//   * @since 2000.12.21
//   */
//  public static boolean looksLikeAnEmailAddress(String s)
//  {
//    UnlimitedPushbackReader upr = null;
//    try
//    {
//      upr = new UnlimitedPushbackReader(new StringReader(s));
//      return s.equals(StreamParser.tryEmailAddress(upr));
//    }
//    catch (IOException e)
//    {
//      throw new UnreachableCodeException("looksLikeAnEmailAddress puked with s=" + s);
//    }
//    finally
//    {
//      IoCloser.close(upr);
//    }
//  }

}

