@@ -565,7 +565,7 @@ private static boolean isLowerCase(int c) {
565565 }
566566
567567 private static int toLowerCase (int c ) {
568- return ( c ^ 0x20 );
568+ return isUpperCase ( c ) ? ( c ^ 0x20 ) : c ;
569569 }
570570
571571 private static String toLowerCase (String s ) {
@@ -579,9 +579,7 @@ private static String toLowerCase(String s) {
579579 int length = chars .length ;
580580
581581 for (int i = pos ; i < length ; i ++) {
582- if (isUpperCase (chars [i ])) {
583- chars [i ] = (char ) toLowerCase (chars [i ]);
584- }
582+ chars [i ] = (char ) toLowerCase (chars [i ]);
585583 }
586584
587585 return new String (chars );
@@ -634,37 +632,27 @@ static String percentDecode(final String source) {
634632 }
635633
636634 byte [] bytes = source .getBytes (StandardCharsets .UTF_8 );
635+ int i = indexOfPercentChar (bytes , 0 );
637636
638- int off = 0 ;
639- int idx = indexOfPercentChar (bytes , off );
640-
641- if (idx == -1 ) {
637+ if (i == -1 ) {
642638 return source ;
643639 }
644640
645641 ByteBuffer buffer = ByteBuffer .wrap (bytes );
642+ buffer .position (i );
643+ int length = buffer .capacity ();
646644
647- while (true ) {
648- int len = idx - off ;
645+ while (i < length ) {
646+ byte b = bytes [ i ] ;
649647
650- if (len > 0 ) {
651- buffer .put (bytes , off , len );
652- off += len ;
648+ if (isPercent (b )) {
649+ buffer .put (percentDecode (bytes , i ));
650+ i += 2 ;
651+ } else {
652+ buffer .put (b );
653653 }
654654
655- buffer .put (percentDecode (bytes , off ));
656- off += 3 ;
657- idx = indexOfPercentChar (bytes , off );
658-
659- if (idx == -1 ) {
660- int rem = bytes .length - off ;
661-
662- if (rem > 0 ) {
663- buffer .put (bytes , off , rem );
664- }
665-
666- break ;
667- }
655+ i ++;
668656 }
669657
670658 return new String (buffer .array (), 0 , buffer .position (), StandardCharsets .UTF_8 );
@@ -687,51 +675,30 @@ private static boolean isPercent(int c) {
687675 return (c == PERCENT_CHAR );
688676 }
689677
690- private static byte [] percentEncode (byte b ) {
691- byte b1 = (byte ) Character .toUpperCase (Character .forDigit ((b >> 4 ) & 0xF , 16 ));
692- byte b2 = (byte ) Character .toUpperCase (Character .forDigit (b & 0xF , 16 ));
693- return new byte [] {(byte ) PERCENT_CHAR , b1 , b2 };
694- }
695-
696678 static String percentEncode (final String source ) {
697679 if (source .isEmpty ()) {
698680 return source ;
699681 }
700682
701683 byte [] bytes = source .getBytes (StandardCharsets .UTF_8 );
702-
703- int off = 0 ;
704- int idx = indexOfUnsafeChar (bytes , off );
705-
706- if (idx == -1 ) {
707- return source ;
708- }
709-
710- ByteBuffer buffer = ByteBuffer .allocate (bytes .length * 3 );
711-
712- while (true ) {
713- int len = idx - off ;
714-
715- if (len > 0 ) {
716- buffer .put (bytes , off , len );
717- off += len ;
718- }
719-
720- buffer .put (percentEncode (bytes [off ++]));
721- idx = indexOfUnsafeChar (bytes , off );
722-
723- if (idx == -1 ) {
724- int rem = bytes .length - off ;
725-
726- if (rem > 0 ) {
727- buffer .put (bytes , off , rem );
728- }
729-
730- break ;
684+ int length = bytes .length ;
685+ ByteBuffer buffer = ByteBuffer .allocate (length * 3 );
686+ boolean changed = false ;
687+
688+ for (byte b : bytes ) {
689+ if (shouldEncode (b )) {
690+ changed = true ;
691+ byte b1 = (byte ) Character .toUpperCase (Character .forDigit ((b >> 4 ) & 0xF , 16 ));
692+ byte b2 = (byte ) Character .toUpperCase (Character .forDigit (b & 0xF , 16 ));
693+ buffer .put ((byte ) PERCENT_CHAR );
694+ buffer .put (b1 );
695+ buffer .put (b2 );
696+ } else {
697+ buffer .put (b );
731698 }
732699 }
733700
734- return new String (buffer .array (), 0 , buffer .position (), StandardCharsets .UTF_8 );
701+ return changed ? new String (buffer .array (), 0 , buffer .position (), StandardCharsets .UTF_8 ) : source ;
735702 }
736703
737704 /**
@@ -948,7 +915,7 @@ public String getCoordinates() {
948915 * @since 1.2.0
949916 */
950917 public boolean isCanonicalEquals (final PackageURL purl ) {
951- return ( this .canonicalize ().equals (purl .canonicalize () ));
918+ return this .canonicalize ().equals (purl .canonicalize ());
952919 }
953920
954921 private static boolean isEmpty (@ Nullable String value ) {
0 commit comments