[slf4j-dev] svn commit: r1112 - in slf4j/trunk: slf4j-api/src/main/java/org/slf4j/helpers slf4j-api/src/test/java/org/slf4j/helpers slf4j-ext slf4j-site/src/site/pages

ceki at slf4j.org ceki at slf4j.org
Mon Aug 18 17:37:10 CEST 2008


Author: ceki
Date: Mon Aug 18 17:37:09 2008
New Revision: 1112

Modified:
   slf4j/trunk/slf4j-api/src/main/java/org/slf4j/helpers/MessageFormatter.java
   slf4j/trunk/slf4j-api/src/test/java/org/slf4j/helpers/MessageFormatterTest.java
   slf4j/trunk/slf4j-ext/   (props changed)
   slf4j/trunk/slf4j-site/src/site/pages/faq.html
   slf4j/trunk/slf4j-site/src/site/pages/news.html

Log:
Parameter substitution code has been simplified. SLF4J now only
cares about the "{}" formatting anchor, that is the '{' character
immediately followed by '}'. Previously, the '{' had meaning on its
own. As a result of this change, users no longer need to escape the
'{' unless it is immediately followed by '}'. Existing messages
which escaped standalone '{' character will be printed with a
preceding backslash. However, no data loss in the printed messages
will occur.

The new code also runs about 5% faster.

Modified: slf4j/trunk/slf4j-api/src/main/java/org/slf4j/helpers/MessageFormatter.java
==============================================================================
--- slf4j/trunk/slf4j-api/src/main/java/org/slf4j/helpers/MessageFormatter.java	(original)
+++ slf4j/trunk/slf4j-api/src/main/java/org/slf4j/helpers/MessageFormatter.java	Mon Aug 18 17:37:09 2008
@@ -35,9 +35,7 @@
  * <p>
  * For example,
  * 
- * <pre>
- * MessageFormatter.format(&quot;Hi {}.&quot;, &quot;there&quot;);
- * </pre>
+ * <pre>MessageFormatter.format(&quot;Hi {}.&quot;, &quot;there&quot;)</pre>
  * 
  * will return the string "Hi there.".
  * <p>
@@ -45,18 +43,28 @@
  * designate the location where arguments need to be substituted within the
  * message pattern.
  * <p>
- * In the rare case where you need to place the '{' or '}' in the message
- * pattern itself but do not want them to be interpreted as a formatting
- * anchors, you can escape the '{' character with '\', that is the backslash
- * character. Only the '{' character should be escaped. There is no need to
- * escape the '}' character. For example,
+ * In case your message contains the '{' or the '}' character, you do not have
+ * to do anything special unless the '}' character immediately follows '}'. For
+ * example,
  * 
  * <pre>
- * MessageFormatter.format(&quot;Set \\{1,2,3} is not equal to {}.&quot;, &quot;1,2&quot;);
+ * MessageFormatter.format(&quot;Set {1,2,3} is not equal to {}.&quot;, &quot;1,2&quot;);
  * </pre>
  * 
  * will return the string "Set {1,2,3} is not equal to 1,2.".
  * 
