Skip to content

Commit 2d9c56b

Browse files
authored
fix: improve performance of encode and decode (#212)
Don't bother partitioning array Skip bytes already in the decode buffer
1 parent 075cd91 commit 2d9c56b

File tree

1 file changed

+29
-60
lines changed

1 file changed

+29
-60
lines changed

src/main/java/com/github/packageurl/PackageURL.java

Lines changed: 29 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -630,43 +630,33 @@ private static byte percentDecode(final byte[] bytes, final int start) {
630630
return ((byte) ((c1 << 4) + c2));
631631
}
632632

633-
public static String percentDecode(final String source) {
633+
private static String percentDecode(final String source) {
634634
if (source.isEmpty()) {
635635
return source;
636636
}
637637

638638
byte[] bytes = source.getBytes(StandardCharsets.UTF_8);
639+
int i = indexOfPercentChar(bytes, 0);
639640

640-
int off = 0;
641-
int idx = indexOfPercentChar(bytes, off);
642-
643-
if (idx == -1) {
641+
if (i == -1) {
644642
return source;
645643
}
646644

647645
ByteBuffer buffer = ByteBuffer.wrap(bytes);
646+
buffer.position(i);
647+
int length = buffer.capacity();
648648

649-
while (true) {
650-
int len = idx - off;
649+
while (i < length) {
650+
byte b = bytes[i];
651651

652-
if (len > 0) {
653-
buffer.put(bytes, off, len);
654-
off += len;
652+
if (isPercent(b)) {
653+
buffer.put(percentDecode(bytes, i));
654+
i += 2;
655+
} else {
656+
buffer.put(b);
655657
}
656658

657-
buffer.put(percentDecode(bytes, off));
658-
off += 3;
659-
idx = indexOfPercentChar(bytes, off);
660-
661-
if (idx == -1) {
662-
int rem = bytes.length - off;
663-
664-
if (rem > 0) {
665-
buffer.put(bytes, off, rem);
666-
}
667-
668-
break;
669-
}
659+
i++;
670660
}
671661

672662
return new String(buffer.array(), 0, buffer.position(), StandardCharsets.UTF_8);
@@ -681,51 +671,30 @@ private static boolean isPercent(int c) {
681671
return (c == PERCENT_CHAR);
682672
}
683673

684-
private static byte[] percentEncode(byte b) {
685-
byte b1 = (byte) Character.toUpperCase(Character.forDigit((b >> 4) & 0xF, 16));
686-
byte b2 = (byte) Character.toUpperCase(Character.forDigit(b & 0xF, 16));
687-
return new byte[] {(byte) PERCENT_CHAR, b1, b2};
688-
}
689-
690-
public static String percentEncode(final String source) {
674+
private static String percentEncode(final String source) {
691675
if (source.isEmpty()) {
692676
return source;
693677
}
694678

695679
byte[] bytes = source.getBytes(StandardCharsets.UTF_8);
696-
697-
int off = 0;
698-
int idx = indexOfUnsafeChar(bytes, off);
699-
700-
if (idx == -1) {
701-
return source;
702-
}
703-
704-
ByteBuffer buffer = ByteBuffer.allocate(bytes.length * 3);
705-
706-
while (true) {
707-
int len = idx - off;
708-
709-
if (len > 0) {
710-
buffer.put(bytes, off, len);
711-
off += len;
712-
}
713-
714-
buffer.put(percentEncode(bytes[off++]));
715-
idx = indexOfUnsafeChar(bytes, off);
716-
717-
if (idx == -1) {
718-
int rem = bytes.length - off;
719-
720-
if (rem > 0) {
721-
buffer.put(bytes, off, rem);
722-
}
723-
724-
break;
680+
int length = bytes.length;
681+
ByteBuffer buffer = ByteBuffer.allocate(length * 3);
682+
boolean changed = false;
683+
684+
for (byte b : bytes) {
685+
if (shouldEncode(b)) {
686+
changed = true;
687+
byte b1 = (byte) Character.toUpperCase(Character.forDigit((b >> 4) & 0xF, 16));
688+
byte b2 = (byte) Character.toUpperCase(Character.forDigit(b & 0xF, 16));
689+
buffer.put((byte) PERCENT_CHAR);
690+
buffer.put(b1);
691+
buffer.put(b2);
692+
} else {
693+
buffer.put(b);
725694
}
726695
}
727696

728-
return new String(buffer.array(), 0, buffer.position(), StandardCharsets.UTF_8);
697+
return changed ? new String(buffer.array(), 0, buffer.position(), StandardCharsets.UTF_8) : source;
729698
}
730699

731700
/**

0 commit comments

Comments
 (0)