Please review the following patch to add the missing codePoint-related
methods to StringBuilder/StringBuffer (there is also a small javadoc
correction in Character).  I needed these methods in the UCD branch and we
had an oustanding item to add these for 1.6, so I went ahead and ported them
to the current trunk.

One issue:  appendCodepoint() essentially inlines Character.toChars() for
efficiency -- it seemed appropriate given the lengths we went to for
efficiency in this code anyway.

Finally, it looks like we are not testing StringBuilder at all -- since
StringBuffer no longer delegates to StringBuilder, I think it needs to be
tested as well to make sure no cut-and-paste error slips in.  A related
question -- would it not be better to have code generate one version from
the other rather than rely on manually keeping them in sync?

-- 
John A. Tamplin
Software Engineer (GWT), Google

--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---

Index: user/test/com/google/gwt/emultest/java/lang/StringBufferTest.java
===================================================================
--- user/test/com/google/gwt/emultest/java/lang/StringBufferTest.java	(revision 3626)
+++ user/test/com/google/gwt/emultest/java/lang/StringBufferTest.java	(working copy)
@@ -27,6 +27,7 @@
    * @return the module name.
    * @see com.google.gwt.junit.client.GWTTestCase#getModuleName()
    */
+  @Override
   public String getModuleName() {
     return "com.google.gwt.emultest.EmulSuite";
   }
