Compare commits

..

No commits in common. "f075688dddfc8264fc5207b58d5866391405ee4d" and "5b293d9ca8ad3255b018bfe5e10ad75e54e55e5a" have entirely different histories.

3 changed files with 42 additions and 69 deletions

View file

@ -36,12 +36,11 @@ compared to other solutions like the standard `URLEncoder` in the JDK or
```java ```java
UrlEncoder.encode("a test &"); // -> "a%20test%20%26" UrlEncoder.encode("a test &"); // -> "a%20test%20%26"
UrlEncoder.encode("%#okékÉȢ smile!😁"); // -> "%25%23ok%C3%A9k%C3%89%C8%A2%20smile%21%F0%9F%98%81" UrlEncoder.encode("%#okékÉȢ smile!😁"); // -> "%25%23ok%C3%A9k%C3%89%C8%A2%20smile%21%F0%9F%98%81"
UrlEncoder.encode("?test=a test", "?="); // -> "?test=a%20test" UrlEncoder.encode("?test=a test", "?="); // -> ?test=a%20test
UrlEncoder.encode("foo bar", true); // -> "foo+bar" (encode space to +) UrlEncoder.encode("foo bar", true); // -> foo+bar (encode space to +)
UrlEncoder.decode("a%20test%20%26"); // -> "a test &" UrlEncoder.decode("a%20test%20%26"); // -> "a test &"
UrlEncoder.decode("%25%23ok%C3%A9k%C3%89%C8%A2%20smile%21%F0%9F%98%81"); // -> "%#okékÉȢ smile!😁" UrlEncoder.decode("%25%23ok%C3%A9k%C3%89%C8%A2%20smile%21%F0%9F%98%81"); // -> "%#okékÉȢ smile!😁"
UrlEncoder.decode("foo+bar", true); // -> "foo bar" (decode + to space)
``` ```
## Gradle, Maven, etc. ## Gradle, Maven, etc.

View file