+ * <p>If for whatever reason you need to place the string "{}" in the message
+ * without its <em>formatting anchor</em> meaning, then you need to escape the
+ * '{' character with '\', that is the backslash character. Only the '{'
+ * character should be escaped. There is no need to escape the '}' character.
+ * For example,
+ * 
+ * <pre>
+ * MessageFormatter.format(&quot;Set \\{} is not equal to {}.&quot;, &quot;1,2&quot;);
+ * </pre>
+ * 
+ * will return the string "Set {} is not equal to 1,2.".
+ * 
  * <p>
  * The escaping behavior just described can be overridden by escaping the escape
  * character '\'. Calling
@@ -73,9 +81,10 @@
  * 
  * @author Ceki G&uuml;lc&uuml;
  */
-public class MessageFormatter {
+final public class MessageFormatter {
   static final char DELIM_START = '{';
   static final char DELIM_STOP = '}';
+  static final String DELIM_STR = "{}";
   private static final char ESCAPE_CHAR = '\\';
 
   /**
@@ -98,7 +107,7 @@
    *                anchor
    * @return The formatted message
    */
-  public static String format(String messagePattern, Object arg) {
+  final public static String format(String messagePattern, Object arg) {
     return arrayFormat(messagePattern, new Object[] { arg });
   }
 
@@ -125,7 +134,7 @@
    *                formatting anchor
    * @return The formatted message
    */
-  public static String format(String messagePattern, Object arg1, Object arg2) {
+  final public static String format(final String messagePattern, Object arg1, Object arg2) {
     return arrayFormat(messagePattern, new Object[] { arg1, arg2 });
   }
 
@@ -141,25 +150,23 @@
    *                formatting anchors
    * @return The formatted message
    */
-  public static String arrayFormat(String messagePattern, Object[] argArray) {
+  final public static String arrayFormat(final String messagePattern,
+      final Object[] argArray) {
     if (messagePattern == null) {
       return null;
     }
-    int i = 0;
-    int len = messagePattern.length();
-    int j = messagePattern.indexOf(DELIM_START);
-
     if (argArray == null) {
       return messagePattern;
     }
-
+    int i = 0;
+    int j;
     StringBuffer sbuf = new StringBuffer(messagePattern.length() + 50);
 
     for (int L = 0; L < argArray.length; L++) {
 
-      j = messagePattern.indexOf(DELIM_START, i);
+      j = messagePattern.indexOf(DELIM_STR, i);
 
-      if (j == -1 || (j + 1 == len)) {
+      if (j == -1) {
         // no more variables
         if (i == 0) { // this is a simple string
           return messagePattern;
@@ -169,8 +176,6 @@
           return sbuf.toString();
         }
       } else {
-        char delimStop = messagePattern.charAt(j + 1);
-
         if (isEscapedDelimeter(messagePattern, j)) {
           if (!isDoubleEscaped(messagePattern, j)) {
             L--; // DELIM_START was escaped, thus should not be incremented
@@ -183,13 +188,8 @@
             // we have to consume one backward slash
             sbuf.append(messagePattern.substring(i, j - 1));
             deeplyAppendParameter(sbuf, argArray[L], new HashMap());
-            // sbuf.append(argArray[L]);
             i = j + 2;
           }
-        } else if ((delimStop != DELIM_STOP)) {
-          // invalid DELIM_START/DELIM_STOP pair
-          sbuf.append(messagePattern.substring(i, messagePattern.length()));
-          return sbuf.toString();
         } else {
           // normal case
           sbuf.append(messagePattern.substring(i, j));
@@ -203,7 +203,7 @@
     return sbuf.toString();
   }
 
-  static boolean isEscapedDelimeter(String messagePattern,
+  final static boolean isEscapedDelimeter(String messagePattern,
       int delimeterStartIndex) {
 
     if (delimeterStartIndex == 0) {
@@ -217,7 +217,7 @@
     }
   }
 
-  static boolean isDoubleEscaped(String messagePattern, int delimeterStartIndex) {
+  final static boolean isDoubleEscaped(String messagePattern, int delimeterStartIndex) {
     if (delimeterStartIndex >= 2
         && messagePattern.charAt(delimeterStartIndex - 2) == ESCAPE_CHAR) {
       return true;

Modified: slf4j/trunk/slf4j-api/src/test/java/org/slf4j/helpers/MessageFormatterTest.java
==============================================================================
--- slf4j/trunk/slf4j-api/src/test/java/org/slf4j/helpers/MessageFormatterTest.java	(original)
+++ slf4j/trunk/slf4j-api/src/test/java/org/slf4j/helpers/MessageFormatterTest.java	Mon Aug 18 17:37:09 2008
@@ -100,19 +100,19 @@
     result = MessageFormatter.format("Incorrect {subst", i3);
     assertEquals("Incorrect {subst", result);
 
-    result = MessageFormatter.format("Value is \\{bla} {}", i3);
+    result = MessageFormatter.format("Value is {bla} {}", i3);
     assertEquals("Value is {bla} 3", result);
 
     result = MessageFormatter.format("Escaped \\{} subst", i3);
     assertEquals("Escaped {} subst", result);
 
-    result = MessageFormatter.format("\\{Escaped", i3);
+    result = MessageFormatter.format("{Escaped", i3);
     assertEquals("{Escaped", result);
 
     result = MessageFormatter.format("\\{}Escaped", i3);
     assertEquals("{}Escaped", result);
 
-    result = MessageFormatter.format("File name is \\{{}}.", "App folder.zip");
+    result = MessageFormatter.format("File name is {{}}.", "App folder.zip");
     assertEquals("File name is {App folder.zip}.", result);
 
     // escaping the escape character
@@ -147,7 +147,7 @@
     assertEquals("Value 1 is smaller than \\{", result);
 
     result = MessageFormatter
-        .format("Value {} is smaller than \\{tail", i1, i2);
+        .format("Value {} is smaller than {tail", i1, i2);
     assertEquals("Value 1 is smaller than {tail", result);
 
     result = MessageFormatter.format("Value \\{} is smaller than {}", i1, i2);
@@ -195,9 +195,9 @@
     assertEquals("Value 1 is smaller than 2", result);
 
     result = MessageFormatter.arrayFormat("Val={}, {, Val={}", ia0);
-    assertEquals("Val=1, {, Val={}", result);
+    assertEquals("Val=1, {, Val=2", result);
 
-    result = MessageFormatter.arrayFormat("Val={}, \\{, Val={}", ia0);
+    result = MessageFormatter.arrayFormat("Val={}, {, Val={}", ia0);
     assertEquals("Val=1, {, Val=2", result);
 
     result = MessageFormatter.arrayFormat("Val1={}, Val2={", ia0);

Modified: slf4j/trunk/slf4j-site/src/site/pages/faq.html
==============================================================================
--- slf4j/trunk/slf4j-site/src/site/pages/faq.html	(original)
+++ slf4j/trunk/slf4j-site/src/site/pages/faq.html	Mon Aug 18 17:37:09 2008
@@ -615,8 +615,7 @@
        disabled.
        </p>
        
- 
-       <p>The following two lines will yield the exact same
+        <p>The following two lines will yield the exact same
        output. However, the second form will outperform the first
        form by a factor of at least 30, in case of a
        <em>disabled</em> logging statement.
@@ -644,18 +643,59 @@
         <p></p> 
 
         <p>Array type arguments, including multi-dimensional arrays,
-        are also supported. </p>
-        
+        are also supported.</p>
+
         <p>SLF4J uses its own message formatting implementation which
         differs from that of the Java platform. This is justified by
-        the fact that SLF4J's implementation performs several orders
-        of magnitude faster but at the cost of being non-standard and
-        less flexible.
+        the fact that SLF4J's implementation performs about 10 times
+        faster but at the cost of being non-standard and less
+        flexible.
+        </p>
+
+        <p><b>Escaping the "{}" pair</b></p>
+
+        <p>The "{}" pair is called the <em>formatting anchor</em>. It
+        serves to designate the location where arguments need to be
+        substituted within the message pattern.
         </p>
 
-        <p>
+        <p>SLF4J only cares about the <em>formatting anchor</em>, that
+        is the '{' character immediately followed by '}'. Thus, in
+        case your message contains the '{' or the '}' character, you
+        do not have to do anything special unless the '}' character
+        immediately follows '}'. For example,
         </p>
 
+        <p class="source">logger.debug("Set {1,2} differs from {}", "3");</p>
+        
+        <p>which will print as "Set {1,2} differs from 3". </p>
+        
+        <p>You could have even written,</p>
+        <p class="source">logger.debug("Set {1,2} differs from {{}}", "3");</p>
+        <p>which would have printed as "Set {1,2} differs from {3}". </p>
+
+        <p>In the extremely rare case where the the "{}" pair occurs
+        naturally within your text and you wish to disable the special
+        meaning of the formatting anchor, then you need to escape the
+        '{' character with '\', that is the backslash character. Only
+        the '{' character should be escaped. There is no need to
+        escape the '}' character. For example,
+        </p>
+
+        <p class="source">logger.debug("Set \\{} differs from {}", "3");</p>
+ 
+        <p>will print as "Set {} differs from 3". Note that within
+        Java code, the backslash cracacter needs to be written as
+        '\\'.</p>
+
+        <p>In the rare case where the "\{}' occurs naturally in the
+        message, you can double escape the formatting anchor so that
+        it retains its original meaning. For example,</p>
+
+        
+        <p class="source">logger.debug("File name is C:\\\\{}.", "file.zip");</p>
+        <p>will print as "File name is C:\file.zip".</p>
+
         <hr />
              
         </dd>

Modified: slf4j/trunk/slf4j-site/src/site/pages/news.html
==============================================================================
--- slf4j/trunk/slf4j-site/src/site/pages/news.html	(original)
+++ slf4j/trunk/slf4j-site/src/site/pages/news.html	Mon Aug 18 17:37:09 2008
@@ -62,6 +62,16 @@
   previously. This enhancement was proposed by "lizongbo".
   </p>
 
+  <p>Parameter substitution code has been simplified. SLF4J now only
+  cares about the "{}" formatting anchor, that is the '{' character
+  immediately followed by '}'. Previously, the '{' had meaning on its
+  own. As a result of this change, users no longer need to escape the
+  '{' unless it is immediately followed by '}'. Existing messages
+  which escaped standalone '{' character will be printed with a
+  preceding backslash. However, no data loss in the printed messages
+  will occur.
+  </p>
+
 
   <p>Added missing <code>getInstance</code> methods to the
   <code>Category</code> class in the log4j-over-slf4j module, fixing



More information about the slf4j-dev mailing list