Optimize replaceNewLines() in EncodingUtil

Return input strings unchanged if no replacement is needed.
Do not create a StringBuilder if not needed.

Instead of appending char by char to the StringBuilder, copy the chunks
between replacements.

Change-Id: I14860db479a2b50d5232d97865b0b114311d53c1
diff --git a/bundles/org.eclipse.rap.rwt/src/org/eclipse/rap/rwt/internal/util/EncodingUtil.java b/bundles/org.eclipse.rap.rwt/src/org/eclipse/rap/rwt/internal/util/EncodingUtil.java
index 2da0161..f8830b7 100644
--- a/bundles/org.eclipse.rap.rwt/src/org/eclipse/rap/rwt/internal/util/EncodingUtil.java
+++ b/bundles/org.eclipse.rap.rwt/src/org/eclipse/rap/rwt/internal/util/EncodingUtil.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2002, 2012 Innoopract Informationssysteme GmbH and others.
+ * Copyright (c) 2002, 2015 Innoopract Informationssysteme GmbH and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -95,27 +95,30 @@
    * @return a copy of the input string with all newline characters replaced
    */
   public static String replaceNewLines( String input, String replacement ) {
-    StringBuilder resultBuffer = new StringBuilder();
+    StringBuilder resultBuffer = null;
     int length = input.length();
+    int start = 0;
     int i = 0;
     while( i < length ) {
       char ch = input.charAt( i );
-      if( ch == '\n' ) {
-        resultBuffer.append( replacement );
-      } else if( ch == '\r' ) {
-        if( i + 1 < length ) {
-          char next = input.charAt( i + 1 );
-          if( ch == '\r' && next == '\n' ) {
-            i++;
-          }
+      if( ch == '\n' || ch == '\r' ) {
+        if (resultBuffer == null) {
+          resultBuffer = new StringBuilder();
         }
+        resultBuffer.append( input, start, i );
         resultBuffer.append( replacement );
-      } else {
-        resultBuffer.append( ch );
+        if( ch == '\r' && i + 1 < length && input.charAt( i + 1 ) == '\n' ) {
+          i++;
+        }
+        start = i + 1;
       }
       i++;
     }
-    return resultBuffer.toString();
+    if (resultBuffer != null) {
+      resultBuffer.append( input, start, i );
+      return resultBuffer.toString();
+    }
+    return input;
   }
 
   /**
diff --git a/tests/org.eclipse.rap.rwt.test/src/org/eclipse/rap/rwt/internal/util/EncodingUtil_Test.java b/tests/org.eclipse.rap.rwt.test/src/org/eclipse/rap/rwt/internal/util/EncodingUtil_Test.java
index 39c02df..cfc7a0e 100644
--- a/tests/org.eclipse.rap.rwt.test/src/org/eclipse/rap/rwt/internal/util/EncodingUtil_Test.java
+++ b/tests/org.eclipse.rap.rwt.test/src/org/eclipse/rap/rwt/internal/util/EncodingUtil_Test.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2013 EclipseSource and others.
+ * Copyright (c) 2009, 2015 EclipseSource and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -11,6 +11,7 @@
 package org.eclipse.rap.rwt.internal.util;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 
 import java.util.Arrays;
@@ -35,25 +36,58 @@
   }
 
   @Test
-  public void testReplaceNewLines() {
+  public void testReplaceNewLines_emptyString() {
+    assertSame( "", EncodingUtil.replaceNewLines( "" ) );
+  }
+
+  @Test
+  public void testReplaceNewLines_withoutNewlines() {
+    assertSame( "foo bar", EncodingUtil.replaceNewLines( "foo bar" ) );
+  }
+
+  @Test
+  public void testReplaceNewLines_unixLineBreaks() {
     String stringToReplace = "First line.\nSecond line.\nThird line.";
     String expected = "First line.\\nSecond line.\\nThird line.";
     String result = EncodingUtil.replaceNewLines( stringToReplace );
-    assertEquals( expected, result );
 
-    stringToReplace = "First line.\rSecond line.\rThird line.";
-    expected = "First line.\\nSecond line.\\nThird line.";
-    result = EncodingUtil.replaceNewLines( stringToReplace );
     assertEquals( expected, result );
+  }
 
-    stringToReplace = "First line.\r\nSecond line.\r\nThird line.";
-    expected = "First line.\\nSecond line.\\nThird line.";
-    result = EncodingUtil.replaceNewLines( stringToReplace );
+  @Test
+  public void testReplaceNewLines_windowsLineBreaks() {
+    String stringToReplace = "First line.\r\nSecond line.\r\nThird line.";
+    String expected = "First line.\\nSecond line.\\nThird line.";
+    String result = EncodingUtil.replaceNewLines( stringToReplace );
+
     assertEquals( expected, result );
+  }
 
-    stringToReplace = "First line.\r\nSecond line.\r\nThird line.";
-    expected = "First line. Second line. Third line.";
-    result = EncodingUtil.replaceNewLines( stringToReplace, " " );
+  @Test
+  public void testReplaceNewLines_oldMacLineBreaks() {
+    String stringToReplace = "First line.\rSecond line.\rThird line.";
+    String expected = "First line.\\nSecond line.\\nThird line.";
+    String result = EncodingUtil.replaceNewLines( stringToReplace );
+
+    assertEquals( expected, result );
+  }
+
+  @Test
+  public void testReplaceNewLines_edgeCases() {
+    assertEquals( "\\nfoo", EncodingUtil.replaceNewLines( "\nfoo" ) );
+    assertEquals( "\\nfoo", EncodingUtil.replaceNewLines( "\r\nfoo" ) );
+    assertEquals( "foo\\n", EncodingUtil.replaceNewLines( "foo\n" ) );
+    assertEquals( "foo\\n", EncodingUtil.replaceNewLines( "foo\r\n" ) );
+    assertEquals( "\\n", EncodingUtil.replaceNewLines( "\n" ) );
+    assertEquals( "\\n", EncodingUtil.replaceNewLines( "\r\n" ) );
+  }
+
+  @Test
+  public void testReplaceNewLines_withReplacement() {
+    String stringToReplace = "First line.\r\nSecond line.\r\nThird line.";
+    String expected = "First line. Second line. Third line.";
+    String result = EncodingUtil.replaceNewLines( stringToReplace, " " );
+
     assertEquals( expected, result );
   }