diff --git a/iabgpp-encoder/pom.xml b/iabgpp-encoder/pom.xml
index fe7ebc3b..e8409069 100644
--- a/iabgpp-encoder/pom.xml
+++ b/iabgpp-encoder/pom.xml
@@ -20,6 +20,11 @@
5.9.2
test
+
+ it.unimi.dsi
+ fastutil
+ 8.5.12
+
@@ -53,4 +58,3 @@
-
diff --git a/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/datatype/encoder/AbstractBase64UrlEncoder.java b/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/datatype/encoder/AbstractBase64UrlEncoder.java
index 698a0994..caac9cc2 100644
--- a/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/datatype/encoder/AbstractBase64UrlEncoder.java
+++ b/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/datatype/encoder/AbstractBase64UrlEncoder.java
@@ -6,6 +6,8 @@
import java.util.stream.Stream;
import com.iab.gpp.encoder.error.DecodingException;
import com.iab.gpp.encoder.error.EncodingException;
+import it.unimi.dsi.fastutil.chars.Char2IntMap;
+import it.unimi.dsi.fastutil.chars.Char2IntOpenHashMap;
public abstract class AbstractBase64UrlEncoder {
@@ -15,9 +17,9 @@ public abstract class AbstractBase64UrlEncoder {
* Base 64 URL character set. Different from standard Base64 char set in that '+' and '/' are
* replaced with '-' and '_'.
*/
- private static String DICT = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+ private static final String DICT = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
// prettier-ignore
- private static Map REVERSE_DICT = Stream
+ private static final Char2IntMap REVERSE_DICT = new Char2IntOpenHashMap(Stream
.of(new Object[][] {{'A', 0}, {'B', 1}, {'C', 2}, {'D', 3}, {'E', 4}, {'F', 5}, {'G', 6}, {'H', 7}, {'I', 8},
{'J', 9}, {'K', 10}, {'L', 11}, {'M', 12}, {'N', 13}, {'O', 14}, {'P', 15}, {'Q', 16}, {'R', 17}, {'S', 18},
{'T', 19}, {'U', 20}, {'V', 21}, {'W', 22}, {'X', 23}, {'Y', 24}, {'Z', 25}, {'a', 26}, {'b', 27}, {'c', 28},
@@ -25,21 +27,17 @@ public abstract class AbstractBase64UrlEncoder {
{'n', 39}, {'o', 40}, {'p', 41}, {'q', 42}, {'r', 43}, {'s', 44}, {'t', 45}, {'u', 46}, {'v', 47}, {'w', 48},
{'x', 49}, {'y', 50}, {'z', 51}, {'0', 52}, {'1', 53}, {'2', 54}, {'3', 55}, {'4', 56}, {'5', 57}, {'6', 58},
{'7', 59}, {'8', 60}, {'9', 61}, {'-', 62}, {'_', 63}})
- .collect(Collectors.toMap(data -> (Character) data[0], data -> (Integer) data[1]));
-
- private static Pattern BITSTRING_VERIFICATION_PATTERN = Pattern.compile("^[0-1]*$", Pattern.CASE_INSENSITIVE);
- private static Pattern BASE64URL_VERIFICATION_PATTERN =
- Pattern.compile("^[A-Za-z0-9\\-_]*$", Pattern.CASE_INSENSITIVE);
+ .collect(Collectors.toMap(data -> (Character) data[0], data -> (Integer) data[1])));
public String encode(String bitString) throws EncodingException {
// should only be 0 or 1
- if (!BITSTRING_VERIFICATION_PATTERN.matcher(bitString).matches()) {
+ if (isInvalidBitString(bitString)) {
throw new EncodingException("Unencodable Base64Url '" + bitString + "'");
}
bitString = pad(bitString);
- String str = "";
+ StringBuilder sb = new StringBuilder();
int index = 0;
while (index <= bitString.length() - 6) {
@@ -47,32 +45,40 @@ public String encode(String bitString) throws EncodingException {
try {
int n = FixedIntegerEncoder.decode(s);
- Character c = AbstractBase64UrlEncoder.DICT.charAt(n);
- str += c;
+ char c = AbstractBase64UrlEncoder.DICT.charAt(n);
+ sb.append(c);
index += 6;
} catch (DecodingException e) {
throw new EncodingException("Unencodable Base64Url '" + bitString + "'");
}
}
- return str;
+ return sb.toString();
}
public String decode(String str) throws DecodingException {
- // should contain only characters from the base64url set
- if (!BASE64URL_VERIFICATION_PATTERN.matcher(str).matches()) {
- throw new DecodingException("Undecodable Base64URL string");
- }
-
- String bitString = "";
+ StringBuilder bitString = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
- Integer n = AbstractBase64UrlEncoder.REVERSE_DICT.get(c);
+ int n = AbstractBase64UrlEncoder.REVERSE_DICT.getOrDefault(c, -1);
+ if (n == -1) {
+ throw new DecodingException("Undecodable Base64URL string");
+ }
String s = FixedIntegerEncoder.encode(n, 6);
- bitString += s;
+ bitString.append(s);
}
- return bitString;
+ return bitString.toString();
+ }
+
+ public static boolean isInvalidBitString(String bitString) {
+ for(int i = 0; i < bitString.length(); i++) {
+ char testChar = bitString.charAt(i);
+ if (testChar != '0' && testChar != '1') {
+ return true;
+ }
+ }
+ return false;
}
}
diff --git a/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/datatype/encoder/FixedIntegerEncoder.java b/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/datatype/encoder/FixedIntegerEncoder.java
index 2870af60..7fb0a7c0 100644
--- a/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/datatype/encoder/FixedIntegerEncoder.java
+++ b/iabgpp-encoder/src/main/java/com/iab/gpp/encoder/datatype/encoder/FixedIntegerEncoder.java
@@ -1,34 +1,34 @@
package com.iab.gpp.encoder.datatype.encoder;
+import static com.iab.gpp.encoder.datatype.encoder.AbstractBase64UrlEncoder.isInvalidBitString;
+
import java.util.regex.Pattern;
import com.iab.gpp.encoder.error.DecodingException;
public class FixedIntegerEncoder {
- private static Pattern BITSTRING_VERIFICATION_PATTERN = Pattern.compile("^[0-1]*$", Pattern.CASE_INSENSITIVE);
-
public static String encode(int value, int bitStringLength) {
// let bitString = value.toString(2);
- String bitString = "";
+ StringBuilder bitString = new StringBuilder();
while (value > 0) {
if ((value & 1) == 1) {
- bitString = "1" + bitString;
+ bitString.insert(0, "1");
} else {
- bitString = "0" + bitString;
+ bitString.insert(0, "0");
}
value = value >> 1;
}
while (bitString.length() < bitStringLength) {
- bitString = "0" + bitString;
+ bitString.insert(0, "0");
}
- return bitString;
+ return bitString.toString();
}
public static int decode(String bitString) throws DecodingException {
- if (!BITSTRING_VERIFICATION_PATTERN.matcher(bitString).matches()) {
+ if (isInvalidBitString(bitString)) {
throw new DecodingException("Undecodable FixedInteger '" + bitString + "'");
}