@@ -33,7 +33,21 @@ final class Base64 {
3333 private Base64 () {
3434 }
3535
36- public static byte [] decode (String in ) {
36+ private static final byte [] MAP = new byte []{
37+ 'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' , 'H' , 'I' , 'J' , 'K' , 'L' , 'M' , 'N' , 'O' , 'P' , 'Q' , 'R' , 'S' ,
38+ 'T' , 'U' , 'V' , 'W' , 'X' , 'Y' , 'Z' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' , 'h' , 'i' , 'j' , 'k' , 'l' ,
39+ 'm' , 'n' , 'o' , 'p' , 'q' , 'r' , 's' , 't' , 'u' , 'v' , 'w' , 'x' , 'y' , 'z' , '0' , '1' , '2' , '3' , '4' ,
40+ '5' , '6' , '7' , '8' , '9' , '+' , '/'
41+ };
42+
43+ private static final byte [] URL_MAP = new byte []{
44+ 'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' , 'H' , 'I' , 'J' , 'K' , 'L' , 'M' , 'N' , 'O' , 'P' , 'Q' , 'R' , 'S' ,
45+ 'T' , 'U' , 'V' , 'W' , 'X' , 'Y' , 'Z' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' , 'h' , 'i' , 'j' , 'k' , 'l' ,
46+ 'm' , 'n' , 'o' , 'p' , 'q' , 'r' , 's' , 't' , 'u' , 'v' , 'w' , 'x' , 'y' , 'z' , '0' , '1' , '2' , '3' , '4' ,
47+ '5' , '6' , '7' , '8' , '9' , '-' , '_'
48+ };
49+
50+ static byte [] decode (String in ) {
3751 // Ignore trailing '=' padding and whitespace from the input.
3852 int limit = in .length ();
3953 for (; limit > 0 ; limit --) {
@@ -114,19 +128,16 @@ public static byte[] decode(String in) {
114128 return prefix ;
115129 }
116130
117- private static final byte [] MAP = new byte []{
118- 'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' , 'H' , 'I' , 'J' , 'K' , 'L' , 'M' , 'N' , 'O' , 'P' , 'Q' , 'R' , 'S' ,
119- 'T' , 'U' , 'V' , 'W' , 'X' , 'Y' , 'Z' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' , 'h' , 'i' , 'j' , 'k' , 'l' ,
120- 'm' , 'n' , 'o' , 'p' , 'q' , 'r' , 's' , 't' , 'u' , 'v' , 'w' , 'x' , 'y' , 'z' , '0' , '1' , '2' , '3' , '4' ,
121- '5' , '6' , '7' , '8' , '9' , '+' , '/'
122- };
131+ static String encode (byte [] in ) {
132+ return encode (in , false , true );
133+ }
123134
124- public static String encode (byte [] in ) {
125- return encode (in , MAP );
135+ static String encode (byte [] in , boolean urlSafe , boolean usePadding ) {
136+ return encode (in , urlSafe ? URL_MAP : MAP , usePadding );
126137 }
127138
128- private static String encode (byte [] in , byte [] map ) {
129- int length = (in .length + 2 ) / 3 * 4 ;
139+ private static String encode (byte [] in , byte [] map , boolean usePadding ) {
140+ int length = outLength (in .length , usePadding ) ;
130141 byte [] out = new byte [length ];
131142 int index = 0 , end = in .length - in .length % 3 ;
132143 for (int i = 0 ; i < end ; i += 3 ) {
@@ -139,16 +150,32 @@ private static String encode(byte[] in, byte[] map) {
139150 case 1 :
140151 out [index ++] = map [(in [end ] & 0xff ) >> 2 ];
141152 out [index ++] = map [(in [end ] & 0x03 ) << 4 ];
142- out [index ++] = '=' ;
143- out [index ++] = '=' ;
153+ if (usePadding ) {
154+ out [index ++] = '=' ;
155+ out [index ] = '=' ;
156+ }
144157 break ;
145158 case 2 :
146159 out [index ++] = map [(in [end ] & 0xff ) >> 2 ];
147160 out [index ++] = map [((in [end ] & 0x03 ) << 4 ) | ((in [end + 1 ] & 0xff ) >> 4 )];
148161 out [index ++] = map [((in [end + 1 ] & 0x0f ) << 2 )];
149- out [index ++] = '=' ;
162+
163+ if (usePadding ) {
164+ out [index ] = '=' ;
165+ }
150166 break ;
151167 }
152168 return new String (out , StandardCharsets .US_ASCII );
153169 }
170+
171+ private static int outLength (int srclen , boolean doPadding ) {
172+ int len ;
173+ if (doPadding ) {
174+ len = 4 * ((srclen + 2 ) / 3 );
175+ } else {
176+ int n = srclen % 3 ;
177+ len = 4 * (srclen / 3 ) + (n == 0 ? 0 : n + 1 );
178+ }
179+ return len ;
180+ }
154181}
0 commit comments