Loading core/java/android/net/Uri.java +8 −105 Original line number Diff line number Diff line Loading @@ -19,12 +19,10 @@ package android.net; import android.os.Parcel; import android.os.Parcelable; import android.util.Log; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.io.ByteArrayOutputStream; import java.net.URLEncoder; import java.nio.charset.Charsets; import java.util.AbstractList; import java.util.ArrayList; import java.util.Collections; Loading @@ -32,6 +30,7 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.RandomAccess; import java.util.Set; import libcore.net.UriCodec; /** * Immutable URI reference. A URI reference includes a URI and a fragment, the Loading Loading @@ -1681,7 +1680,8 @@ public abstract class Uri implements Parcelable, Comparable<Uri> { if (separator == end) { return ""; } else { return decode(query.substring(separator + 1, end)); String encodedValue = query.substring(separator + 1, end); return UriCodec.decode(encodedValue, true, Charsets.UTF_8, false); } } Loading Loading @@ -1877,9 +1877,6 @@ public abstract class Uri implements Parcelable, Comparable<Uri> { || (allow != null && allow.indexOf(c) != NOT_FOUND); } /** Unicode replacement character: \\uFFFD. */ private static final byte[] REPLACEMENT = { (byte) 0xFF, (byte) 0xFD }; /** * Decodes '%'-escaped octets in the given string using the UTF-8 scheme. * Replaces invalid octets with the unicode replacement character Loading @@ -1890,104 +1887,10 @@ public abstract class Uri implements Parcelable, Comparable<Uri> { * s is null */ public static String decode(String s) { /* Compared to java.net.URLEncoderDecoder.decode(), this method decodes a chunk at a time instead of one character at a time, and it doesn't throw exceptions. It also only allocates memory when necessary--if there's nothing to decode, this method won't do much. */ if (s == null) { return null; } // Lazily-initialized buffers. StringBuilder decoded = null; ByteArrayOutputStream out = null; int oldLength = s.length(); // This loop alternates between copying over normal characters and // escaping in chunks. This results in fewer method calls and // allocations than decoding one character at a time. int current = 0; while (current < oldLength) { // Start in "copying" mode where we copy over normal characters. // Find the next escape sequence. int nextEscape = s.indexOf('%', current); if (nextEscape == NOT_FOUND) { if (decoded == null) { // We didn't actually decode anything. return s; } else { // Append the remainder and return the decoded string. decoded.append(s, current, oldLength); return decoded.toString(); } } // Prepare buffers. if (decoded == null) { // Looks like we're going to need the buffers... // We know the new string will be shorter. Using the old length // may overshoot a bit, but it will save us from resizing the // buffer. decoded = new StringBuilder(oldLength); out = new ByteArrayOutputStream(4); } else { // Clear decoding buffer. out.reset(); } // Append characters leading up to the escape. if (nextEscape > current) { decoded.append(s, current, nextEscape); current = nextEscape; } else { // assert current == nextEscape } // Switch to "decoding" mode where we decode a string of escape // sequences. // Decode and append escape sequences. Escape sequences look like // "%ab" where % is literal and a and b are hex digits. try { do { if (current + 2 >= oldLength) { // Truncated escape sequence. out.write(REPLACEMENT); } else { int a = Character.digit(s.charAt(current + 1), 16); int b = Character.digit(s.charAt(current + 2), 16); if (a == -1 || b == -1) { // Non hex digits. out.write(REPLACEMENT); } else { // Combine the hex digits into one byte and write. out.write((a << 4) + b); } } // Move passed the escape sequence. current += 3; } while (current < oldLength && s.charAt(current) == '%'); // Decode UTF-8 bytes into a string and append it. decoded.append(out.toString(DEFAULT_ENCODING)); } catch (UnsupportedEncodingException e) { throw new AssertionError(e); } catch (IOException e) { throw new AssertionError(e); } } // If we don't have a buffer, we didn't have to decode anything. return decoded == null ? s : decoded.toString(); return UriCodec.decode(s, false, Charsets.UTF_8, false); } /** Loading core/tests/coretests/src/android/net/UriTest.java +9 −5 Original line number Diff line number Diff line Loading @@ -16,17 +16,15 @@ package android.net; import android.net.Uri; import android.content.ContentUris; import android.os.Parcel; import android.test.suitebuilder.annotation.SmallTest; import junit.framework.TestCase; import java.io.File; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Set; import junit.framework.TestCase; public class UriTest extends TestCase { Loading Loading @@ -748,4 +746,10 @@ public class UriTest extends TestCase { assertEquals(Arrays.asList("a", "", ""), Uri.parse("http://foo/path?abc=a&abc=&abc=").getQueryParameters("abc")); } // http://code.google.com/p/android/issues/detail?id=21064 public void testPlusCharacterInQuery() { assertEquals("d e", Uri.parse("http://a/b?c=d%20e").getQueryParameter("c")); assertEquals("d e", Uri.parse("http://a/b?c=d+e").getQueryParameter("c")); } } Loading
core/java/android/net/Uri.java +8 −105 Original line number Diff line number Diff line Loading @@ -19,12 +19,10 @@ package android.net; import android.os.Parcel; import android.os.Parcelable; import android.util.Log; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.io.ByteArrayOutputStream; import java.net.URLEncoder; import java.nio.charset.Charsets; import java.util.AbstractList; import java.util.ArrayList; import java.util.Collections; Loading @@ -32,6 +30,7 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.RandomAccess; import java.util.Set; import libcore.net.UriCodec; /** * Immutable URI reference. A URI reference includes a URI and a fragment, the Loading Loading @@ -1681,7 +1680,8 @@ public abstract class Uri implements Parcelable, Comparable<Uri> { if (separator == end) { return ""; } else { return decode(query.substring(separator + 1, end)); String encodedValue = query.substring(separator + 1, end); return UriCodec.decode(encodedValue, true, Charsets.UTF_8, false); } } Loading Loading @@ -1877,9 +1877,6 @@ public abstract class Uri implements Parcelable, Comparable<Uri> { || (allow != null && allow.indexOf(c) != NOT_FOUND); } /** Unicode replacement character: \\uFFFD. */ private static final byte[] REPLACEMENT = { (byte) 0xFF, (byte) 0xFD }; /** * Decodes '%'-escaped octets in the given string using the UTF-8 scheme. * Replaces invalid octets with the unicode replacement character Loading @@ -1890,104 +1887,10 @@ public abstract class Uri implements Parcelable, Comparable<Uri> { * s is null */ public static String decode(String s) { /* Compared to java.net.URLEncoderDecoder.decode(), this method decodes a chunk at a time instead of one character at a time, and it doesn't throw exceptions. It also only allocates memory when necessary--if there's nothing to decode, this method won't do much. */ if (s == null) { return null; } // Lazily-initialized buffers. StringBuilder decoded = null; ByteArrayOutputStream out = null; int oldLength = s.length(); // This loop alternates between copying over normal characters and // escaping in chunks. This results in fewer method calls and // allocations than decoding one character at a time. int current = 0; while (current < oldLength) { // Start in "copying" mode where we copy over normal characters. // Find the next escape sequence. int nextEscape = s.indexOf('%', current); if (nextEscape == NOT_FOUND) { if (decoded == null) { // We didn't actually decode anything. return s; } else { // Append the remainder and return the decoded string. decoded.append(s, current, oldLength); return decoded.toString(); } } // Prepare buffers. if (decoded == null) { // Looks like we're going to need the buffers... // We know the new string will be shorter. Using the old length // may overshoot a bit, but it will save us from resizing the // buffer. decoded = new StringBuilder(oldLength); out = new ByteArrayOutputStream(4); } else { // Clear decoding buffer. out.reset(); } // Append characters leading up to the escape. if (nextEscape > current) { decoded.append(s, current, nextEscape); current = nextEscape; } else { // assert current == nextEscape } // Switch to "decoding" mode where we decode a string of escape // sequences. // Decode and append escape sequences. Escape sequences look like // "%ab" where % is literal and a and b are hex digits. try { do { if (current + 2 >= oldLength) { // Truncated escape sequence. out.write(REPLACEMENT); } else { int a = Character.digit(s.charAt(current + 1), 16); int b = Character.digit(s.charAt(current + 2), 16); if (a == -1 || b == -1) { // Non hex digits. out.write(REPLACEMENT); } else { // Combine the hex digits into one byte and write. out.write((a << 4) + b); } } // Move passed the escape sequence. current += 3; } while (current < oldLength && s.charAt(current) == '%'); // Decode UTF-8 bytes into a string and append it. decoded.append(out.toString(DEFAULT_ENCODING)); } catch (UnsupportedEncodingException e) { throw new AssertionError(e); } catch (IOException e) { throw new AssertionError(e); } } // If we don't have a buffer, we didn't have to decode anything. return decoded == null ? s : decoded.toString(); return UriCodec.decode(s, false, Charsets.UTF_8, false); } /** Loading
core/tests/coretests/src/android/net/UriTest.java +9 −5 Original line number Diff line number Diff line Loading @@ -16,17 +16,15 @@ package android.net; import android.net.Uri; import android.content.ContentUris; import android.os.Parcel; import android.test.suitebuilder.annotation.SmallTest; import junit.framework.TestCase; import java.io.File; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Set; import junit.framework.TestCase; public class UriTest extends TestCase { Loading Loading @@ -748,4 +746,10 @@ public class UriTest extends TestCase { assertEquals(Arrays.asList("a", "", ""), Uri.parse("http://foo/path?abc=a&abc=&abc=").getQueryParameters("abc")); } // http://code.google.com/p/android/issues/detail?id=21064 public void testPlusCharacterInQuery() { assertEquals("d e", Uri.parse("http://a/b?c=d%20e").getQueryParameter("c")); assertEquals("d e", Uri.parse("http://a/b?c=d+e").getQueryParameter("c")); } }