@@ -91,6 +92,34 @@
   }
 
   /**
+   * Test the various codePoint-related methods.
+   */
+  public void testCodepoint() {
+    StringBuffer buf = new StringBuffer();
+    buf.appendCodePoint('C');
+    buf.appendCodePoint(67328);
+    buf.append('T');
+    assertEquals("C\uD801\uDF00T", buf.toString());
+    assertEquals('C', buf.codePointAt(0));
+    assertEquals(67328, buf.codePointAt(1));
+    assertEquals(0xDF00, buf.codePointAt(2));
+    assertEquals('T', buf.codePointAt(3));
+    assertEquals('C', buf.codePointBefore(1));
+    assertEquals(0xD801, buf.codePointBefore(2));
+    assertEquals(67328, buf.codePointBefore(3));
+    assertEquals('T', buf.codePointBefore(4));
+    assertEquals(3, buf.codePointCount(0, 4));
+    assertEquals(2, buf.codePointCount(0, 3));
+    assertEquals(2, buf.codePointCount(0, 2));
+    assertEquals(1, buf.codePointCount(1, 3));
+    assertEquals(1, buf.offsetByCodePoints(0, 1));
+    assertEquals(3, buf.offsetByCodePoints(1, 1));
+    assertEquals(3, buf.offsetByCodePoints(0, 2));
+    assertEquals(1, buf.offsetByCodePoints(3, -1));
+    assertEquals(0, buf.offsetByCodePoints(1, -1));
+  }
+
+  /**
    * This method tests string creation and equality.
    */
   public void testContructor() {
@@ -350,6 +379,7 @@
 
     bld = new StringBuilder();
     bld.append(new Object() {
+      @Override
       public String toString() {
         return "obj";
       }
@@ -440,6 +470,7 @@
 
     bld = new StringBuilder("01234");
     bld.insert(2, new Object() {
+      @Override
       public String toString() {
         return "obj";
       }
Index: user/super/com/google/gwt/emul/java/lang/StringBuffer.java
===================================================================
--- user/super/com/google/gwt/emul/java/lang/StringBuffer.java	(revision 3626)
+++ user/super/com/google/gwt/emul/java/lang/StringBuffer.java	(working copy)
@@ -121,6 +121,21 @@
     return this;
   }
 
+  public StringBuffer appendCodePoint(int codePoint) {
+    if (codePoint < 0 || codePoint > Character.MAX_CODE_POINT) {
+      throw new IllegalArgumentException();
+    }
+    if (codePoint >= Character.MIN_SUPPLEMENTARY_CODE_POINT) {
+      impl.appendNonNull(data, String.valueOf(
+          Character.getHighSurrogate(codePoint)));
+      impl.appendNonNull(data, String.valueOf(
+          Character.getLowSurrogate(codePoint)));
+    } else {
+      impl.appendNonNull(data, String.valueOf((char) codePoint));
+    }
+    return this;
+  }
+
   /**
    * This implementation does not track capacity; always returns
    * [EMAIL PROTECTED] Integer#MAX_VALUE}.
@@ -133,6 +148,18 @@
     return toString().charAt(index);
   }
 
+  public int codePointAt(int index) {
+    return toString().codePointAt(index);
+  }
+
+  public int codePointBefore(int index) {
+    return toString().codePointBefore(index);
+  }
+
+  public int codePointCount(int beginIndex, int endIndex) {
+    return toString().codePointCount(beginIndex, endIndex);
+  }
+
   public StringBuffer delete(int start, int end) {
     return replace(start, end, "");
   }
@@ -226,6 +253,10 @@
     return impl.length(data);
   }
 
+  public int offsetByCodePoints(int index, int codePointOffset) {
+    return toString().offsetByCodePoints(index, codePointOffset);
+  }
+
   public StringBuffer replace(int start, int end, String toInsert) {
     impl.replace(data, start, end, toInsert);
     return this;
Index: user/super/com/google/gwt/emul/java/lang/StringBuilder.java
===================================================================
--- user/super/com/google/gwt/emul/java/lang/StringBuilder.java	(revision 3626)
+++ user/super/com/google/gwt/emul/java/lang/StringBuilder.java	(working copy)
@@ -121,6 +121,21 @@
     return this;
   }
 
+  public StringBuilder appendCodePoint(int codePoint) {
+    if (codePoint < 0 || codePoint > Character.MAX_CODE_POINT) {
+      throw new IllegalArgumentException();
+    }
+    if (codePoint >= Character.MIN_SUPPLEMENTARY_CODE_POINT) {
+      impl.appendNonNull(data, String.valueOf(
+          Character.getHighSurrogate(codePoint)));
+      impl.appendNonNull(data, String.valueOf(
+          Character.getLowSurrogate(codePoint)));
+    } else {
+      impl.appendNonNull(data, String.valueOf((char) codePoint));
+    }
+    return this;
+  }
+
   /**
    * This implementation does not track capacity; always returns
    * [EMAIL PROTECTED] Integer#MAX_VALUE}.
@@ -133,6 +148,18 @@
     return toString().charAt(index);
   }
 
+  public int codePointAt(int index) {
+    return toString().codePointAt(index);
+  }
+
+  public int codePointBefore(int index) {
+    return toString().codePointBefore(index);
+  }
+
+  public int codePointCount(int beginIndex, int endIndex) {
+    return toString().codePointCount(beginIndex, endIndex);
+  }
+
   public StringBuilder delete(int start, int end) {
     return replace(start, end, "");
   }
@@ -226,6 +253,10 @@
     return impl.length(data);
   }
 
+  public int offsetByCodePoints(int index, int codePointOffset) {
+    return toString().offsetByCodePoints(index, codePointOffset);
+  }
+
   public StringBuilder replace(int start, int end, String toInsert) {
     impl.replace(data, start, end, toInsert);
     return this;
Index: user/super/com/google/gwt/emul/java/lang/Character.java
===================================================================
--- user/super/com/google/gwt/emul/java/lang/Character.java	(revision 3626)
+++ user/super/com/google/gwt/emul/java/lang/Character.java	(working copy)
@@ -412,7 +412,7 @@
 
   /**
    * Computes the high surrogate character of the UTF16 representation of a
-   * non-BMP code point. See [EMAIL PROTECTED] getLowSurrogate}.
+   * non-BMP code point. See [EMAIL PROTECTED] #getLowSurrogate}.
    * 
    * @param codePoint requested codePoint, required to be >=
    *          MIN_SUPPLEMENTARY_CODE_POINT
@@ -425,7 +425,7 @@
 
   /**
    * Computes the low surrogate character of the UTF16 representation of a
-   * non-BMP code point. See [EMAIL PROTECTED] getHighSurrogate}.
+   * non-BMP code point. See [EMAIL PROTECTED] #getHighSurrogate}.
    * 
    * @param codePoint requested codePoint, required to be >=
    *          MIN_SUPPLEMENTARY_CODE_POINT

Reply via email to