diff --git a/lib/src/main/java/com/uwyn/urlencoder/UrlEncoder.java b/lib/src/main/java/com/uwyn/urlencoder/UrlEncoder.java
index 984349f..27b9a2f 100644
--- a/lib/src/main/java/com/uwyn/urlencoder/UrlEncoder.java
+++ b/lib/src/main/java/com/uwyn/urlencoder/UrlEncoder.java
@@ -69,6 +69,20 @@ public final class UrlEncoder {
* @since 1.0
*/
public static String decode(String source) {
+ return decode(source, false);
+ }
+
+ /**
+ * Transforms a provided String
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 String
object.
+ * @see #encode(String, String)
+ * @since 1.0
+ */
+ public static String decode(String source, boolean plusToSpace) {
if (source == null || source.isEmpty()) {
return source;
}
@@ -83,10 +97,7 @@ public final class UrlEncoder {
ch = source.charAt(i);
if (ch == '%') {
- if (out == null) {
- out = new StringBuilder(length);
- out.append(source, 0, i);
- }
+ out = startConstructingIfNeeded(out, source, i);
if (bytes_buffer == null) {
// the remaining characters divided by the length
@@ -119,7 +130,10 @@ public final class UrlEncoder {
bytes_pos = 0;
}
- if (out != null) {
+ if (plusToSpace && ch == '+') {
+ out = startConstructingIfNeeded(out, source, i);
+ out.append(" ");
+ } else if (out != null) {
out.append(ch);
}
@@ -138,6 +152,14 @@ public final class UrlEncoder {
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 String
object into a new string,
* containing only valid URL characters in the UTF-8 encoding.
@@ -210,10 +232,8 @@ public final class UrlEncoder {
}
i += 1;
} else {
- if (out == null) {
- out = new StringBuilder(source.length());
- out.append(source, 0, i);
- }
+ out = startConstructingIfNeeded(out, source, i);
+
var cp = source.codePointAt(i);
if (cp < 0x80) {
if (spaceToPlus && ch == ' ') {
diff --git a/lib/src/test/java/com/uwyn/urlencoder/UrlEncoderTest.java b/lib/src/test/java/com/uwyn/urlencoder/UrlEncoderTest.java
index 1a7d25d..be7408d 100644
--- a/lib/src/test/java/com/uwyn/urlencoder/UrlEncoderTest.java
+++ b/lib/src/test/java/com/uwyn/urlencoder/UrlEncoderTest.java
@@ -101,6 +101,13 @@ class UrlEncoderTest {
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}")
@MethodSource("validMap")
void testMainDecode(String expected, String source) {