package ch.deletescape.primitives;

import ch.deletescape.primitives.arrays.PrCharArray;

/**
 * Technically String isn't a primitive type, but it is used almost the same way.
 * 
 * @author deletescape
 */
public final class PrString {
  private static final char[] FORMAT_TOKEN = new char[] { '{', '}' };
  private static final int TOKEN_LENGTH = FORMAT_TOKEN.length;
  private static final char[] FORMAT_NULL_REPLACEMENT = new char[] { 'n', 'u', 'l', 'l' };

  /**
   * Private Constructor to prevent initialization
   */
  private PrString() {}

  /**
   * Reverses all chars in a String. For example reversing {@code "Test"} would result in
   * {@code "tseT"}.
   * 
   * @param str
   *          the String to be reversed
   * @return the reversed version of {@code str} or {@code null} if {@code str} is {@code null}.
   */
  public static String reverse(String str) {
    if (str == null || str.isEmpty()) {
      return str;
    }
    char[] ca = str.toCharArray();
    final int maxIdx = ca.length - 1;
    for (int i = 0; i <= maxIdx / 2; i++) {
      char c = ca[i];
      ca[i] = ca[maxIdx - i];
      ca[maxIdx - i] = c;
    }
    return new String(ca);
  }

  // following TODOs need to be done before making this a public api method
  // TODO: Throw exceptions in illegal cases (see TODOs in Test)
  static String simpleFormat(String format, Object... elements) {
    if (elements == null) {
      return format;
    }
    // Working with a char array is better for performance than working with a String
    char[] str = format.toCharArray();
    int lastIndex = 0;
    for (Object element : elements) {
      int idx = PrCharArray.findSequence(lastIndex, str, FORMAT_TOKEN);
      if (idx == -1) {
        throw new SimpleFormatException(simpleFormat("Too many elements supplied for \"{}\"", format));
      }
      // Replace null values with the string "null" which is a char[] for performance reasons
      char[] eStr = element != null ? element.toString().toCharArray() : FORMAT_NULL_REPLACEMENT;
      // We want to trim away the {} token, so we subtract it from the format strings total length
      int lenArr = str.length - TOKEN_LENGTH;
      int lenIns = eStr.length;
      // A Temporary array of the required size is created
      char[] arr = new char[lenArr + lenIns];
      // Here we take the first part of our original format string and place it in the temp array
      System.arraycopy(str, 0, arr, 0, idx);
      // Placing the replacement at the index of our token
      System.arraycopy(eStr, 0, arr, idx, lenIns);
      // Adding the end of the format string back to our new string, trimming away the {} sequence
      System.arraycopy(str, idx + TOKEN_LENGTH, arr, idx + lenIns, lenArr - idx);
      // Reassigning the value of our temp array to our original array
      str = arr;
      lastIndex = idx + lenIns;
    }
    if (PrCharArray.findSequence(lastIndex, str, FORMAT_TOKEN) != -1) {
      throw new SimpleFormatException(simpleFormat("Not enough elements supplied for \"{}\"", format));
    }
    return new String(str);
  }

}

@@ -1174,211 +1174,1000 @@
 %0A  /
-/ following TODOs need to be done before making this a public api method%0A  // TODO: Throw exceptions in illegal cases (see TODOs in Test)%0A  static String simpleFormat(String format, Object... elements) %7B
+**%0A   * This is a simple and fast alternative to %7B@link String#format(String, Object...)%7D, formatting%0A   * works by replacing %22%7B%7D%22 tokens with the supplied elements. %22Hello %7B%7D!%22 and a element %22World%22%0A   * would result in %22Hello World!%22. Elements with null values are replaced by the String %22null%22%0A   * %0A   * @param format%0A   *          a formatting string following the described syntax%0A   * @param elements%0A   *          the elements to be used as replacements for formatting tokens by invoking%0A   *          %7B@code toString()%7D on them.%0A   * @return a formatted String.%0A   * @throws SimpleFormatException%0A   *           if there are either too many or not enough elements for the number of formatting%0A   *           tokens%0A   */%0A  public static String simpleFormat(String format, Object... elements) %7B%0A    // We simply return the format string if we have no elements at all%0A    // TODO: This should be improved to also check if there are any formatting tokens inside the%0A    // format string
 %0A   
@@ -2476,16 +2476,138 @@
 TOKEN);%0A
+      // If there are still elements left but no more formatting tokens can be found there are too%0A      // many elements%0A
       if
@@ -3739,39 +3739,242 @@
     
-lastIndex = idx + lenIns;%0A    %7D
+// We need a way to save how much of the string we have processed already%0A      lastIndex = idx + lenIns;%0A    %7D%0A    // If we end up here with the end of the string still containing formatting tokens there aren't%0A    // enough elements
 %0A   

Make PrString#simpleFormat a part of the public api