@ -69,20 +69,6 @@ public final class UrlEncoder {
* @since 1.0 * @since 1.0
*/ */
public static String decode(String source) { public static String decode(String source) {
return decode(source, false);
}
/**
* Transforms a provided <code>String</code> URL into a new string,
* containing decoded URL characters in the UTF-8 encoding.
*
* @param source The string URL that has to be decoded
* @param plusToSpace Convert any {@code +} to space.
* @return The decoded <code>String</code> object.
* @see #encode(String, String)
* @since 1.0
*/
public static String decode(String source, boolean plusToSpace) {
if (source == null || source.isEmpty()) { if (source == null || source.isEmpty()) {
return source; return source;
} }
@ -97,7 +83,10 @@ public final class UrlEncoder {
ch = source.charAt(i); ch = source.charAt(i);
if (ch == '%') { if (ch == '%') {
out = startConstructingIfNeeded(out, source, i); if (out == null) {
out = new StringBuilder(length);
out.append(source, 0, i);
}
if (bytes_buffer == null) { if (bytes_buffer == null) {
// the remaining characters divided by the length // the remaining characters divided by the length
@ -130,10 +119,7 @@ public final class UrlEncoder {
bytes_pos = 0; bytes_pos = 0;
} }
if (plusToSpace && ch == '+') { if (out != null) {
out = startConstructingIfNeeded(out, source, i);
out.append(" ");
} else if (out != null) {
out.append(ch); out.append(ch);
} }
@ -152,14 +138,6 @@ public final class UrlEncoder {
return out.toString(); return out.toString();
} }
private static StringBuilder startConstructingIfNeeded(StringBuilder out, String source, int currentSourcePosition) {
if (out == null) {
out = new StringBuilder(source.length());
out.append(source, 0, currentSourcePosition);
}
return out;
}
/** /**
* Transforms a provided <code>String</code> object into a new string, * Transforms a provided <code>String</code> object into a new string,
* containing only valid URL characters in the UTF-8 encoding. * containing only valid URL characters in the UTF-8 encoding.
@ -232,15 +210,17 @@ public final class UrlEncoder {
} }
i += 1; i += 1;
} else { } else {
out = startConstructingIfNeeded(out, source, i); if (out == null) {
out = new StringBuilder(source.length());
var cp = source.codePointAt(i); out.append(source, 0, i);
if (cp < 0x80) { }
if (spaceToPlus && ch == ' ') { if (spaceToPlus && ch == ' ') {
out.append('+'); out.append('+');
i += 1;
} else { } else {
var cp = source.codePointAt(i);
if (cp < 0x80) {
appendUrlEncodedByte(out, cp); appendUrlEncodedByte(out, cp);
}
i += 1; i += 1;
} else if (Character.isBmpCodePoint(cp)) { } else if (Character.isBmpCodePoint(cp)) {
for (var b : Character.toString(ch).getBytes(StandardCharsets.UTF_8)) { for (var b : Character.toString(ch).getBytes(StandardCharsets.UTF_8)) {
@ -257,6 +237,7 @@ public final class UrlEncoder {
} }
} }
} }
}
if (out == null) { if (out == null) {
return source; return source;

View file

@ -101,17 +101,10 @@ class UrlEncoderTest {
assertEquals("foo bar", UrlEncoder.encode("foo bar", " ", true)); assertEquals("foo bar", UrlEncoder.encode("foo bar", " ", true));
} }
@Test
void testDecodePlusToSpace() {
assertEquals("foo bar", UrlEncoder.decode("foo+bar", true));
assertEquals("foo bar foo", UrlEncoder.decode("foo+bar++foo", true));
assertEquals("foo bar foo", UrlEncoder.decode("foo+%20bar%20+foo", true));
}
@ParameterizedTest(name = "processMain(-d {1}) should be {0}") @ParameterizedTest(name = "processMain(-d {1}) should be {0}")
@MethodSource("validMap") @MethodSource("validMap")
void testMainDecode(String expected, String source) { void testMainDecode(String expected, String source) {
var result = UrlEncoder.processMain("-d", source); var result = UrlEncoder.processMain(new String[]{"-d", source});
assertEquals(expected, result.output); assertEquals(expected, result.output);
assertEquals(0, result.status, "processMain(-d " + source + ").status"); assertEquals(0, result.status, "processMain(-d " + source + ").status");
} }
@ -119,7 +112,7 @@ class UrlEncoderTest {
@ParameterizedTest(name = "processMain(-e {0})") @ParameterizedTest(name = "processMain(-e {0})")
@MethodSource("validMap") @MethodSource("validMap")
void testMainEncode(String source, String expected) { void testMainEncode(String source, String expected) {
var result = UrlEncoder.processMain(source); var result = UrlEncoder.processMain(new String[]{source});
assertEquals(expected, result.output); assertEquals(expected, result.output);
assertEquals(0, result.status, "processMain(-e " + source + ").status"); assertEquals(0, result.status, "processMain(-e " + source + ").status");
} }
@ -127,20 +120,20 @@ class UrlEncoderTest {
@ParameterizedTest(name = "processMain(-d {0})") @ParameterizedTest(name = "processMain(-d {0})")
@MethodSource("invalid") @MethodSource("invalid")
void testMainEncodeWithExceptions(String source) { void testMainEncodeWithExceptions(String source) {
assertThrows(IllegalArgumentException.class, () -> UrlEncoder.processMain("-d", source), source); assertThrows(IllegalArgumentException.class, () -> UrlEncoder.processMain(new String[]{"-d", source}), source);
} }
@Test @Test
void testMainTooManyArgs() { void testMainTooManyArgs() {
assertTrue(UrlEncoder.processMain("foo", "bar", "test").output.contains("Usage :"), "too many args"); assertTrue(UrlEncoder.processMain(new String[]{"foo", "bar", "test"}).output.contains("Usage :"), "too many args");
} }
@Test @Test
void testMainWithEmptyArgs() { void testMainWithEmptyArgs() {
assertTrue(UrlEncoder.processMain(" ", " ").output.contains("Usage :"), "processMain(' ', ' ')"); assertTrue(UrlEncoder.processMain(new String[]{" ", " "}).output.contains("Usage :"), "processMain(' ', ' ')");
assertTrue(UrlEncoder.processMain("foo", " ").output.contains("Usage :"), "processMain('foo', ' ')"); assertTrue(UrlEncoder.processMain(new String[]{"foo", " "}).output.contains("Usage :"), "processMain('foo', ' ')");
assertTrue(UrlEncoder.processMain(" ", "foo").output.contains("Usage :"), "processMain(' ', 'foo')"); assertTrue(UrlEncoder.processMain(new String[]{" ", "foo"}).output.contains("Usage :"), "processMain(' ', 'foo')");
assertTrue(UrlEncoder.processMain("-d ", "").output.contains("Usage :"), "processMain('-d', '')"); assertTrue(UrlEncoder.processMain(new String[]{"-d ", ""}).output.contains("Usage :"), "processMain('-d', '')");
assertEquals("%20", UrlEncoder.processMain(new String[]{"-e", " "}).output, "processMain('-e', ' ')"); assertEquals("%20", UrlEncoder.processMain(new String[]{"-e", " "}).output, "processMain('-e', ' ')");
assertEquals(" ", UrlEncoder.processMain(new String[]{"-d", " "}).output, "processMain('-d', ' ')"); assertEquals(" ", UrlEncoder.processMain(new String[]{"-d", " "}).output, "processMain('-d', ' ')");
} }
@ -148,7 +141,7 @@ class UrlEncoderTest {
@ParameterizedTest @ParameterizedTest
@ValueSource(strings = {"", "-d", "-e"}) @ValueSource(strings = {"", "-d", "-e"})
void testMainWithInvalidArgs(String arg) { void testMainWithInvalidArgs(String arg) {
var result = UrlEncoder.processMain(arg); var result = UrlEncoder.processMain(new String[]{arg});
assertTrue(result.output.contains("Usage :"), "processMain('" + arg + "')"); assertTrue(result.output.contains("Usage :"), "processMain('" + arg + "')");
assertEquals(1, result.status, "processMain('" + arg + "').status"); assertEquals(1, result.status, "processMain('" + arg + "').status");
} }
@ -156,14 +149,14 @@ class UrlEncoderTest {
@ParameterizedTest(name = "processMain(-e {0})") @ParameterizedTest(name = "processMain(-e {0})")
@MethodSource("validMap") @MethodSource("validMap")
void testMainWithOption(String source, String expected) { void testMainWithOption(String source, String expected) {
var result = UrlEncoder.processMain("-e", source); var result = UrlEncoder.processMain(new String[]{"-e", source});
assertEquals(expected, result.output); assertEquals(expected, result.output);
assertEquals(0, result.status, "processMain(-e " + source + ").status"); assertEquals(0, result.status, "processMain(-e " + source + ").status");
} }
@Test @Test
void testMainWithUnknownOptions() { void testMainWithUnknownOptions() {
assertTrue(UrlEncoder.processMain("-p").output.contains("Usage :"), "processMain(-p)"); assertTrue(UrlEncoder.processMain(new String[]{"-p"}).output.contains("Usage :"), "processMain(-p)");
assertTrue(UrlEncoder.processMain("-").output.contains("Usage :"), "processMain(-)"); assertTrue(UrlEncoder.processMain(new String[]{"-"}).output.contains("Usage :"), "processMain(-)");
} }
} }