Added spaceToPlus parameter to encode function

This commit is contained in:
Erik C. Thauvin 2023-01-05 20:42:00 -08:00
parent 50ffe56ba8
commit f8b9376f40
6 changed files with 41 additions and 39 deletions

View file

@ -37,6 +37,7 @@ compared to other solutions like the standard `URLEncoder` in the JDK.
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("?test=a test", allow = "?=") // -> ?test=a%20test
UrlEncoder.endode("foo bar", spaceToPlus = true) // -> foo+bar
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!😁

View file

@ -23,7 +23,7 @@ plugins {
description = "A simple defensive library to encode/decode URL components"
group = "net.thauvin.erik"
version = "1.0.1"
version = "1.2.1-SNAPSHOT"
val mavenName = "UrlEncoder"
@ -40,7 +40,7 @@ repositories {
dependencies {
// testImplementation("com.willowtreeapps.assertk:assertk-jvm:0.25")
testImplementation("org.junit.jupiter:junit-jupiter:5.9.0")
testImplementation("org.junit.jupiter:junit-jupiter:5.9.1")
}
base {

View file

@ -9,6 +9,6 @@
<ID>MagicNumber:UrlEncoder.kt$UrlEncoder$3</ID>
<ID>MagicNumber:UrlEncoder.kt$UrlEncoder$4</ID>
<ID>MaxLineLength:UrlEncoder.kt$UrlEncoder$*</ID>
<ID>NestedBlockDepth:UrlEncoder.kt$UrlEncoder$@JvmStatic fun encode(source: String, allow: String): String</ID>
<ID>NestedBlockDepth:UrlEncoder.kt$UrlEncoder$@JvmStatic @JvmOverloads fun encode(source: String, allow: String = "", spaceToPlus: Boolean = false): String</ID>
</CurrentIssues>
</SmellBaseline>

View file

@ -8,7 +8,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>net.thauvin.erik</groupId>
<artifactId>urlencoder</artifactId>
<version>1.0.1</version>
<version>1.2.1-SNAPSHOT</version>
<name>UrlEncoder for Kotlin</name>
<description>A simple defensive library to encode/decode URL components</description>
<url>https://github.com/ethauvin/urlencoder</url>

View file

@ -40,7 +40,7 @@ import kotlin.system.exitProcess
object UrlEncoder {
private val hexDigits = "0123456789ABCDEF".toCharArray()
internal val usage =
"Usage : java -jar urlencoder-*all.jar [-ed] text" + System.lineSeparator() +
"Usage : java -jar urlencoder-*all.jar [-ed] <text>" + System.lineSeparator() +
"Encode and decode URL components defensively." + System.lineSeparator() + " -e encode (default) " +
System.lineSeparator() + " -d decode"
@ -85,7 +85,7 @@ object UrlEncoder {
*/
@JvmStatic
fun decode(source: String): String {
if (source.isBlank()) {
if (source.isEmpty()) {
return source
}
@ -142,7 +142,8 @@ object UrlEncoder {
* - Letters, numbers, unreserved (`_-!.'()*`) and allowed characters are left intact.
*/
@JvmStatic
fun encode(source: String, allow: String): String {
@JvmOverloads
fun encode(source: String, allow: String = "", spaceToPlus: Boolean = false): String {
if (source.isEmpty()) {
return source
}
@ -159,22 +160,27 @@ object UrlEncoder {
out = StringBuilder(source.length)
out.append(source, 0, i)
}
val cp = source.codePointAt(i)
if (cp < 0x80) {
out.appendEncodedByte(cp)
if (spaceToPlus && ch == ' ') {
out.append('+')
i++
} else if (Character.isBmpCodePoint(cp)) {
for (b in ch.toString().toByteArray(StandardCharsets.UTF_8)) {
out.appendEncodedByte(b.toInt())
} else {
val cp = source.codePointAt(i)
if (cp < 0x80) {
out.appendEncodedByte(cp)
i++
} else if (Character.isBmpCodePoint(cp)) {
for (b in ch.toString().toByteArray(StandardCharsets.UTF_8)) {
out.appendEncodedByte(b.toInt())
}
i++
} else if (Character.isSupplementaryCodePoint(cp)) {
val high = Character.highSurrogate(cp)
val low = Character.lowSurrogate(cp)
for (b in charArrayOf(high, low).concatToString().toByteArray(StandardCharsets.UTF_8)) {
out.appendEncodedByte(b.toInt())
}
i += 2
}
i++
} else if (Character.isSupplementaryCodePoint(cp)) {
val high = Character.highSurrogate(cp)
val low = Character.lowSurrogate(cp)
for (b in charArrayOf(high, low).concatToString().toByteArray(StandardCharsets.UTF_8)) {
out.appendEncodedByte(b.toInt())
}
i += 2
}
}
}
@ -182,17 +188,6 @@ object UrlEncoder {
return out?.toString() ?: source
}
/**
* Transforms a provided [String] object into a new string, containing only valid URL characters in the UTF-8
* encoding.
*
* - Letters, numbers, unreserved (`_-!.'()*`) and allowed characters are left intact.
*/
@JvmStatic
fun encode(source: String, vararg allow: Char): String {
return encode(source, String(allow))
}
/**
* Encodes and decodes URLs from the command line.
*

View file

@ -81,23 +81,29 @@ class UrlEncoderTest {
@Test
fun `Encode Empty or Blank`() {
assertTrue(encode("", "").isEmpty(), "encode('','')")
assertTrue(encode("", allow = "").isEmpty(), "encode('','')")
assertEquals("", encode(""), "encode('')")
assertEquals("%20", encode(" "), "encode('')")
assertEquals("%20", encode(" "), "encode(' ')")
}
@Test
fun `Encode when None needed`() {
assertSame(same, encode(same))
assertSame(same, encode(same, ""), "with empty allow")
assertSame(same, encode(same, allow = ""), "with empty allow")
}
@Test
fun `Encode with Allow Arg`() {
assertEquals("?test=a%20test", encode("?test=a test", '=', '?'), "encode(x, =, ?)")
assertEquals("?test=a%20test", encode("?test=a test", "=?"), "encode(x, =?)")
assertEquals("aaa", encode("aaa", 'a'), "encode(aaa, a)")
assertEquals(" ", encode(" ", ' '), "encode(' ', ' ')")
assertEquals("?test=a%20test", encode("?test=a test", allow = "=?"), "encode(x, =?)")
assertEquals("aaa", encode("aaa", "a"), "encode(aaa, a)")
assertEquals(" ", encode(" ", " "), "encode(' ', ' ')")
}
@Test
fun `Encode with Space to Plus`() {
assertEquals("foo+bar", encode("foo bar", spaceToPlus = true))
assertEquals("foo+bar++foo", encode("foo bar foo", spaceToPlus = true))
assertEquals("foo bar", encode("foo bar", " ", true))
}
@ParameterizedTest(name = "processMain(-d {1}) should be {0}")