This is an automated email from the ASF dual-hosted git repository.
aherbert pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/commons-codec.git.
from 7118544 Upgrade to parent 51
new f19ec78 Bugfix - buffer must always hold at least 'size' bytes
new 081756b Add Base16 Input and Output Streams
new 564c47c Add support for strict decoding - addresses review comments by @garydgregory and @aherbert
new 1b594c0 Fix typos
new 019ee2c Refactored to use a Lookup Table
new 9727285 Throw IllegalArgumentException for characters outside of alphabet
new 77fa03c Expand on the functionality in the Javadoc
new 196f32e Abstract common test code into BaseNTestData
new 0b672eb Imporve array equality assertions in tests
new 065b106 Address code-review comments by @aherbert
new 4024b40 Address out-of-bounds for array size with int wrap-around
new a1712d8 Add missing cases suggested by @aherbert
new 0686543 Remove test as requested by @aherbert
new 427998a Revert changes to Hex classes, will be moved to separate PR
new 467b85c Remove redundant comments that refer to removed code
new 919e2f3 Add javadoc <p> tags
new 74343c0 CODEC-290: Track changes
new e80304c Merge branch 'adamretter-base16'
The 18 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
pom.xml | 7 +
src/changes/changes.xml | 1 +
.../org/apache/commons/codec/binary/Base16.java | 267 +++++++++
.../commons/codec/binary/Base16InputStream.java | 81 +++
.../commons/codec/binary/Base16OutputStream.java | 81 +++
.../org/apache/commons/codec/binary/Base32.java | 2 +-
.../org/apache/commons/codec/binary/Base64.java | 2 +-
.../apache/commons/codec/binary/BaseNCodec.java | 2 +-
.../codec/binary/Base16InputStreamTest.java | 440 +++++++++++++++
.../codec/binary/Base16OutputStreamTest.java | 287 ++++++++++
.../apache/commons/codec/binary/Base16Test.java | 602 +++++++++++++++++++++
.../commons/codec/binary/Base16TestData.java | 33 ++
.../codec/binary/Base32InputStreamTest.java | 41 +-
.../codec/binary/Base32OutputStreamTest.java | 28 +-
.../apache/commons/codec/binary/Base32Test.java | 6 +-
.../commons/codec/binary/Base32TestData.java | 89 ---
.../codec/binary/Base64InputStreamTest.java | 55 +-
.../codec/binary/Base64OutputStreamTest.java | 40 +-
.../apache/commons/codec/binary/Base64Test.java | 17 +-
.../commons/codec/binary/Base64TestData.java | 136 -----
.../{Base64TestData.java => BaseNTestData.java} | 106 ++--
21 files changed, 1932 insertions(+), 391 deletions(-)
create mode 100644 src/main/java/org/apache/commons/codec/binary/Base16.java
create mode 100644 src/main/java/org/apache/commons/codec/binary/Base16InputStream.java
create mode 100644 src/main/java/org/apache/commons/codec/binary/Base16OutputStream.java
create mode 100644 src/test/java/org/apache/commons/codec/binary/Base16InputStreamTest.java
create mode 100644 src/test/java/org/apache/commons/codec/binary/Base16OutputStreamTest.java
create mode 100644 src/test/java/org/apache/commons/codec/binary/Base16Test.java
create mode 100644 src/test/java/org/apache/commons/codec/binary/Base16TestData.java
copy src/test/java/org/apache/commons/codec/binary/{Base64TestData.java => BaseNTestData.java} (64%)
This is an automated email from the ASF dual-hosted git repository.
aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-codec.git
commit 019ee2c989d21bb5de8e26a12bbf87f2f870fa7e
Author: Adam Retter <ad...@googlemail.com>
AuthorDate: Sun May 31 23:46:05 2020 +0200
Refactored to use a Lookup Table
---
.../org/apache/commons/codec/binary/Base16.java | 312 ++++++-------
.../commons/codec/binary/Base16InputStream.java | 26 +-
.../commons/codec/binary/Base16OutputStream.java | 26 +-
.../codec/binary/Base16InputStreamTest.java | 155 ++++---
.../codec/binary/Base16OutputStreamTest.java | 169 +++----
.../apache/commons/codec/binary/Base16Test.java | 485 ++++++++++-----------
6 files changed, 586 insertions(+), 587 deletions(-)
diff --git a/src/main/java/org/apache/commons/codec/binary/Base16.java b/src/main/java/org/apache/commons/codec/binary/Base16.java
index 1732f69..eb875cb 100644
--- a/src/main/java/org/apache/commons/codec/binary/Base16.java
+++ b/src/main/java/org/apache/commons/codec/binary/Base16.java
@@ -18,9 +18,6 @@
package org.apache.commons.codec.binary;
import org.apache.commons.codec.CodecPolicy;
-import org.apache.commons.codec.DecoderException;
-
-import java.nio.charset.Charset;
/**
* Provides Base16 encoding and decoding.
@@ -29,79 +26,118 @@ import java.nio.charset.Charset;
* This class is thread-safe.
* </p>
*
+ * @see <a href="https://tools.ietf.org/html/rfc4648#section-8">RFC 4648 - 8. Base 16 Encoding</a>
+ *
* @since 1.15
*/
public class Base16 extends BaseNCodec {
- private static final int BYTES_PER_UNENCODED_BLOCK = 1;
+ /**
+ * BASE16 characters are 4 bits in length.
+ * They are formed by taking an 8-bit group,
+ * which is converted into two BASE16 characters.
+ */
+ private static final int BITS_PER_ENCODED_BYTE = 4;
private static final int BYTES_PER_ENCODED_BLOCK = 2;
+ private static final int BYTES_PER_UNENCODED_BLOCK = 1;
+
+ /**
+ * This array is a lookup table that translates Unicode characters drawn from the "Base16 Alphabet" (as specified
+ * in Table 5 of RFC 4648) into their 4-bit positive integer equivalents. Characters that are not in the Base16
+ * alphabet but fall within the bounds of the array are translated to -1.
+ */
+ private static final byte[] UPPER_CASE_DECODE_TABLE = {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 00-0f
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 10-1f
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 20-2f
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, // 30-3f 0-9
+ -1, 10, 11, 12, 13, 14, 15 // 40-46 A-F
+ };
- private final boolean toLowerCase;
- private final Charset charset;
+ /**
+ * This array is a lookup table that translates 4-bit positive integer index values into their "Base16 Alphabet"
+ * equivalents as specified in Table 5 of RFC 4648.
+ */
+ private static final byte[] UPPER_CASE_ENCODE_TABLE = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'A', 'B', 'C', 'D', 'E', 'F'
+ };
/**
- * Creates a Base16 codec used for decoding and encoding.
+ * This array is a lookup table that translates Unicode characters drawn from the a lower-case "Base16 Alphabet"
+ * into their 4-bit positive integer equivalents. Characters that are not in the Base16
+ * alphabet but fall within the bounds of the array are translated to -1.
*/
- protected Base16() {
- this(Hex.DEFAULT_CHARSET);
- }
+ private static final byte[] LOWER_CASE_DECODE_TABLE = {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 00-0f
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 10-1f
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 20-2f
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, // 30-3f 0-9
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 40-4f
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 50-5f
+ -1, 10, 11, 12, 13, 14, 15 // 60-66 a-f
+ };
+
+ /**
+ * This array is a lookup table that translates 4-bit positive integer index values into their "Base16 Alphabet"
+ * lower-case equivalents.
+ */
+ private static final byte[] LOWER_CASE_ENCODE_TABLE = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'a', 'b', 'c', 'd', 'e', 'f'
+ };
+
+ /** Mask used to extract 4 bits, used when decoding character. */
+ private static final int MASK_4BITS = 0x0f;
+
+ /**
+ * Decode table to use.
+ */
+ private final byte[] decodeTable;
+
+ /**
+ * Encode table to use.
+ */
+ private final byte[] encodeTable;
/**
* Creates a Base16 codec used for decoding and encoding.
- *
- * @param charset the charset.
*/
- protected Base16(final Charset charset) {
- this(true, charset);
+ public Base16() {
+ this(false);
}
/**
* Creates a Base16 codec used for decoding and encoding.
*
- * @param toLowerCase {@code true} converts to lowercase, {@code false} to uppercase.
- * @param charset the charset.
+ * @param lowerCase if {@code true} then use a lower-case Base16 alphabet.
*/
- protected Base16(final boolean toLowerCase, final Charset charset) {
- super(BYTES_PER_UNENCODED_BLOCK, BYTES_PER_ENCODED_BLOCK, 0, 0);
- this.toLowerCase = toLowerCase;
- this.charset = charset;
+ public Base16(final boolean lowerCase) {
+ this(lowerCase, DECODING_POLICY_DEFAULT);
}
/**
* Creates a Base16 codec used for decoding and encoding.
*
- * @param toLowerCase {@code true} converts to lowercase, {@code false} to uppercase.
- * @param charset the charset.
+ * @param lowerCase if {@code true} then use a lower-case Base16 alphabet.
* @param decodingPolicy Decoding policy.
*/
- protected Base16(final boolean toLowerCase, final Charset charset, final CodecPolicy decodingPolicy) {
+ public Base16(final boolean lowerCase, final CodecPolicy decodingPolicy) {
super(BYTES_PER_UNENCODED_BLOCK, BYTES_PER_ENCODED_BLOCK, 0, 0,
PAD_DEFAULT, decodingPolicy);
- this.toLowerCase = toLowerCase;
- this.charset = charset;
- }
-
- @Override
- void encode(final byte[] data, final int offset, final int length, final Context context) {
- if (context.eof) {
- return;
- }
- if (length < 0) {
- context.eof = true;
- return;
+ if (lowerCase) {
+ this.encodeTable = LOWER_CASE_ENCODE_TABLE;
+ this.decodeTable = LOWER_CASE_DECODE_TABLE;
+ } else {
+ this.encodeTable = UPPER_CASE_ENCODE_TABLE;
+ this.decodeTable = UPPER_CASE_DECODE_TABLE;
}
-
- final char[] chars = Hex.encodeHex(data, offset, length, toLowerCase);
- final byte[] encoded = new String(chars).getBytes(charset);
-
- final byte[] buffer = ensureBufferSize(encoded.length, context);
- System.arraycopy(encoded, 0, buffer, context.pos, encoded.length);
-
- context.pos += encoded.length;
}
@Override
- void decode(final byte[] data, final int offset, final int length, final Context context) {
+ void decode(final byte[] data, int offset, final int length, final Context context) {
if (context.eof || length < 0) {
context.eof = true;
if (context.ibitWorkArea > 0) {
@@ -119,178 +155,84 @@ public class Base16 extends BaseNCodec {
return;
}
- // NOTE: Each pair of bytes is really a pair of hex-chars, therefore each pair represents one byte
-
// we must have an even number of chars to decode
- final char[] encodedChars = new char[availableChars % 2 == 0 ? availableChars : availableChars - 1];
+ final int charsToProcess = availableChars % BYTES_PER_ENCODED_BLOCK == 0 ? availableChars : availableChars - 1;
+
+ final byte[] buffer = ensureBufferSize(charsToProcess / BYTES_PER_ENCODED_BLOCK, context);
- // copy all (or part of) data into encodedChars
+ int result;
int i = 0;
if (dataLen < availableChars) {
// we have 1/2 byte from previous invocation to decode
- encodedChars[i++] = (char)context.ibitWorkArea;
- context.ibitWorkArea = -1; // reset for next iteration!
- }
- final int copyLen = encodedChars.length - i;
- for (int j = offset; j < copyLen + offset; j++) {
- encodedChars[i++] = (char) data[j];
- }
+ result = decodeTable[context.ibitWorkArea] << BITS_PER_ENCODED_BYTE;
+ result |= decodeTable[data[offset++]];
+ i = 2;
- // decode encodedChars into buffer
- final byte[] buffer = ensureBufferSize(encodedChars.length / 2, context);
- try {
- final int written = Hex.decodeHex(encodedChars, buffer, context.pos);
- context.pos += written;
- } catch (final DecoderException e) {
- throw new RuntimeException(e); // this method ensures that this cannot happen at runtime!
+ buffer[context.pos++] = (byte)result;
+
+ // reset for next invocation!
+ context.ibitWorkArea = -1;
}
- // we have one char of a hex-pair left over
- if (copyLen < dataLen) {
- context.ibitWorkArea = data[offset + dataLen - 1]; // store 1/2 byte for next invocation of decode
+ while (i < charsToProcess) {
+ result = decodeTable[data[offset++]] << BITS_PER_ENCODED_BYTE;
+ result |= decodeTable[data[offset++]];
+ i += 2;
+ buffer[context.pos++] = (byte)result;
}
- }
- /**
- * Validates whether decoding allows an entire final trailing character that cannot be
- * used for a complete byte.
- *
- * @throws IllegalArgumentException if strict decoding is enabled
- */
- private void validateTrailingCharacter() {
- if (isStrictDecoding()) {
- throw new IllegalArgumentException("Strict decoding: Last encoded character is a valid base 16 alphabet" +
- "character but not a possible encoding. " +
- "Decoding requires at least two characters to create one byte.");
+ // we have one char of a hex-pair left over
+ if (i < dataLen) {
+ context.ibitWorkArea = data[i]; // store 1/2 byte for next invocation of decode
}
}
@Override
- protected boolean isInAlphabet(final byte value) {
- if (value >= '0' && value <= '9') {
- return true;
+ void encode(final byte[] data, final int offset, final int length, final Context context) {
+ if (context.eof) {
+ return;
}
- if (toLowerCase) {
- return value >= 'a' && value <= 'f';
- } else {
- return value >= 'A' && value <= 'F';
+ if (length < 0) {
+ context.eof = true;
+ return;
}
- }
- /**
- * Returns whether or not the {@code c} is in the base 16 alphabet.
- *
- * @param c The value to test
- * @return {@code true} if the value is defined in the the base 16 alphabet, {@code false} otherwise.
- */
- public static boolean isBase16(final char c) {
- return
- (c >= '0' && c <= '9')
- || (c >= 'A' && c <= 'F')
- || (c >= 'a' && c <= 'f');
- }
-
- /**
- * Tests a given String to see if it contains only valid characters within the Base16 alphabet.
- *
- * @param base16 String to test
- * @return {@code true} if all characters in the String are valid characters in the Base16 alphabet or if
- * the String is empty; {@code false}, otherwise
- */
- public static boolean isBase16(final String base16) {
- return isBase16(base16.toCharArray());
- }
+ final byte[] buffer = ensureBufferSize(length * BYTES_PER_ENCODED_BLOCK, context);
- /**
- * Tests a given char array to see if it contains only valid characters within the Base16 alphabet.
- *
- * @param arrayChars char array to test
- * @return {@code true} if all chars are valid characters in the Base16 alphabet or if the char array is empty;
- * {@code false}, otherwise
- */
- public static boolean isBase16(final char[] arrayChars) {
- for (int i = 0; i < arrayChars.length; i++) {
- if (!isBase16(arrayChars[i])) {
- return false;
- }
+ final int end = offset + length;
+ for (int i = offset; i < end; i++) {
+ final int value = data[i];
+ final int high = (value >> BITS_PER_ENCODED_BYTE) & MASK_4BITS;
+ final int low = value & MASK_4BITS;
+ buffer[context.pos++] = encodeTable[high];
+ buffer[context.pos++] = encodeTable[low];
}
- return true;
}
/**
- * Tests a given char array to see if it contains only valid characters within the Base16 alphabet.
+ * Returns whether or not the {@code octet} is in the Base16 alphabet.
*
- * @param arrayChars byte array to test
- * @return {@code true} if all chars are valid characters in the Base16 alphabet or if the byte array is empty;
- * {@code false}, otherwise
- */
- public static boolean isBase16(final byte[] arrayChars) {
- for (int i = 0; i < arrayChars.length; i++) {
- if (!isBase16((char) arrayChars[i])) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Encodes binary data using the base16 algorithm.
+ * @param octet The value to test.
*
- * @param binaryData Array containing binary data to encode.
- * @return Base16-encoded data.
+ * @return {@code true} if the value is defined in the the Base16 alphabet {@code false} otherwise.
*/
- public static byte[] encodeBase16(final byte[] binaryData) {
- return encodeBase16(binaryData, true, Hex.DEFAULT_CHARSET, Integer.MAX_VALUE);
+ @Override
+ public boolean isInAlphabet(final byte octet) {
+ return octet >= 0 && octet < decodeTable.length && decodeTable[octet] != -1;
}
/**
- * Encodes binary data using the base16 algorithm.
+ * Validates whether decoding allows an entire final trailing character that cannot be
+ * used for a complete byte.
*
- * @param binaryData Array containing binary data to encode.
- * @param toLowerCase {@code true} converts to lowercase, {@code false} to uppercase.
- * @param charset the charset.
- * @param maxResultSize The maximum result size to accept.
- * @return Base16-encoded data.
- * @throws IllegalArgumentException Thrown when the input array needs an output array bigger than maxResultSize
+ * @throws IllegalArgumentException if strict decoding is enabled
*/
- public static byte[] encodeBase16(final byte[] binaryData, final boolean toLowerCase, final Charset charset,
- final int maxResultSize) {
- if (binaryData == null || binaryData.length == 0) {
- return binaryData;
- }
-
- // Create this so can use the super-class method
- // Also ensures that the same roundings are performed by the ctor and the code
- final Base16 b16 = new Base16(toLowerCase, charset);
- final long len = b16.getEncodedLength(binaryData);
- if (len > maxResultSize) {
- throw new IllegalArgumentException("Input array too big, the output array would be bigger (" +
- len +
- ") than the specified maximum size of " +
- maxResultSize);
+ private void validateTrailingCharacter() {
+ if (isStrictDecoding()) {
+ throw new IllegalArgumentException("Strict decoding: Last encoded character is a valid base 16 alphabet" +
+ "character but not a possible encoding. " +
+ "Decoding requires at least two characters to create one byte.");
}
-
- return b16.encode(binaryData);
- }
-
- /**
- * Decodes a Base16 String into octets.
- *
- * @param base16String String containing Base16 data
- * @return Array containing decoded data.
- */
- public static byte[] decodeBase16(final String base16String) {
- return new Base16().decode(base16String);
- }
-
- /**
- * Decodes Base16 data into octets.
- *
- * @param base16Data Byte array containing Base16 data
- * @return Array containing decoded data.
- */
- public static byte[] decodeBase16(final byte[] base16Data) {
- return new Base16().decode(base16Data);
}
}
diff --git a/src/main/java/org/apache/commons/codec/binary/Base16InputStream.java b/src/main/java/org/apache/commons/codec/binary/Base16InputStream.java
index 94e8cf4..9bd5066 100644
--- a/src/main/java/org/apache/commons/codec/binary/Base16InputStream.java
+++ b/src/main/java/org/apache/commons/codec/binary/Base16InputStream.java
@@ -17,8 +17,9 @@
package org.apache.commons.codec.binary;
+import org.apache.commons.codec.CodecPolicy;
+
import java.io.InputStream;
-import java.nio.charset.Charset;
/**
* Provides Base16 encoding and decoding in a streaming fashion (unlimited size).
@@ -48,7 +49,20 @@ public class Base16InputStream extends BaseNCodecInputStream {
* @param doEncode true if we should encode all data read from us, false if we should decode.
*/
public Base16InputStream(final InputStream in, final boolean doEncode) {
- this(in, doEncode, true, Hex.DEFAULT_CHARSET);
+ this(in, doEncode, false);
+ }
+
+ /**
+ * Creates a Base16InputStream such that all data read is either Base16-encoded or Base16-decoded from the original
+ * provided InputStream.
+ *
+ * @param in InputStream to wrap.
+ * @param doEncode true if we should encode all data read from us, false if we should decode.
+ * @param lowerCase if {@code true} then use a lower-case Base16 alphabet.
+ */
+ public Base16InputStream(final InputStream in, final boolean doEncode,
+ final boolean lowerCase) {
+ this(in, doEncode, lowerCase, CodecPolicy.LENIENT);
}
/**
@@ -57,11 +71,11 @@ public class Base16InputStream extends BaseNCodecInputStream {
*
* @param in InputStream to wrap.
* @param doEncode true if we should encode all data read from us, false if we should decode.
- * @param toLowerCase {@code true} converts to lowercase, {@code false} to uppercase.
- * @param charset the charset.
+ * @param lowerCase if {@code true} then use a lower-case Base16 alphabet.
+ * @param decodingPolicy Decoding policy.
*/
public Base16InputStream(final InputStream in, final boolean doEncode,
- final boolean toLowerCase, final Charset charset) {
- super(in, new Base16(toLowerCase, charset), doEncode);
+ final boolean lowerCase, final CodecPolicy decodingPolicy) {
+ super(in, new Base16(lowerCase, decodingPolicy), doEncode);
}
}
diff --git a/src/main/java/org/apache/commons/codec/binary/Base16OutputStream.java b/src/main/java/org/apache/commons/codec/binary/Base16OutputStream.java
index e214320..9a52ab8 100644
--- a/src/main/java/org/apache/commons/codec/binary/Base16OutputStream.java
+++ b/src/main/java/org/apache/commons/codec/binary/Base16OutputStream.java
@@ -17,8 +17,9 @@
package org.apache.commons.codec.binary;
+import org.apache.commons.codec.CodecPolicy;
+
import java.io.OutputStream;
-import java.nio.charset.Charset;
/**
* Provides Hex encoding and decoding in a streaming fashion (unlimited size).
@@ -48,7 +49,20 @@ public class Base16OutputStream extends BaseNCodecOutputStream {
* @param doEncode true if we should encode all data written to us, false if we should decode.
*/
public Base16OutputStream(final OutputStream out, final boolean doEncode) {
- this(out, doEncode, true, Hex.DEFAULT_CHARSET);
+ this(out, doEncode, false);
+ }
+
+ /**
+ * Creates a Base16OutputStream such that all data written is either Hex-encoded or Hex-decoded to the
+ * original provided OutputStream.
+ *
+ * @param out OutputStream to wrap.
+ * @param doEncode true if we should encode all data written to us, false if we should decode.
+ * @param lowerCase if {@code true} then use a lower-case Base16 alphabet.
+ */
+ public Base16OutputStream(final OutputStream out, final boolean doEncode,
+ final boolean lowerCase) {
+ this(out, doEncode, lowerCase, CodecPolicy.LENIENT);
}
/**
@@ -57,11 +71,11 @@ public class Base16OutputStream extends BaseNCodecOutputStream {
*
* @param out OutputStream to wrap.
* @param doEncode true if we should encode all data written to us, false if we should decode.
- * @param toLowerCase {@code true} converts to lowercase, {@code false} to uppercase.
- * @param charset the charset.
+ * @param lowerCase if {@code true} then use a lower-case Base16 alphabet.
+ * @param decodingPolicy Decoding policy.
*/
public Base16OutputStream(final OutputStream out, final boolean doEncode,
- final boolean toLowerCase, final Charset charset) {
- super(out, new Base16(toLowerCase, charset), doEncode);
+ final boolean lowerCase, final CodecPolicy decodingPolicy) {
+ super(out, new Base16(lowerCase, decodingPolicy), doEncode);
}
}
diff --git a/src/test/java/org/apache/commons/codec/binary/Base16InputStreamTest.java b/src/test/java/org/apache/commons/codec/binary/Base16InputStreamTest.java
index 9d4d2a2..c3c8ee0 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base16InputStreamTest.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base16InputStreamTest.java
@@ -36,7 +36,7 @@ public class Base16InputStreamTest {
/**
* Decodes to {202, 254, 186, 190, 255, 255}
*/
- private static final String ENCODED_B16 = "cafebabeffff";
+ private static final String ENCODED_B16 = "CAFEBABEFFFF";
private static final String STRING_FIXTURE = "Hello World";
@@ -81,7 +81,7 @@ public class Base16InputStreamTest {
@Test
public void testBase16InputStreamByChunk() throws IOException {
// Hello World test.
- byte[] encoded = StringUtils.getBytesUtf8("48656c6c6f20576f726c64");
+ byte[] encoded = StringUtils.getBytesUtf8("48656C6C6F20576F726C64");
byte[] decoded = StringUtils.getBytesUtf8(STRING_FIXTURE);
testByChunk(encoded, decoded);
@@ -91,7 +91,7 @@ public class Base16InputStreamTest {
testByChunk(encoded, decoded);
// OpenSSL interop test.
- encoded = StringUtils.getBytesUtf8(Base16TestData.ENCODED_UTF8_LOWERCASE);
+ encoded = StringUtils.getBytesUtf8(Base16TestData.ENCODED_UTF8_UPPERCASE);
decoded = Base16TestData.DECODED;
testByChunk(encoded, decoded);
@@ -100,7 +100,7 @@ public class Base16InputStreamTest {
final byte[][] randomData = Base16TestData.randomData(i);
encoded = randomData[1];
decoded = randomData[0];
- testByChunk(encoded, decoded);
+ testByChunk(encoded, decoded, true);
}
}
@@ -112,7 +112,7 @@ public class Base16InputStreamTest {
@Test
public void testBase16InputStreamByteByByte() throws IOException {
// Hello World test.
- byte[] encoded = StringUtils.getBytesUtf8("48656c6c6f20576f726c64");
+ byte[] encoded = StringUtils.getBytesUtf8("48656C6C6F20576F726C64");
byte[] decoded = StringUtils.getBytesUtf8(STRING_FIXTURE);
testByteByByte(encoded, decoded);
@@ -122,7 +122,7 @@ public class Base16InputStreamTest {
testByteByByte(encoded, decoded);
// OpenSSL interop test.
- encoded = StringUtils.getBytesUtf8(Base16TestData.ENCODED_UTF8_LOWERCASE);
+ encoded = StringUtils.getBytesUtf8(Base16TestData.ENCODED_UTF8_UPPERCASE);
decoded = Base16TestData.DECODED;
testByteByByte(encoded, decoded);
@@ -131,7 +131,7 @@ public class Base16InputStreamTest {
final byte[][] randomData = Base16TestData.randomData(i);
encoded = randomData[1];
decoded = randomData[0];
- testByteByByte(encoded, decoded);
+ testByteByByte(encoded, decoded, true);
}
}
@@ -147,38 +147,52 @@ public class Base16InputStreamTest {
* @throws IOException Usually signifies a bug in the Base16 commons-codec implementation.
*/
private void testByChunk(final byte[] encoded, final byte[] decoded) throws IOException {
+ testByChunk(encoded, decoded, false);
+ }
- // Start with encode.
- InputStream in;
- in = new Base16InputStream(new ByteArrayInputStream(decoded), true);
- byte[] output = Base16TestData.streamToBytes(in);
+ /**
+ * Tests method does three tests on the supplied data: 1. encoded ---[DECODE]--> decoded 2. decoded ---[ENCODE]--> encoded 3. decoded
+ * ---[WRAP-WRAP-WRAP-etc...] --> decoded
+ * <p/>
+ * By "[WRAP-WRAP-WRAP-etc...]" we mean situation where the Base16InputStream wraps itself in encode and decode mode over and over
+ * again.
+ *
+ * @param encoded Base16 encoded data
+ * @param decoded the data from above, but decoded
+ * @param lowerCase if {@code true} then use a lower-case Base16 alphabet
+ * @throws IOException Usually signifies a bug in the Base16 commons-codec implementation.
+ */
+ private void testByChunk(final byte[] encoded, final byte[] decoded, final boolean lowerCase) throws IOException {
- assertEquals("EOF", -1, in.read());
- assertEquals("Still EOF", -1, in.read());
- assertArrayEquals("Streaming Base16 encode", encoded, output);
+ // Start with encode.
+ try (final InputStream in = new Base16InputStream(new ByteArrayInputStream(decoded), true, lowerCase)) {
+ final byte[] output = Base16TestData.streamToBytes(in);
- in.close();
+ assertEquals("EOF", -1, in.read());
+ assertEquals("Still EOF", -1, in.read());
+ assertArrayEquals("Streaming Base16 encode", encoded, output);
+ }
// Now let's try decode.
- in = new Base16InputStream(new ByteArrayInputStream(encoded));
- output = Base16TestData.streamToBytes(in);
-
- assertEquals("EOF", -1, in.read());
- assertEquals("Still EOF", -1, in.read());
- assertArrayEquals("Streaming Base16 decode", decoded, output);
-
- // I always wanted to do this! (wrap encoder with decoder etc etc).
- in = new ByteArrayInputStream(decoded);
- for (int i = 0; i < 10; i++) {
- in = new Base16InputStream(in, true);
- in = new Base16InputStream(in, false);
+ try (final InputStream in = new Base16InputStream(new ByteArrayInputStream(encoded), false, lowerCase)) {
+ final byte[] output = Base16TestData.streamToBytes(in);
+
+ assertEquals("EOF", -1, in.read());
+ assertEquals("Still EOF", -1, in.read());
+ assertArrayEquals("Streaming Base16 decode", decoded, output);
}
- output = Base16TestData.streamToBytes(in);
- assertEquals("EOF", -1, in.read());
- assertEquals("Still EOF", -1, in.read());
- assertArrayEquals("Streaming Base16 wrap-wrap-wrap!", decoded, output);
- in.close();
+ // wrap encoder with decoder
+ try (final InputStream in = new ByteArrayInputStream(decoded);
+ final InputStream inEncode = new Base16InputStream(in, true, lowerCase);
+ final InputStream inDecode = new Base16InputStream(inEncode, false, lowerCase)) {
+
+ final byte[] output = Base16TestData.streamToBytes(inDecode);
+
+ assertEquals("EOF", -1, inDecode.read());
+ assertEquals("Still EOF", -1, inDecode.read());
+ assertArrayEquals("Streaming Base16 wrap-wrap!", decoded, output);
+ }
}
/**
@@ -193,48 +207,61 @@ public class Base16InputStreamTest {
* @throws IOException Usually signifies a bug in the Base16 commons-codec implementation.
*/
private void testByteByByte(final byte[] encoded, final byte[] decoded) throws IOException {
+ testByteByByte(encoded, decoded, false);
+ }
+
+ /**
+ * Tests method does three tests on the supplied data: 1. encoded ---[DECODE]--> decoded 2. decoded ---[ENCODE]--> encoded 3. decoded
+ * ---[WRAP-WRAP-WRAP-etc...] --> decoded
+ * <p/>
+ * By "[WRAP-WRAP-WRAP-etc...]" we mean situation where the Base16InputStream wraps itself in encode and decode mode over and over
+ * again.
+ *
+ * @param encoded Base16 encoded data
+ * @param decoded the data from above, but decoded
+ * @param lowerCase if {@code true} then use a lower-case Base16 alphabet
+ * @throws IOException Usually signifies a bug in the Base16 commons-codec implementation.
+ */
+ private void testByteByByte(final byte[] encoded, final byte[] decoded, final boolean lowerCase) throws IOException {
// Start with encode.
- InputStream in;
- in = new Base16InputStream(new ByteArrayInputStream(decoded), true);
- byte[] output = new byte[encoded.length];
- for (int i = 0; i < output.length; i++) {
- output[i] = (byte) in.read();
- }
+ try (final InputStream in = new Base16InputStream(new ByteArrayInputStream(decoded), true, lowerCase)) {
+ final byte[] output = new byte[encoded.length];
+ for (int i = 0; i < output.length; i++) {
+ output[i] = (byte) in.read();
+ }
- assertEquals("EOF", -1, in.read());
- assertEquals("Still EOF", -1, in.read());
- assertArrayEquals("Streaming Base16 encode", encoded, output);
+ assertEquals("EOF", -1, in.read());
+ assertEquals("Still EOF", -1, in.read());
+ assertArrayEquals("Streaming Base16 encode", encoded, output);
+ }
- in.close();
// Now let's try decode.
- in = new Base16InputStream(new ByteArrayInputStream(encoded));
- output = new byte[decoded.length];
- for (int i = 0; i < output.length; i++) {
- output[i] = (byte) in.read();
+ try (final InputStream in = new Base16InputStream(new ByteArrayInputStream(encoded), false, lowerCase)) {
+ final byte[] output = new byte[decoded.length];
+ for (int i = 0; i < output.length; i++) {
+ output[i] = (byte) in.read();
+ }
+
+ assertEquals("EOF", -1, in.read());
+ assertEquals("Still EOF", -1, in.read());
+ assertArrayEquals("Streaming Base16 decode", decoded, output);
}
- assertEquals("EOF", -1, in.read());
- assertEquals("Still EOF", -1, in.read());
- assertArrayEquals("Streaming Base16 decode", decoded, output);
+ // wrap encoder with decoder
+ try (final InputStream in = new ByteArrayInputStream(decoded);
+ final InputStream inEncode = new Base16InputStream(in, true, lowerCase);
+ final InputStream inDecode = new Base16InputStream(inEncode, false, lowerCase)) {
- in.close();
+ final byte[] output = new byte[decoded.length];
+ for (int i = 0; i < output.length; i++) {
+ output[i] = (byte) inDecode.read();
+ }
- // I always wanted to do this! (wrap encoder with decoder etc etc).
- in = new ByteArrayInputStream(decoded);
- for (int i = 0; i < 10; i++) {
- in = new Base16InputStream(in, true);
- in = new Base16InputStream(in, false);
+ assertEquals("EOF", -1, inDecode.read());
+ assertEquals("Still EOF", -1, inDecode.read());
+ assertArrayEquals("Streaming Base16 wrap-wrap!", decoded, output);
}
- output = new byte[decoded.length];
- for (int i = 0; i < output.length; i++) {
- output[i] = (byte) in.read();
- }
-
- assertEquals("EOF", -1, in.read());
- assertEquals("Still EOF", -1, in.read());
- assertArrayEquals("Streaming Base16 wrap-wrap-wrap!", decoded, output);
- in.close();
}
/**
diff --git a/src/test/java/org/apache/commons/codec/binary/Base16OutputStreamTest.java b/src/test/java/org/apache/commons/codec/binary/Base16OutputStreamTest.java
index 6f91f51..6bb5d34 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base16OutputStreamTest.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base16OutputStreamTest.java
@@ -54,7 +54,7 @@ public class Base16OutputStreamTest {
@Test
public void testBase16OutputStreamByChunk() throws Exception {
// Hello World test.
- byte[] encoded = StringUtils.getBytesUtf8("48656c6c6f20576f726c64");
+ byte[] encoded = StringUtils.getBytesUtf8("48656C6C6F20576F726C64");
byte[] decoded = StringUtils.getBytesUtf8(STRING_FIXTURE);
testByChunk(encoded, decoded);
@@ -68,7 +68,7 @@ public class Base16OutputStreamTest {
final byte[][] randomData = Base16TestData.randomData(i);
encoded = randomData[1];
decoded = randomData[0];
- testByChunk(encoded, decoded);
+ testByChunk(encoded, decoded, true);
}
}
@@ -80,7 +80,7 @@ public class Base16OutputStreamTest {
@Test
public void testBase16OutputStreamByteByByte() throws IOException {
// Hello World test.
- byte[] encoded = StringUtils.getBytesUtf8("48656c6c6f20576f726c64");
+ byte[] encoded = StringUtils.getBytesUtf8("48656C6C6F20576F726C64");
byte[] decoded = StringUtils.getBytesUtf8(STRING_FIXTURE);
testByteByByte(encoded, decoded);
@@ -94,7 +94,7 @@ public class Base16OutputStreamTest {
final byte[][] randomData = Base16TestData.randomData(i);
encoded = randomData[1];
decoded = randomData[0];
- testByteByByte(encoded, decoded);
+ testByteByByte(encoded, decoded, true);
}
}
@@ -105,43 +105,54 @@ public class Base16OutputStreamTest {
* By "[WRAP-WRAP-WRAP-etc...]" we mean situation where the Base16OutputStream wraps itself in encode and decode
* mode over and over again.
*
- * @param encoded
- * base16 encoded data
- * @param decoded
- * the data from above, but decoded
- * @throws IOException
- * Usually signifies a bug in the Base16 commons-codec implementation.
+ * @param encoded base16 encoded data
+ * @param decoded the data from above, but decoded
+ * @throws IOException Usually signifies a bug in the Base16 commons-codec implementation.
*/
private void testByChunk(final byte[] encoded, final byte[] decoded) throws IOException {
+ testByChunk(encoded, decoded, false);
+ }
+
+ /**
+ * Test method does three tests on the supplied data: 1. encoded ---[DECODE]--> decoded 2. decoded ---[ENCODE]-->
+ * encoded 3. decoded ---[WRAP-WRAP-WRAP-etc...] --> decoded
+ * <p/>
+ * By "[WRAP-WRAP-WRAP-etc...]" we mean situation where the Base16OutputStream wraps itself in encode and decode
+ * mode over and over again.
+ *
+ * @param encoded base16 encoded data
+ * @param decoded the data from above, but decoded
+ * @param lowerCase if {@code true} then use a lower-case Base16 alphabet
+ * @throws IOException Usually signifies a bug in the Base16 commons-codec implementation.
+ */
+ private void testByChunk(final byte[] encoded, final byte[] decoded, final boolean lowerCase) throws IOException {
// Start with encode.
- ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
- OutputStream out = new Base16OutputStream(byteOut, true);
- out.write(decoded);
- out.close();
- byte[] output = byteOut.toByteArray();
- assertArrayEquals("Streaming chunked base16 encode", encoded, output);
+ try (final ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
+ final OutputStream out = new Base16OutputStream(byteOut, true, lowerCase)) {
+ out.write(decoded);
+ final byte[] output = byteOut.toByteArray();
+ assertArrayEquals("Streaming chunked base16 encode", encoded, output);
+ }
// Now let's try decode.
- byteOut = new ByteArrayOutputStream();
- out = new Base16OutputStream(byteOut, false);
- out.write(encoded);
- out.close();
- output = byteOut.toByteArray();
- assertArrayEquals("Streaming chunked base16 decode", decoded, output);
-
- // I always wanted to do this! (wrap encoder with decoder etc etc).
- byteOut = new ByteArrayOutputStream();
- out = byteOut;
- for (int i = 0; i < 10; i++) {
- out = new Base16OutputStream(out, false);
- out = new Base16OutputStream(out, true);
+ try (final ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
+ final OutputStream out = new Base16OutputStream(byteOut, false, lowerCase)) {
+ out.write(encoded);
+ final byte[] output = byteOut.toByteArray();
+ assertArrayEquals("Streaming chunked base16 decode", decoded, output);
}
- out.write(decoded);
- out.close();
- output = byteOut.toByteArray();
- assertArrayEquals("Streaming chunked base16 wrap-wrap-wrap!", decoded, output);
+ // wrap encoder with decoder
+ try (final ByteArrayOutputStream byteOut = new ByteArrayOutputStream()) {
+ final OutputStream decoderOut = new Base16OutputStream(byteOut, false, lowerCase);
+ final OutputStream encoderOut = new Base16OutputStream(decoderOut, true, lowerCase);
+
+ encoderOut.write(decoded);
+ final byte[] output = byteOut.toByteArray();
+
+ assertArrayEquals("Streaming chunked base16 wrap-wrap!", decoded, output);
+ }
}
/**
@@ -151,60 +162,68 @@ public class Base16OutputStreamTest {
* By "[WRAP-WRAP-WRAP-etc...]" we mean situation where the Base16OutputStream wraps itself in encode and decode
* mode over and over again.
*
- * @param encoded
- * base16 encoded data
- * @param decoded
- * the data from above, but decoded
- * @throws IOException
- * Usually signifies a bug in the Base16 commons-codec implementation.
+ * @param encoded base16 encoded data
+ * @param decoded the data from above, but decoded
+ * @throws IOException Usually signifies a bug in the Base16 commons-codec implementation.
*/
private void testByteByByte(final byte[] encoded, final byte[] decoded) throws IOException {
+ testByteByByte(encoded, decoded, false);
+ }
+
+ /**
+ * Test method does three tests on the supplied data: 1. encoded ---[DECODE]--> decoded 2. decoded ---[ENCODE]-->
+ * encoded 3. decoded ---[WRAP-WRAP-WRAP-etc...] --> decoded
+ * <p/>
+ * By "[WRAP-WRAP-WRAP-etc...]" we mean situation where the Base16OutputStream wraps itself in encode and decode
+ * mode over and over again.
+ *
+ * @param encoded base16 encoded data
+ * @param decoded the data from above, but decoded
+ * @throws IOException Usually signifies a bug in the Base16 commons-codec implementation.
+ */
+ private void testByteByByte(final byte[] encoded, final byte[] decoded, final boolean lowerCase) throws IOException {
// Start with encode.
- ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
- OutputStream out = new Base16OutputStream(byteOut, true);
- for (final byte element : decoded) {
- out.write(element);
+ try (final ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
+ final OutputStream out = new Base16OutputStream(byteOut, true, lowerCase)) {
+ for (final byte element : decoded) {
+ out.write(element);
+ }
+ final byte[] output = byteOut.toByteArray();
+ assertArrayEquals("Streaming byte-by-byte base16 encode", encoded, output);
}
- out.close();
- byte[] output = byteOut.toByteArray();
- assertArrayEquals("Streaming byte-by-byte base16 encode", encoded, output);
// Now let's try decode.
- byteOut = new ByteArrayOutputStream();
- out = new Base16OutputStream(byteOut, false);
- for (final byte element : encoded) {
- out.write(element);
+ try (final ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
+ final OutputStream out = new Base16OutputStream(byteOut, false, lowerCase)) {
+ for (final byte element : encoded) {
+ out.write(element);
+ }
+ final byte[] output = byteOut.toByteArray();
+ assertArrayEquals("Streaming byte-by-byte base16 decode", decoded, output);
}
- out.close();
- output = byteOut.toByteArray();
- assertArrayEquals("Streaming byte-by-byte base16 decode", decoded, output);
// Now let's try decode with tonnes of flushes.
- byteOut = new ByteArrayOutputStream();
- out = new Base16OutputStream(byteOut, false);
- for (final byte element : encoded) {
- out.write(element);
- out.flush();
- }
- out.close();
- output = byteOut.toByteArray();
- assertArrayEquals("Streaming byte-by-byte flush() base16 decode", decoded, output);
-
- // I always wanted to do this! (wrap encoder with decoder etc etc).
- byteOut = new ByteArrayOutputStream();
- out = byteOut;
- for (int i = 0; i < 10; i++) {
- out = new Base16OutputStream(out, false);
- out = new Base16OutputStream(out, true);
- }
- for (final byte element : decoded) {
- out.write(element);
+ try (final ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
+ final OutputStream out = new Base16OutputStream(byteOut, false, lowerCase)) {
+ for (final byte element : encoded) {
+ out.write(element);
+ out.flush();
+ }
+ final byte[] output = byteOut.toByteArray();
+ assertArrayEquals("Streaming byte-by-byte flush() base16 decode", decoded, output);
}
- out.close();
- output = byteOut.toByteArray();
- assertArrayEquals("Streaming byte-by-byte base16 wrap-wrap-wrap!", decoded, output);
+ // wrap encoder with decoder
+ try (final ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
+ final OutputStream decoderOut = new Base16OutputStream(byteOut, false, lowerCase);
+ final OutputStream encoderOut = new Base16OutputStream(decoderOut, true, lowerCase)) {
+ for (final byte element : decoded) {
+ encoderOut.write(element);
+ }
+ final byte[] output = byteOut.toByteArray();
+ assertArrayEquals("Streaming byte-by-byte base16 wrap-wrap!", decoded, output);
+ }
}
/**
diff --git a/src/test/java/org/apache/commons/codec/binary/Base16Test.java b/src/test/java/org/apache/commons/codec/binary/Base16Test.java
index eb273fa..989520a 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base16Test.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base16Test.java
@@ -29,11 +29,9 @@ import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Random;
-import static org.apache.commons.codec.CharEncoding.UTF_8;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -56,43 +54,18 @@ public class Base16Test {
}
/**
- * Test the isStringBase16 method.
- */
- @Test
- public void testIsStringBase16() {
- final String nullString = null;
- final String emptyString = "";
- final String validString = "cafebabec0a1f2e3b4a5b6e7c8";
- final String invalidString = validString + (char) 0; // append null
- // character
-
- try {
- Base16.isBase16(nullString);
- fail("Base16.isStringBase16() should not be null-safe.");
- } catch (final NullPointerException npe) {
- assertNotNull("Base16.isStringBase16() should not be null-safe.", npe);
- }
-
- assertTrue("Base16.isStringBase16(empty-string) is true", Base16.isBase16(emptyString));
- assertTrue("Base16.isStringBase16(valid-string) is true", Base16.isBase16(validString));
- assertFalse("Base16.isStringBase16(invalid-string) is false", Base16.isBase16(invalidString));
- }
-
- /**
* Test the Base16 implementation
*/
@Test
public void testBase16() {
final String content = "Hello World";
- String encodedContent;
- byte[] encodedBytes = Base16.encodeBase16(StringUtils.getBytesUtf8(content));
- encodedContent = StringUtils.newStringUtf8(encodedBytes);
- assertEquals("encoding hello world", "48656c6c6f20576f726c64", encodedContent);
+ final byte[] encodedBytes = new Base16().encode(StringUtils.getBytesUtf8(content));
+ final String encodedContent = StringUtils.newStringUtf8(encodedBytes);
+ assertEquals("encoding hello world", "48656C6C6F20576F726C64", encodedContent);
- Base16 b16 = new Base16();
- encodedBytes = b16.encode(StringUtils.getBytesUtf8(content));
- encodedContent = StringUtils.newStringUtf8(encodedBytes);
- assertEquals("encoding hello world", "48656c6c6f20576f726c64", encodedContent);
+ final byte[] decodedBytes = new Base16().decode(encodedBytes);
+ final String decodedContent = StringUtils.newStringUtf8(decodedBytes);
+ assertEquals("decoding hello world", content, decodedContent);
}
@Test
@@ -118,7 +91,7 @@ public class Base16Test {
buffer = ArrayUtils.addAll(new byte[startPasSize], buffer);
final byte[] encodedBytes = new Base16().encode(buffer, startPasSize, bytesUtf8.length);
encodedContent = StringUtils.newStringUtf8(encodedBytes);
- assertEquals("encoding hello world", "48656c6c6f20576f726c64", encodedContent);
+ assertEquals("encoding hello world", "48656C6C6F20576F726C64", encodedContent);
}
/**
@@ -128,33 +101,35 @@ public class Base16Test {
@Test(expected=RuntimeException.class)
public void testCodec68() {
final byte[] x = new byte[] { 'n', 'H', '=', '=', (byte) 0x9c };
- Base16.decodeBase16(x);
+ final Base16 b16 = new Base16();
+ b16.decode(x);
}
@Test
public void testConstructors() {
new Base16();
- new Base16();
- new Base16(CHARSET_UTF8);
- new Base16(false, CHARSET_UTF8);
+ new Base16(false);
+ new Base16(true);
+ new Base16(false, CodecPolicy.LENIENT);
+ new Base16(false, CodecPolicy.STRICT);
}
@Test
- public void testConstructor_Charset() {
- final Base16 Base16 = new Base16(CHARSET_UTF8);
+ public void testConstructor_LowerCase() {
+ final Base16 Base16 = new Base16(true);
final byte[] encoded = Base16.encode(Base16TestData.DECODED);
final String expectedResult = Base16TestData.ENCODED_UTF8_LOWERCASE;
final String result = StringUtils.newStringUtf8(encoded);
- assertEquals("new Base16(UTF_8)", expectedResult, result);
+ assertEquals("new Base16(true)", expectedResult, result);
}
@Test
- public void testConstructor_Boolean_Charset() {
- final Base16 Base16 = new Base16(false, CHARSET_UTF8);
+ public void testConstructor_LowerCase_DecodingPolicy() {
+ final Base16 Base16 = new Base16(false, CodecPolicy.STRICT);
final byte[] encoded = Base16.encode(Base16TestData.DECODED);
final String expectedResult = Base16TestData.ENCODED_UTF8_UPPERCASE;
final String result = StringUtils.newStringUtf8(encoded);
- assertEquals("new Base16(false, UTF_8)", result, expectedResult);
+ assertEquals("new Base16(false, CodecPolicy.STRICT)", result, expectedResult);
}
/**
@@ -163,14 +138,14 @@ public class Base16Test {
@Test
public void testEmptyBase16() {
byte[] empty = new byte[0];
- byte[] result = Base16.encodeBase16(empty);
+ byte[] result = new Base16().encode(empty);
assertEquals("empty Base16 encode", 0, result.length);
- assertEquals("empty Base16 encode", null, Base16.encodeBase16(null));
+ assertEquals("empty Base16 encode", null, new Base16().encode(null));
empty = new byte[0];
- result = Base16.decodeBase16(empty);
+ result = new Base16().decode(empty);
assertEquals("empty Base16 decode", 0, result.length);
- assertEquals("empty Base16 encode", null, Base16.decodeBase16((byte[]) null));
+ assertEquals("empty Base16 encode", null, new Base16().decode((byte[]) null));
}
// encode/decode a large random array
@@ -180,9 +155,8 @@ public class Base16Test {
final int len = this.getRandom().nextInt(10000) + 1;
final byte[] data = new byte[len];
this.getRandom().nextBytes(data);
- final byte[] enc = Base16.encodeBase16(data);
- assertTrue(Base16.isBase16(enc));
- final byte[] data2 = Base16.decodeBase16(enc);
+ final byte[] enc = new Base16().encode(data);
+ final byte[] data2 = new Base16().decode(enc);
assertArrayEquals(data, data2);
}
}
@@ -193,82 +167,46 @@ public class Base16Test {
for (int i = 0; i < 12; i++) {
final byte[] data = new byte[i];
this.getRandom().nextBytes(data);
- final byte[] enc = Base16.encodeBase16(data);
- assertTrue("\"" + new String(enc) + "\" is Base16 data.", Base16.isBase16(enc));
- final byte[] data2 = Base16.decodeBase16(enc);
+ final byte[] enc = new Base16().encode(data);
+ final byte[] data2 = new Base16().decode(enc);
assertArrayEquals(toString(data) + " equals " + toString(data2), data, data2);
}
}
@Test
- public void testEncodeOverMaxSize() {
- testEncodeOverMaxSize(-1);
- testEncodeOverMaxSize(0);
- testEncodeOverMaxSize(1);
- testEncodeOverMaxSize(2);
- }
-
- private void testEncodeOverMaxSize(final int maxSize) {
- try {
- Base16.encodeBase16(Base16TestData.DECODED, true, CHARSET_UTF8, maxSize);
- fail("Expected " + IllegalArgumentException.class.getName());
- } catch (final IllegalArgumentException e) {
- // Expected
- }
- }
-
- @Test
- public void testIsArrayByteBase16() {
- assertFalse(Base16.isBase16(new char[] { (char)Byte.MIN_VALUE }));
- assertFalse(Base16.isBase16(new char[] { (char)-125 }));
- assertFalse(Base16.isBase16(new char[] { (char)-10 }));
- assertFalse(Base16.isBase16(new char[] { 0 }));
- assertFalse(Base16.isBase16(new char[] { 64, Byte.MAX_VALUE }));
- assertFalse(Base16.isBase16(new char[] { Byte.MAX_VALUE }));
- assertTrue(Base16.isBase16(new char[] { 'A' }));
- assertFalse(Base16.isBase16(new char[] { 'A', (char)Byte.MIN_VALUE }));
- assertTrue(Base16.isBase16(new char[] { 'A', 'F', 'a' }));
- assertFalse(Base16.isBase16(new char[] { '/', '=', '+' }));
- assertFalse(Base16.isBase16(new char[] { '$' }));
- }
-
- @Test
public void testKnownDecodings() {
- assertEquals("The quick brown fox jumped over the lazy dogs.", new String(Base16.decodeBase16(
+ assertEquals("The quick brown fox jumped over the lazy dogs.", new String(new Base16(true).decode(
"54686520717569636b2062726f776e20666f78206a756d706564206f76657220746865206c617a7920646f67732e".getBytes(CHARSET_UTF8))));
- assertEquals("It was the best of times, it was the worst of times.", new String(Base16.decodeBase16(
+ assertEquals("It was the best of times, it was the worst of times.", new String(new Base16(true).decode(
"497420776173207468652062657374206f662074696d65732c206974207761732074686520776f727374206f662074696d65732e".getBytes(CHARSET_UTF8))));
assertEquals("http://jakarta.apache.org/commmons", new String(
- Base16.decodeBase16("687474703a2f2f6a616b617274612e6170616368652e6f72672f636f6d6d6d6f6e73".getBytes(CHARSET_UTF8))));
- assertEquals("AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz", new String(Base16.decodeBase16(
+ new Base16(true).decode("687474703a2f2f6a616b617274612e6170616368652e6f72672f636f6d6d6d6f6e73".getBytes(CHARSET_UTF8))));
+ assertEquals("AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz", new String(new Base16(true).decode(
"4161426243634464456546664767486849694a6a4b6b4c6c4d6d4e6e4f6f50705171527253735474557556765777587859795a7a".getBytes(CHARSET_UTF8))));
assertEquals("{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }",
- new String(Base16.decodeBase16("7b20302c20312c20322c20332c20342c20352c20362c20372c20382c2039207d".getBytes(CHARSET_UTF8))));
- assertEquals("xyzzy!", new String(Base16.decodeBase16("78797a7a7921".getBytes(CHARSET_UTF8))));
+ new String(new Base16(true).decode("7b20302c20312c20322c20332c20342c20352c20362c20372c20382c2039207d".getBytes(CHARSET_UTF8))));
+ assertEquals("xyzzy!", new String(new Base16(true).decode("78797a7a7921".getBytes(CHARSET_UTF8))));
}
@Test
public void testKnownEncodings() {
assertEquals("54686520717569636b2062726f776e20666f78206a756d706564206f76657220746865206c617a7920646f67732e", new String(
- Base16.encodeBase16("The quick brown fox jumped over the lazy dogs.".getBytes(CHARSET_UTF8))));
+ new Base16(true).encode("The quick brown fox jumped over the lazy dogs.".getBytes(CHARSET_UTF8))));
assertEquals("497420776173207468652062657374206f662074696d65732c206974207761732074686520776f727374206f662074696d65732e", new String(
- Base16.encodeBase16("It was the best of times, it was the worst of times.".getBytes(CHARSET_UTF8))));
+ new Base16(true).encode("It was the best of times, it was the worst of times.".getBytes(CHARSET_UTF8))));
assertEquals("687474703a2f2f6a616b617274612e6170616368652e6f72672f636f6d6d6d6f6e73",
- new String(Base16.encodeBase16("http://jakarta.apache.org/commmons".getBytes(CHARSET_UTF8))));
+ new String(new Base16(true).encode("http://jakarta.apache.org/commmons".getBytes(CHARSET_UTF8))));
assertEquals("4161426243634464456546664767486849694a6a4b6b4c6c4d6d4e6e4f6f50705171527253735474557556765777587859795a7a", new String(
- Base16.encodeBase16("AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz".getBytes(CHARSET_UTF8))));
+ new Base16(true).encode("AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz".getBytes(CHARSET_UTF8))));
assertEquals("7b20302c20312c20322c20332c20342c20352c20362c20372c20382c2039207d",
- new String(Base16.encodeBase16("{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }".getBytes(CHARSET_UTF8))));
- assertEquals("78797a7a7921", new String(Base16.encodeBase16("xyzzy!".getBytes(CHARSET_UTF8))));
+ new String(new Base16(true).encode("{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }".getBytes(CHARSET_UTF8))));
+ assertEquals("78797a7a7921", new String(new Base16(true).encode("xyzzy!".getBytes(CHARSET_UTF8))));
}
@Test
public void testNonBase16Test() {
final byte[] bArray = { '%' };
- assertFalse("Invalid Base16 array was incorrectly validated as " + "an array of Base16 encoded data",
- Base16.isBase16(bArray));
-
try {
final Base16 b16 = new Base16();
final byte[] result = b16.decode(bArray);
@@ -296,7 +234,7 @@ public class Base16Test {
@Test
public void testObjectDecodeWithValidParameter() throws Exception {
final String original = "Hello World!";
- final Object o = Base16.encodeBase16(original.getBytes(CHARSET_UTF8));
+ final Object o = new Base16().encode(original.getBytes(CHARSET_UTF8));
final Base16 b16 = new Base16();
final Object oDecoded = b16.decode(o);
@@ -322,9 +260,8 @@ public class Base16Test {
final String original = "Hello World!";
final Object origObj = original.getBytes(CHARSET_UTF8);
- final Base16 b16 = new Base16();
- final Object oEncoded = b16.encode(origObj);
- final byte[] bArray = Base16.decodeBase16((byte[]) oEncoded);
+ final Object oEncoded = new Base16().encode(origObj);
+ final byte[] bArray = new Base16().decode((byte[]) oEncoded);
final String dest = new String(bArray);
assertEquals("dest string does not equal original", original, dest);
@@ -333,149 +270,166 @@ public class Base16Test {
@Test
public void testObjectEncode() {
final Base16 b16 = new Base16();
- assertEquals("48656c6c6f20576f726c64", new String(b16.encode("Hello World".getBytes(CHARSET_UTF8))));
+ assertEquals("48656C6C6F20576F726C64", new String(b16.encode("Hello World".getBytes(CHARSET_UTF8))));
}
@Test
public void testPairs() {
- assertEquals("0000", new String(Base16.encodeBase16(new byte[] { 0, 0 })));
+ assertEquals("0000", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 0 })));
+ assertEquals("0001", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 1 })));
+ assertEquals("0002", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 2 })));
+ assertEquals("0003", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 3 })));
+ assertEquals("0004", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 4 })));
+ assertEquals("0005", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 5 })));
+ assertEquals("0006", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 6 })));
+ assertEquals("0007", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 7 })));
+ assertEquals("0008", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 8 })));
+ assertEquals("0009", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 9 })));
+ assertEquals("000A", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 10 })));
+ assertEquals("000B", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 11 })));
+ assertEquals("000C", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 12 })));
+ assertEquals("000D", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 13 })));
+ assertEquals("000E", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 14 })));
+ assertEquals("000F", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 15 })));
+ assertEquals("0010", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 16 })));
+ assertEquals("0011", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 17 })));
for (int i = -128; i <= 127; i++) {
final byte test[] = { (byte) i, (byte) i };
- assertArrayEquals(test, Base16.decodeBase16(Base16.encodeBase16(test)));
+ assertArrayEquals(test, new Base16().decode(new Base16().encode(test)));
}
}
@Test
public void testSingletons() {
- assertEquals("00", new String(Base16.encodeBase16(new byte[] { (byte) 0 })));
- assertEquals("01", new String(Base16.encodeBase16(new byte[] { (byte) 1 })));
- assertEquals("02", new String(Base16.encodeBase16(new byte[] { (byte) 2 })));
- assertEquals("03", new String(Base16.encodeBase16(new byte[] { (byte) 3 })));
- assertEquals("04", new String(Base16.encodeBase16(new byte[] { (byte) 4 })));
- assertEquals("05", new String(Base16.encodeBase16(new byte[] { (byte) 5 })));
- assertEquals("06", new String(Base16.encodeBase16(new byte[] { (byte) 6 })));
- assertEquals("07", new String(Base16.encodeBase16(new byte[] { (byte) 7 })));
- assertEquals("08", new String(Base16.encodeBase16(new byte[] { (byte) 8 })));
- assertEquals("09", new String(Base16.encodeBase16(new byte[] { (byte) 9 })));
- assertEquals("0a", new String(Base16.encodeBase16(new byte[] { (byte) 10 })));
- assertEquals("0b", new String(Base16.encodeBase16(new byte[] { (byte) 11 })));
- assertEquals("0c", new String(Base16.encodeBase16(new byte[] { (byte) 12 })));
- assertEquals("0d", new String(Base16.encodeBase16(new byte[] { (byte) 13 })));
- assertEquals("0e", new String(Base16.encodeBase16(new byte[] { (byte) 14 })));
- assertEquals("0f", new String(Base16.encodeBase16(new byte[] { (byte) 15 })));
- assertEquals("10", new String(Base16.encodeBase16(new byte[] { (byte) 16 })));
- assertEquals("11", new String(Base16.encodeBase16(new byte[] { (byte) 17 })));
- assertEquals("12", new String(Base16.encodeBase16(new byte[] { (byte) 18 })));
- assertEquals("13", new String(Base16.encodeBase16(new byte[] { (byte) 19 })));
- assertEquals("14", new String(Base16.encodeBase16(new byte[] { (byte) 20 })));
- assertEquals("15", new String(Base16.encodeBase16(new byte[] { (byte) 21 })));
- assertEquals("16", new String(Base16.encodeBase16(new byte[] { (byte) 22 })));
- assertEquals("17", new String(Base16.encodeBase16(new byte[] { (byte) 23 })));
- assertEquals("18", new String(Base16.encodeBase16(new byte[] { (byte) 24 })));
- assertEquals("19", new String(Base16.encodeBase16(new byte[] { (byte) 25 })));
- assertEquals("1a", new String(Base16.encodeBase16(new byte[] { (byte) 26 })));
- assertEquals("1b", new String(Base16.encodeBase16(new byte[] { (byte) 27 })));
- assertEquals("1c", new String(Base16.encodeBase16(new byte[] { (byte) 28 })));
- assertEquals("1d", new String(Base16.encodeBase16(new byte[] { (byte) 29 })));
- assertEquals("1e", new String(Base16.encodeBase16(new byte[] { (byte) 30 })));
- assertEquals("1f", new String(Base16.encodeBase16(new byte[] { (byte) 31 })));
- assertEquals("20", new String(Base16.encodeBase16(new byte[] { (byte) 32 })));
- assertEquals("21", new String(Base16.encodeBase16(new byte[] { (byte) 33 })));
- assertEquals("22", new String(Base16.encodeBase16(new byte[] { (byte) 34 })));
- assertEquals("23", new String(Base16.encodeBase16(new byte[] { (byte) 35 })));
- assertEquals("24", new String(Base16.encodeBase16(new byte[] { (byte) 36 })));
- assertEquals("25", new String(Base16.encodeBase16(new byte[] { (byte) 37 })));
- assertEquals("26", new String(Base16.encodeBase16(new byte[] { (byte) 38 })));
- assertEquals("27", new String(Base16.encodeBase16(new byte[] { (byte) 39 })));
- assertEquals("28", new String(Base16.encodeBase16(new byte[] { (byte) 40 })));
- assertEquals("29", new String(Base16.encodeBase16(new byte[] { (byte) 41 })));
- assertEquals("2a", new String(Base16.encodeBase16(new byte[] { (byte) 42 })));
- assertEquals("2b", new String(Base16.encodeBase16(new byte[] { (byte) 43 })));
- assertEquals("2c", new String(Base16.encodeBase16(new byte[] { (byte) 44 })));
- assertEquals("2d", new String(Base16.encodeBase16(new byte[] { (byte) 45 })));
- assertEquals("2e", new String(Base16.encodeBase16(new byte[] { (byte) 46 })));
- assertEquals("2f", new String(Base16.encodeBase16(new byte[] { (byte) 47 })));
- assertEquals("30", new String(Base16.encodeBase16(new byte[] { (byte) 48 })));
- assertEquals("31", new String(Base16.encodeBase16(new byte[] { (byte) 49 })));
- assertEquals("32", new String(Base16.encodeBase16(new byte[] { (byte) 50 })));
- assertEquals("33", new String(Base16.encodeBase16(new byte[] { (byte) 51 })));
- assertEquals("34", new String(Base16.encodeBase16(new byte[] { (byte) 52 })));
- assertEquals("35", new String(Base16.encodeBase16(new byte[] { (byte) 53 })));
- assertEquals("36", new String(Base16.encodeBase16(new byte[] { (byte) 54 })));
- assertEquals("37", new String(Base16.encodeBase16(new byte[] { (byte) 55 })));
- assertEquals("38", new String(Base16.encodeBase16(new byte[] { (byte) 56 })));
- assertEquals("39", new String(Base16.encodeBase16(new byte[] { (byte) 57 })));
- assertEquals("3a", new String(Base16.encodeBase16(new byte[] { (byte) 58 })));
- assertEquals("3b", new String(Base16.encodeBase16(new byte[] { (byte) 59 })));
- assertEquals("3c", new String(Base16.encodeBase16(new byte[] { (byte) 60 })));
- assertEquals("3d", new String(Base16.encodeBase16(new byte[] { (byte) 61 })));
- assertEquals("3e", new String(Base16.encodeBase16(new byte[] { (byte) 62 })));
- assertEquals("3f", new String(Base16.encodeBase16(new byte[] { (byte) 63 })));
- assertEquals("40", new String(Base16.encodeBase16(new byte[] { (byte) 64 })));
- assertEquals("41", new String(Base16.encodeBase16(new byte[] { (byte) 65 })));
- assertEquals("42", new String(Base16.encodeBase16(new byte[] { (byte) 66 })));
- assertEquals("43", new String(Base16.encodeBase16(new byte[] { (byte) 67 })));
- assertEquals("44", new String(Base16.encodeBase16(new byte[] { (byte) 68 })));
- assertEquals("45", new String(Base16.encodeBase16(new byte[] { (byte) 69 })));
- assertEquals("46", new String(Base16.encodeBase16(new byte[] { (byte) 70 })));
- assertEquals("47", new String(Base16.encodeBase16(new byte[] { (byte) 71 })));
- assertEquals("48", new String(Base16.encodeBase16(new byte[] { (byte) 72 })));
- assertEquals("49", new String(Base16.encodeBase16(new byte[] { (byte) 73 })));
- assertEquals("4a", new String(Base16.encodeBase16(new byte[] { (byte) 74 })));
- assertEquals("4b", new String(Base16.encodeBase16(new byte[] { (byte) 75 })));
- assertEquals("4c", new String(Base16.encodeBase16(new byte[] { (byte) 76 })));
- assertEquals("4d", new String(Base16.encodeBase16(new byte[] { (byte) 77 })));
- assertEquals("4e", new String(Base16.encodeBase16(new byte[] { (byte) 78 })));
- assertEquals("4f", new String(Base16.encodeBase16(new byte[] { (byte) 79 })));
- assertEquals("50", new String(Base16.encodeBase16(new byte[] { (byte) 80 })));
- assertEquals("51", new String(Base16.encodeBase16(new byte[] { (byte) 81 })));
- assertEquals("52", new String(Base16.encodeBase16(new byte[] { (byte) 82 })));
- assertEquals("53", new String(Base16.encodeBase16(new byte[] { (byte) 83 })));
- assertEquals("54", new String(Base16.encodeBase16(new byte[] { (byte) 84 })));
- assertEquals("55", new String(Base16.encodeBase16(new byte[] { (byte) 85 })));
- assertEquals("56", new String(Base16.encodeBase16(new byte[] { (byte) 86 })));
- assertEquals("57", new String(Base16.encodeBase16(new byte[] { (byte) 87 })));
- assertEquals("58", new String(Base16.encodeBase16(new byte[] { (byte) 88 })));
- assertEquals("59", new String(Base16.encodeBase16(new byte[] { (byte) 89 })));
- assertEquals("5a", new String(Base16.encodeBase16(new byte[] { (byte) 90 })));
- assertEquals("5b", new String(Base16.encodeBase16(new byte[] { (byte) 91 })));
- assertEquals("5c", new String(Base16.encodeBase16(new byte[] { (byte) 92 })));
- assertEquals("5d", new String(Base16.encodeBase16(new byte[] { (byte) 93 })));
- assertEquals("5e", new String(Base16.encodeBase16(new byte[] { (byte) 94 })));
- assertEquals("5f", new String(Base16.encodeBase16(new byte[] { (byte) 95 })));
- assertEquals("60", new String(Base16.encodeBase16(new byte[] { (byte) 96 })));
- assertEquals("61", new String(Base16.encodeBase16(new byte[] { (byte) 97 })));
- assertEquals("62", new String(Base16.encodeBase16(new byte[] { (byte) 98 })));
- assertEquals("63", new String(Base16.encodeBase16(new byte[] { (byte) 99 })));
- assertEquals("64", new String(Base16.encodeBase16(new byte[] { (byte) 100 })));
- assertEquals("65", new String(Base16.encodeBase16(new byte[] { (byte) 101 })));
- assertEquals("66", new String(Base16.encodeBase16(new byte[] { (byte) 102 })));
- assertEquals("67", new String(Base16.encodeBase16(new byte[] { (byte) 103 })));
- assertEquals("68", new String(Base16.encodeBase16(new byte[] { (byte) 104 })));
+ assertEquals("00", new String(new Base16().encode(new byte[] { (byte) 0 })));
+ assertEquals("01", new String(new Base16().encode(new byte[] { (byte) 1 })));
+ assertEquals("02", new String(new Base16().encode(new byte[] { (byte) 2 })));
+ assertEquals("03", new String(new Base16().encode(new byte[] { (byte) 3 })));
+ assertEquals("04", new String(new Base16().encode(new byte[] { (byte) 4 })));
+ assertEquals("05", new String(new Base16().encode(new byte[] { (byte) 5 })));
+ assertEquals("06", new String(new Base16().encode(new byte[] { (byte) 6 })));
+ assertEquals("07", new String(new Base16().encode(new byte[] { (byte) 7 })));
+ assertEquals("08", new String(new Base16().encode(new byte[] { (byte) 8 })));
+ assertEquals("09", new String(new Base16().encode(new byte[] { (byte) 9 })));
+ assertEquals("0A", new String(new Base16().encode(new byte[] { (byte) 10 })));
+ assertEquals("0B", new String(new Base16().encode(new byte[] { (byte) 11 })));
+ assertEquals("0C", new String(new Base16().encode(new byte[] { (byte) 12 })));
+ assertEquals("0D", new String(new Base16().encode(new byte[] { (byte) 13 })));
+ assertEquals("0E", new String(new Base16().encode(new byte[] { (byte) 14 })));
+ assertEquals("0F", new String(new Base16().encode(new byte[] { (byte) 15 })));
+ assertEquals("10", new String(new Base16().encode(new byte[] { (byte) 16 })));
+ assertEquals("11", new String(new Base16().encode(new byte[] { (byte) 17 })));
+ assertEquals("12", new String(new Base16().encode(new byte[] { (byte) 18 })));
+ assertEquals("13", new String(new Base16().encode(new byte[] { (byte) 19 })));
+ assertEquals("14", new String(new Base16().encode(new byte[] { (byte) 20 })));
+ assertEquals("15", new String(new Base16().encode(new byte[] { (byte) 21 })));
+ assertEquals("16", new String(new Base16().encode(new byte[] { (byte) 22 })));
+ assertEquals("17", new String(new Base16().encode(new byte[] { (byte) 23 })));
+ assertEquals("18", new String(new Base16().encode(new byte[] { (byte) 24 })));
+ assertEquals("19", new String(new Base16().encode(new byte[] { (byte) 25 })));
+ assertEquals("1A", new String(new Base16().encode(new byte[] { (byte) 26 })));
+ assertEquals("1B", new String(new Base16().encode(new byte[] { (byte) 27 })));
+ assertEquals("1C", new String(new Base16().encode(new byte[] { (byte) 28 })));
+ assertEquals("1D", new String(new Base16().encode(new byte[] { (byte) 29 })));
+ assertEquals("1E", new String(new Base16().encode(new byte[] { (byte) 30 })));
+ assertEquals("1F", new String(new Base16().encode(new byte[] { (byte) 31 })));
+ assertEquals("20", new String(new Base16().encode(new byte[] { (byte) 32 })));
+ assertEquals("21", new String(new Base16().encode(new byte[] { (byte) 33 })));
+ assertEquals("22", new String(new Base16().encode(new byte[] { (byte) 34 })));
+ assertEquals("23", new String(new Base16().encode(new byte[] { (byte) 35 })));
+ assertEquals("24", new String(new Base16().encode(new byte[] { (byte) 36 })));
+ assertEquals("25", new String(new Base16().encode(new byte[] { (byte) 37 })));
+ assertEquals("26", new String(new Base16().encode(new byte[] { (byte) 38 })));
+ assertEquals("27", new String(new Base16().encode(new byte[] { (byte) 39 })));
+ assertEquals("28", new String(new Base16().encode(new byte[] { (byte) 40 })));
+ assertEquals("29", new String(new Base16().encode(new byte[] { (byte) 41 })));
+ assertEquals("2A", new String(new Base16().encode(new byte[] { (byte) 42 })));
+ assertEquals("2B", new String(new Base16().encode(new byte[] { (byte) 43 })));
+ assertEquals("2C", new String(new Base16().encode(new byte[] { (byte) 44 })));
+ assertEquals("2D", new String(new Base16().encode(new byte[] { (byte) 45 })));
+ assertEquals("2E", new String(new Base16().encode(new byte[] { (byte) 46 })));
+ assertEquals("2F", new String(new Base16().encode(new byte[] { (byte) 47 })));
+ assertEquals("30", new String(new Base16().encode(new byte[] { (byte) 48 })));
+ assertEquals("31", new String(new Base16().encode(new byte[] { (byte) 49 })));
+ assertEquals("32", new String(new Base16().encode(new byte[] { (byte) 50 })));
+ assertEquals("33", new String(new Base16().encode(new byte[] { (byte) 51 })));
+ assertEquals("34", new String(new Base16().encode(new byte[] { (byte) 52 })));
+ assertEquals("35", new String(new Base16().encode(new byte[] { (byte) 53 })));
+ assertEquals("36", new String(new Base16().encode(new byte[] { (byte) 54 })));
+ assertEquals("37", new String(new Base16().encode(new byte[] { (byte) 55 })));
+ assertEquals("38", new String(new Base16().encode(new byte[] { (byte) 56 })));
+ assertEquals("39", new String(new Base16().encode(new byte[] { (byte) 57 })));
+ assertEquals("3A", new String(new Base16().encode(new byte[] { (byte) 58 })));
+ assertEquals("3B", new String(new Base16().encode(new byte[] { (byte) 59 })));
+ assertEquals("3C", new String(new Base16().encode(new byte[] { (byte) 60 })));
+ assertEquals("3D", new String(new Base16().encode(new byte[] { (byte) 61 })));
+ assertEquals("3E", new String(new Base16().encode(new byte[] { (byte) 62 })));
+ assertEquals("3F", new String(new Base16().encode(new byte[] { (byte) 63 })));
+ assertEquals("40", new String(new Base16().encode(new byte[] { (byte) 64 })));
+ assertEquals("41", new String(new Base16().encode(new byte[] { (byte) 65 })));
+ assertEquals("42", new String(new Base16().encode(new byte[] { (byte) 66 })));
+ assertEquals("43", new String(new Base16().encode(new byte[] { (byte) 67 })));
+ assertEquals("44", new String(new Base16().encode(new byte[] { (byte) 68 })));
+ assertEquals("45", new String(new Base16().encode(new byte[] { (byte) 69 })));
+ assertEquals("46", new String(new Base16().encode(new byte[] { (byte) 70 })));
+ assertEquals("47", new String(new Base16().encode(new byte[] { (byte) 71 })));
+ assertEquals("48", new String(new Base16().encode(new byte[] { (byte) 72 })));
+ assertEquals("49", new String(new Base16().encode(new byte[] { (byte) 73 })));
+ assertEquals("4A", new String(new Base16().encode(new byte[] { (byte) 74 })));
+ assertEquals("4B", new String(new Base16().encode(new byte[] { (byte) 75 })));
+ assertEquals("4C", new String(new Base16().encode(new byte[] { (byte) 76 })));
+ assertEquals("4D", new String(new Base16().encode(new byte[] { (byte) 77 })));
+ assertEquals("4E", new String(new Base16().encode(new byte[] { (byte) 78 })));
+ assertEquals("4F", new String(new Base16().encode(new byte[] { (byte) 79 })));
+ assertEquals("50", new String(new Base16().encode(new byte[] { (byte) 80 })));
+ assertEquals("51", new String(new Base16().encode(new byte[] { (byte) 81 })));
+ assertEquals("52", new String(new Base16().encode(new byte[] { (byte) 82 })));
+ assertEquals("53", new String(new Base16().encode(new byte[] { (byte) 83 })));
+ assertEquals("54", new String(new Base16().encode(new byte[] { (byte) 84 })));
+ assertEquals("55", new String(new Base16().encode(new byte[] { (byte) 85 })));
+ assertEquals("56", new String(new Base16().encode(new byte[] { (byte) 86 })));
+ assertEquals("57", new String(new Base16().encode(new byte[] { (byte) 87 })));
+ assertEquals("58", new String(new Base16().encode(new byte[] { (byte) 88 })));
+ assertEquals("59", new String(new Base16().encode(new byte[] { (byte) 89 })));
+ assertEquals("5A", new String(new Base16().encode(new byte[] { (byte) 90 })));
+ assertEquals("5B", new String(new Base16().encode(new byte[] { (byte) 91 })));
+ assertEquals("5C", new String(new Base16().encode(new byte[] { (byte) 92 })));
+ assertEquals("5D", new String(new Base16().encode(new byte[] { (byte) 93 })));
+ assertEquals("5E", new String(new Base16().encode(new byte[] { (byte) 94 })));
+ assertEquals("5F", new String(new Base16().encode(new byte[] { (byte) 95 })));
+ assertEquals("60", new String(new Base16().encode(new byte[] { (byte) 96 })));
+ assertEquals("61", new String(new Base16().encode(new byte[] { (byte) 97 })));
+ assertEquals("62", new String(new Base16().encode(new byte[] { (byte) 98 })));
+ assertEquals("63", new String(new Base16().encode(new byte[] { (byte) 99 })));
+ assertEquals("64", new String(new Base16().encode(new byte[] { (byte) 100 })));
+ assertEquals("65", new String(new Base16().encode(new byte[] { (byte) 101 })));
+ assertEquals("66", new String(new Base16().encode(new byte[] { (byte) 102 })));
+ assertEquals("67", new String(new Base16().encode(new byte[] { (byte) 103 })));
+ assertEquals("68", new String(new Base16().encode(new byte[] { (byte) 104 })));
for (int i = -128; i <= 127; i++) {
final byte test[] = { (byte) i };
- assertTrue(Arrays.equals(test, Base16.decodeBase16(Base16.encodeBase16(test))));
+ assertTrue(Arrays.equals(test, new Base16().decode(new Base16().encode(test))));
}
}
@Test
public void testTriplets() {
- assertEquals("000000", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 0 })));
- assertEquals("000001", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 1 })));
- assertEquals("000002", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 2 })));
- assertEquals("000003", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 3 })));
- assertEquals("000004", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 4 })));
- assertEquals("000005", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 5 })));
- assertEquals("000006", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 6 })));
- assertEquals("000007", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 7 })));
- assertEquals("000008", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 8 })));
- assertEquals("000009", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 9 })));
- assertEquals("00000a", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 10 })));
- assertEquals("00000b", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 11 })));
- assertEquals("00000c", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 12 })));
- assertEquals("00000d", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 13 })));
- assertEquals("00000e", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 14 })));
- assertEquals("00000f", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 15 })));
+ assertEquals("000000", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 0, (byte) 0 })));
+ assertEquals("000001", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 0, (byte) 1 })));
+ assertEquals("000002", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 0, (byte) 2 })));
+ assertEquals("000003", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 0, (byte) 3 })));
+ assertEquals("000004", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 0, (byte) 4 })));
+ assertEquals("000005", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 0, (byte) 5 })));
+ assertEquals("000006", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 0, (byte) 6 })));
+ assertEquals("000007", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 0, (byte) 7 })));
+ assertEquals("000008", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 0, (byte) 8 })));
+ assertEquals("000009", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 0, (byte) 9 })));
+ assertEquals("00000A", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 0, (byte) 10 })));
+ assertEquals("00000B", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 0, (byte) 11 })));
+ assertEquals("00000C", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 0, (byte) 12 })));
+ assertEquals("00000D", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 0, (byte) 13 })));
+ assertEquals("00000E", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 0, (byte) 14 })));
+ assertEquals("00000F", new String(new Base16().encode(new byte[] { (byte) 0, (byte) 0, (byte) 15 })));
}
@Test
@@ -485,30 +439,30 @@ public class Base16Test {
final byte[] b2 = new byte[0];
final byte[] b3 = null;
- assertEquals("byteToString Hello World", "48656c6c6f20576f726c64", Base16.encodeToString(b1));
- assertEquals("byteToString static Hello World", "48656c6c6f20576f726c64", StringUtils.newStringUtf8(Base16.encodeBase16(b1)));
+ assertEquals("byteToString Hello World", "48656C6C6F20576F726C64", Base16.encodeToString(b1));
+ assertEquals("byteToString static Hello World", "48656C6C6F20576F726C64", StringUtils.newStringUtf8(new Base16().encode(b1)));
assertEquals("byteToString \"\"", "", Base16.encodeToString(b2));
- assertEquals("byteToString static \"\"", "", StringUtils.newStringUtf8(Base16.encodeBase16(b2)));
+ assertEquals("byteToString static \"\"", "", StringUtils.newStringUtf8(new Base16().encode(b2)));
assertEquals("byteToString null", null, Base16.encodeToString(b3));
- assertEquals("byteToString static null", null, StringUtils.newStringUtf8(Base16.encodeBase16(b3)));
+ assertEquals("byteToString static null", null, StringUtils.newStringUtf8(new Base16().encode(b3)));
}
@Test
public void testStringToByteVariations() throws DecoderException {
final Base16 Base16 = new Base16();
- final String s1 = "48656c6c6f20576f726c64";
+ final String s1 = "48656C6C6F20576F726C64";
final String s2 = "";
final String s3 = null;
assertEquals("StringToByte Hello World", "Hello World", StringUtils.newStringUtf8(Base16.decode(s1)));
assertEquals("StringToByte Hello World", "Hello World",
- StringUtils.newStringUtf8((byte[]) Base16.decode((Object) s1)));
+ StringUtils.newStringUtf8((byte[]) new Base16().decode((Object) s1)));
assertEquals("StringToByte static Hello World", "Hello World",
- StringUtils.newStringUtf8(Base16.decodeBase16(s1)));
- assertEquals("StringToByte \"\"", "", StringUtils.newStringUtf8(Base16.decode(s2)));
- assertEquals("StringToByte static \"\"", "", StringUtils.newStringUtf8(Base16.decodeBase16(s2)));
- assertEquals("StringToByte null", null, StringUtils.newStringUtf8(Base16.decode(s3)));
- assertEquals("StringToByte static null", null, StringUtils.newStringUtf8(Base16.decodeBase16(s3)));
+ StringUtils.newStringUtf8(new Base16().decode(s1)));
+ assertEquals("StringToByte \"\"", "", StringUtils.newStringUtf8(new Base16().decode(s2)));
+ assertEquals("StringToByte static \"\"", "", StringUtils.newStringUtf8(new Base16().decode(s2)));
+ assertEquals("StringToByte null", null, StringUtils.newStringUtf8(new Base16().decode(s3)));
+ assertEquals("StringToByte static null", null, StringUtils.newStringUtf8(new Base16().decode(s3)));
}
private String toString(final byte[] data) {
@@ -523,14 +477,13 @@ public class Base16Test {
}
/**
- * Test for CODEC-265: Encode a 1GiB file.
+ * Test for CODEC-265: Encode a ~1GiB file.
*
* @see <a href="https://issues.apache.org/jira/projects/CODEC/issues/CODEC-265">CODEC-265</a>
*/
- @Test(expected = IllegalArgumentException.class)
public void testCodec265_over() {
- // 1GiB file to encode: 2^30 bytes
- final int size1GiB = 1 << 30;
+ // almost 1GiB file to encode: 2^29 bytes
+ final int size1GiB = 1 << 29;
// Expecting a size of 2 output bytes per 1 input byte
final int blocks = size1GiB;
@@ -551,14 +504,24 @@ public class Base16Test {
Assume.assumeTrue("Not enough free memory for the test", presumableFreeMemory > estimatedMemory);
final byte[] bytes = new byte[size1GiB];
- final byte[] encoded = Base16.encodeBase16(bytes);
+ final byte[] encoded = new Base16().encode(bytes);
assertEquals(expectedLength, encoded.length);
}
@Test
public void testIsInAlphabet() {
+ // invalid bounds
+ Base16 b16 = new Base16(true);
+ assertFalse(b16.isInAlphabet((byte)0));
+ assertFalse(b16.isInAlphabet((byte)1));
+ assertFalse(b16.isInAlphabet((byte)-1));
+ assertFalse(b16.isInAlphabet((byte)-15));
+ assertFalse(b16.isInAlphabet((byte)-16));
+ assertFalse(b16.isInAlphabet((byte)128));
+ assertFalse(b16.isInAlphabet((byte)255));
+
// lower-case
- Base16 b16 = new Base16(true, CHARSET_UTF8);
+ b16 = new Base16(true);
for (char c = '0'; c <= '9'; c++) {
assertTrue(b16.isInAlphabet((byte) c));
}
@@ -574,7 +537,7 @@ public class Base16Test {
assertFalse(b16.isInAlphabet((byte) ('z' + 1)));
// upper-case
- b16 = new Base16(false, CHARSET_UTF8);
+ b16 = new Base16(false);
for (char c = '0'; c <= '9'; c++) {
assertTrue(b16.isInAlphabet((byte) c));
}
@@ -592,7 +555,7 @@ public class Base16Test {
@Test
public void testDecodeSingleBytes() {
- final String encoded = "556e74696c206e6578742074696d6521";
+ final String encoded = "556E74696C206E6578742074696D6521";
final BaseNCodec.Context context = new BaseNCodec.Context();
final Base16 b16 = new Base16();
@@ -620,11 +583,31 @@ public class Base16Test {
assertEquals("Until next time!", decoded);
}
+ @Test
+ public void testDecodeSingleBytesOptimisation() {
+ final BaseNCodec.Context context = new BaseNCodec.Context();
+ context.ibitWorkArea = 0;
+
+ final byte[] data = new byte[1];
+
+ final Base16 b16 = new Base16();
+
+ data[0] = (byte) 'E';
+ b16.decode(data, 0, 1, context);
+ assertEquals(69, context.ibitWorkArea);
+
+ data[0] = (byte) 'F';
+ b16.decode(data, 0, 1, context);
+ assertEquals(-1, context.ibitWorkArea);
+
+ assertEquals(-17, context.buffer[0]);
+ }
+
@Test(expected=IllegalArgumentException.class)
public void testStrictDecoding() {
final String encoded = "aabbccdde"; // Note the trailing `e` which does not make up a hex-pair and so is only 1/2 byte
- final Base16 b16 = new Base16(true, CHARSET_UTF8, CodecPolicy.STRICT);
+ final Base16 b16 = new Base16(true, CodecPolicy.STRICT);
b16.decode(StringUtils.getBytesUtf8(encoded));
}
@@ -632,7 +615,7 @@ public class Base16Test {
public void testLenientDecoding() {
final String encoded = "aabbccdde"; // Note the trailing `e` which does not make up a hex-pair and so is only 1/2 byte
- final Base16 b16 = new Base16(true, CHARSET_UTF8, CodecPolicy.LENIENT);
+ final Base16 b16 = new Base16(true, CodecPolicy.LENIENT);
final byte[] decoded = b16.decode(StringUtils.getBytesUtf8(encoded));
assertArrayEquals(new byte[] {(byte)0xaa, (byte)0xbb, (byte)0xcc, (byte)0xdd}, decoded);
This is an automated email from the ASF dual-hosted git repository.
aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-codec.git
commit 564c47cbcbe3ade57c106ed83fa83d910d30d408
Author: Adam Retter <ad...@googlemail.com>
AuthorDate: Tue Apr 21 12:19:33 2020 +0200
Add support for strict decoding - addresses review comments by @garydgregory and @aherbert
---
.../org/apache/commons/codec/binary/Base16.java | 36 +++++++++++++++++++---
.../apache/commons/codec/binary/Base16Test.java | 20 ++++++++++++
2 files changed, 52 insertions(+), 4 deletions(-)
diff --git a/src/main/java/org/apache/commons/codec/binary/Base16.java b/src/main/java/org/apache/commons/codec/binary/Base16.java
index f94c115..1732f69 100644
--- a/src/main/java/org/apache/commons/codec/binary/Base16.java
+++ b/src/main/java/org/apache/commons/codec/binary/Base16.java
@@ -17,6 +17,7 @@
package org.apache.commons.codec.binary;
+import org.apache.commons.codec.CodecPolicy;
import org.apache.commons.codec.DecoderException;
import java.nio.charset.Charset;
@@ -66,6 +67,19 @@ public class Base16 extends BaseNCodec {
this.charset = charset;
}
+ /**
+ * Creates a Base16 codec used for decoding and encoding.
+ *
+ * @param toLowerCase {@code true} converts to lowercase, {@code false} to uppercase.
+ * @param charset the charset.
+ * @param decodingPolicy Decoding policy.
+ */
+ protected Base16(final boolean toLowerCase, final Charset charset, final CodecPolicy decodingPolicy) {
+ super(BYTES_PER_UNENCODED_BLOCK, BYTES_PER_ENCODED_BLOCK, 0, 0,
+ PAD_DEFAULT, decodingPolicy);
+ this.toLowerCase = toLowerCase;
+ this.charset = charset;
+ }
@Override
void encode(final byte[] data, final int offset, final int length, final Context context) {
@@ -88,11 +102,11 @@ public class Base16 extends BaseNCodec {
@Override
void decode(final byte[] data, final int offset, final int length, final Context context) {
- if (context.eof) {
- return;
- }
- if (length < 0) {
+ if (context.eof || length < 0) {
context.eof = true;
+ if (context.ibitWorkArea > 0) {
+ validateTrailingCharacter();
+ }
return;
}
@@ -137,6 +151,20 @@ public class Base16 extends BaseNCodec {
}
}
+ /**
+ * Validates whether decoding allows an entire final trailing character that cannot be
+ * used for a complete byte.
+ *
+ * @throws IllegalArgumentException if strict decoding is enabled
+ */
+ private void validateTrailingCharacter() {
+ if (isStrictDecoding()) {
+ throw new IllegalArgumentException("Strict decoding: Last encoded character is a valid base 16 alphabet" +
+ "character but not a possible encoding. " +
+ "Decoding requires at least two characters to create one byte.");
+ }
+ }
+
@Override
protected boolean isInAlphabet(final byte value) {
if (value >= '0' && value <= '9') {
diff --git a/src/test/java/org/apache/commons/codec/binary/Base16Test.java b/src/test/java/org/apache/commons/codec/binary/Base16Test.java
index e0bf357..eb273fa 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base16Test.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base16Test.java
@@ -17,6 +17,7 @@
package org.apache.commons.codec.binary;
+import org.apache.commons.codec.CodecPolicy;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.EncoderException;
import org.apache.commons.lang3.ArrayUtils;
@@ -28,6 +29,7 @@ import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Random;
+import static org.apache.commons.codec.CharEncoding.UTF_8;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -617,4 +619,22 @@ public class Base16Test {
assertEquals("Until next time!", decoded);
}
+
+ @Test(expected=IllegalArgumentException.class)
+ public void testStrictDecoding() {
+ final String encoded = "aabbccdde"; // Note the trailing `e` which does not make up a hex-pair and so is only 1/2 byte
+
+ final Base16 b16 = new Base16(true, CHARSET_UTF8, CodecPolicy.STRICT);
+ b16.decode(StringUtils.getBytesUtf8(encoded));
+ }
+
+ @Test
+ public void testLenientDecoding() {
+ final String encoded = "aabbccdde"; // Note the trailing `e` which does not make up a hex-pair and so is only 1/2 byte
+
+ final Base16 b16 = new Base16(true, CHARSET_UTF8, CodecPolicy.LENIENT);
+
+ final byte[] decoded = b16.decode(StringUtils.getBytesUtf8(encoded));
+ assertArrayEquals(new byte[] {(byte)0xaa, (byte)0xbb, (byte)0xcc, (byte)0xdd}, decoded);
+ }
}
This is an automated email from the ASF dual-hosted git repository.
aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-codec.git
commit 97272858836aa93f28f2f675c8c1d124cf753e25
Author: Adam Retter <ad...@googlemail.com>
AuthorDate: Mon Jun 1 15:10:17 2020 +0200
Throw IllegalArgumentException for characters outside of alphabet
---
.../org/apache/commons/codec/binary/Base16.java | 29 ++++++++++++++++------
.../apache/commons/codec/binary/Base16Test.java | 26 ++++++++++---------
2 files changed, 35 insertions(+), 20 deletions(-)
diff --git a/src/main/java/org/apache/commons/codec/binary/Base16.java b/src/main/java/org/apache/commons/codec/binary/Base16.java
index eb875cb..b421e23 100644
--- a/src/main/java/org/apache/commons/codec/binary/Base16.java
+++ b/src/main/java/org/apache/commons/codec/binary/Base16.java
@@ -151,7 +151,7 @@ public class Base16 extends BaseNCodec {
// small optimisation to short-cut the rest of this method when it is fed byte-by-byte
if (availableChars == 1 && availableChars == dataLen) {
- context.ibitWorkArea = data[offset]; // store 1/2 byte for next invocation of decode
+ context.ibitWorkArea = decodeOctet(data[offset]) + 1; // store 1/2 byte for next invocation of decode, we offset by +1 as empty-value is 0
return;
}
@@ -164,29 +164,42 @@ public class Base16 extends BaseNCodec {
int i = 0;
if (dataLen < availableChars) {
// we have 1/2 byte from previous invocation to decode
- result = decodeTable[context.ibitWorkArea] << BITS_PER_ENCODED_BYTE;
- result |= decodeTable[data[offset++]];
+ result = (context.ibitWorkArea - 1) << BITS_PER_ENCODED_BYTE;
+ result |= decodeOctet(data[offset++]);
i = 2;
buffer[context.pos++] = (byte)result;
- // reset for next invocation!
- context.ibitWorkArea = -1;
+ // reset to empty-value for next invocation!
+ context.ibitWorkArea = 0;
}
while (i < charsToProcess) {
- result = decodeTable[data[offset++]] << BITS_PER_ENCODED_BYTE;
- result |= decodeTable[data[offset++]];
+ result = decodeOctet(data[offset++]) << BITS_PER_ENCODED_BYTE;
+ result |= decodeOctet(data[offset++]);
i += 2;
buffer[context.pos++] = (byte)result;
}
// we have one char of a hex-pair left over
if (i < dataLen) {
- context.ibitWorkArea = data[i]; // store 1/2 byte for next invocation of decode
+ context.ibitWorkArea = decodeOctet(data[i]) + 1; // store 1/2 byte for next invocation of decode, we offset by +1 as empty-value is 0
}
}
+ private int decodeOctet(final byte octet) {
+ int decoded = -1;
+ if (octet >= 0 && octet < decodeTable.length) {
+ decoded = decodeTable[octet];
+ }
+
+ if (decoded == -1) {
+ throw new IllegalArgumentException("Invalid octet in encoded value: " + (int)octet);
+ }
+
+ return decoded;
+ }
+
@Override
void encode(final byte[] data, final int offset, final int length, final Context context) {
if (context.eof) {
diff --git a/src/test/java/org/apache/commons/codec/binary/Base16Test.java b/src/test/java/org/apache/commons/codec/binary/Base16Test.java
index 989520a..72bff8a 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base16Test.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base16Test.java
@@ -205,16 +205,17 @@ public class Base16Test {
@Test
public void testNonBase16Test() {
- final byte[] bArray = { '%' };
-
- try {
- final Base16 b16 = new Base16();
- final byte[] result = b16.decode(bArray);
-
- assertEquals("The result should be empty as the test encoded content did "
- + "not contain any valid base 16 characters", 0, result.length);
- } catch (final Exception e) {
- fail("Exception was thrown when trying to decode invalid Base16 encoded data");
+ final byte[] invalidEncodedChars = { '/', ':', '@', 'G', '%', '`', 'g' };
+
+ final byte[] encoded = new byte[1];
+ for (final byte invalidEncodedChar : invalidEncodedChars) {
+ try {
+ encoded[0] = invalidEncodedChar;
+ new Base16().decode(encoded);
+ fail("IllegalArgumentException should have been thrown when trying to decode invalid Base16 char: " + (char)invalidEncodedChar);
+ } catch (final Exception e) {
+ assertTrue(e instanceof IllegalArgumentException);
+ }
}
}
@@ -591,14 +592,15 @@ public class Base16Test {
final byte[] data = new byte[1];
final Base16 b16 = new Base16();
+ assertEquals(0, context.ibitWorkArea);
data[0] = (byte) 'E';
b16.decode(data, 0, 1, context);
- assertEquals(69, context.ibitWorkArea);
+ assertEquals(15, context.ibitWorkArea);
data[0] = (byte) 'F';
b16.decode(data, 0, 1, context);
- assertEquals(-1, context.ibitWorkArea);
+ assertEquals(0, context.ibitWorkArea);
assertEquals(-17, context.buffer[0]);
}
This is an automated email from the ASF dual-hosted git repository.
aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-codec.git
commit 77fa03c451ab7ead39bdb9dcc610251dbf2751f6
Author: Adam Retter <ad...@googlemail.com>
AuthorDate: Wed Jun 24 11:47:17 2020 +0200
Expand on the functionality in the Javadoc
---
src/main/java/org/apache/commons/codec/binary/Base16.java | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/src/main/java/org/apache/commons/codec/binary/Base16.java b/src/main/java/org/apache/commons/codec/binary/Base16.java
index b421e23..5db9043 100644
--- a/src/main/java/org/apache/commons/codec/binary/Base16.java
+++ b/src/main/java/org/apache/commons/codec/binary/Base16.java
@@ -26,6 +26,15 @@ import org.apache.commons.codec.CodecPolicy;
* This class is thread-safe.
* </p>
*
+ * This implementation strictly follows RFC 4648, and as such unlike
+ * the {@link Base32} and {@link Base64} implementations,
+ * it does not ignore invalid alphabet characters or whitespace,
+ * neither does it offer chunking or padding characters.
+ *
+ * The only additional feature above those specified in RFC 4648
+ * is support for working with a lower-case alphabet in addition
+ * to the default upper-case alphabet.
+ *
* @see <a href="https://tools.ietf.org/html/rfc4648#section-8">RFC 4648 - 8. Base 16 Encoding</a>
*
* @since 1.15
This is an automated email from the ASF dual-hosted git repository.
aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-codec.git
commit 1b594c035d79b579819753938f5e53d9435b38b8
Author: Adam Retter <ad...@googlemail.com>
AuthorDate: Tue Apr 21 12:19:54 2020 +0200
Fix typos
---
src/main/java/org/apache/commons/codec/binary/Base32.java | 2 +-
src/main/java/org/apache/commons/codec/binary/Base64.java | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/main/java/org/apache/commons/codec/binary/Base32.java b/src/main/java/org/apache/commons/codec/binary/Base32.java
index 845206f..cae0b37 100644
--- a/src/main/java/org/apache/commons/codec/binary/Base32.java
+++ b/src/main/java/org/apache/commons/codec/binary/Base32.java
@@ -618,7 +618,7 @@ public class Base32 extends BaseNCodec {
if (isStrictDecoding()) {
throw new IllegalArgumentException(
"Strict decoding: Last encoded character(s) (before the paddings if any) are valid base 32 alphabet but not a possible encoding. " +
- "Decoding requries either 2, 4, 5, or 7 trailing 5-bit characters to create bytes.");
+ "Decoding requires either 2, 4, 5, or 7 trailing 5-bit characters to create bytes.");
}
}
}
diff --git a/src/main/java/org/apache/commons/codec/binary/Base64.java b/src/main/java/org/apache/commons/codec/binary/Base64.java
index 72cff5f..76a14d2 100644
--- a/src/main/java/org/apache/commons/codec/binary/Base64.java
+++ b/src/main/java/org/apache/commons/codec/binary/Base64.java
@@ -841,7 +841,7 @@ public class Base64 extends BaseNCodec {
if (isStrictDecoding()) {
throw new IllegalArgumentException(
"Strict decoding: Last encoded character (before the paddings if any) is a valid base 64 alphabet but not a possible encoding. " +
- "Decoding requries at least two trailing 6-bit characters to create bytes.");
+ "Decoding requires at least two trailing 6-bit characters to create bytes.");
}
}
This is an automated email from the ASF dual-hosted git repository.
aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-codec.git
commit 068654372f77a595fba00bf3b145902af1a596b4
Author: Adam Retter <ad...@googlemail.com>
AuthorDate: Mon Jun 29 21:03:34 2020 +0200
Remove test as requested by @aherbert
---
.../apache/commons/codec/binary/Base16Test.java | 34 ----------------------
1 file changed, 34 deletions(-)
diff --git a/src/test/java/org/apache/commons/codec/binary/Base16Test.java b/src/test/java/org/apache/commons/codec/binary/Base16Test.java
index 299d73a..c9a6332 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base16Test.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base16Test.java
@@ -21,7 +21,6 @@ import org.apache.commons.codec.CodecPolicy;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.EncoderException;
import org.apache.commons.lang3.ArrayUtils;
-import org.junit.Assume;
import org.junit.Test;
import java.nio.charset.Charset;
@@ -478,39 +477,6 @@ public class Base16Test {
return buf.toString();
}
- /**
- * Test for CODEC-265: Encode a ~1GiB file.
- *
- * @see <a href="https://issues.apache.org/jira/projects/CODEC/issues/CODEC-265">CODEC-265</a>
- */
- @Test
- public void testCodec265_over() {
- // almost 1GiB file to encode: 2^29 bytes
- final int size1GiB = 1 << 29;
-
- // Expecting a size of 2 output bytes per 1 input byte
- final int blocks = size1GiB;
- final int expectedLength = 2 * blocks;
-
- // This test is memory hungry. Check we can run it.
- final long presumableFreeMemory = BaseNCodecTest.getPresumableFreeMemory();
-
- // Estimate the maximum memory required:
- // 1GiB + 1GiB + ~2GiB + ~1.33GiB + 32 KiB = ~5.33GiB
- //
- // 1GiB: Input buffer to encode
- // 1GiB: Existing working buffer (due to doubling of default buffer size of 8192)
- // ~2GiB: New working buffer to allocate (due to doubling)
- // ~1.33GiB: Expected output size (since the working buffer is copied at the end)
- // 32KiB: Some head room
- final long estimatedMemory = (long) size1GiB * 4 + expectedLength + 32 * 1024;
- Assume.assumeTrue("Not enough free memory for the test", presumableFreeMemory > estimatedMemory);
-
- final byte[] bytes = new byte[size1GiB];
- final byte[] encoded = new Base16().encode(bytes);
- assertEquals(expectedLength, encoded.length);
- }
-
@Test(expected = IllegalArgumentException.class)
public void checkEncodeLengthBounds() {
final Base16 base16 = new Base16();
This is an automated email from the ASF dual-hosted git repository.
aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-codec.git
commit 196f32e5011d6709e48c5d255bf8079c71b1c0e6
Author: Adam Retter <ad...@googlemail.com>
AuthorDate: Wed Jun 24 12:18:01 2020 +0200
Abstract common test code into BaseNTestData
---
.../codec/binary/Base16InputStreamTest.java | 16 +--
.../codec/binary/Base16OutputStreamTest.java | 6 +-
.../apache/commons/codec/binary/Base16Test.java | 4 +-
.../commons/codec/binary/Base16TestData.java | 78 ------------
.../codec/binary/Base32InputStreamTest.java | 16 +--
.../codec/binary/Base32OutputStreamTest.java | 4 +-
.../apache/commons/codec/binary/Base32Test.java | 6 +-
.../commons/codec/binary/Base32TestData.java | 87 -------------
.../codec/binary/Base64InputStreamTest.java | 28 +++--
.../codec/binary/Base64OutputStreamTest.java | 14 ++-
.../apache/commons/codec/binary/Base64Test.java | 17 +--
.../commons/codec/binary/Base64TestData.java | 136 ---------------------
.../{Base64TestData.java => BaseNTestData.java} | 106 ++++++----------
13 files changed, 95 insertions(+), 423 deletions(-)
diff --git a/src/test/java/org/apache/commons/codec/binary/Base16InputStreamTest.java b/src/test/java/org/apache/commons/codec/binary/Base16InputStreamTest.java
index c3c8ee0..99066e7 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base16InputStreamTest.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base16InputStreamTest.java
@@ -92,12 +92,13 @@ public class Base16InputStreamTest {
// OpenSSL interop test.
encoded = StringUtils.getBytesUtf8(Base16TestData.ENCODED_UTF8_UPPERCASE);
- decoded = Base16TestData.DECODED;
+ decoded = BaseNTestData.DECODED;
testByChunk(encoded, decoded);
// test random data of sizes 0 thru 150
+ final BaseNCodec codec = new Base16(true);
for (int i = 0; i <= 150; i++) {
- final byte[][] randomData = Base16TestData.randomData(i);
+ final byte[][] randomData = BaseNTestData.randomData(codec, i);
encoded = randomData[1];
decoded = randomData[0];
testByChunk(encoded, decoded, true);
@@ -123,12 +124,13 @@ public class Base16InputStreamTest {
// OpenSSL interop test.
encoded = StringUtils.getBytesUtf8(Base16TestData.ENCODED_UTF8_UPPERCASE);
- decoded = Base16TestData.DECODED;
+ decoded = BaseNTestData.DECODED;
testByteByByte(encoded, decoded);
// test random data of sizes 0 thru 150
+ final BaseNCodec codec = new Base16(true);
for (int i = 0; i <= 150; i++) {
- final byte[][] randomData = Base16TestData.randomData(i);
+ final byte[][] randomData = BaseNTestData.randomData(codec, i);
encoded = randomData[1];
decoded = randomData[0];
testByteByByte(encoded, decoded, true);
@@ -166,7 +168,7 @@ public class Base16InputStreamTest {
// Start with encode.
try (final InputStream in = new Base16InputStream(new ByteArrayInputStream(decoded), true, lowerCase)) {
- final byte[] output = Base16TestData.streamToBytes(in);
+ final byte[] output = BaseNTestData.streamToBytes(in);
assertEquals("EOF", -1, in.read());
assertEquals("Still EOF", -1, in.read());
@@ -175,7 +177,7 @@ public class Base16InputStreamTest {
// Now let's try decode.
try (final InputStream in = new Base16InputStream(new ByteArrayInputStream(encoded), false, lowerCase)) {
- final byte[] output = Base16TestData.streamToBytes(in);
+ final byte[] output = BaseNTestData.streamToBytes(in);
assertEquals("EOF", -1, in.read());
assertEquals("Still EOF", -1, in.read());
@@ -187,7 +189,7 @@ public class Base16InputStreamTest {
final InputStream inEncode = new Base16InputStream(in, true, lowerCase);
final InputStream inDecode = new Base16InputStream(inEncode, false, lowerCase)) {
- final byte[] output = Base16TestData.streamToBytes(inDecode);
+ final byte[] output = BaseNTestData.streamToBytes(inDecode);
assertEquals("EOF", -1, inDecode.read());
assertEquals("Still EOF", -1, inDecode.read());
diff --git a/src/test/java/org/apache/commons/codec/binary/Base16OutputStreamTest.java b/src/test/java/org/apache/commons/codec/binary/Base16OutputStreamTest.java
index 6bb5d34..fd7b27a 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base16OutputStreamTest.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base16OutputStreamTest.java
@@ -64,8 +64,9 @@ public class Base16OutputStreamTest {
testByChunk(encoded, decoded);
// test random data of sizes 0 thru 150
+ final BaseNCodec codec = new Base16(true);
for (int i = 0; i <= 150; i++) {
- final byte[][] randomData = Base16TestData.randomData(i);
+ final byte[][] randomData = BaseNTestData.randomData(codec, i);
encoded = randomData[1];
decoded = randomData[0];
testByChunk(encoded, decoded, true);
@@ -90,8 +91,9 @@ public class Base16OutputStreamTest {
testByteByByte(encoded, decoded);
// test random data of sizes 0 thru 150
+ final BaseNCodec codec = new Base16(true);
for (int i = 0; i <= 150; i++) {
- final byte[][] randomData = Base16TestData.randomData(i);
+ final byte[][] randomData = BaseNTestData.randomData(codec, i);
encoded = randomData[1];
decoded = randomData[0];
testByteByByte(encoded, decoded, true);
diff --git a/src/test/java/org/apache/commons/codec/binary/Base16Test.java b/src/test/java/org/apache/commons/codec/binary/Base16Test.java
index 72bff8a..577a842 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base16Test.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base16Test.java
@@ -117,7 +117,7 @@ public class Base16Test {
@Test
public void testConstructor_LowerCase() {
final Base16 Base16 = new Base16(true);
- final byte[] encoded = Base16.encode(Base16TestData.DECODED);
+ final byte[] encoded = Base16.encode(BaseNTestData.DECODED);
final String expectedResult = Base16TestData.ENCODED_UTF8_LOWERCASE;
final String result = StringUtils.newStringUtf8(encoded);
assertEquals("new Base16(true)", expectedResult, result);
@@ -126,7 +126,7 @@ public class Base16Test {
@Test
public void testConstructor_LowerCase_DecodingPolicy() {
final Base16 Base16 = new Base16(false, CodecPolicy.STRICT);
- final byte[] encoded = Base16.encode(Base16TestData.DECODED);
+ final byte[] encoded = Base16.encode(BaseNTestData.DECODED);
final String expectedResult = Base16TestData.ENCODED_UTF8_UPPERCASE;
final String result = StringUtils.newStringUtf8(encoded);
assertEquals("new Base16(false, CodecPolicy.STRICT)", result, expectedResult);
diff --git a/src/test/java/org/apache/commons/codec/binary/Base16TestData.java b/src/test/java/org/apache/commons/codec/binary/Base16TestData.java
index 575df32..09be1ca 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base16TestData.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base16TestData.java
@@ -17,11 +17,6 @@
package org.apache.commons.codec.binary;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Random;
-
/**
* This random data was encoded by OpenSSL. Java had nothing to do with it. This data helps us test interop between
* Commons-Codec and OpenSSL.
@@ -35,77 +30,4 @@ public class Base16TestData {
final static String ENCODED_UTF8_UPPERCASE
= "F483CD2B052F74B888029E9CB73D764A2426386B2D5B262F48F79EBEE7C386BCDAC2CEB9BE8CA42A36C88F7DD85936BDC40EDCFC51F2A56725AD9850EE89DF737244F77049E5F4F847DCC011D8DB8F2D61BF8658367113E1625E5CC2C9FF9A7EA81A53B0FA5EA56F03355632D5CD36FF5C320BE92003A0AF45477D712AFF96DF3C00476C4D5E063029F5F84C2E02261D8AFC6ECE7F9C2CCF2ADA37B0AA5239DAD3FD27B0ACF2FA86EF5B3AF960042CABE6FD4A2FBF268E8BE39D3147E343424B88B907BBAA7D3B0520BD0AA20CACC4BFF02E828D1D4CF67360613208FE4656B95EDD041D81C8881E7A5D7785544CF [...]
-
- final static byte[] DECODED
- = {-12, -125, -51, 43, 5, 47, 116, -72, -120, 2, -98, -100, -73, 61, 118, 74, 36, 38, 56, 107, 45, 91, 38,
- 47, 72, -9, -98, -66, -25, -61, -122, -68, -38, -62, -50, -71, -66, -116, -92, 42, 54, -56, -113, 125,
- -40, 89, 54, -67, -60, 14, -36, -4, 81, -14, -91, 103, 37, -83, -104, 80, -18, -119, -33, 115, 114, 68,
- -9, 112, 73, -27, -12, -8, 71, -36, -64, 17, -40, -37, -113, 45, 97, -65, -122, 88, 54, 113, 19, -31, 98,
- 94, 92, -62, -55, -1, -102, 126, -88, 26, 83, -80, -6, 94, -91, 111, 3, 53, 86, 50, -43, -51, 54, -1, 92,
- 50, 11, -23, 32, 3, -96, -81, 69, 71, 125, 113, 42, -1, -106, -33, 60, 0, 71, 108, 77, 94, 6, 48, 41, -11,
- -8, 76, 46, 2, 38, 29, -118, -4, 110, -50, 127, -100, 44, -49, 42, -38, 55, -80, -86, 82, 57, -38, -45,
- -3, 39, -80, -84, -14, -6, -122, -17, 91, 58, -7, 96, 4, 44, -85, -26, -3, 74, 47, -65, 38, -114, -117,
- -29, -99, 49, 71, -29, 67, 66, 75, -120, -71, 7, -69, -86, 125, 59, 5, 32, -67, 10, -94, 12, -84, -60, -65,
- -16, 46, -126, -115, 29, 76, -10, 115, 96, 97, 50, 8, -2, 70, 86, -71, 94, -35, 4, 29, -127, -56, -120,
- 30, 122, 93, 119, -123, 84, 76, -15, -111, 81, -75, -34, 41, -72, 126, -7, 77, -33, 108, -110, 39, -125,
- -5, 16, 92, -51, -56, 96, 28, -116, 103, -68, 109, -12, 117, -110, -44, -75, 28, 69, -44, 59, 62, -68,
- 39, -4, -119, 80, 91, 19, -116, 122, -81, -118, 100, -108, -88, 2, -8, -106, -75, -37, 30, -83, 124, -121,
- 108, -127, 26, -1, -8, 102, -81, -118, 127, -113, -51, 36, -46, 15, 106, -33, -104, 106, -43, -84, -122,
- 51, -33, 124, -32, 2, -45, 73, -90, 124, 89, -20, -123, 109, -100, 117, 11, 16, -65, 66, -118, -97, -9,
- 101, 7, -1, 41, 65, 70, 116, -119, 54, 126, 44, 75, 74, 26, -34, -27, 27, 54, -13, -89, -90, 64, 120, 15,
- -43, 123, 82, -33, 90, -74, 41, -62, 38, -68, 62, -62, 34, 92, 50, 95, -67, -110, -99, -71, -44, -123,
- 49, 4, 96, 56, 113, 76, 97, -47, -26, -79, -109, 115, -125, 90, 124, 8, -9, -111, 36, -74, 101, -114, 43,
- 0, -110, 63, 76, 99, 91, 2, 12, -60, 56, -14, -125, 0, 6, -27, 31, 31, -109, -47, -3, 109, 88, -75, -74,
- 19, 26, -66, 110, 39, 13, -50, 47, 104, -38, 18, 19, 84, 103, 100, -42, 48, 110, 37, 21, -107, 83, -52,
- -12, 71, 37, -68, -107, -109, 89, -34, -94, -127, 103, -128, -48, -52, 71, 0, 15, 34, 56, -50, 85, -98,
- 106, -87, -3, 97, -116, -19, 64, -22, -25, -38, -63, 33, -45, 80, 10, -121, -109, 37, -96, 36, 18, -48,
- 46, 44, -66, 115, -94, 3, -102, -27, -17, -116, -51, 88, -17, 7, -109, 24, 66, 83, -91, 105, -92, -19,
- 66, -76, 64, -91, 118, -71, 103, -123, 95, 17, -87, -18, -11, 66, -74, 126, 45, 83, -14, 50, 79, 20, 45,
- -113, -103, 119, -101, -58, -99, 27, -100, -17, -107, 91, -26, -32, -56, 71, 72, 34, 66, 16, 9, -90, 106,
- -44, -62, -106, 11, 114, -82, -120, -28, -67, 4, -99, 109, -20, -19, 0, -40, -110, -119, 42, -6, 4, -31,
- 67, 110, -105, 53, 118, 76, 96, -126, -8, -96, 39, -102, 52, 106, 64, 26, -105, -108, -103, -96, -116,
- 116, 0, -96, 115, 89, 40, -23, -102, -2, -30, 16, 58, -53, -33, 14, 122, -94, 113, -121, 67, -103, -4,
- -126, 98, -27, 124, -12, 120, -64, -44, 127, 45, -120, 50, 124, -27, 87, -20, -84, 81, -35, 113, -77,
- -64, -96, -48, -87, -117, -82, 90, -64, -108, -121, 125, -45, -50, -44, -48, -50, 52, -30, -66, -7, 46,
- -40, -47, 85, -44, -126, -122, 24, -84, 21, 120, 99, -74, 27, 11, -52, 32, -2, 122, -100, -118, 106, -9,
- -106, 109, -19, 71, 42, 126, 66, -56, 10, -51, -44, 68, 109, -13, 81, -109, 65, 121, 60, -68, -117, 126,
- -59, 4, -107, -22, 99, -77, 84, 29, 87, 119, -60, 87, 82, -55, -74, 44, -80, 3, 123, -101, 84, -44, 9, 71,
- 24, 91, 99, 22, -65, 11, -11, -14, -38, -84, 105, -101, -85, -17, 116, -65, 118, -105, 122, -75, 113,
- -57, -81, -33, -110, 28, 104, -24, -110, -57, -78, 38, -5, -15, -79, 87, 105, 85, 41, -42, -114, -67,
- -123, 70, 12, 61, 115, 5, 23, -70, 99, 96, -80, 65, -65, 105, -45, -49, 37, -33, -1, 119, -88, 100, 121,
- -25, -35, -51, 10, 43, -113, 61, 103, 44, 13, 108, 20, 74, 19, 53, 19, 37, -76, 20, -43, -11, 23, -58, -25,
- -52, 121, -40, -118, 58, 50, 19, -8, -33, -30, -49, -27, -11, -80, 93, -17, 34, 93, 69, 100, 66, -54, 40,
- 118, 89, -52, -87, 2, 35, -120, 18, 64, 108, 31, -25, 66, 78, 6, -91, -69, -53, 17, 14, -125, 33, -31, -110,
- 1, 5, -40, 7, 126, -122, 84, -55, -62, -22, 69, -28, 5, 45, -106, 120, 74, 94, 51, 74, 108, -19, -26, -12,
- 49, 64, 88, 68, 41, -65, 126, 125, -1, -8, -83, -67, 74, 2, -114, -80, -119, -9, -89, -125, 21, 95, 34,
- -58, -74, 111, -103, 99, 95, 48, 42, 94, -50, -55, -112, -5, -26, 11, -89, -38, -19, 126, 25, 102, 119,
- 81, -94, 70, -79, 98, 91, -73, 114, 15, 14, 87, -21, -122, -1, -90, 0, 29, -104, -91, -93, -58, -83, -48,
- -22, 100, -112, -41, 77, 22, -24, 112, -72, 105, 100, 6, -86, -39, 40, -43, 35, -2, 4, -94, 97, -121, 52,
- -22, 1, 127, -81, -4, -6, -119, 96, 35, -91, 114, 81, 91, 90, -86, -36, 34, -39, 93, -42, 69, 103, -11,
- 107, -87, 119, -107, -114, -45, -128, -69, 96};
-
- static byte[] streamToBytes(final InputStream is) throws IOException {
- final ByteArrayOutputStream os = new ByteArrayOutputStream();
- final byte[] buf = new byte[4096];
- int read;
- while ((read = is.read(buf)) > -1) {
- os.write(buf, 0, read);
- }
- return os.toByteArray();
- }
-
- /**
- * Returns an encoded and decoded copy of the same random data.
- *
- * @param size amount of random data to generate and encode
- * @return two byte[] arrays: [0] = decoded, [1] = encoded
- */
- static byte[][] randomData(final int size) {
- final Random r = new Random();
- final byte[] decoded = new byte[size];
- r.nextBytes(decoded);
- final char[] encodedChars = Hex.encodeHex(decoded);
- final byte[] encoded = new String(encodedChars).getBytes(Hex.DEFAULT_CHARSET);
- return new byte[][] {decoded, encoded};
- }
}
diff --git a/src/test/java/org/apache/commons/codec/binary/Base32InputStreamTest.java b/src/test/java/org/apache/commons/codec/binary/Base32InputStreamTest.java
index fe77eee..164f6c3 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base32InputStreamTest.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base32InputStreamTest.java
@@ -57,7 +57,7 @@ public class Base32InputStreamTest {
// we skip the first character read from the reader
ins.skip(1);
- final byte[] decodedBytes = Base32TestData.streamToBytes(ins, new byte[64]);
+ final byte[] decodedBytes = BaseNTestData.streamToBytes(ins, new byte[64]);
final String str = StringUtils.newStringUtf8(decodedBytes);
assertEquals(STRING_FIXTURE.substring(1), str);
@@ -222,7 +222,7 @@ public class Base32InputStreamTest {
// test random data of sizes 0 thru 150
final BaseNCodec codec = new Base32();
for (int i = 0; i <= 150; i++) {
- final byte[][] randomData = Base32TestData.randomData(codec, i);
+ final byte[][] randomData = BaseNTestData.randomData(codec, i);
encoded = randomData[1];
decoded = randomData[0];
testByChunk(encoded, decoded, 0, LF);
@@ -256,7 +256,7 @@ public class Base32InputStreamTest {
// test random data of sizes 0 thru 150
final BaseNCodec codec = new Base32();
for (int i = 0; i <= 150; i++) {
- final byte[][] randomData = Base32TestData.randomData(codec, i);
+ final byte[][] randomData = BaseNTestData.randomData(codec, i);
encoded = randomData[1];
decoded = randomData[0];
testByteByByte(encoded, decoded, 0, LF);
@@ -287,7 +287,7 @@ public class Base32InputStreamTest {
InputStream in;
in = new Base32InputStream(new ByteArrayInputStream(decoded), true, chunkSize, separator);
- byte[] output = Base32TestData.streamToBytes(in);
+ byte[] output = BaseNTestData.streamToBytes(in);
assertEquals("EOF", -1, in.read());
assertEquals("Still EOF", -1, in.read());
@@ -295,7 +295,7 @@ public class Base32InputStreamTest {
// Now let's try decode.
in = new Base32InputStream(new ByteArrayInputStream(encoded));
- output = Base32TestData.streamToBytes(in);
+ output = BaseNTestData.streamToBytes(in);
assertEquals("EOF", -1, in.read());
assertEquals("Still EOF", -1, in.read());
@@ -307,7 +307,7 @@ public class Base32InputStreamTest {
in = new Base32InputStream(in, true, chunkSize, separator);
in = new Base32InputStream(in, false);
}
- output = Base32TestData.streamToBytes(in);
+ output = BaseNTestData.streamToBytes(in);
assertEquals("EOF", -1, in.read());
assertEquals("Still EOF", -1, in.read());
@@ -572,13 +572,13 @@ public class Base32InputStreamTest {
Base32InputStream in = new Base32InputStream(new ByteArrayInputStream(encoded), false);
// Default is lenient decoding; it should not throw
assertFalse(in.isStrictDecoding());
- Base32TestData.streamToBytes(in);
+ BaseNTestData.streamToBytes(in);
// Strict decoding should throw
in = new Base32InputStream(new ByteArrayInputStream(encoded), false, 0, null, CodecPolicy.STRICT);
assertTrue(in.isStrictDecoding());
try {
- Base32TestData.streamToBytes(in);
+ BaseNTestData.streamToBytes(in);
fail();
} catch (final IllegalArgumentException ex) {
// expected
diff --git a/src/test/java/org/apache/commons/codec/binary/Base32OutputStreamTest.java b/src/test/java/org/apache/commons/codec/binary/Base32OutputStreamTest.java
index a276f8e..5ab7724 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base32OutputStreamTest.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base32OutputStreamTest.java
@@ -117,7 +117,7 @@ public class Base32OutputStreamTest {
// test random data of sizes 0 thru 150
final BaseNCodec codec = new Base32();
for (int i = 0; i <= 150; i++) {
- final byte[][] randomData = Base32TestData.randomData(codec, i);
+ final byte[][] randomData = BaseNTestData.randomData(codec, i);
encoded = randomData[1];
decoded = randomData[0];
testByChunk(encoded, decoded, 0, LF);
@@ -152,7 +152,7 @@ public class Base32OutputStreamTest {
// test random data of sizes 0 thru 150
final BaseNCodec codec = new Base32();
for (int i = 0; i <= 150; i++) {
- final byte[][] randomData = Base32TestData.randomData(codec, i);
+ final byte[][] randomData = BaseNTestData.randomData(codec, i);
encoded = randomData[1];
decoded = randomData[0];
testByteByByte(encoded, decoded, 0, LF);
diff --git a/src/test/java/org/apache/commons/codec/binary/Base32Test.java b/src/test/java/org/apache/commons/codec/binary/Base32Test.java
index 65c828e..83f1c2f 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base32Test.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base32Test.java
@@ -244,7 +244,7 @@ public class Base32Test {
public void testRandomBytes() {
for (int i = 0; i < 20; i++) {
final Base32 codec = new Base32();
- final byte[][] b = Base32TestData.randomData(codec, i);
+ final byte[][] b = BaseNTestData.randomData(codec, i);
assertEquals(""+i+" "+codec.lineLength,b[1].length,codec.getEncodedLength(b[0]));
//assertEquals(b[0],codec.decode(b[1]));
}
@@ -254,7 +254,7 @@ public class Base32Test {
public void testRandomBytesChunked() {
for (int i = 0; i < 20; i++) {
final Base32 codec = new Base32(10);
- final byte[][] b = Base32TestData.randomData(codec, i);
+ final byte[][] b = BaseNTestData.randomData(codec, i);
assertEquals(""+i+" "+codec.lineLength,b[1].length,codec.getEncodedLength(b[0]));
//assertEquals(b[0],codec.decode(b[1]));
}
@@ -264,7 +264,7 @@ public class Base32Test {
public void testRandomBytesHex() {
for (int i = 0; i < 20; i++) {
final Base32 codec = new Base32(true);
- final byte[][] b = Base32TestData.randomData(codec, i);
+ final byte[][] b = BaseNTestData.randomData(codec, i);
assertEquals(""+i+" "+codec.lineLength,b[1].length,codec.getEncodedLength(b[0]));
//assertEquals(b[0],codec.decode(b[1]));
}
diff --git a/src/test/java/org/apache/commons/codec/binary/Base32TestData.java b/src/test/java/org/apache/commons/codec/binary/Base32TestData.java
index 420fc12..98225f4 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base32TestData.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base32TestData.java
@@ -17,10 +17,6 @@
package org.apache.commons.codec.binary;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Random;
-
/**
* This random data was encoded by OpenSSL. Java had nothing to do with it. This data helps us test interop between
* Commons-Codec and OpenSSL. Notice that OpenSSL creates 64 character lines instead of the 76 of Commons-Codec.
@@ -37,87 +33,4 @@ public class Base32TestData {
// Some utility code to help test chunked reads of the InputStream.
- private final static int SIZE_KEY = 0;
- private final static int LAST_READ_KEY = 1;
-
- static byte[] streamToBytes(final InputStream in) throws IOException {
- // new byte[7] is obviously quite slow, but helps exercise the code.
- return streamToBytes(in, new byte[7]);
- }
-
- static byte[] streamToBytes(final InputStream in, byte[] buf) throws IOException {
- try {
- int[] status = fill(buf, 0, in);
- int size = status[SIZE_KEY];
- int lastRead = status[LAST_READ_KEY];
- while (lastRead != -1) {
- buf = resizeArray(buf);
- status = fill(buf, size, in);
- size = status[SIZE_KEY];
- lastRead = status[LAST_READ_KEY];
- }
- if (buf.length != size) {
- final byte[] smallerBuf = new byte[size];
- System.arraycopy(buf, 0, smallerBuf, 0, size);
- buf = smallerBuf;
- }
- }
- finally {
- in.close();
- }
- return buf;
- }
-
- private static int[] fill(final byte[] buf, final int offset, final InputStream in)
- throws IOException {
- int read = in.read(buf, offset, buf.length - offset);
- int lastRead = read;
- if (read == -1) {
- read = 0;
- }
- while (lastRead != -1 && read + offset < buf.length) {
- lastRead = in.read(buf, offset + read, buf.length - read - offset);
- if (lastRead != -1) {
- read += lastRead;
- }
- }
- return new int[]{offset + read, lastRead};
- }
-
- private static byte[] resizeArray(final byte[] bytes) {
- final byte[] biggerBytes = new byte[bytes.length * 2];
- System.arraycopy(bytes, 0, biggerBytes, 0, bytes.length);
- return biggerBytes;
- }
-
-
- /**
- * Returns an encoded and decoded copy of the same random data.
- *
- * @param codec the codec to use
- * @param size amount of random data to generate and encode
- * @return two byte[] arrays: [0] = decoded, [1] = encoded
- */
- static byte[][] randomData(final BaseNCodec codec, final int size) {
- final Random r = new Random();
- final byte[] decoded = new byte[size];
- r.nextBytes(decoded);
- final byte[] encoded = codec.encode(decoded);
- return new byte[][] {decoded, encoded};
- }
-
- /**
- * Tests the supplied byte[] array to see if it contains the specified byte c.
- *
- * @param bytes byte[] array to test
- * @param c byte to look for
- * @return true if bytes contains c, false otherwise
- */
- static boolean bytesContain(final byte[] bytes, final byte c) {
- for (final byte b : bytes) {
- if (b == c) { return true; }
- }
- return false;
- }
-
}
diff --git a/src/test/java/org/apache/commons/codec/binary/Base64InputStreamTest.java b/src/test/java/org/apache/commons/codec/binary/Base64InputStreamTest.java
index 83a0285..731457a 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base64InputStreamTest.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base64InputStreamTest.java
@@ -66,7 +66,7 @@ public class Base64InputStreamTest {
// we skip the first character read from the reader
ins.skip(1);
- final byte[] decodedBytes = Base64TestData.streamToBytes(ins, new byte[64]);
+ final byte[] decodedBytes = BaseNTestData.streamToBytes(ins, new byte[64]);
final String str = StringUtils.newStringUtf8(decodedBytes);
assertEquals(STRING_FIXTURE.substring(1), str);
@@ -144,7 +144,7 @@ public class Base64InputStreamTest {
final Base64InputStream stream = new Base64InputStream(data);
// This line causes an NPE in commons-codec-1.4.jar:
- final byte[] decodedBytes = Base64TestData.streamToBytes(stream, new byte[1024]);
+ final byte[] decodedBytes = BaseNTestData.streamToBytes(stream, new byte[1024]);
final String decoded = StringUtils.newStringUtf8(decodedBytes);
assertEquals("codec-98 NPE Base64InputStream", Base64TestData.CODEC_98_NPE_DECODED, decoded);
@@ -219,18 +219,19 @@ public class Base64InputStreamTest {
// OpenSSL interop test.
encoded = StringUtils.getBytesUtf8(Base64TestData.ENCODED_64_CHARS_PER_LINE);
- decoded = Base64TestData.DECODED;
+ decoded = BaseNTestData.DECODED;
testByChunk(encoded, decoded, BaseNCodec.PEM_CHUNK_SIZE, LF);
// Single Line test.
final String singleLine = Base64TestData.ENCODED_64_CHARS_PER_LINE.replaceAll("\n", "");
encoded = StringUtils.getBytesUtf8(singleLine);
- decoded = Base64TestData.DECODED;
+ decoded = BaseNTestData.DECODED;
testByChunk(encoded, decoded, 0, LF);
// test random data of sizes 0 thru 150
+ final BaseNCodec codec = new Base64(0, null, false);
for (int i = 0; i <= 150; i++) {
- final byte[][] randomData = Base64TestData.randomData(i, false);
+ final byte[][] randomData = BaseNTestData.randomData(codec, i);
encoded = randomData[1];
decoded = randomData[0];
testByChunk(encoded, decoded, 0, LF);
@@ -257,18 +258,19 @@ public class Base64InputStreamTest {
// OpenSSL interop test.
encoded = StringUtils.getBytesUtf8(Base64TestData.ENCODED_64_CHARS_PER_LINE);
- decoded = Base64TestData.DECODED;
+ decoded = BaseNTestData.DECODED;
testByteByByte(encoded, decoded, BaseNCodec.PEM_CHUNK_SIZE, LF);
// Single Line test.
final String singleLine = Base64TestData.ENCODED_64_CHARS_PER_LINE.replaceAll("\n", "");
encoded = StringUtils.getBytesUtf8(singleLine);
- decoded = Base64TestData.DECODED;
+ decoded = BaseNTestData.DECODED;
testByteByByte(encoded, decoded, 0, LF);
// test random data of sizes 0 thru 150
+ final BaseNCodec codec = new Base64(0, null, false);
for (int i = 0; i <= 150; i++) {
- final byte[][] randomData = Base64TestData.randomData(i, false);
+ final byte[][] randomData = BaseNTestData.randomData(codec, i);
encoded = randomData[1];
decoded = randomData[0];
testByteByByte(encoded, decoded, 0, LF);
@@ -298,7 +300,7 @@ public class Base64InputStreamTest {
// Start with encode.
InputStream in;
in = new Base64InputStream(new ByteArrayInputStream(decoded), true, chunkSize, separator);
- byte[] output = Base64TestData.streamToBytes(in);
+ byte[] output = BaseNTestData.streamToBytes(in);
assertEquals("EOF", -1, in.read());
assertEquals("Still EOF", -1, in.read());
@@ -308,7 +310,7 @@ public class Base64InputStreamTest {
// Now let's try decode.
in = new Base64InputStream(new ByteArrayInputStream(encoded));
- output = Base64TestData.streamToBytes(in);
+ output = BaseNTestData.streamToBytes(in);
assertEquals("EOF", -1, in.read());
assertEquals("Still EOF", -1, in.read());
@@ -320,7 +322,7 @@ public class Base64InputStreamTest {
in = new Base64InputStream(in, true, chunkSize, separator);
in = new Base64InputStream(in, false);
}
- output = Base64TestData.streamToBytes(in);
+ output = BaseNTestData.streamToBytes(in);
assertEquals("EOF", -1, in.read());
assertEquals("Still EOF", -1, in.read());
@@ -585,13 +587,13 @@ public class Base64InputStreamTest {
Base64InputStream in = new Base64InputStream(new ByteArrayInputStream(encoded), false);
// Default is lenient decoding; it should not throw
assertFalse(in.isStrictDecoding());
- Base64TestData.streamToBytes(in);
+ BaseNTestData.streamToBytes(in);
// Strict decoding should throw
in = new Base64InputStream(new ByteArrayInputStream(encoded), false, 0, null, CodecPolicy.STRICT);
assertTrue(in.isStrictDecoding());
try {
- Base64TestData.streamToBytes(in);
+ BaseNTestData.streamToBytes(in);
fail();
} catch (final IllegalArgumentException ex) {
// expected
diff --git a/src/test/java/org/apache/commons/codec/binary/Base64OutputStreamTest.java b/src/test/java/org/apache/commons/codec/binary/Base64OutputStreamTest.java
index a2e3157..0b2480f 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base64OutputStreamTest.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base64OutputStreamTest.java
@@ -111,18 +111,19 @@ public class Base64OutputStreamTest {
// OpenSSL interop test.
encoded = StringUtils.getBytesUtf8(Base64TestData.ENCODED_64_CHARS_PER_LINE);
- decoded = Base64TestData.DECODED;
+ decoded = BaseNTestData.DECODED;
testByChunk(encoded, decoded, BaseNCodec.PEM_CHUNK_SIZE, LF);
// Single Line test.
final String singleLine = Base64TestData.ENCODED_64_CHARS_PER_LINE.replaceAll("\n", "");
encoded = StringUtils.getBytesUtf8(singleLine);
- decoded = Base64TestData.DECODED;
+ decoded = BaseNTestData.DECODED;
testByChunk(encoded, decoded, 0, LF);
// test random data of sizes 0 thru 150
+ final BaseNCodec codec = new Base64(0, null, false);
for (int i = 0; i <= 150; i++) {
- final byte[][] randomData = Base64TestData.randomData(i, false);
+ final byte[][] randomData = BaseNTestData.randomData(codec, i);
encoded = randomData[1];
decoded = randomData[0];
testByChunk(encoded, decoded, 0, LF);
@@ -149,18 +150,19 @@ public class Base64OutputStreamTest {
// OpenSSL interop test.
encoded = StringUtils.getBytesUtf8(Base64TestData.ENCODED_64_CHARS_PER_LINE);
- decoded = Base64TestData.DECODED;
+ decoded = BaseNTestData.DECODED;
testByteByByte(encoded, decoded, 64, LF);
// Single Line test.
final String singleLine = Base64TestData.ENCODED_64_CHARS_PER_LINE.replaceAll("\n", "");
encoded = StringUtils.getBytesUtf8(singleLine);
- decoded = Base64TestData.DECODED;
+ decoded = BaseNTestData.DECODED;
testByteByByte(encoded, decoded, 0, LF);
// test random data of sizes 0 thru 150
+ final BaseNCodec codec = new Base64(0, null, false);
for (int i = 0; i <= 150; i++) {
- final byte[][] randomData = Base64TestData.randomData(i, false);
+ final byte[][] randomData = BaseNTestData.randomData(codec, i);
encoded = randomData[1];
decoded = randomData[0];
testByteByByte(encoded, decoded, 0, LF);
diff --git a/src/test/java/org/apache/commons/codec/binary/Base64Test.java b/src/test/java/org/apache/commons/codec/binary/Base64Test.java
index 884b4a2..caf5363 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base64Test.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base64Test.java
@@ -186,7 +186,7 @@ public class Base64Test {
*/
@Test
public void testChunkedEncodeMultipleOf76() {
- final byte[] expectedEncode = Base64.encodeBase64(Base64TestData.DECODED, true);
+ final byte[] expectedEncode = Base64.encodeBase64(BaseNTestData.DECODED, true);
// convert to "\r\n" so we're equal to the old openssl encoding test
// stored
// in Base64TestData.ENCODED_76_CHARS_PER_LINE:
@@ -309,7 +309,7 @@ public class Base64Test {
@Test
public void testConstructor_Int_ByteArray_Boolean() {
final Base64 base64 = new Base64(65, new byte[] { '\t' }, false);
- final byte[] encoded = base64.encode(Base64TestData.DECODED);
+ final byte[] encoded = base64.encode(BaseNTestData.DECODED);
String expectedResult = Base64TestData.ENCODED_64_CHARS_PER_LINE;
expectedResult = expectedResult.replace('\n', '\t');
final String result = StringUtils.newStringUtf8(encoded);
@@ -320,7 +320,7 @@ public class Base64Test {
public void testConstructor_Int_ByteArray_Boolean_UrlSafe() {
// url-safe variation
final Base64 base64 = new Base64(64, new byte[] { '\t' }, true);
- final byte[] encoded = base64.encode(Base64TestData.DECODED);
+ final byte[] encoded = base64.encode(BaseNTestData.DECODED);
String expectedResult = Base64TestData.ENCODED_64_CHARS_PER_LINE;
expectedResult = expectedResult.replaceAll("=", ""); // url-safe has no
// == padding.
@@ -450,7 +450,7 @@ public class Base64Test {
private void testEncodeOverMaxSize(final int maxSize) throws Exception {
try {
- Base64.encodeBase64(Base64TestData.DECODED, true, false, maxSize);
+ Base64.encodeBase64(BaseNTestData.DECODED, true, false, maxSize);
fail("Expected " + IllegalArgumentException.class.getName());
} catch (final IllegalArgumentException e) {
// Expected
@@ -1149,15 +1149,16 @@ public class Base64Test {
@Test
public void testUrlSafe() {
// test random data of sizes 0 thru 150
+ final BaseNCodec codec = new Base64(true);
for (int i = 0; i <= 150; i++) {
- final byte[][] randomData = Base64TestData.randomData(i, true);
+ final byte[][] randomData = BaseNTestData.randomData(codec, i);
final byte[] encoded = randomData[1];
final byte[] decoded = randomData[0];
final byte[] result = Base64.decodeBase64(encoded);
assertTrue("url-safe i=" + i, Arrays.equals(decoded, result));
- assertFalse("url-safe i=" + i + " no '='", Base64TestData.bytesContain(encoded, (byte) '='));
- assertFalse("url-safe i=" + i + " no '\\'", Base64TestData.bytesContain(encoded, (byte) '\\'));
- assertFalse("url-safe i=" + i + " no '+'", Base64TestData.bytesContain(encoded, (byte) '+'));
+ assertFalse("url-safe i=" + i + " no '='", BaseNTestData.bytesContain(encoded, (byte) '='));
+ assertFalse("url-safe i=" + i + " no '\\'", BaseNTestData.bytesContain(encoded, (byte) '\\'));
+ assertFalse("url-safe i=" + i + " no '+'", BaseNTestData.bytesContain(encoded, (byte) '+'));
}
}
diff --git a/src/test/java/org/apache/commons/codec/binary/Base64TestData.java b/src/test/java/org/apache/commons/codec/binary/Base64TestData.java
index 3e53d3a..5e45860 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base64TestData.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base64TestData.java
@@ -17,8 +17,6 @@
package org.apache.commons.codec.binary;
-import java.io.IOException;
-import java.io.InputStream;
import java.util.Random;
/**
@@ -84,138 +82,4 @@ public class Base64TestData {
+ "WcypAiOIEkBsH+dCTgalu8sRDoMh4ZIBBdgHfoZUycLqReQFLZZ4Sl4zSmzt5vQxQFhEKb9+ff/4\n"
+ "rb1KAo6wifengxVfIsa2b5ljXzAqXs7JkPvmC6fa7X4ZZndRokaxYlu3cg8OV+uG/6YAHZilo8at\n"
+ "0OpkkNdNFuhwuGlkBqrZKNUj/gSiYYc06gF/r/z6iWAjpXJRW1qq3CLZXdZFZ/VrqXeVjtOAu2A=\n";
-
- final static byte[] DECODED
- = {-12, -125, -51, 43, 5, 47, 116, -72, -120, 2, -98, -100, -73, 61, 118, 74, 36, 38, 56, 107, 45, 91, 38,
- 47, 72, -9, -98, -66, -25, -61, -122, -68, -38, -62, -50, -71, -66, -116, -92, 42, 54, -56, -113, 125,
- -40, 89, 54, -67, -60, 14, -36, -4, 81, -14, -91, 103, 37, -83, -104, 80, -18, -119, -33, 115, 114, 68,
- -9, 112, 73, -27, -12, -8, 71, -36, -64, 17, -40, -37, -113, 45, 97, -65, -122, 88, 54, 113, 19, -31, 98,
- 94, 92, -62, -55, -1, -102, 126, -88, 26, 83, -80, -6, 94, -91, 111, 3, 53, 86, 50, -43, -51, 54, -1, 92,
- 50, 11, -23, 32, 3, -96, -81, 69, 71, 125, 113, 42, -1, -106, -33, 60, 0, 71, 108, 77, 94, 6, 48, 41, -11,
- -8, 76, 46, 2, 38, 29, -118, -4, 110, -50, 127, -100, 44, -49, 42, -38, 55, -80, -86, 82, 57, -38, -45,
- -3, 39, -80, -84, -14, -6, -122, -17, 91, 58, -7, 96, 4, 44, -85, -26, -3, 74, 47, -65, 38, -114, -117,
- -29, -99, 49, 71, -29, 67, 66, 75, -120, -71, 7, -69, -86, 125, 59, 5, 32, -67, 10, -94, 12, -84, -60, -65,
- -16, 46, -126, -115, 29, 76, -10, 115, 96, 97, 50, 8, -2, 70, 86, -71, 94, -35, 4, 29, -127, -56, -120,
- 30, 122, 93, 119, -123, 84, 76, -15, -111, 81, -75, -34, 41, -72, 126, -7, 77, -33, 108, -110, 39, -125,
- -5, 16, 92, -51, -56, 96, 28, -116, 103, -68, 109, -12, 117, -110, -44, -75, 28, 69, -44, 59, 62, -68,
- 39, -4, -119, 80, 91, 19, -116, 122, -81, -118, 100, -108, -88, 2, -8, -106, -75, -37, 30, -83, 124, -121,
- 108, -127, 26, -1, -8, 102, -81, -118, 127, -113, -51, 36, -46, 15, 106, -33, -104, 106, -43, -84, -122,
- 51, -33, 124, -32, 2, -45, 73, -90, 124, 89, -20, -123, 109, -100, 117, 11, 16, -65, 66, -118, -97, -9,
- 101, 7, -1, 41, 65, 70, 116, -119, 54, 126, 44, 75, 74, 26, -34, -27, 27, 54, -13, -89, -90, 64, 120, 15,
- -43, 123, 82, -33, 90, -74, 41, -62, 38, -68, 62, -62, 34, 92, 50, 95, -67, -110, -99, -71, -44, -123,
- 49, 4, 96, 56, 113, 76, 97, -47, -26, -79, -109, 115, -125, 90, 124, 8, -9, -111, 36, -74, 101, -114, 43,
- 0, -110, 63, 76, 99, 91, 2, 12, -60, 56, -14, -125, 0, 6, -27, 31, 31, -109, -47, -3, 109, 88, -75, -74,
- 19, 26, -66, 110, 39, 13, -50, 47, 104, -38, 18, 19, 84, 103, 100, -42, 48, 110, 37, 21, -107, 83, -52,
- -12, 71, 37, -68, -107, -109, 89, -34, -94, -127, 103, -128, -48, -52, 71, 0, 15, 34, 56, -50, 85, -98,
- 106, -87, -3, 97, -116, -19, 64, -22, -25, -38, -63, 33, -45, 80, 10, -121, -109, 37, -96, 36, 18, -48,
- 46, 44, -66, 115, -94, 3, -102, -27, -17, -116, -51, 88, -17, 7, -109, 24, 66, 83, -91, 105, -92, -19,
- 66, -76, 64, -91, 118, -71, 103, -123, 95, 17, -87, -18, -11, 66, -74, 126, 45, 83, -14, 50, 79, 20, 45,
- -113, -103, 119, -101, -58, -99, 27, -100, -17, -107, 91, -26, -32, -56, 71, 72, 34, 66, 16, 9, -90, 106,
- -44, -62, -106, 11, 114, -82, -120, -28, -67, 4, -99, 109, -20, -19, 0, -40, -110, -119, 42, -6, 4, -31,
- 67, 110, -105, 53, 118, 76, 96, -126, -8, -96, 39, -102, 52, 106, 64, 26, -105, -108, -103, -96, -116,
- 116, 0, -96, 115, 89, 40, -23, -102, -2, -30, 16, 58, -53, -33, 14, 122, -94, 113, -121, 67, -103, -4,
- -126, 98, -27, 124, -12, 120, -64, -44, 127, 45, -120, 50, 124, -27, 87, -20, -84, 81, -35, 113, -77,
- -64, -96, -48, -87, -117, -82, 90, -64, -108, -121, 125, -45, -50, -44, -48, -50, 52, -30, -66, -7, 46,
- -40, -47, 85, -44, -126, -122, 24, -84, 21, 120, 99, -74, 27, 11, -52, 32, -2, 122, -100, -118, 106, -9,
- -106, 109, -19, 71, 42, 126, 66, -56, 10, -51, -44, 68, 109, -13, 81, -109, 65, 121, 60, -68, -117, 126,
- -59, 4, -107, -22, 99, -77, 84, 29, 87, 119, -60, 87, 82, -55, -74, 44, -80, 3, 123, -101, 84, -44, 9, 71,
- 24, 91, 99, 22, -65, 11, -11, -14, -38, -84, 105, -101, -85, -17, 116, -65, 118, -105, 122, -75, 113,
- -57, -81, -33, -110, 28, 104, -24, -110, -57, -78, 38, -5, -15, -79, 87, 105, 85, 41, -42, -114, -67,
- -123, 70, 12, 61, 115, 5, 23, -70, 99, 96, -80, 65, -65, 105, -45, -49, 37, -33, -1, 119, -88, 100, 121,
- -25, -35, -51, 10, 43, -113, 61, 103, 44, 13, 108, 20, 74, 19, 53, 19, 37, -76, 20, -43, -11, 23, -58, -25,
- -52, 121, -40, -118, 58, 50, 19, -8, -33, -30, -49, -27, -11, -80, 93, -17, 34, 93, 69, 100, 66, -54, 40,
- 118, 89, -52, -87, 2, 35, -120, 18, 64, 108, 31, -25, 66, 78, 6, -91, -69, -53, 17, 14, -125, 33, -31, -110,
- 1, 5, -40, 7, 126, -122, 84, -55, -62, -22, 69, -28, 5, 45, -106, 120, 74, 94, 51, 74, 108, -19, -26, -12,
- 49, 64, 88, 68, 41, -65, 126, 125, -1, -8, -83, -67, 74, 2, -114, -80, -119, -9, -89, -125, 21, 95, 34,
- -58, -74, 111, -103, 99, 95, 48, 42, 94, -50, -55, -112, -5, -26, 11, -89, -38, -19, 126, 25, 102, 119,
- 81, -94, 70, -79, 98, 91, -73, 114, 15, 14, 87, -21, -122, -1, -90, 0, 29, -104, -91, -93, -58, -83, -48,
- -22, 100, -112, -41, 77, 22, -24, 112, -72, 105, 100, 6, -86, -39, 40, -43, 35, -2, 4, -94, 97, -121, 52,
- -22, 1, 127, -81, -4, -6, -119, 96, 35, -91, 114, 81, 91, 90, -86, -36, 34, -39, 93, -42, 69, 103, -11,
- 107, -87, 119, -107, -114, -45, -128, -69, 96};
-
- // Some utility code to help test chunked reads of the InputStream.
-
- private final static int SIZE_KEY = 0;
- private final static int LAST_READ_KEY = 1;
-
- static byte[] streamToBytes(final InputStream in) throws IOException {
- // new byte[7] is obviously quite slow, but helps exercise the code.
- return streamToBytes(in, new byte[7]);
- }
-
- static byte[] streamToBytes(final InputStream in, byte[] buf) throws IOException {
- try {
- int[] status = fill(buf, 0, in);
- int size = status[SIZE_KEY];
- int lastRead = status[LAST_READ_KEY];
- while (lastRead != -1) {
- buf = resizeArray(buf);
- status = fill(buf, size, in);
- size = status[SIZE_KEY];
- lastRead = status[LAST_READ_KEY];
- }
- if (buf.length != size) {
- final byte[] smallerBuf = new byte[size];
- System.arraycopy(buf, 0, smallerBuf, 0, size);
- buf = smallerBuf;
- }
- }
- finally {
- in.close();
- }
- return buf;
- }
-
- private static int[] fill(final byte[] buf, final int offset, final InputStream in)
- throws IOException {
- int read = in.read(buf, offset, buf.length - offset);
- int lastRead = read;
- if (read == -1) {
- read = 0;
- }
- while (lastRead != -1 && read + offset < buf.length) {
- lastRead = in.read(buf, offset + read, buf.length - read - offset);
- if (lastRead != -1) {
- read += lastRead;
- }
- }
- return new int[]{offset + read, lastRead};
- }
-
- private static byte[] resizeArray(final byte[] bytes) {
- final byte[] biggerBytes = new byte[bytes.length * 2];
- System.arraycopy(bytes, 0, biggerBytes, 0, bytes.length);
- return biggerBytes;
- }
-
-
- /**
- * Returns an encoded and decoded copy of the same random data.
- *
- * @param size amount of random data to generate and encode
- * @param urlSafe true if encoding be urlSafe
- * @return two byte[] arrays: [0] = decoded, [1] = encoded
- */
- static byte[][] randomData(final int size, final boolean urlSafe) {
- final Random r = new Random();
- final byte[] decoded = new byte[size];
- r.nextBytes(decoded);
- final byte[] encoded = urlSafe ? Base64.encodeBase64URLSafe(decoded) : Base64.encodeBase64(decoded);
- return new byte[][] {decoded, encoded};
- }
-
- /**
- * Tests the supplied byte[] array to see if it contains the specified byte c.
- *
- * @param bytes byte[] array to test
- * @param c byte to look for
- * @return true if bytes contains c, false otherwise
- */
- static boolean bytesContain(final byte[] bytes, final byte c) {
- for (final byte b : bytes) {
- if (b == c) { return true; }
- }
- return false;
- }
-
}
diff --git a/src/test/java/org/apache/commons/codec/binary/Base64TestData.java b/src/test/java/org/apache/commons/codec/binary/BaseNTestData.java
similarity index 64%
copy from src/test/java/org/apache/commons/codec/binary/Base64TestData.java
copy to src/test/java/org/apache/commons/codec/binary/BaseNTestData.java
index 3e53d3a..5a43dbe 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base64TestData.java
+++ b/src/test/java/org/apache/commons/codec/binary/BaseNTestData.java
@@ -17,73 +17,17 @@
package org.apache.commons.codec.binary;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Random;
/**
- * This random data was encoded by OpenSSL. Java had nothing to do with it. This data helps us test interop between
- * Commons-Codec and OpenSSL. Notice that OpenSSL creates 64 character lines instead of the 76 of Commons-Codec.
+ * Data and functions common to BaseN tests.
*
- * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>
- * @since 1.4
+ * @since 1.15
*/
-public class Base64TestData {
-
- public static final String CODEC_101_MULTIPLE_OF_3 = "124";
-
- public static final String CODEC_98_NPE
- = "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM";
-
- public static final String CODEC_98_NPE_DECODED
- = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123";
-
-
- // OpenSSL doesn't include the final \n, but it would be annoying beyond belief
- // to further parameterize commons-codec to support this pointless variation.
- final static String ENCODED_64_CHARS_PER_LINE
- = "9IPNKwUvdLiIAp6ctz12SiQmOGstWyYvSPeevufDhrzaws65voykKjbIj33YWTa9\n"
- + "xA7c/FHypWclrZhQ7onfc3JE93BJ5fT4R9zAEdjbjy1hv4ZYNnET4WJeXMLJ/5p+\n"
- + "qBpTsPpepW8DNVYy1c02/1wyC+kgA6CvRUd9cSr/lt88AEdsTV4GMCn1+EwuAiYd\n"
- + "ivxuzn+cLM8q2jewqlI52tP9J7Cs8vqG71s6+WAELKvm/UovvyaOi+OdMUfjQ0JL\n"
- + "iLkHu6p9OwUgvQqiDKzEv/Augo0dTPZzYGEyCP5GVrle3QQdgciIHnpdd4VUTPGR\n"
- + "UbXeKbh++U3fbJIng/sQXM3IYByMZ7xt9HWS1LUcRdQ7Prwn/IlQWxOMeq+KZJSo\n"
- + "AviWtdserXyHbIEa//hmr4p/j80k0g9q35hq1ayGM9984ALTSaZ8WeyFbZx1CxC/\n"
- + "Qoqf92UH/ylBRnSJNn4sS0oa3uUbNvOnpkB4D9V7Ut9atinCJrw+wiJcMl+9kp25\n"
- + "1IUxBGA4cUxh0eaxk3ODWnwI95EktmWOKwCSP0xjWwIMxDjygwAG5R8fk9H9bVi1\n"
- + "thMavm4nDc4vaNoSE1RnZNYwbiUVlVPM9EclvJWTWd6igWeA0MxHAA8iOM5Vnmqp\n"
- + "/WGM7UDq59rBIdNQCoeTJaAkEtAuLL5zogOa5e+MzVjvB5MYQlOlaaTtQrRApXa5\n"
- + "Z4VfEanu9UK2fi1T8jJPFC2PmXebxp0bnO+VW+bgyEdIIkIQCaZq1MKWC3KuiOS9\n"
- + "BJ1t7O0A2JKJKvoE4UNulzV2TGCC+KAnmjRqQBqXlJmgjHQAoHNZKOma/uIQOsvf\n"
- + "DnqicYdDmfyCYuV89HjA1H8tiDJ85VfsrFHdcbPAoNCpi65awJSHfdPO1NDONOK+\n"
- + "+S7Y0VXUgoYYrBV4Y7YbC8wg/nqcimr3lm3tRyp+QsgKzdREbfNRk0F5PLyLfsUE\n"
- + "lepjs1QdV3fEV1LJtiywA3ubVNQJRxhbYxa/C/Xy2qxpm6vvdL92l3q1ccev35Ic\n"
- + "aOiSx7Im+/GxV2lVKdaOvYVGDD1zBRe6Y2CwQb9p088l3/93qGR5593NCiuPPWcs\n"
- + "DWwUShM1EyW0FNX1F8bnzHnYijoyE/jf4s/l9bBd7yJdRWRCyih2WcypAiOIEkBs\n"
- + "H+dCTgalu8sRDoMh4ZIBBdgHfoZUycLqReQFLZZ4Sl4zSmzt5vQxQFhEKb9+ff/4\n"
- + "rb1KAo6wifengxVfIsa2b5ljXzAqXs7JkPvmC6fa7X4ZZndRokaxYlu3cg8OV+uG\n"
- + "/6YAHZilo8at0OpkkNdNFuhwuGlkBqrZKNUj/gSiYYc06gF/r/z6iWAjpXJRW1qq\n"
- + "3CLZXdZFZ/VrqXeVjtOAu2A=\n";
-
- final static String ENCODED_76_CHARS_PER_LINE
- = "9IPNKwUvdLiIAp6ctz12SiQmOGstWyYvSPeevufDhrzaws65voykKjbIj33YWTa9xA7c/FHypWcl\n"
- + "rZhQ7onfc3JE93BJ5fT4R9zAEdjbjy1hv4ZYNnET4WJeXMLJ/5p+qBpTsPpepW8DNVYy1c02/1wy\n"
- + "C+kgA6CvRUd9cSr/lt88AEdsTV4GMCn1+EwuAiYdivxuzn+cLM8q2jewqlI52tP9J7Cs8vqG71s6\n"
- + "+WAELKvm/UovvyaOi+OdMUfjQ0JLiLkHu6p9OwUgvQqiDKzEv/Augo0dTPZzYGEyCP5GVrle3QQd\n"
- + "gciIHnpdd4VUTPGRUbXeKbh++U3fbJIng/sQXM3IYByMZ7xt9HWS1LUcRdQ7Prwn/IlQWxOMeq+K\n"
- + "ZJSoAviWtdserXyHbIEa//hmr4p/j80k0g9q35hq1ayGM9984ALTSaZ8WeyFbZx1CxC/Qoqf92UH\n"
- + "/ylBRnSJNn4sS0oa3uUbNvOnpkB4D9V7Ut9atinCJrw+wiJcMl+9kp251IUxBGA4cUxh0eaxk3OD\n"
- + "WnwI95EktmWOKwCSP0xjWwIMxDjygwAG5R8fk9H9bVi1thMavm4nDc4vaNoSE1RnZNYwbiUVlVPM\n"
- + "9EclvJWTWd6igWeA0MxHAA8iOM5Vnmqp/WGM7UDq59rBIdNQCoeTJaAkEtAuLL5zogOa5e+MzVjv\n"
- + "B5MYQlOlaaTtQrRApXa5Z4VfEanu9UK2fi1T8jJPFC2PmXebxp0bnO+VW+bgyEdIIkIQCaZq1MKW\n"
- + "C3KuiOS9BJ1t7O0A2JKJKvoE4UNulzV2TGCC+KAnmjRqQBqXlJmgjHQAoHNZKOma/uIQOsvfDnqi\n"
- + "cYdDmfyCYuV89HjA1H8tiDJ85VfsrFHdcbPAoNCpi65awJSHfdPO1NDONOK++S7Y0VXUgoYYrBV4\n"
- + "Y7YbC8wg/nqcimr3lm3tRyp+QsgKzdREbfNRk0F5PLyLfsUElepjs1QdV3fEV1LJtiywA3ubVNQJ\n"
- + "RxhbYxa/C/Xy2qxpm6vvdL92l3q1ccev35IcaOiSx7Im+/GxV2lVKdaOvYVGDD1zBRe6Y2CwQb9p\n"
- + "088l3/93qGR5593NCiuPPWcsDWwUShM1EyW0FNX1F8bnzHnYijoyE/jf4s/l9bBd7yJdRWRCyih2\n"
- + "WcypAiOIEkBsH+dCTgalu8sRDoMh4ZIBBdgHfoZUycLqReQFLZZ4Sl4zSmzt5vQxQFhEKb9+ff/4\n"
- + "rb1KAo6wifengxVfIsa2b5ljXzAqXs7JkPvmC6fa7X4ZZndRokaxYlu3cg8OV+uG/6YAHZilo8at\n"
- + "0OpkkNdNFuhwuGlkBqrZKNUj/gSiYYc06gF/r/z6iWAjpXJRW1qq3CLZXdZFZ/VrqXeVjtOAu2A=\n";
+public class BaseNTestData {
final static byte[] DECODED
= {-12, -125, -51, 43, 5, 47, 116, -72, -120, 2, -98, -100, -73, 61, 118, 74, 36, 38, 56, 107, 45, 91, 38,
@@ -133,16 +77,38 @@ public class Base64TestData {
-22, 1, 127, -81, -4, -6, -119, 96, 35, -91, 114, 81, 91, 90, -86, -36, 34, -39, 93, -42, 69, 103, -11,
107, -87, 119, -107, -114, -45, -128, -69, 96};
- // Some utility code to help test chunked reads of the InputStream.
+ /**
+ * Read all bytes from an InputStream into a byte array.
+ *
+ * @param in the input stream.
+ * @return the byte array
+ *
+ * @throws IOException if an error occurs whilst reading the input stream
+ */
+ static byte[] streamToBytes(final InputStream in) throws IOException {
+ final ByteArrayOutputStream os = new ByteArrayOutputStream();
+ final byte[] buf = new byte[4096];
+ int read;
+ while ((read = in.read(buf)) > -1) {
+ os.write(buf, 0, read);
+ }
+ return os.toByteArray();
+ }
private final static int SIZE_KEY = 0;
private final static int LAST_READ_KEY = 1;
- static byte[] streamToBytes(final InputStream in) throws IOException {
- // new byte[7] is obviously quite slow, but helps exercise the code.
- return streamToBytes(in, new byte[7]);
- }
-
+ /**
+ * Read all bytes from an InputStream into a byte array
+ * in chunks of {@code buf.length}.
+ *
+ * @param in the input stream.
+ * @param buf the byte array to use for chunking
+ *
+ * @return the bytes read from the input stream
+ *
+ * @throws IOException if an error occurs whilst reading the input stream
+ */
static byte[] streamToBytes(final InputStream in, byte[] buf) throws IOException {
try {
int[] status = fill(buf, 0, in);
@@ -188,19 +154,18 @@ public class Base64TestData {
return biggerBytes;
}
-
/**
* Returns an encoded and decoded copy of the same random data.
*
+ * @param codec the codec to use
* @param size amount of random data to generate and encode
- * @param urlSafe true if encoding be urlSafe
* @return two byte[] arrays: [0] = decoded, [1] = encoded
*/
- static byte[][] randomData(final int size, final boolean urlSafe) {
+ static byte[][] randomData(final BaseNCodec codec, final int size) {
final Random r = new Random();
final byte[] decoded = new byte[size];
r.nextBytes(decoded);
- final byte[] encoded = urlSafe ? Base64.encodeBase64URLSafe(decoded) : Base64.encodeBase64(decoded);
+ final byte[] encoded = codec.encode(decoded);
return new byte[][] {decoded, encoded};
}
@@ -217,5 +182,4 @@ public class Base64TestData {
}
return false;
}
-
}
This is an automated email from the ASF dual-hosted git repository.
aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-codec.git
commit 467b85c190dcca2b3c2016cda303be0432757b5b
Author: aherbert <ah...@apache.org>
AuthorDate: Tue Jun 30 15:09:31 2020 +0100
Remove redundant comments that refer to removed code
---
src/test/java/org/apache/commons/codec/binary/Base32TestData.java | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/test/java/org/apache/commons/codec/binary/Base32TestData.java b/src/test/java/org/apache/commons/codec/binary/Base32TestData.java
index 98225f4..10ad70e 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base32TestData.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base32TestData.java
@@ -31,6 +31,4 @@ public class Base32TestData {
static final String BASE32_FIXTURE = "JBSWY3DPEBLW64TMMQ======\r\n";
// static final String BASE32HEX_FIXTURE = "91IMOR3F41BMUSJCCG======";
- // Some utility code to help test chunked reads of the InputStream.
-
}
This is an automated email from the ASF dual-hosted git repository.
aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-codec.git
commit 4024b4039a886ca1de2325ce04638c8e4ee340a5
Author: Adam Retter <ad...@googlemail.com>
AuthorDate: Wed Jun 24 13:15:24 2020 +0200
Address out-of-bounds for array size with int wrap-around
---
src/main/java/org/apache/commons/codec/binary/Base16.java | 7 ++++++-
src/test/java/org/apache/commons/codec/binary/Base16Test.java | 7 +++++++
2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/src/main/java/org/apache/commons/codec/binary/Base16.java b/src/main/java/org/apache/commons/codec/binary/Base16.java
index 86ba2cf..886b5cd 100644
--- a/src/main/java/org/apache/commons/codec/binary/Base16.java
+++ b/src/main/java/org/apache/commons/codec/binary/Base16.java
@@ -220,7 +220,12 @@ public class Base16 extends BaseNCodec {
return;
}
- final byte[] buffer = ensureBufferSize(length * BYTES_PER_ENCODED_BLOCK, context);
+ final int size = length * BYTES_PER_ENCODED_BLOCK;
+ if (size < 0) {
+ throw new IllegalArgumentException("Input length exceeds maximum size for encoded data: " + length);
+ }
+
+ final byte[] buffer = ensureBufferSize(size, context);
final int end = offset + length;
for (int i = offset; i < end; i++) {
diff --git a/src/test/java/org/apache/commons/codec/binary/Base16Test.java b/src/test/java/org/apache/commons/codec/binary/Base16Test.java
index 0c06553..35e4054 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base16Test.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base16Test.java
@@ -483,6 +483,7 @@ public class Base16Test {
*
* @see <a href="https://issues.apache.org/jira/projects/CODEC/issues/CODEC-265">CODEC-265</a>
*/
+ @Test
public void testCodec265_over() {
// almost 1GiB file to encode: 2^29 bytes
final int size1GiB = 1 << 29;
@@ -510,6 +511,12 @@ public class Base16Test {
assertEquals(expectedLength, encoded.length);
}
+ @Test(expected = IllegalArgumentException.class)
+ public void checkEncodeLengthBounds() {
+ final Base16 base16 = new Base16();
+ base16.encode(new byte[10], 0, 1 << 30);
+ }
+
@Test
public void testIsInAlphabet() {
// invalid bounds
This is an automated email from the ASF dual-hosted git repository.
aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-codec.git
commit 0b672eb12df68545c9703e32e9bf74d6993cb464
Author: Adam Retter <ad...@googlemail.com>
AuthorDate: Wed Jun 24 12:33:26 2020 +0200
Imporve array equality assertions in tests
---
.../codec/binary/Base32InputStreamTest.java | 25 ++++++++++----------
.../codec/binary/Base32OutputStreamTest.java | 24 +++++++++----------
.../codec/binary/Base64InputStreamTest.java | 27 +++++++++++-----------
.../codec/binary/Base64OutputStreamTest.java | 26 ++++++++++-----------
4 files changed, 50 insertions(+), 52 deletions(-)
diff --git a/src/test/java/org/apache/commons/codec/binary/Base32InputStreamTest.java b/src/test/java/org/apache/commons/codec/binary/Base32InputStreamTest.java
index 164f6c3..03670ae 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base32InputStreamTest.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base32InputStreamTest.java
@@ -17,21 +17,20 @@
package org.apache.commons.codec.binary;
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.util.Arrays;
import org.apache.commons.codec.CodecPolicy;
import org.junit.Test;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
public class Base32InputStreamTest {
private static final String ENCODED_FOO = "MZXW6===";
@@ -291,7 +290,7 @@ public class Base32InputStreamTest {
assertEquals("EOF", -1, in.read());
assertEquals("Still EOF", -1, in.read());
- assertTrue("Streaming base32 encode", Arrays.equals(output, encoded));
+ assertArrayEquals("Streaming base32 encode", encoded, output);
// Now let's try decode.
in = new Base32InputStream(new ByteArrayInputStream(encoded));
@@ -299,7 +298,7 @@ public class Base32InputStreamTest {
assertEquals("EOF", -1, in.read());
assertEquals("Still EOF", -1, in.read());
- assertTrue("Streaming base32 decode", Arrays.equals(output, decoded));
+ assertArrayEquals("Streaming base32 decode", decoded, output);
// I always wanted to do this! (wrap encoder with decoder etc etc).
in = new ByteArrayInputStream(decoded);
@@ -311,7 +310,7 @@ public class Base32InputStreamTest {
assertEquals("EOF", -1, in.read());
assertEquals("Still EOF", -1, in.read());
- assertTrue("Streaming base32 wrap-wrap-wrap!", Arrays.equals(output, decoded));
+ assertArrayEquals("Streaming base32 wrap-wrap-wrap!", decoded, output);
in.close();
}
@@ -345,7 +344,7 @@ public class Base32InputStreamTest {
assertEquals("EOF", -1, in.read());
assertEquals("Still EOF", -1, in.read());
- assertTrue("Streaming base32 encode", Arrays.equals(output, encoded));
+ assertArrayEquals("Streaming base32 encode", encoded, output);
in.close();
@@ -358,7 +357,7 @@ public class Base32InputStreamTest {
assertEquals("EOF", -1, in.read());
assertEquals("Still EOF", -1, in.read());
- assertTrue("Streaming base32 decode", Arrays.equals(output, decoded));
+ assertArrayEquals("Streaming base32 decode", decoded, output);
in.close();
@@ -375,7 +374,7 @@ public class Base32InputStreamTest {
assertEquals("EOF", -1, in.read());
assertEquals("Still EOF", -1, in.read());
- assertTrue("Streaming base32 wrap-wrap-wrap!", Arrays.equals(output, decoded));
+ assertArrayEquals("Streaming base32 wrap-wrap-wrap!", decoded, output);
}
/**
diff --git a/src/test/java/org/apache/commons/codec/binary/Base32OutputStreamTest.java b/src/test/java/org/apache/commons/codec/binary/Base32OutputStreamTest.java
index 5ab7724..ad4c4af 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base32OutputStreamTest.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base32OutputStreamTest.java
@@ -17,17 +17,17 @@
package org.apache.commons.codec.binary;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
-import java.util.Arrays;
import org.apache.commons.codec.CodecPolicy;
import org.junit.Test;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
public class Base32OutputStreamTest {
private final static byte[] CR_LF = {(byte) '\r', (byte) '\n'};
@@ -185,7 +185,7 @@ public class Base32OutputStreamTest {
out.write(decoded);
out.close();
byte[] output = byteOut.toByteArray();
- assertTrue("Streaming chunked Base32 encode", Arrays.equals(output, encoded));
+ assertArrayEquals("Streaming chunked Base32 encode", encoded, output);
// Now let's try decode.
byteOut = new ByteArrayOutputStream();
@@ -193,7 +193,7 @@ public class Base32OutputStreamTest {
out.write(encoded);
out.close();
output = byteOut.toByteArray();
- assertTrue("Streaming chunked Base32 decode", Arrays.equals(output, decoded));
+ assertArrayEquals("Streaming chunked Base32 decode", decoded, output);
// I always wanted to do this! (wrap encoder with decoder etc etc).
byteOut = new ByteArrayOutputStream();
@@ -206,7 +206,7 @@ public class Base32OutputStreamTest {
out.close();
output = byteOut.toByteArray();
- assertTrue("Streaming chunked Base32 wrap-wrap-wrap!", Arrays.equals(output, decoded));
+ assertArrayEquals("Streaming chunked Base32 wrap-wrap-wrap!", decoded, output);
}
/**
@@ -237,7 +237,7 @@ public class Base32OutputStreamTest {
}
out.close();
byte[] output = byteOut.toByteArray();
- assertTrue("Streaming byte-by-byte Base32 encode", Arrays.equals(output, encoded));
+ assertArrayEquals("Streaming byte-by-byte Base32 encode", encoded, output);
// Now let's try decode.
byteOut = new ByteArrayOutputStream();
@@ -247,7 +247,7 @@ public class Base32OutputStreamTest {
}
out.close();
output = byteOut.toByteArray();
- assertTrue("Streaming byte-by-byte Base32 decode", Arrays.equals(output, decoded));
+ assertArrayEquals("Streaming byte-by-byte Base32 decode", decoded, output);
// Now let's try decode with tonnes of flushes.
byteOut = new ByteArrayOutputStream();
@@ -258,7 +258,7 @@ public class Base32OutputStreamTest {
}
out.close();
output = byteOut.toByteArray();
- assertTrue("Streaming byte-by-byte flush() Base32 decode", Arrays.equals(output, decoded));
+ assertArrayEquals("Streaming byte-by-byte flush() Base32 decode", decoded, output);
// I always wanted to do this! (wrap encoder with decoder etc etc).
byteOut = new ByteArrayOutputStream();
@@ -273,7 +273,7 @@ public class Base32OutputStreamTest {
out.close();
output = byteOut.toByteArray();
- assertTrue("Streaming byte-by-byte Base32 wrap-wrap-wrap!", Arrays.equals(output, decoded));
+ assertArrayEquals("Streaming byte-by-byte Base32 wrap-wrap-wrap!", decoded, output);
}
/**
diff --git a/src/test/java/org/apache/commons/codec/binary/Base64InputStreamTest.java b/src/test/java/org/apache/commons/codec/binary/Base64InputStreamTest.java
index 731457a..1e80dde 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base64InputStreamTest.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base64InputStreamTest.java
@@ -17,24 +17,23 @@
package org.apache.commons.codec.binary;
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.util.Arrays;
import org.apache.commons.codec.CodecPolicy;
import org.junit.Test;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
/**
* @since 1.4
*/
@@ -304,7 +303,7 @@ public class Base64InputStreamTest {
assertEquals("EOF", -1, in.read());
assertEquals("Still EOF", -1, in.read());
- assertTrue("Streaming base64 encode", Arrays.equals(output, encoded));
+ assertArrayEquals("Streaming base64 encode", encoded, output);
in.close();
@@ -314,7 +313,7 @@ public class Base64InputStreamTest {
assertEquals("EOF", -1, in.read());
assertEquals("Still EOF", -1, in.read());
- assertTrue("Streaming base64 decode", Arrays.equals(output, decoded));
+ assertArrayEquals("Streaming base64 decode", decoded, output);
// I always wanted to do this! (wrap encoder with decoder etc etc).
in = new ByteArrayInputStream(decoded);
@@ -326,7 +325,7 @@ public class Base64InputStreamTest {
assertEquals("EOF", -1, in.read());
assertEquals("Still EOF", -1, in.read());
- assertTrue("Streaming base64 wrap-wrap-wrap!", Arrays.equals(output, decoded));
+ assertArrayEquals("Streaming base64 wrap-wrap-wrap!", decoded, output);
in.close();
}
@@ -360,7 +359,7 @@ public class Base64InputStreamTest {
assertEquals("EOF", -1, in.read());
assertEquals("Still EOF", -1, in.read());
- assertTrue("Streaming base64 encode", Arrays.equals(output, encoded));
+ assertArrayEquals("Streaming base64 encode", encoded, output);
in.close();
// Now let's try decode.
@@ -372,7 +371,7 @@ public class Base64InputStreamTest {
assertEquals("EOF", -1, in.read());
assertEquals("Still EOF", -1, in.read());
- assertTrue("Streaming base64 decode", Arrays.equals(output, decoded));
+ assertArrayEquals("Streaming base64 decode", decoded, output);
in.close();
@@ -389,7 +388,7 @@ public class Base64InputStreamTest {
assertEquals("EOF", -1, in.read());
assertEquals("Still EOF", -1, in.read());
- assertTrue("Streaming base64 wrap-wrap-wrap!", Arrays.equals(output, decoded));
+ assertArrayEquals("Streaming base64 wrap-wrap-wrap!", decoded, output);
in.close();
}
diff --git a/src/test/java/org/apache/commons/codec/binary/Base64OutputStreamTest.java b/src/test/java/org/apache/commons/codec/binary/Base64OutputStreamTest.java
index 0b2480f..51a9a5c 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base64OutputStreamTest.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base64OutputStreamTest.java
@@ -17,18 +17,18 @@
package org.apache.commons.codec.binary;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
-import java.util.Arrays;
import org.apache.commons.codec.CodecPolicy;
import org.junit.Test;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
/**
* @since 1.4
*/
@@ -195,7 +195,7 @@ public class Base64OutputStreamTest {
out.write(decoded);
out.close();
byte[] output = byteOut.toByteArray();
- assertTrue("Streaming chunked base64 encode", Arrays.equals(output, encoded));
+ assertArrayEquals("Streaming chunked base64 encode", encoded, output);
// Now let's try decode.
byteOut = new ByteArrayOutputStream();
@@ -203,7 +203,7 @@ public class Base64OutputStreamTest {
out.write(encoded);
out.close();
output = byteOut.toByteArray();
- assertTrue("Streaming chunked base64 decode", Arrays.equals(output, decoded));
+ assertArrayEquals("Streaming chunked base64 decode", decoded, output);
// I always wanted to do this! (wrap encoder with decoder etc etc).
byteOut = new ByteArrayOutputStream();
@@ -216,7 +216,7 @@ public class Base64OutputStreamTest {
out.close();
output = byteOut.toByteArray();
- assertTrue("Streaming chunked base64 wrap-wrap-wrap!", Arrays.equals(output, decoded));
+ assertArrayEquals("Streaming chunked base64 wrap-wrap-wrap!", decoded, output);
}
/**
@@ -247,7 +247,7 @@ public class Base64OutputStreamTest {
}
out.close();
byte[] output = byteOut.toByteArray();
- assertTrue("Streaming byte-by-byte base64 encode", Arrays.equals(output, encoded));
+ assertArrayEquals("Streaming byte-by-byte base64 encode", encoded, output);
// Now let's try decode.
byteOut = new ByteArrayOutputStream();
@@ -257,7 +257,7 @@ public class Base64OutputStreamTest {
}
out.close();
output = byteOut.toByteArray();
- assertTrue("Streaming byte-by-byte base64 decode", Arrays.equals(output, decoded));
+ assertArrayEquals("Streaming byte-by-byte base64 decode", decoded, output);
// Now let's try decode with tonnes of flushes.
byteOut = new ByteArrayOutputStream();
@@ -268,7 +268,7 @@ public class Base64OutputStreamTest {
}
out.close();
output = byteOut.toByteArray();
- assertTrue("Streaming byte-by-byte flush() base64 decode", Arrays.equals(output, decoded));
+ assertArrayEquals("Streaming byte-by-byte flush() base64 decode", decoded, output);
// I always wanted to do this! (wrap encoder with decoder etc etc).
byteOut = new ByteArrayOutputStream();
@@ -283,7 +283,7 @@ public class Base64OutputStreamTest {
out.close();
output = byteOut.toByteArray();
- assertTrue("Streaming byte-by-byte base64 wrap-wrap-wrap!", Arrays.equals(output, decoded));
+ assertArrayEquals("Streaming byte-by-byte base64 wrap-wrap-wrap!", decoded, output);
}
/**
This is an automated email from the ASF dual-hosted git repository.
aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-codec.git
commit 427998a47a25c4bbc6098c7418cafffcfed53f53
Author: Adam Retter <ad...@googlemail.com>
AuthorDate: Mon Jun 29 22:19:16 2020 +0200
Revert changes to Hex classes, will be moved to separate PR
---
.../java/org/apache/commons/codec/binary/Hex.java | 85 ++--------------------
.../org/apache/commons/codec/binary/HexTest.java | 34 ---------
2 files changed, 7 insertions(+), 112 deletions(-)
diff --git a/src/main/java/org/apache/commons/codec/binary/Hex.java b/src/main/java/org/apache/commons/codec/binary/Hex.java
index 9c9a862..57c05bd 100644
--- a/src/main/java/org/apache/commons/codec/binary/Hex.java
+++ b/src/main/java/org/apache/commons/codec/binary/Hex.java
@@ -54,13 +54,13 @@ public class Hex implements BinaryEncoder, BinaryDecoder {
/**
* Used to build output as Hex
*/
- static final char[] DIGITS_LOWER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
+ private static final char[] DIGITS_LOWER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
'e', 'f' };
/**
* Used to build output as Hex
*/
- static final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
+ private static final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
'E', 'F' };
/**
@@ -73,38 +73,17 @@ public class Hex implements BinaryEncoder, BinaryDecoder {
* @throws DecoderException Thrown if an odd number or illegal of characters is supplied
*/
public static byte[] decodeHex(final char[] data) throws DecoderException {
- final byte[] out = new byte[data.length >> 1];
- decodeHex(data, out, 0);
- return out;
- }
- /**
- * Converts an array of characters representing hexadecimal values into an array of bytes of those same values. The
- * returned array will be half the length of the passed array, as it takes two characters to represent any given
- * byte. An exception is thrown if the passed char array has an odd number of elements.
- *
- * @param data An array of characters containing hexadecimal digits
- * @param out A byte array to contain the binary data decoded from the supplied char array.
- * @param outOffset The position within {@code out} to start writing the decoded bytes.
- * @return the number of bytes written to {@code out}.
- * @throws DecoderException Thrown if an odd number or illegal of characters is supplied
- *
- * @since 1.15
- */
- public static int decodeHex(final char[] data, final byte[] out, final int outOffset) throws DecoderException {
final int len = data.length;
if ((len & 0x01) != 0) {
throw new DecoderException("Odd number of characters.");
}
- final int outLen = len >> 1;
- if (out.length - outOffset < outLen) {
- throw new DecoderException("out is not large enough to accommodate decoded data.");
- }
+ final byte[] out = new byte[len >> 1];
// two characters form the hex value.
- for (int i = outOffset, j = 0; j < len; i++) {
+ for (int i = 0, j = 0; j < len; i++) {
int f = toDigit(data[j], j) << 4;
j++;
f = f | toDigit(data[j], j);
@@ -112,7 +91,7 @@ public class Hex implements BinaryEncoder, BinaryDecoder {
out[i] = (byte) (f & 0xFF);
}
- return outLen;
+ return out;
}
/**
@@ -169,62 +148,12 @@ public class Hex implements BinaryEncoder, BinaryDecoder {
protected static char[] encodeHex(final byte[] data, final char[] toDigits) {
final int l = data.length;
final char[] out = new char[l << 1];
- encodeHex(data, 0, data.length, toDigits, out, 0);
- return out;
- }
-
- /**
- * Converts an array of bytes into an array of characters representing the hexadecimal values of each byte in order.
- *
- * @param data a byte[] to convert to Hex characters
- * @param dataOffset the position in {@code data} to start encoding from
- * @param dataLen the number of bytes from {@code dataOffset} to encode
- * @param toLowerCase {@code true} converts to lowercase, {@code false} to uppercase
- * @return A char[] containing the appropriate characters from the alphabet For best results, this should be either
- * upper- or lower-case hex.
- * @since 1.15
- */
- protected static char[] encodeHex(final byte[] data, final int dataOffset, final int dataLen,
- final boolean toLowerCase) {
- final char[] out = new char[dataLen << 1];
- encodeHex(data, dataOffset, dataLen, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER, out, 0);
- return out;
- }
-
- /**
- * Converts an array of bytes into an array of characters representing the hexadecimal values of each byte in order.
- *
- * @param data a byte[] to convert to Hex characters
- * @param dataOffset the position in {@code data} to start encoding from
- * @param dataLen the number of bytes from {@code dataOffset} to encode
- * @param toLowerCase {@code true} converts to lowercase, {@code false} to uppercase
- * @param out a char[] which will hold the resultant appropriate characters from the alphabet.
- * @param outOffset the position within {@code out} at which to start writing the encoded characters.
- * @since 1.15
- */
- protected static void encodeHex(final byte[] data, final int dataOffset, final int dataLen,
- final boolean toLowerCase, final char[] out, final int outOffset) {
- encodeHex(data, dataOffset, dataLen, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER, out, outOffset);
- }
-
- /**
- * Converts an array of bytes into an array of characters representing the hexadecimal values of each byte in order.
- *
- * @param data a byte[] to convert to Hex characters
- * @param dataOffset the position in {@code data} to start encoding from
- * @param dataLen the number of bytes from {@code dataOffset} to encode
- * @param toDigits the output alphabet (must contain at least 16 chars)
- * @param out a char[] which will hold the resultant appropriate characters from the alphabet.
- * @param outOffset the position within {@code out} at which to start writing the encoded characters.
- * @since 1.15
- */
- protected static void encodeHex(final byte[] data, final int dataOffset, final int dataLen, final char[] toDigits,
- final char[] out, final int outOffset) {
// two characters form the hex value.
- for (int i = dataOffset, j = outOffset; i < dataOffset + dataLen; i++) {
+ for (int i = 0, j = 0; i < l; i++) {
out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
out[j++] = toDigits[0x0F & data[i]];
}
+ return out;
}
/**
diff --git a/src/test/java/org/apache/commons/codec/binary/HexTest.java b/src/test/java/org/apache/commons/codec/binary/HexTest.java
index 324aaa0..4c29548 100644
--- a/src/test/java/org/apache/commons/codec/binary/HexTest.java
+++ b/src/test/java/org/apache/commons/codec/binary/HexTest.java
@@ -17,7 +17,6 @@
package org.apache.commons.codec.binary;
-import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -341,18 +340,6 @@ public class HexTest {
checkDecodeHexCharArrayOddCharacters(new char[] { 'A', 'B', 'C', 'D', 'E' });
}
- @Test(expected = DecoderException.class)
- public void testDecodeHexCharArrayOutBufferUnderSized() throws DecoderException {
- final byte[] out = new byte[4];
- Hex.decodeHex("aabbccddeeff".toCharArray(), out, 0);
- }
-
- @Test(expected = DecoderException.class)
- public void testDecodeHexCharArrayOutBufferUnderSizedByOffset() throws DecoderException {
- final byte[] out = new byte[6];
- Hex.decodeHex("aabbccddeeff".toCharArray(), out, 1);
- }
-
@Test
public void testDecodeHexStringOddCharacters() {
try {
@@ -454,27 +441,6 @@ public class HexTest {
}
@Test
- public void testEncodeDecodeHexCharArrayRandomToOutput() throws DecoderException, EncoderException {
- final Random random = new Random();
- for (int i = 5; i > 0; i--) {
- final byte[] data = new byte[random.nextInt(10000) + 1];
- random.nextBytes(data);
-
- // lower-case
- final char[] lowerEncodedChars = new char[data.length * 2];
- Hex.encodeHex(data, 0, data.length, true, lowerEncodedChars, 0);
- final byte[] decodedLowerCaseBytes = Hex.decodeHex(lowerEncodedChars);
- assertArrayEquals(data, decodedLowerCaseBytes);
-
- // upper-case
- final char[] upperEncodedChars = new char[data.length * 2];
- Hex.encodeHex(data, 0, data.length, false, upperEncodedChars, 0);
- final byte[] decodedUpperCaseBytes = Hex.decodeHex(upperEncodedChars);
- assertArrayEquals(data, decodedUpperCaseBytes);
- }
- }
-
- @Test
public void testEncodeHexByteArrayEmpty() {
assertTrue(Arrays.equals(new char[0], Hex.encodeHex(new byte[0])));
assertTrue(Arrays.equals(new byte[0], new Hex().encode(new byte[0])));
This is an automated email from the ASF dual-hosted git repository.
aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-codec.git
commit f19ec7891da4f591910e3a28d6ba87c6bbacba38
Author: Adam Retter <ad...@googlemail.com>
AuthorDate: Sat Apr 18 23:23:05 2020 +0200
Bugfix - buffer must always hold at least 'size' bytes
---
src/main/java/org/apache/commons/codec/binary/BaseNCodec.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/main/java/org/apache/commons/codec/binary/BaseNCodec.java b/src/main/java/org/apache/commons/codec/binary/BaseNCodec.java
index bd1d7c2..33f9916 100644
--- a/src/main/java/org/apache/commons/codec/binary/BaseNCodec.java
+++ b/src/main/java/org/apache/commons/codec/binary/BaseNCodec.java
@@ -567,7 +567,7 @@ public abstract class BaseNCodec implements BinaryEncoder, BinaryDecoder {
*/
protected byte[] ensureBufferSize(final int size, final Context context){
if (context.buffer == null) {
- context.buffer = new byte[getDefaultBufferSize()];
+ context.buffer = new byte[Math.max(size, getDefaultBufferSize())];
context.pos = 0;
context.readPos = 0;
This is an automated email from the ASF dual-hosted git repository.
aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-codec.git
commit 081756b86e25ec5ea7bc786e88a7d56b76f88ef9
Author: Adam Retter <ad...@googlemail.com>
AuthorDate: Sat Apr 18 23:56:17 2020 +0200
Add Base16 Input and Output Streams
---
pom.xml | 7 +
.../org/apache/commons/codec/binary/Base16.java | 268 +++++++++
.../commons/codec/binary/Base16InputStream.java | 67 +++
.../commons/codec/binary/Base16OutputStream.java | 67 +++
.../java/org/apache/commons/codec/binary/Hex.java | 85 ++-
.../codec/binary/Base16InputStreamTest.java | 411 ++++++++++++++
.../codec/binary/Base16OutputStreamTest.java | 266 +++++++++
.../apache/commons/codec/binary/Base16Test.java | 620 +++++++++++++++++++++
.../commons/codec/binary/Base16TestData.java | 111 ++++
.../org/apache/commons/codec/binary/HexTest.java | 34 ++
10 files changed, 1929 insertions(+), 7 deletions(-)
diff --git a/pom.xml b/pom.xml
index 05bb8d3..8041b03 100644
--- a/pom.xml
+++ b/pom.xml
@@ -207,6 +207,13 @@ limitations under the License.
<role>Submitted Match Rating Approach (MRA) phonetic encoder and tests [CODEC-161]</role>
</roles>
</contributor>
+ <contributor>
+ <name>Adam Retter</name>
+ <organization>Evolved Binary</organization>
+ <roles>
+ <role>Base16 Input and Output Streams</role>
+ </roles>
+ </contributor>
</contributors>
<!-- Codec only has test dependencies ATM -->
<dependencies>
diff --git a/src/main/java/org/apache/commons/codec/binary/Base16.java b/src/main/java/org/apache/commons/codec/binary/Base16.java
new file mode 100644
index 0000000..f94c115
--- /dev/null
+++ b/src/main/java/org/apache/commons/codec/binary/Base16.java
@@ -0,0 +1,268 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.codec.binary;
+
+import org.apache.commons.codec.DecoderException;
+
+import java.nio.charset.Charset;
+
+/**
+ * Provides Base16 encoding and decoding.
+ *
+ * <p>
+ * This class is thread-safe.
+ * </p>
+ *
+ * @since 1.15
+ */
+public class Base16 extends BaseNCodec {
+
+ private static final int BYTES_PER_UNENCODED_BLOCK = 1;
+ private static final int BYTES_PER_ENCODED_BLOCK = 2;
+
+ private final boolean toLowerCase;
+ private final Charset charset;
+
+ /**
+ * Creates a Base16 codec used for decoding and encoding.
+ */
+ protected Base16() {
+ this(Hex.DEFAULT_CHARSET);
+ }
+
+ /**
+ * Creates a Base16 codec used for decoding and encoding.
+ *
+ * @param charset the charset.
+ */
+ protected Base16(final Charset charset) {
+ this(true, charset);
+ }
+
+ /**
+ * Creates a Base16 codec used for decoding and encoding.
+ *
+ * @param toLowerCase {@code true} converts to lowercase, {@code false} to uppercase.
+ * @param charset the charset.
+ */
+ protected Base16(final boolean toLowerCase, final Charset charset) {
+ super(BYTES_PER_UNENCODED_BLOCK, BYTES_PER_ENCODED_BLOCK, 0, 0);
+ this.toLowerCase = toLowerCase;
+ this.charset = charset;
+ }
+
+
+ @Override
+ void encode(final byte[] data, final int offset, final int length, final Context context) {
+ if (context.eof) {
+ return;
+ }
+ if (length < 0) {
+ context.eof = true;
+ return;
+ }
+
+ final char[] chars = Hex.encodeHex(data, offset, length, toLowerCase);
+ final byte[] encoded = new String(chars).getBytes(charset);
+
+ final byte[] buffer = ensureBufferSize(encoded.length, context);
+ System.arraycopy(encoded, 0, buffer, context.pos, encoded.length);
+
+ context.pos += encoded.length;
+ }
+
+ @Override
+ void decode(final byte[] data, final int offset, final int length, final Context context) {
+ if (context.eof) {
+ return;
+ }
+ if (length < 0) {
+ context.eof = true;
+ return;
+ }
+
+ final int dataLen = Math.min(data.length - offset, length);
+ final int availableChars = (context.ibitWorkArea > 0 ? 1 : 0) + dataLen;
+
+ // small optimisation to short-cut the rest of this method when it is fed byte-by-byte
+ if (availableChars == 1 && availableChars == dataLen) {
+ context.ibitWorkArea = data[offset]; // store 1/2 byte for next invocation of decode
+ return;
+ }
+
+ // NOTE: Each pair of bytes is really a pair of hex-chars, therefore each pair represents one byte
+
+ // we must have an even number of chars to decode
+ final char[] encodedChars = new char[availableChars % 2 == 0 ? availableChars : availableChars - 1];
+
+ // copy all (or part of) data into encodedChars
+ int i = 0;
+ if (dataLen < availableChars) {
+ // we have 1/2 byte from previous invocation to decode
+ encodedChars[i++] = (char)context.ibitWorkArea;
+ context.ibitWorkArea = -1; // reset for next iteration!
+ }
+ final int copyLen = encodedChars.length - i;
+ for (int j = offset; j < copyLen + offset; j++) {
+ encodedChars[i++] = (char) data[j];
+ }
+
+ // decode encodedChars into buffer
+ final byte[] buffer = ensureBufferSize(encodedChars.length / 2, context);
+ try {
+ final int written = Hex.decodeHex(encodedChars, buffer, context.pos);
+ context.pos += written;
+ } catch (final DecoderException e) {
+ throw new RuntimeException(e); // this method ensures that this cannot happen at runtime!
+ }
+
+ // we have one char of a hex-pair left over
+ if (copyLen < dataLen) {
+ context.ibitWorkArea = data[offset + dataLen - 1]; // store 1/2 byte for next invocation of decode
+ }
+ }
+
+ @Override
+ protected boolean isInAlphabet(final byte value) {
+ if (value >= '0' && value <= '9') {
+ return true;
+ }
+
+ if (toLowerCase) {
+ return value >= 'a' && value <= 'f';
+ } else {
+ return value >= 'A' && value <= 'F';
+ }
+ }
+
+ /**
+ * Returns whether or not the {@code c} is in the base 16 alphabet.
+ *
+ * @param c The value to test
+ * @return {@code true} if the value is defined in the the base 16 alphabet, {@code false} otherwise.
+ */
+ public static boolean isBase16(final char c) {
+ return
+ (c >= '0' && c <= '9')
+ || (c >= 'A' && c <= 'F')
+ || (c >= 'a' && c <= 'f');
+ }
+
+ /**
+ * Tests a given String to see if it contains only valid characters within the Base16 alphabet.
+ *
+ * @param base16 String to test
+ * @return {@code true} if all characters in the String are valid characters in the Base16 alphabet or if
+ * the String is empty; {@code false}, otherwise
+ */
+ public static boolean isBase16(final String base16) {
+ return isBase16(base16.toCharArray());
+ }
+
+ /**
+ * Tests a given char array to see if it contains only valid characters within the Base16 alphabet.
+ *
+ * @param arrayChars char array to test
+ * @return {@code true} if all chars are valid characters in the Base16 alphabet or if the char array is empty;
+ * {@code false}, otherwise
+ */
+ public static boolean isBase16(final char[] arrayChars) {
+ for (int i = 0; i < arrayChars.length; i++) {
+ if (!isBase16(arrayChars[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Tests a given char array to see if it contains only valid characters within the Base16 alphabet.
+ *
+ * @param arrayChars byte array to test
+ * @return {@code true} if all chars are valid characters in the Base16 alphabet or if the byte array is empty;
+ * {@code false}, otherwise
+ */
+ public static boolean isBase16(final byte[] arrayChars) {
+ for (int i = 0; i < arrayChars.length; i++) {
+ if (!isBase16((char) arrayChars[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Encodes binary data using the base16 algorithm.
+ *
+ * @param binaryData Array containing binary data to encode.
+ * @return Base16-encoded data.
+ */
+ public static byte[] encodeBase16(final byte[] binaryData) {
+ return encodeBase16(binaryData, true, Hex.DEFAULT_CHARSET, Integer.MAX_VALUE);
+ }
+
+ /**
+ * Encodes binary data using the base16 algorithm.
+ *
+ * @param binaryData Array containing binary data to encode.
+ * @param toLowerCase {@code true} converts to lowercase, {@code false} to uppercase.
+ * @param charset the charset.
+ * @param maxResultSize The maximum result size to accept.
+ * @return Base16-encoded data.
+ * @throws IllegalArgumentException Thrown when the input array needs an output array bigger than maxResultSize
+ */
+ public static byte[] encodeBase16(final byte[] binaryData, final boolean toLowerCase, final Charset charset,
+ final int maxResultSize) {
+ if (binaryData == null || binaryData.length == 0) {
+ return binaryData;
+ }
+
+ // Create this so can use the super-class method
+ // Also ensures that the same roundings are performed by the ctor and the code
+ final Base16 b16 = new Base16(toLowerCase, charset);
+ final long len = b16.getEncodedLength(binaryData);
+ if (len > maxResultSize) {
+ throw new IllegalArgumentException("Input array too big, the output array would be bigger (" +
+ len +
+ ") than the specified maximum size of " +
+ maxResultSize);
+ }
+
+ return b16.encode(binaryData);
+ }
+
+ /**
+ * Decodes a Base16 String into octets.
+ *
+ * @param base16String String containing Base16 data
+ * @return Array containing decoded data.
+ */
+ public static byte[] decodeBase16(final String base16String) {
+ return new Base16().decode(base16String);
+ }
+
+ /**
+ * Decodes Base16 data into octets.
+ *
+ * @param base16Data Byte array containing Base16 data
+ * @return Array containing decoded data.
+ */
+ public static byte[] decodeBase16(final byte[] base16Data) {
+ return new Base16().decode(base16Data);
+ }
+}
diff --git a/src/main/java/org/apache/commons/codec/binary/Base16InputStream.java b/src/main/java/org/apache/commons/codec/binary/Base16InputStream.java
new file mode 100644
index 0000000..94e8cf4
--- /dev/null
+++ b/src/main/java/org/apache/commons/codec/binary/Base16InputStream.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.codec.binary;
+
+import java.io.InputStream;
+import java.nio.charset.Charset;
+
+/**
+ * Provides Base16 encoding and decoding in a streaming fashion (unlimited size).
+ * <p>
+ * The default behavior of the Base16InputStream is to DECODE, whereas the default behavior of the
+ * {@link Base16OutputStream} is to ENCODE, but this behavior can be overridden by using a different constructor.
+ * </p>
+ *
+ * @since 1.15
+ */
+public class Base16InputStream extends BaseNCodecInputStream {
+
+ /**
+ * Creates a Base16InputStream such that all data read is Base16-decoded from the original provided InputStream.
+ *
+ * @param in InputStream to wrap.
+ */
+ public Base16InputStream(final InputStream in) {
+ this(in, false);
+ }
+
+ /**
+ * Creates a Base16InputStream such that all data read is either Base16-encoded or Base16-decoded from the original
+ * provided InputStream.
+ *
+ * @param in InputStream to wrap.
+ * @param doEncode true if we should encode all data read from us, false if we should decode.
+ */
+ public Base16InputStream(final InputStream in, final boolean doEncode) {
+ this(in, doEncode, true, Hex.DEFAULT_CHARSET);
+ }
+
+ /**
+ * Creates a Base16InputStream such that all data read is either Base16-encoded or Base16-decoded from the original
+ * provided InputStream.
+ *
+ * @param in InputStream to wrap.
+ * @param doEncode true if we should encode all data read from us, false if we should decode.
+ * @param toLowerCase {@code true} converts to lowercase, {@code false} to uppercase.
+ * @param charset the charset.
+ */
+ public Base16InputStream(final InputStream in, final boolean doEncode,
+ final boolean toLowerCase, final Charset charset) {
+ super(in, new Base16(toLowerCase, charset), doEncode);
+ }
+}
diff --git a/src/main/java/org/apache/commons/codec/binary/Base16OutputStream.java b/src/main/java/org/apache/commons/codec/binary/Base16OutputStream.java
new file mode 100644
index 0000000..e214320
--- /dev/null
+++ b/src/main/java/org/apache/commons/codec/binary/Base16OutputStream.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.codec.binary;
+
+import java.io.OutputStream;
+import java.nio.charset.Charset;
+
+/**
+ * Provides Hex encoding and decoding in a streaming fashion (unlimited size).
+ * <p>
+ * The default behavior of the HexOutputStream is to ENCODE, whereas the default behavior of the
+ * {@link Base16InputStream} is to DECODE. But this behavior can be overridden by using a different constructor.
+ * </p>
+ *
+ * @since 1.15
+ */
+public class Base16OutputStream extends BaseNCodecOutputStream {
+
+ /**
+ * Creates a Base16OutputStream such that all data written is Hex-encoded to the original provided OutputStream.
+ *
+ * @param out OutputStream to wrap.
+ */
+ public Base16OutputStream(final OutputStream out) {
+ this(out, true);
+ }
+
+ /**
+ * Creates a Base16OutputStream such that all data written is either Hex-encoded or Hex-decoded to the
+ * original provided OutputStream.
+ *
+ * @param out OutputStream to wrap.
+ * @param doEncode true if we should encode all data written to us, false if we should decode.
+ */
+ public Base16OutputStream(final OutputStream out, final boolean doEncode) {
+ this(out, doEncode, true, Hex.DEFAULT_CHARSET);
+ }
+
+ /**
+ * Creates a Base16OutputStream such that all data written is either Hex-encoded or Hex-decoded to the
+ * original provided OutputStream.
+ *
+ * @param out OutputStream to wrap.
+ * @param doEncode true if we should encode all data written to us, false if we should decode.
+ * @param toLowerCase {@code true} converts to lowercase, {@code false} to uppercase.
+ * @param charset the charset.
+ */
+ public Base16OutputStream(final OutputStream out, final boolean doEncode,
+ final boolean toLowerCase, final Charset charset) {
+ super(out, new Base16(toLowerCase, charset), doEncode);
+ }
+}
diff --git a/src/main/java/org/apache/commons/codec/binary/Hex.java b/src/main/java/org/apache/commons/codec/binary/Hex.java
index 57c05bd..9c9a862 100644
--- a/src/main/java/org/apache/commons/codec/binary/Hex.java
+++ b/src/main/java/org/apache/commons/codec/binary/Hex.java
@@ -54,13 +54,13 @@ public class Hex implements BinaryEncoder, BinaryDecoder {
/**
* Used to build output as Hex
*/
- private static final char[] DIGITS_LOWER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
+ static final char[] DIGITS_LOWER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
'e', 'f' };
/**
* Used to build output as Hex
*/
- private static final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
+ static final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
'E', 'F' };
/**
@@ -73,17 +73,38 @@ public class Hex implements BinaryEncoder, BinaryDecoder {
* @throws DecoderException Thrown if an odd number or illegal of characters is supplied
*/
public static byte[] decodeHex(final char[] data) throws DecoderException {
+ final byte[] out = new byte[data.length >> 1];
+ decodeHex(data, out, 0);
+ return out;
+ }
+ /**
+ * Converts an array of characters representing hexadecimal values into an array of bytes of those same values. The
+ * returned array will be half the length of the passed array, as it takes two characters to represent any given
+ * byte. An exception is thrown if the passed char array has an odd number of elements.
+ *
+ * @param data An array of characters containing hexadecimal digits
+ * @param out A byte array to contain the binary data decoded from the supplied char array.
+ * @param outOffset The position within {@code out} to start writing the decoded bytes.
+ * @return the number of bytes written to {@code out}.
+ * @throws DecoderException Thrown if an odd number or illegal of characters is supplied
+ *
+ * @since 1.15
+ */
+ public static int decodeHex(final char[] data, final byte[] out, final int outOffset) throws DecoderException {
final int len = data.length;
if ((len & 0x01) != 0) {
throw new DecoderException("Odd number of characters.");
}
- final byte[] out = new byte[len >> 1];
+ final int outLen = len >> 1;
+ if (out.length - outOffset < outLen) {
+ throw new DecoderException("out is not large enough to accommodate decoded data.");
+ }
// two characters form the hex value.
- for (int i = 0, j = 0; j < len; i++) {
+ for (int i = outOffset, j = 0; j < len; i++) {
int f = toDigit(data[j], j) << 4;
j++;
f = f | toDigit(data[j], j);
@@ -91,7 +112,7 @@ public class Hex implements BinaryEncoder, BinaryDecoder {
out[i] = (byte) (f & 0xFF);
}
- return out;
+ return outLen;
}
/**
@@ -148,12 +169,62 @@ public class Hex implements BinaryEncoder, BinaryDecoder {
protected static char[] encodeHex(final byte[] data, final char[] toDigits) {
final int l = data.length;
final char[] out = new char[l << 1];
+ encodeHex(data, 0, data.length, toDigits, out, 0);
+ return out;
+ }
+
+ /**
+ * Converts an array of bytes into an array of characters representing the hexadecimal values of each byte in order.
+ *
+ * @param data a byte[] to convert to Hex characters
+ * @param dataOffset the position in {@code data} to start encoding from
+ * @param dataLen the number of bytes from {@code dataOffset} to encode
+ * @param toLowerCase {@code true} converts to lowercase, {@code false} to uppercase
+ * @return A char[] containing the appropriate characters from the alphabet For best results, this should be either
+ * upper- or lower-case hex.
+ * @since 1.15
+ */
+ protected static char[] encodeHex(final byte[] data, final int dataOffset, final int dataLen,
+ final boolean toLowerCase) {
+ final char[] out = new char[dataLen << 1];
+ encodeHex(data, dataOffset, dataLen, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER, out, 0);
+ return out;
+ }
+
+ /**
+ * Converts an array of bytes into an array of characters representing the hexadecimal values of each byte in order.
+ *
+ * @param data a byte[] to convert to Hex characters
+ * @param dataOffset the position in {@code data} to start encoding from
+ * @param dataLen the number of bytes from {@code dataOffset} to encode
+ * @param toLowerCase {@code true} converts to lowercase, {@code false} to uppercase
+ * @param out a char[] which will hold the resultant appropriate characters from the alphabet.
+ * @param outOffset the position within {@code out} at which to start writing the encoded characters.
+ * @since 1.15
+ */
+ protected static void encodeHex(final byte[] data, final int dataOffset, final int dataLen,
+ final boolean toLowerCase, final char[] out, final int outOffset) {
+ encodeHex(data, dataOffset, dataLen, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER, out, outOffset);
+ }
+
+ /**
+ * Converts an array of bytes into an array of characters representing the hexadecimal values of each byte in order.
+ *
+ * @param data a byte[] to convert to Hex characters
+ * @param dataOffset the position in {@code data} to start encoding from
+ * @param dataLen the number of bytes from {@code dataOffset} to encode
+ * @param toDigits the output alphabet (must contain at least 16 chars)
+ * @param out a char[] which will hold the resultant appropriate characters from the alphabet.
+ * @param outOffset the position within {@code out} at which to start writing the encoded characters.
+ * @since 1.15
+ */
+ protected static void encodeHex(final byte[] data, final int dataOffset, final int dataLen, final char[] toDigits,
+ final char[] out, final int outOffset) {
// two characters form the hex value.
- for (int i = 0, j = 0; i < l; i++) {
+ for (int i = dataOffset, j = outOffset; i < dataOffset + dataLen; i++) {
out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
out[j++] = toDigits[0x0F & data[i]];
}
- return out;
}
/**
diff --git a/src/test/java/org/apache/commons/codec/binary/Base16InputStreamTest.java b/src/test/java/org/apache/commons/codec/binary/Base16InputStreamTest.java
new file mode 100644
index 0000000..9d4d2a2
--- /dev/null
+++ b/src/test/java/org/apache/commons/codec/binary/Base16InputStreamTest.java
@@ -0,0 +1,411 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.codec.binary;
+
+import org.junit.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.fail;
+
+/**
+ * @since 1.15
+ */
+public class Base16InputStreamTest {
+
+ /**
+ * Decodes to {202, 254, 186, 190, 255, 255}
+ */
+ private static final String ENCODED_B16 = "cafebabeffff";
+
+ private static final String STRING_FIXTURE = "Hello World";
+
+ /**
+ * Tests skipping past the end of a stream.
+ *
+ * @throws IOException for some failure scenarios.
+ */
+ @Test
+ public void testAvailable() throws IOException {
+ final InputStream ins = new ByteArrayInputStream(StringUtils.getBytesIso8859_1(ENCODED_B16));
+ try (final Base16InputStream b16Stream = new Base16InputStream(ins)) {
+ assertEquals(1, b16Stream.available());
+ assertEquals(6, b16Stream.skip(10));
+ // End of stream reached
+ assertEquals(0, b16Stream.available());
+ assertEquals(-1, b16Stream.read());
+ assertEquals(-1, b16Stream.read());
+ assertEquals(0, b16Stream.available());
+ }
+ }
+
+ /**
+ * Tests the Base16InputStream implementation against empty input.
+ *
+ * @throws IOException for some failure scenarios.
+ */
+ @Test
+ public void testBase16EmptyInputStream() throws IOException {
+ final byte[] emptyEncoded = new byte[0];
+ final byte[] emptyDecoded = new byte[0];
+ testByteByByte(emptyEncoded, emptyDecoded);
+ testByChunk(emptyEncoded, emptyDecoded);
+ }
+
+ /**
+ * Tests the Base16InputStream implementation.
+ *
+ * @throws IOException
+ * for some failure scenarios.
+ */
+ @Test
+ public void testBase16InputStreamByChunk() throws IOException {
+ // Hello World test.
+ byte[] encoded = StringUtils.getBytesUtf8("48656c6c6f20576f726c64");
+ byte[] decoded = StringUtils.getBytesUtf8(STRING_FIXTURE);
+ testByChunk(encoded, decoded);
+
+ // Single Byte test.
+ encoded = StringUtils.getBytesUtf8("41");
+ decoded = new byte[] { (byte) 0x41 };
+ testByChunk(encoded, decoded);
+
+ // OpenSSL interop test.
+ encoded = StringUtils.getBytesUtf8(Base16TestData.ENCODED_UTF8_LOWERCASE);
+ decoded = Base16TestData.DECODED;
+ testByChunk(encoded, decoded);
+
+ // test random data of sizes 0 thru 150
+ for (int i = 0; i <= 150; i++) {
+ final byte[][] randomData = Base16TestData.randomData(i);
+ encoded = randomData[1];
+ decoded = randomData[0];
+ testByChunk(encoded, decoded);
+ }
+ }
+
+ /**
+ * Tests the Base16InputStream implementation.
+ *
+ * @throws IOException for some failure scenarios.
+ */
+ @Test
+ public void testBase16InputStreamByteByByte() throws IOException {
+ // Hello World test.
+ byte[] encoded = StringUtils.getBytesUtf8("48656c6c6f20576f726c64");
+ byte[] decoded = StringUtils.getBytesUtf8(STRING_FIXTURE);
+ testByteByByte(encoded, decoded);
+
+ // Single Byte test.
+ encoded = StringUtils.getBytesUtf8("41");
+ decoded = new byte[] { (byte) 0x41 };
+ testByteByByte(encoded, decoded);
+
+ // OpenSSL interop test.
+ encoded = StringUtils.getBytesUtf8(Base16TestData.ENCODED_UTF8_LOWERCASE);
+ decoded = Base16TestData.DECODED;
+ testByteByByte(encoded, decoded);
+
+ // test random data of sizes 0 thru 150
+ for (int i = 0; i <= 150; i++) {
+ final byte[][] randomData = Base16TestData.randomData(i);
+ encoded = randomData[1];
+ decoded = randomData[0];
+ testByteByByte(encoded, decoded);
+ }
+ }
+
+ /**
+ * Tests method does three tests on the supplied data: 1. encoded ---[DECODE]--> decoded 2. decoded ---[ENCODE]--> encoded 3. decoded
+ * ---[WRAP-WRAP-WRAP-etc...] --> decoded
+ * <p/>
+ * By "[WRAP-WRAP-WRAP-etc...]" we mean situation where the Base16InputStream wraps itself in encode and decode mode over and over
+ * again.
+ *
+ * @param encoded Base16 encoded data
+ * @param decoded the data from above, but decoded
+ * @throws IOException Usually signifies a bug in the Base16 commons-codec implementation.
+ */
+ private void testByChunk(final byte[] encoded, final byte[] decoded) throws IOException {
+
+ // Start with encode.
+ InputStream in;
+ in = new Base16InputStream(new ByteArrayInputStream(decoded), true);
+ byte[] output = Base16TestData.streamToBytes(in);
+
+ assertEquals("EOF", -1, in.read());
+ assertEquals("Still EOF", -1, in.read());
+ assertArrayEquals("Streaming Base16 encode", encoded, output);
+
+ in.close();
+
+ // Now let's try decode.
+ in = new Base16InputStream(new ByteArrayInputStream(encoded));
+ output = Base16TestData.streamToBytes(in);
+
+ assertEquals("EOF", -1, in.read());
+ assertEquals("Still EOF", -1, in.read());
+ assertArrayEquals("Streaming Base16 decode", decoded, output);
+
+ // I always wanted to do this! (wrap encoder with decoder etc etc).
+ in = new ByteArrayInputStream(decoded);
+ for (int i = 0; i < 10; i++) {
+ in = new Base16InputStream(in, true);
+ in = new Base16InputStream(in, false);
+ }
+ output = Base16TestData.streamToBytes(in);
+
+ assertEquals("EOF", -1, in.read());
+ assertEquals("Still EOF", -1, in.read());
+ assertArrayEquals("Streaming Base16 wrap-wrap-wrap!", decoded, output);
+ in.close();
+ }
+
+ /**
+ * Tests method does three tests on the supplied data: 1. encoded ---[DECODE]--> decoded 2. decoded ---[ENCODE]--> encoded 3. decoded
+ * ---[WRAP-WRAP-WRAP-etc...] --> decoded
+ * <p/>
+ * By "[WRAP-WRAP-WRAP-etc...]" we mean situation where the Base16InputStream wraps itself in encode and decode mode over and over
+ * again.
+ *
+ * @param encoded Base16 encoded data
+ * @param decoded the data from above, but decoded
+ * @throws IOException Usually signifies a bug in the Base16 commons-codec implementation.
+ */
+ private void testByteByByte(final byte[] encoded, final byte[] decoded) throws IOException {
+
+ // Start with encode.
+ InputStream in;
+ in = new Base16InputStream(new ByteArrayInputStream(decoded), true);
+ byte[] output = new byte[encoded.length];
+ for (int i = 0; i < output.length; i++) {
+ output[i] = (byte) in.read();
+ }
+
+ assertEquals("EOF", -1, in.read());
+ assertEquals("Still EOF", -1, in.read());
+ assertArrayEquals("Streaming Base16 encode", encoded, output);
+
+ in.close();
+ // Now let's try decode.
+ in = new Base16InputStream(new ByteArrayInputStream(encoded));
+ output = new byte[decoded.length];
+ for (int i = 0; i < output.length; i++) {
+ output[i] = (byte) in.read();
+ }
+
+ assertEquals("EOF", -1, in.read());
+ assertEquals("Still EOF", -1, in.read());
+ assertArrayEquals("Streaming Base16 decode", decoded, output);
+
+ in.close();
+
+ // I always wanted to do this! (wrap encoder with decoder etc etc).
+ in = new ByteArrayInputStream(decoded);
+ for (int i = 0; i < 10; i++) {
+ in = new Base16InputStream(in, true);
+ in = new Base16InputStream(in, false);
+ }
+ output = new byte[decoded.length];
+ for (int i = 0; i < output.length; i++) {
+ output[i] = (byte) in.read();
+ }
+
+ assertEquals("EOF", -1, in.read());
+ assertEquals("Still EOF", -1, in.read());
+ assertArrayEquals("Streaming Base16 wrap-wrap-wrap!", decoded, output);
+ in.close();
+ }
+
+ /**
+ * Tests markSupported.
+ *
+ * @throws IOException for some failure scenarios.
+ */
+ @Test
+ public void testMarkSupported() throws IOException {
+ final byte[] decoded = StringUtils.getBytesUtf8(STRING_FIXTURE);
+ final ByteArrayInputStream bin = new ByteArrayInputStream(decoded);
+ try (final Base16InputStream in = new Base16InputStream(bin, true)) {
+ // Always returns false for now.
+ assertFalse("Base16InputStream.markSupported() is false", in.markSupported());
+ }
+ }
+
+ /**
+ * Tests read returning 0
+ *
+ * @throws IOException for some failure scenarios.
+ */
+ @Test
+ public void testRead0() throws IOException {
+ final byte[] decoded = StringUtils.getBytesUtf8(STRING_FIXTURE);
+ final byte[] buf = new byte[1024];
+ int bytesRead = 0;
+ final ByteArrayInputStream bin = new ByteArrayInputStream(decoded);
+ try (final Base16InputStream in = new Base16InputStream(bin, true)) {
+ bytesRead = in.read(buf, 0, 0);
+ assertEquals("Base16InputStream.read(buf, 0, 0) returns 0", 0, bytesRead);
+ }
+ }
+
+ /**
+ * Tests read with null.
+ *
+ * @throws Exception for some failure scenarios.
+ */
+ @Test
+ public void testReadNull() throws IOException {
+ final byte[] decoded = StringUtils.getBytesUtf8(STRING_FIXTURE);
+ final ByteArrayInputStream bin = new ByteArrayInputStream(decoded);
+ try (final Base16InputStream in = new Base16InputStream(bin, true)) {
+ in.read(null, 0, 0);
+ fail("Base16InputStream.read(null, 0, 0) to throw a NullPointerException");
+ } catch (final NullPointerException e) {
+ // Expected
+ }
+ }
+
+ /**
+ * Tests read throwing IndexOutOfBoundsException
+ *
+ * @throws IOException for some failure scenarios.
+ */
+ @Test
+ public void testReadOutOfBounds() throws IOException {
+ final byte[] decoded = StringUtils.getBytesUtf8(STRING_FIXTURE);
+ final byte[] buf = new byte[1024];
+ final ByteArrayInputStream bin = new ByteArrayInputStream(decoded);
+ try (final Base16InputStream in = new Base16InputStream(bin, true)) {
+
+ try {
+ in.read(buf, -1, 0);
+ fail("Expected Base16InputStream.read(buf, -1, 0) to throw IndexOutOfBoundsException");
+ } catch (final IndexOutOfBoundsException e) {
+ // Expected
+ }
+
+ try {
+ in.read(buf, 0, -1);
+ fail("Expected Base16InputStream.read(buf, 0, -1) to throw IndexOutOfBoundsException");
+ } catch (final IndexOutOfBoundsException e) {
+ // Expected
+ }
+
+ try {
+ in.read(buf, buf.length + 1, 0);
+ fail("Base16InputStream.read(buf, buf.length + 1, 0) throws IndexOutOfBoundsException");
+ } catch (final IndexOutOfBoundsException e) {
+ // Expected
+ }
+
+ try {
+ in.read(buf, buf.length - 1, 2);
+ fail("Base16InputStream.read(buf, buf.length - 1, 2) throws IndexOutOfBoundsException");
+ } catch (final IndexOutOfBoundsException e) {
+ // Expected
+ }
+ }
+ }
+
+ /**
+ * Tests skipping number of characters larger than the internal buffer.
+ *
+ * @throws IOException for some failure scenarios.
+ */
+ @Test
+ public void testSkipBig() throws IOException {
+ final InputStream ins = new ByteArrayInputStream(StringUtils.getBytesIso8859_1(ENCODED_B16));
+ try (final Base16InputStream b16Stream = new Base16InputStream(ins)) {
+ assertEquals(6, b16Stream.skip(Integer.MAX_VALUE));
+ // End of stream reached
+ assertEquals(-1, b16Stream.read());
+ assertEquals(-1, b16Stream.read());
+ }
+ }
+
+ /**
+ * Tests skipping as a noop
+ *
+ * @throws IOException for some failure scenarios.
+ */
+ @Test
+ public void testSkipNone() throws IOException {
+ final InputStream ins = new ByteArrayInputStream(StringUtils.getBytesIso8859_1(ENCODED_B16));
+ try (final Base16InputStream b16Stream = new Base16InputStream(ins)) {
+ final byte[] actualBytes = new byte[6];
+ assertEquals(0, b16Stream.skip(0));
+ b16Stream.read(actualBytes, 0, actualBytes.length);
+ assertArrayEquals(actualBytes, new byte[] {(byte)202, (byte)254, (byte)186, (byte)190, (byte)255, (byte)255});
+ // End of stream reached
+ assertEquals(-1, b16Stream.read());
+ }
+ }
+
+ /**
+ * Tests skipping past the end of a stream.
+ *
+ * @throws IOException for some failure scenarios.
+ */
+ @Test
+ public void testSkipPastEnd() throws IOException {
+ final InputStream ins = new ByteArrayInputStream(StringUtils.getBytesIso8859_1(ENCODED_B16));
+ try (final Base16InputStream b16Stream = new Base16InputStream(ins)) {
+ // due to CODEC-130, skip now skips correctly decoded characters rather than encoded
+ assertEquals(6, b16Stream.skip(10));
+ // End of stream reached
+ assertEquals(-1, b16Stream.read());
+ assertEquals(-1, b16Stream.read());
+ }
+ }
+
+ /**
+ * Tests skipping to the end of a stream.
+ *
+ * @throws IOException for some failure scenarios.
+ */
+ @Test
+ public void testSkipToEnd() throws IOException {
+ final InputStream ins = new ByteArrayInputStream(StringUtils.getBytesIso8859_1(ENCODED_B16));
+ try (final Base16InputStream b16Stream = new Base16InputStream(ins)) {
+ // due to CODEC-130, skip now skips correctly decoded characters rather than encoded
+ assertEquals(6, b16Stream.skip(6));
+ // End of stream reached
+ assertEquals(-1, b16Stream.read());
+ assertEquals(-1, b16Stream.read());
+ }
+ }
+
+ /**
+ * Tests if negative arguments to skip are handled correctly.
+ *
+ * @throws IOException for some failure scenarios.
+ */
+ @Test(expected=IllegalArgumentException.class)
+ public void testSkipWrongArgument() throws IOException {
+ final InputStream ins = new ByteArrayInputStream(StringUtils.getBytesIso8859_1(ENCODED_B16));
+ try (final Base16InputStream b16Stream = new Base16InputStream(ins)) {
+ b16Stream.skip(-10);
+ }
+ }
+}
diff --git a/src/test/java/org/apache/commons/codec/binary/Base16OutputStreamTest.java b/src/test/java/org/apache/commons/codec/binary/Base16OutputStreamTest.java
new file mode 100644
index 0000000..6f91f51
--- /dev/null
+++ b/src/test/java/org/apache/commons/codec/binary/Base16OutputStreamTest.java
@@ -0,0 +1,266 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.codec.binary;
+
+import org.junit.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.fail;
+
+/**
+ * @since 1.15
+ */
+public class Base16OutputStreamTest {
+
+ private static final String STRING_FIXTURE = "Hello World";
+
+ /**
+ * Test the Base16OutputStream implementation against empty input.
+ *
+ * @throws IOException for some failure scenarios..
+ */
+ @Test
+ public void testBase16EmptyOutputStream() throws IOException {
+ final byte[] emptyEncoded = new byte[0];
+ final byte[] emptyDecoded = new byte[0];
+ testByteByByte(emptyEncoded, emptyDecoded);
+ testByChunk(emptyEncoded, emptyDecoded);
+ }
+
+ /**
+ * Test the Base16OutputStream implementation
+ *
+ * @throws IOException for some failure scenarios.
+ */
+ @Test
+ public void testBase16OutputStreamByChunk() throws Exception {
+ // Hello World test.
+ byte[] encoded = StringUtils.getBytesUtf8("48656c6c6f20576f726c64");
+ byte[] decoded = StringUtils.getBytesUtf8(STRING_FIXTURE);
+ testByChunk(encoded, decoded);
+
+ // Single Byte test.
+ encoded = StringUtils.getBytesUtf8("41");
+ decoded = new byte[]{(byte) 0x41};
+ testByChunk(encoded, decoded);
+
+ // test random data of sizes 0 thru 150
+ for (int i = 0; i <= 150; i++) {
+ final byte[][] randomData = Base16TestData.randomData(i);
+ encoded = randomData[1];
+ decoded = randomData[0];
+ testByChunk(encoded, decoded);
+ }
+ }
+
+ /**
+ * Test the Base16OutputStream implementation
+ *
+ * @throws IOException for some failure scenarios.
+ */
+ @Test
+ public void testBase16OutputStreamByteByByte() throws IOException {
+ // Hello World test.
+ byte[] encoded = StringUtils.getBytesUtf8("48656c6c6f20576f726c64");
+ byte[] decoded = StringUtils.getBytesUtf8(STRING_FIXTURE);
+ testByteByByte(encoded, decoded);
+
+ // Single Byte test.
+ encoded = StringUtils.getBytesUtf8("41");
+ decoded = new byte[]{(byte) 0x41};
+ testByteByByte(encoded, decoded);
+
+ // test random data of sizes 0 thru 150
+ for (int i = 0; i <= 150; i++) {
+ final byte[][] randomData = Base16TestData.randomData(i);
+ encoded = randomData[1];
+ decoded = randomData[0];
+ testByteByByte(encoded, decoded);
+ }
+ }
+
+ /**
+ * Test method does three tests on the supplied data: 1. encoded ---[DECODE]--> decoded 2. decoded ---[ENCODE]-->
+ * encoded 3. decoded ---[WRAP-WRAP-WRAP-etc...] --> decoded
+ * <p/>
+ * By "[WRAP-WRAP-WRAP-etc...]" we mean situation where the Base16OutputStream wraps itself in encode and decode
+ * mode over and over again.
+ *
+ * @param encoded
+ * base16 encoded data
+ * @param decoded
+ * the data from above, but decoded
+ * @throws IOException
+ * Usually signifies a bug in the Base16 commons-codec implementation.
+ */
+ private void testByChunk(final byte[] encoded, final byte[] decoded) throws IOException {
+
+ // Start with encode.
+ ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
+ OutputStream out = new Base16OutputStream(byteOut, true);
+ out.write(decoded);
+ out.close();
+ byte[] output = byteOut.toByteArray();
+ assertArrayEquals("Streaming chunked base16 encode", encoded, output);
+
+ // Now let's try decode.
+ byteOut = new ByteArrayOutputStream();
+ out = new Base16OutputStream(byteOut, false);
+ out.write(encoded);
+ out.close();
+ output = byteOut.toByteArray();
+ assertArrayEquals("Streaming chunked base16 decode", decoded, output);
+
+ // I always wanted to do this! (wrap encoder with decoder etc etc).
+ byteOut = new ByteArrayOutputStream();
+ out = byteOut;
+ for (int i = 0; i < 10; i++) {
+ out = new Base16OutputStream(out, false);
+ out = new Base16OutputStream(out, true);
+ }
+ out.write(decoded);
+ out.close();
+ output = byteOut.toByteArray();
+
+ assertArrayEquals("Streaming chunked base16 wrap-wrap-wrap!", decoded, output);
+ }
+
+ /**
+ * Test method does three tests on the supplied data: 1. encoded ---[DECODE]--> decoded 2. decoded ---[ENCODE]-->
+ * encoded 3. decoded ---[WRAP-WRAP-WRAP-etc...] --> decoded
+ * <p/>
+ * By "[WRAP-WRAP-WRAP-etc...]" we mean situation where the Base16OutputStream wraps itself in encode and decode
+ * mode over and over again.
+ *
+ * @param encoded
+ * base16 encoded data
+ * @param decoded
+ * the data from above, but decoded
+ * @throws IOException
+ * Usually signifies a bug in the Base16 commons-codec implementation.
+ */
+ private void testByteByByte(final byte[] encoded, final byte[] decoded) throws IOException {
+
+ // Start with encode.
+ ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
+ OutputStream out = new Base16OutputStream(byteOut, true);
+ for (final byte element : decoded) {
+ out.write(element);
+ }
+ out.close();
+ byte[] output = byteOut.toByteArray();
+ assertArrayEquals("Streaming byte-by-byte base16 encode", encoded, output);
+
+ // Now let's try decode.
+ byteOut = new ByteArrayOutputStream();
+ out = new Base16OutputStream(byteOut, false);
+ for (final byte element : encoded) {
+ out.write(element);
+ }
+ out.close();
+ output = byteOut.toByteArray();
+ assertArrayEquals("Streaming byte-by-byte base16 decode", decoded, output);
+
+ // Now let's try decode with tonnes of flushes.
+ byteOut = new ByteArrayOutputStream();
+ out = new Base16OutputStream(byteOut, false);
+ for (final byte element : encoded) {
+ out.write(element);
+ out.flush();
+ }
+ out.close();
+ output = byteOut.toByteArray();
+ assertArrayEquals("Streaming byte-by-byte flush() base16 decode", decoded, output);
+
+ // I always wanted to do this! (wrap encoder with decoder etc etc).
+ byteOut = new ByteArrayOutputStream();
+ out = byteOut;
+ for (int i = 0; i < 10; i++) {
+ out = new Base16OutputStream(out, false);
+ out = new Base16OutputStream(out, true);
+ }
+ for (final byte element : decoded) {
+ out.write(element);
+ }
+ out.close();
+ output = byteOut.toByteArray();
+
+ assertArrayEquals("Streaming byte-by-byte base16 wrap-wrap-wrap!", decoded, output);
+ }
+
+ /**
+ * Tests Base16OutputStream.write for expected IndexOutOfBoundsException conditions.
+ *
+ * @throws IOException for some failure scenarios.
+ */
+ @Test
+ public void testWriteOutOfBounds() throws IOException {
+ final byte[] buf = new byte[1024];
+ final ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ try (final Base16OutputStream out = new Base16OutputStream(bout)) {
+
+ try {
+ out.write(buf, -1, 1);
+ fail("Expected Base16OutputStream.write(buf, -1, 1) to throw a IndexOutOfBoundsException");
+ } catch (final IndexOutOfBoundsException ioobe) {
+ // Expected
+ }
+
+ try {
+ out.write(buf, 1, -1);
+ fail("Expected Base16OutputStream.write(buf, 1, -1) to throw a IndexOutOfBoundsException");
+ } catch (final IndexOutOfBoundsException ioobe) {
+ // Expected
+ }
+
+ try {
+ out.write(buf, buf.length + 1, 0);
+ fail("Expected Base16OutputStream.write(buf, buf.length + 1, 0) to throw a IndexOutOfBoundsException");
+ } catch (final IndexOutOfBoundsException ioobe) {
+ // Expected
+ }
+
+ try {
+ out.write(buf, buf.length - 1, 2);
+ fail("Expected Base16OutputStream.write(buf, buf.length - 1, 2) to throw a IndexOutOfBoundsException");
+ } catch (final IndexOutOfBoundsException ioobe) {
+ // Expected
+ }
+ }
+ }
+
+ /**
+ * Tests Base16OutputStream.write(null).
+ *
+ * @throws IOException for some failure scenarios.
+ */
+ @Test
+ public void testWriteToNullCoverage() throws IOException {
+ final ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ try (final Base16OutputStream out = new Base16OutputStream(bout)) {
+ out.write(null, 0, 0);
+ fail("Expcted Base16OutputStream.write(null) to throw a NullPointerException");
+ } catch (final NullPointerException e) {
+ // Expected
+ }
+ }
+}
diff --git a/src/test/java/org/apache/commons/codec/binary/Base16Test.java b/src/test/java/org/apache/commons/codec/binary/Base16Test.java
new file mode 100644
index 0000000..e0bf357
--- /dev/null
+++ b/src/test/java/org/apache/commons/codec/binary/Base16Test.java
@@ -0,0 +1,620 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.codec.binary;
+
+import org.apache.commons.codec.DecoderException;
+import org.apache.commons.codec.EncoderException;
+import org.apache.commons.lang3.ArrayUtils;
+import org.junit.Assume;
+import org.junit.Test;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Random;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * Test cases for Base16 class.
+ *
+ * @since 1.15
+ */
+public class Base16Test {
+
+ private static final Charset CHARSET_UTF8 = StandardCharsets.UTF_8;
+
+ private final Random random = new Random();
+
+ /**
+ * @return Returns the random.
+ */
+ public Random getRandom() {
+ return this.random;
+ }
+
+ /**
+ * Test the isStringBase16 method.
+ */
+ @Test
+ public void testIsStringBase16() {
+ final String nullString = null;
+ final String emptyString = "";
+ final String validString = "cafebabec0a1f2e3b4a5b6e7c8";
+ final String invalidString = validString + (char) 0; // append null
+ // character
+
+ try {
+ Base16.isBase16(nullString);
+ fail("Base16.isStringBase16() should not be null-safe.");
+ } catch (final NullPointerException npe) {
+ assertNotNull("Base16.isStringBase16() should not be null-safe.", npe);
+ }
+
+ assertTrue("Base16.isStringBase16(empty-string) is true", Base16.isBase16(emptyString));
+ assertTrue("Base16.isStringBase16(valid-string) is true", Base16.isBase16(validString));
+ assertFalse("Base16.isStringBase16(invalid-string) is false", Base16.isBase16(invalidString));
+ }
+
+ /**
+ * Test the Base16 implementation
+ */
+ @Test
+ public void testBase16() {
+ final String content = "Hello World";
+ String encodedContent;
+ byte[] encodedBytes = Base16.encodeBase16(StringUtils.getBytesUtf8(content));
+ encodedContent = StringUtils.newStringUtf8(encodedBytes);
+ assertEquals("encoding hello world", "48656c6c6f20576f726c64", encodedContent);
+
+ Base16 b16 = new Base16();
+ encodedBytes = b16.encode(StringUtils.getBytesUtf8(content));
+ encodedContent = StringUtils.newStringUtf8(encodedBytes);
+ assertEquals("encoding hello world", "48656c6c6f20576f726c64", encodedContent);
+ }
+
+ @Test
+ public void testBase16AtBufferStart() {
+ testBase16InBuffer(0, 100);
+ }
+
+ @Test
+ public void testBase16AtBufferEnd() {
+ testBase16InBuffer(100, 0);
+ }
+
+ @Test
+ public void testBase16AtBufferMiddle() {
+ testBase16InBuffer(100, 100);
+ }
+
+ private void testBase16InBuffer(final int startPasSize, final int endPadSize) {
+ final String content = "Hello World";
+ String encodedContent;
+ final byte[] bytesUtf8 = StringUtils.getBytesUtf8(content);
+ byte[] buffer = ArrayUtils.addAll(bytesUtf8, new byte[endPadSize]);
+ buffer = ArrayUtils.addAll(new byte[startPasSize], buffer);
+ final byte[] encodedBytes = new Base16().encode(buffer, startPasSize, bytesUtf8.length);
+ encodedContent = StringUtils.newStringUtf8(encodedBytes);
+ assertEquals("encoding hello world", "48656c6c6f20576f726c64", encodedContent);
+ }
+
+ /**
+ * isBase16 throws RuntimeException on some
+ * non-Base16 bytes
+ */
+ @Test(expected=RuntimeException.class)
+ public void testCodec68() {
+ final byte[] x = new byte[] { 'n', 'H', '=', '=', (byte) 0x9c };
+ Base16.decodeBase16(x);
+ }
+
+ @Test
+ public void testConstructors() {
+ new Base16();
+ new Base16();
+ new Base16(CHARSET_UTF8);
+ new Base16(false, CHARSET_UTF8);
+ }
+
+ @Test
+ public void testConstructor_Charset() {
+ final Base16 Base16 = new Base16(CHARSET_UTF8);
+ final byte[] encoded = Base16.encode(Base16TestData.DECODED);
+ final String expectedResult = Base16TestData.ENCODED_UTF8_LOWERCASE;
+ final String result = StringUtils.newStringUtf8(encoded);
+ assertEquals("new Base16(UTF_8)", expectedResult, result);
+ }
+
+ @Test
+ public void testConstructor_Boolean_Charset() {
+ final Base16 Base16 = new Base16(false, CHARSET_UTF8);
+ final byte[] encoded = Base16.encode(Base16TestData.DECODED);
+ final String expectedResult = Base16TestData.ENCODED_UTF8_UPPERCASE;
+ final String result = StringUtils.newStringUtf8(encoded);
+ assertEquals("new Base16(false, UTF_8)", result, expectedResult);
+ }
+
+ /**
+ * Test encode and decode of empty byte array.
+ */
+ @Test
+ public void testEmptyBase16() {
+ byte[] empty = new byte[0];
+ byte[] result = Base16.encodeBase16(empty);
+ assertEquals("empty Base16 encode", 0, result.length);
+ assertEquals("empty Base16 encode", null, Base16.encodeBase16(null));
+
+ empty = new byte[0];
+ result = Base16.decodeBase16(empty);
+ assertEquals("empty Base16 decode", 0, result.length);
+ assertEquals("empty Base16 encode", null, Base16.decodeBase16((byte[]) null));
+ }
+
+ // encode/decode a large random array
+ @Test
+ public void testEncodeDecodeRandom() {
+ for (int i = 1; i < 5; i++) {
+ final int len = this.getRandom().nextInt(10000) + 1;
+ final byte[] data = new byte[len];
+ this.getRandom().nextBytes(data);
+ final byte[] enc = Base16.encodeBase16(data);
+ assertTrue(Base16.isBase16(enc));
+ final byte[] data2 = Base16.decodeBase16(enc);
+ assertArrayEquals(data, data2);
+ }
+ }
+
+ // encode/decode random arrays from size 0 to size 11
+ @Test
+ public void testEncodeDecodeSmall() {
+ for (int i = 0; i < 12; i++) {
+ final byte[] data = new byte[i];
+ this.getRandom().nextBytes(data);
+ final byte[] enc = Base16.encodeBase16(data);
+ assertTrue("\"" + new String(enc) + "\" is Base16 data.", Base16.isBase16(enc));
+ final byte[] data2 = Base16.decodeBase16(enc);
+ assertArrayEquals(toString(data) + " equals " + toString(data2), data, data2);
+ }
+ }
+
+ @Test
+ public void testEncodeOverMaxSize() {
+ testEncodeOverMaxSize(-1);
+ testEncodeOverMaxSize(0);
+ testEncodeOverMaxSize(1);
+ testEncodeOverMaxSize(2);
+ }
+
+ private void testEncodeOverMaxSize(final int maxSize) {
+ try {
+ Base16.encodeBase16(Base16TestData.DECODED, true, CHARSET_UTF8, maxSize);
+ fail("Expected " + IllegalArgumentException.class.getName());
+ } catch (final IllegalArgumentException e) {
+ // Expected
+ }
+ }
+
+ @Test
+ public void testIsArrayByteBase16() {
+ assertFalse(Base16.isBase16(new char[] { (char)Byte.MIN_VALUE }));
+ assertFalse(Base16.isBase16(new char[] { (char)-125 }));
+ assertFalse(Base16.isBase16(new char[] { (char)-10 }));
+ assertFalse(Base16.isBase16(new char[] { 0 }));
+ assertFalse(Base16.isBase16(new char[] { 64, Byte.MAX_VALUE }));
+ assertFalse(Base16.isBase16(new char[] { Byte.MAX_VALUE }));
+ assertTrue(Base16.isBase16(new char[] { 'A' }));
+ assertFalse(Base16.isBase16(new char[] { 'A', (char)Byte.MIN_VALUE }));
+ assertTrue(Base16.isBase16(new char[] { 'A', 'F', 'a' }));
+ assertFalse(Base16.isBase16(new char[] { '/', '=', '+' }));
+ assertFalse(Base16.isBase16(new char[] { '$' }));
+ }
+
+ @Test
+ public void testKnownDecodings() {
+ assertEquals("The quick brown fox jumped over the lazy dogs.", new String(Base16.decodeBase16(
+ "54686520717569636b2062726f776e20666f78206a756d706564206f76657220746865206c617a7920646f67732e".getBytes(CHARSET_UTF8))));
+ assertEquals("It was the best of times, it was the worst of times.", new String(Base16.decodeBase16(
+ "497420776173207468652062657374206f662074696d65732c206974207761732074686520776f727374206f662074696d65732e".getBytes(CHARSET_UTF8))));
+ assertEquals("http://jakarta.apache.org/commmons", new String(
+ Base16.decodeBase16("687474703a2f2f6a616b617274612e6170616368652e6f72672f636f6d6d6d6f6e73".getBytes(CHARSET_UTF8))));
+ assertEquals("AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz", new String(Base16.decodeBase16(
+ "4161426243634464456546664767486849694a6a4b6b4c6c4d6d4e6e4f6f50705171527253735474557556765777587859795a7a".getBytes(CHARSET_UTF8))));
+ assertEquals("{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }",
+ new String(Base16.decodeBase16("7b20302c20312c20322c20332c20342c20352c20362c20372c20382c2039207d".getBytes(CHARSET_UTF8))));
+ assertEquals("xyzzy!", new String(Base16.decodeBase16("78797a7a7921".getBytes(CHARSET_UTF8))));
+ }
+
+ @Test
+ public void testKnownEncodings() {
+ assertEquals("54686520717569636b2062726f776e20666f78206a756d706564206f76657220746865206c617a7920646f67732e", new String(
+ Base16.encodeBase16("The quick brown fox jumped over the lazy dogs.".getBytes(CHARSET_UTF8))));
+ assertEquals("497420776173207468652062657374206f662074696d65732c206974207761732074686520776f727374206f662074696d65732e", new String(
+ Base16.encodeBase16("It was the best of times, it was the worst of times.".getBytes(CHARSET_UTF8))));
+ assertEquals("687474703a2f2f6a616b617274612e6170616368652e6f72672f636f6d6d6d6f6e73",
+ new String(Base16.encodeBase16("http://jakarta.apache.org/commmons".getBytes(CHARSET_UTF8))));
+ assertEquals("4161426243634464456546664767486849694a6a4b6b4c6c4d6d4e6e4f6f50705171527253735474557556765777587859795a7a", new String(
+ Base16.encodeBase16("AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz".getBytes(CHARSET_UTF8))));
+ assertEquals("7b20302c20312c20322c20332c20342c20352c20362c20372c20382c2039207d",
+ new String(Base16.encodeBase16("{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }".getBytes(CHARSET_UTF8))));
+ assertEquals("78797a7a7921", new String(Base16.encodeBase16("xyzzy!".getBytes(CHARSET_UTF8))));
+ }
+
+ @Test
+ public void testNonBase16Test() {
+ final byte[] bArray = { '%' };
+
+ assertFalse("Invalid Base16 array was incorrectly validated as " + "an array of Base16 encoded data",
+ Base16.isBase16(bArray));
+
+ try {
+ final Base16 b16 = new Base16();
+ final byte[] result = b16.decode(bArray);
+
+ assertEquals("The result should be empty as the test encoded content did "
+ + "not contain any valid base 16 characters", 0, result.length);
+ } catch (final Exception e) {
+ fail("Exception was thrown when trying to decode invalid Base16 encoded data");
+ }
+ }
+
+ @Test
+ public void testObjectDecodeWithInvalidParameter() {
+ final Base16 b16 = new Base16();
+
+ try {
+ b16.decode(Integer.valueOf(5));
+ fail("decode(Object) didn't throw an exception when passed an Integer object");
+ } catch (final DecoderException e) {
+ // ignored
+ }
+
+ }
+
+ @Test
+ public void testObjectDecodeWithValidParameter() throws Exception {
+ final String original = "Hello World!";
+ final Object o = Base16.encodeBase16(original.getBytes(CHARSET_UTF8));
+
+ final Base16 b16 = new Base16();
+ final Object oDecoded = b16.decode(o);
+ final byte[] baDecoded = (byte[]) oDecoded;
+ final String dest = new String(baDecoded);
+
+ assertEquals("dest string does not equal original", original, dest);
+ }
+
+ @Test
+ public void testObjectEncodeWithInvalidParameter() {
+ final Base16 b16 = new Base16();
+ try {
+ b16.encode("Yadayadayada");
+ fail("encode(Object) didn't throw an exception when passed a String object");
+ } catch (final EncoderException e) {
+ // Expected
+ }
+ }
+
+ @Test
+ public void testObjectEncodeWithValidParameter() throws Exception {
+ final String original = "Hello World!";
+ final Object origObj = original.getBytes(CHARSET_UTF8);
+
+ final Base16 b16 = new Base16();
+ final Object oEncoded = b16.encode(origObj);
+ final byte[] bArray = Base16.decodeBase16((byte[]) oEncoded);
+ final String dest = new String(bArray);
+
+ assertEquals("dest string does not equal original", original, dest);
+ }
+
+ @Test
+ public void testObjectEncode() {
+ final Base16 b16 = new Base16();
+ assertEquals("48656c6c6f20576f726c64", new String(b16.encode("Hello World".getBytes(CHARSET_UTF8))));
+ }
+
+ @Test
+ public void testPairs() {
+ assertEquals("0000", new String(Base16.encodeBase16(new byte[] { 0, 0 })));
+ for (int i = -128; i <= 127; i++) {
+ final byte test[] = { (byte) i, (byte) i };
+ assertArrayEquals(test, Base16.decodeBase16(Base16.encodeBase16(test)));
+ }
+ }
+
+ @Test
+ public void testSingletons() {
+ assertEquals("00", new String(Base16.encodeBase16(new byte[] { (byte) 0 })));
+ assertEquals("01", new String(Base16.encodeBase16(new byte[] { (byte) 1 })));
+ assertEquals("02", new String(Base16.encodeBase16(new byte[] { (byte) 2 })));
+ assertEquals("03", new String(Base16.encodeBase16(new byte[] { (byte) 3 })));
+ assertEquals("04", new String(Base16.encodeBase16(new byte[] { (byte) 4 })));
+ assertEquals("05", new String(Base16.encodeBase16(new byte[] { (byte) 5 })));
+ assertEquals("06", new String(Base16.encodeBase16(new byte[] { (byte) 6 })));
+ assertEquals("07", new String(Base16.encodeBase16(new byte[] { (byte) 7 })));
+ assertEquals("08", new String(Base16.encodeBase16(new byte[] { (byte) 8 })));
+ assertEquals("09", new String(Base16.encodeBase16(new byte[] { (byte) 9 })));
+ assertEquals("0a", new String(Base16.encodeBase16(new byte[] { (byte) 10 })));
+ assertEquals("0b", new String(Base16.encodeBase16(new byte[] { (byte) 11 })));
+ assertEquals("0c", new String(Base16.encodeBase16(new byte[] { (byte) 12 })));
+ assertEquals("0d", new String(Base16.encodeBase16(new byte[] { (byte) 13 })));
+ assertEquals("0e", new String(Base16.encodeBase16(new byte[] { (byte) 14 })));
+ assertEquals("0f", new String(Base16.encodeBase16(new byte[] { (byte) 15 })));
+ assertEquals("10", new String(Base16.encodeBase16(new byte[] { (byte) 16 })));
+ assertEquals("11", new String(Base16.encodeBase16(new byte[] { (byte) 17 })));
+ assertEquals("12", new String(Base16.encodeBase16(new byte[] { (byte) 18 })));
+ assertEquals("13", new String(Base16.encodeBase16(new byte[] { (byte) 19 })));
+ assertEquals("14", new String(Base16.encodeBase16(new byte[] { (byte) 20 })));
+ assertEquals("15", new String(Base16.encodeBase16(new byte[] { (byte) 21 })));
+ assertEquals("16", new String(Base16.encodeBase16(new byte[] { (byte) 22 })));
+ assertEquals("17", new String(Base16.encodeBase16(new byte[] { (byte) 23 })));
+ assertEquals("18", new String(Base16.encodeBase16(new byte[] { (byte) 24 })));
+ assertEquals("19", new String(Base16.encodeBase16(new byte[] { (byte) 25 })));
+ assertEquals("1a", new String(Base16.encodeBase16(new byte[] { (byte) 26 })));
+ assertEquals("1b", new String(Base16.encodeBase16(new byte[] { (byte) 27 })));
+ assertEquals("1c", new String(Base16.encodeBase16(new byte[] { (byte) 28 })));
+ assertEquals("1d", new String(Base16.encodeBase16(new byte[] { (byte) 29 })));
+ assertEquals("1e", new String(Base16.encodeBase16(new byte[] { (byte) 30 })));
+ assertEquals("1f", new String(Base16.encodeBase16(new byte[] { (byte) 31 })));
+ assertEquals("20", new String(Base16.encodeBase16(new byte[] { (byte) 32 })));
+ assertEquals("21", new String(Base16.encodeBase16(new byte[] { (byte) 33 })));
+ assertEquals("22", new String(Base16.encodeBase16(new byte[] { (byte) 34 })));
+ assertEquals("23", new String(Base16.encodeBase16(new byte[] { (byte) 35 })));
+ assertEquals("24", new String(Base16.encodeBase16(new byte[] { (byte) 36 })));
+ assertEquals("25", new String(Base16.encodeBase16(new byte[] { (byte) 37 })));
+ assertEquals("26", new String(Base16.encodeBase16(new byte[] { (byte) 38 })));
+ assertEquals("27", new String(Base16.encodeBase16(new byte[] { (byte) 39 })));
+ assertEquals("28", new String(Base16.encodeBase16(new byte[] { (byte) 40 })));
+ assertEquals("29", new String(Base16.encodeBase16(new byte[] { (byte) 41 })));
+ assertEquals("2a", new String(Base16.encodeBase16(new byte[] { (byte) 42 })));
+ assertEquals("2b", new String(Base16.encodeBase16(new byte[] { (byte) 43 })));
+ assertEquals("2c", new String(Base16.encodeBase16(new byte[] { (byte) 44 })));
+ assertEquals("2d", new String(Base16.encodeBase16(new byte[] { (byte) 45 })));
+ assertEquals("2e", new String(Base16.encodeBase16(new byte[] { (byte) 46 })));
+ assertEquals("2f", new String(Base16.encodeBase16(new byte[] { (byte) 47 })));
+ assertEquals("30", new String(Base16.encodeBase16(new byte[] { (byte) 48 })));
+ assertEquals("31", new String(Base16.encodeBase16(new byte[] { (byte) 49 })));
+ assertEquals("32", new String(Base16.encodeBase16(new byte[] { (byte) 50 })));
+ assertEquals("33", new String(Base16.encodeBase16(new byte[] { (byte) 51 })));
+ assertEquals("34", new String(Base16.encodeBase16(new byte[] { (byte) 52 })));
+ assertEquals("35", new String(Base16.encodeBase16(new byte[] { (byte) 53 })));
+ assertEquals("36", new String(Base16.encodeBase16(new byte[] { (byte) 54 })));
+ assertEquals("37", new String(Base16.encodeBase16(new byte[] { (byte) 55 })));
+ assertEquals("38", new String(Base16.encodeBase16(new byte[] { (byte) 56 })));
+ assertEquals("39", new String(Base16.encodeBase16(new byte[] { (byte) 57 })));
+ assertEquals("3a", new String(Base16.encodeBase16(new byte[] { (byte) 58 })));
+ assertEquals("3b", new String(Base16.encodeBase16(new byte[] { (byte) 59 })));
+ assertEquals("3c", new String(Base16.encodeBase16(new byte[] { (byte) 60 })));
+ assertEquals("3d", new String(Base16.encodeBase16(new byte[] { (byte) 61 })));
+ assertEquals("3e", new String(Base16.encodeBase16(new byte[] { (byte) 62 })));
+ assertEquals("3f", new String(Base16.encodeBase16(new byte[] { (byte) 63 })));
+ assertEquals("40", new String(Base16.encodeBase16(new byte[] { (byte) 64 })));
+ assertEquals("41", new String(Base16.encodeBase16(new byte[] { (byte) 65 })));
+ assertEquals("42", new String(Base16.encodeBase16(new byte[] { (byte) 66 })));
+ assertEquals("43", new String(Base16.encodeBase16(new byte[] { (byte) 67 })));
+ assertEquals("44", new String(Base16.encodeBase16(new byte[] { (byte) 68 })));
+ assertEquals("45", new String(Base16.encodeBase16(new byte[] { (byte) 69 })));
+ assertEquals("46", new String(Base16.encodeBase16(new byte[] { (byte) 70 })));
+ assertEquals("47", new String(Base16.encodeBase16(new byte[] { (byte) 71 })));
+ assertEquals("48", new String(Base16.encodeBase16(new byte[] { (byte) 72 })));
+ assertEquals("49", new String(Base16.encodeBase16(new byte[] { (byte) 73 })));
+ assertEquals("4a", new String(Base16.encodeBase16(new byte[] { (byte) 74 })));
+ assertEquals("4b", new String(Base16.encodeBase16(new byte[] { (byte) 75 })));
+ assertEquals("4c", new String(Base16.encodeBase16(new byte[] { (byte) 76 })));
+ assertEquals("4d", new String(Base16.encodeBase16(new byte[] { (byte) 77 })));
+ assertEquals("4e", new String(Base16.encodeBase16(new byte[] { (byte) 78 })));
+ assertEquals("4f", new String(Base16.encodeBase16(new byte[] { (byte) 79 })));
+ assertEquals("50", new String(Base16.encodeBase16(new byte[] { (byte) 80 })));
+ assertEquals("51", new String(Base16.encodeBase16(new byte[] { (byte) 81 })));
+ assertEquals("52", new String(Base16.encodeBase16(new byte[] { (byte) 82 })));
+ assertEquals("53", new String(Base16.encodeBase16(new byte[] { (byte) 83 })));
+ assertEquals("54", new String(Base16.encodeBase16(new byte[] { (byte) 84 })));
+ assertEquals("55", new String(Base16.encodeBase16(new byte[] { (byte) 85 })));
+ assertEquals("56", new String(Base16.encodeBase16(new byte[] { (byte) 86 })));
+ assertEquals("57", new String(Base16.encodeBase16(new byte[] { (byte) 87 })));
+ assertEquals("58", new String(Base16.encodeBase16(new byte[] { (byte) 88 })));
+ assertEquals("59", new String(Base16.encodeBase16(new byte[] { (byte) 89 })));
+ assertEquals("5a", new String(Base16.encodeBase16(new byte[] { (byte) 90 })));
+ assertEquals("5b", new String(Base16.encodeBase16(new byte[] { (byte) 91 })));
+ assertEquals("5c", new String(Base16.encodeBase16(new byte[] { (byte) 92 })));
+ assertEquals("5d", new String(Base16.encodeBase16(new byte[] { (byte) 93 })));
+ assertEquals("5e", new String(Base16.encodeBase16(new byte[] { (byte) 94 })));
+ assertEquals("5f", new String(Base16.encodeBase16(new byte[] { (byte) 95 })));
+ assertEquals("60", new String(Base16.encodeBase16(new byte[] { (byte) 96 })));
+ assertEquals("61", new String(Base16.encodeBase16(new byte[] { (byte) 97 })));
+ assertEquals("62", new String(Base16.encodeBase16(new byte[] { (byte) 98 })));
+ assertEquals("63", new String(Base16.encodeBase16(new byte[] { (byte) 99 })));
+ assertEquals("64", new String(Base16.encodeBase16(new byte[] { (byte) 100 })));
+ assertEquals("65", new String(Base16.encodeBase16(new byte[] { (byte) 101 })));
+ assertEquals("66", new String(Base16.encodeBase16(new byte[] { (byte) 102 })));
+ assertEquals("67", new String(Base16.encodeBase16(new byte[] { (byte) 103 })));
+ assertEquals("68", new String(Base16.encodeBase16(new byte[] { (byte) 104 })));
+ for (int i = -128; i <= 127; i++) {
+ final byte test[] = { (byte) i };
+ assertTrue(Arrays.equals(test, Base16.decodeBase16(Base16.encodeBase16(test))));
+ }
+ }
+
+ @Test
+ public void testTriplets() {
+ assertEquals("000000", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 0 })));
+ assertEquals("000001", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 1 })));
+ assertEquals("000002", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 2 })));
+ assertEquals("000003", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 3 })));
+ assertEquals("000004", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 4 })));
+ assertEquals("000005", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 5 })));
+ assertEquals("000006", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 6 })));
+ assertEquals("000007", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 7 })));
+ assertEquals("000008", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 8 })));
+ assertEquals("000009", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 9 })));
+ assertEquals("00000a", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 10 })));
+ assertEquals("00000b", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 11 })));
+ assertEquals("00000c", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 12 })));
+ assertEquals("00000d", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 13 })));
+ assertEquals("00000e", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 14 })));
+ assertEquals("00000f", new String(Base16.encodeBase16(new byte[] { (byte) 0, (byte) 0, (byte) 15 })));
+ }
+
+ @Test
+ public void testByteToStringVariations() throws DecoderException {
+ final Base16 Base16 = new Base16();
+ final byte[] b1 = StringUtils.getBytesUtf8("Hello World");
+ final byte[] b2 = new byte[0];
+ final byte[] b3 = null;
+
+ assertEquals("byteToString Hello World", "48656c6c6f20576f726c64", Base16.encodeToString(b1));
+ assertEquals("byteToString static Hello World", "48656c6c6f20576f726c64", StringUtils.newStringUtf8(Base16.encodeBase16(b1)));
+ assertEquals("byteToString \"\"", "", Base16.encodeToString(b2));
+ assertEquals("byteToString static \"\"", "", StringUtils.newStringUtf8(Base16.encodeBase16(b2)));
+ assertEquals("byteToString null", null, Base16.encodeToString(b3));
+ assertEquals("byteToString static null", null, StringUtils.newStringUtf8(Base16.encodeBase16(b3)));
+ }
+
+ @Test
+ public void testStringToByteVariations() throws DecoderException {
+ final Base16 Base16 = new Base16();
+ final String s1 = "48656c6c6f20576f726c64";
+ final String s2 = "";
+ final String s3 = null;
+
+ assertEquals("StringToByte Hello World", "Hello World", StringUtils.newStringUtf8(Base16.decode(s1)));
+ assertEquals("StringToByte Hello World", "Hello World",
+ StringUtils.newStringUtf8((byte[]) Base16.decode((Object) s1)));
+ assertEquals("StringToByte static Hello World", "Hello World",
+ StringUtils.newStringUtf8(Base16.decodeBase16(s1)));
+ assertEquals("StringToByte \"\"", "", StringUtils.newStringUtf8(Base16.decode(s2)));
+ assertEquals("StringToByte static \"\"", "", StringUtils.newStringUtf8(Base16.decodeBase16(s2)));
+ assertEquals("StringToByte null", null, StringUtils.newStringUtf8(Base16.decode(s3)));
+ assertEquals("StringToByte static null", null, StringUtils.newStringUtf8(Base16.decodeBase16(s3)));
+ }
+
+ private String toString(final byte[] data) {
+ final StringBuilder buf = new StringBuilder();
+ for (int i = 0; i < data.length; i++) {
+ buf.append(data[i]);
+ if (i != data.length - 1) {
+ buf.append(",");
+ }
+ }
+ return buf.toString();
+ }
+
+ /**
+ * Test for CODEC-265: Encode a 1GiB file.
+ *
+ * @see <a href="https://issues.apache.org/jira/projects/CODEC/issues/CODEC-265">CODEC-265</a>
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testCodec265_over() {
+ // 1GiB file to encode: 2^30 bytes
+ final int size1GiB = 1 << 30;
+
+ // Expecting a size of 2 output bytes per 1 input byte
+ final int blocks = size1GiB;
+ final int expectedLength = 2 * blocks;
+
+ // This test is memory hungry. Check we can run it.
+ final long presumableFreeMemory = BaseNCodecTest.getPresumableFreeMemory();
+
+ // Estimate the maximum memory required:
+ // 1GiB + 1GiB + ~2GiB + ~1.33GiB + 32 KiB = ~5.33GiB
+ //
+ // 1GiB: Input buffer to encode
+ // 1GiB: Existing working buffer (due to doubling of default buffer size of 8192)
+ // ~2GiB: New working buffer to allocate (due to doubling)
+ // ~1.33GiB: Expected output size (since the working buffer is copied at the end)
+ // 32KiB: Some head room
+ final long estimatedMemory = (long) size1GiB * 4 + expectedLength + 32 * 1024;
+ Assume.assumeTrue("Not enough free memory for the test", presumableFreeMemory > estimatedMemory);
+
+ final byte[] bytes = new byte[size1GiB];
+ final byte[] encoded = Base16.encodeBase16(bytes);
+ assertEquals(expectedLength, encoded.length);
+ }
+
+ @Test
+ public void testIsInAlphabet() {
+ // lower-case
+ Base16 b16 = new Base16(true, CHARSET_UTF8);
+ for (char c = '0'; c <= '9'; c++) {
+ assertTrue(b16.isInAlphabet((byte) c));
+ }
+ for (char c = 'a'; c <= 'f'; c++) {
+ assertTrue(b16.isInAlphabet((byte) c));
+ }
+ for (char c = 'A'; c <= 'F'; c++) {
+ assertFalse(b16.isInAlphabet((byte) c));
+ }
+ assertFalse(b16.isInAlphabet((byte) ('0' - 1)));
+ assertFalse(b16.isInAlphabet((byte) ('9' + 1)));
+ assertFalse(b16.isInAlphabet((byte) ('a' - 1)));
+ assertFalse(b16.isInAlphabet((byte) ('z' + 1)));
+
+ // upper-case
+ b16 = new Base16(false, CHARSET_UTF8);
+ for (char c = '0'; c <= '9'; c++) {
+ assertTrue(b16.isInAlphabet((byte) c));
+ }
+ for (char c = 'a'; c <= 'f'; c++) {
+ assertFalse(b16.isInAlphabet((byte) c));
+ }
+ for (char c = 'A'; c <= 'F'; c++) {
+ assertTrue(b16.isInAlphabet((byte) c));
+ }
+ assertFalse(b16.isInAlphabet((byte) ('0' - 1)));
+ assertFalse(b16.isInAlphabet((byte) ('9' + 1)));
+ assertFalse(b16.isInAlphabet((byte) ('A' - 1)));
+ assertFalse(b16.isInAlphabet((byte) ('F' + 1)));
+ }
+
+ @Test
+ public void testDecodeSingleBytes() {
+ final String encoded = "556e74696c206e6578742074696d6521";
+
+ final BaseNCodec.Context context = new BaseNCodec.Context();
+ final Base16 b16 = new Base16();
+
+ final byte[] encocdedBytes = StringUtils.getBytesUtf8(encoded);
+
+ // decode byte-by-byte
+ b16.decode(encocdedBytes, 0, 1, context);
+ b16.decode(encocdedBytes, 1, 1, context); // yields "U"
+ b16.decode(encocdedBytes, 2, 1, context);
+ b16.decode(encocdedBytes, 3, 1, context); // yields "n"
+
+ // decode split hex-pairs
+ b16.decode(encocdedBytes, 4, 3, context); // yields "t"
+ b16.decode(encocdedBytes, 7, 3, context); // yields "il"
+ b16.decode(encocdedBytes, 10, 3, context); // yields " "
+
+ // decode remaining
+ b16.decode(encocdedBytes, 13, 19, context); // yields "next time!"
+
+ final byte[] decodedBytes = new byte[context.pos];
+ System.arraycopy(context.buffer, context.readPos, decodedBytes, 0, decodedBytes.length);
+ final String decoded = StringUtils.newStringUtf8(decodedBytes);
+
+ assertEquals("Until next time!", decoded);
+ }
+}
diff --git a/src/test/java/org/apache/commons/codec/binary/Base16TestData.java b/src/test/java/org/apache/commons/codec/binary/Base16TestData.java
new file mode 100644
index 0000000..575df32
--- /dev/null
+++ b/src/test/java/org/apache/commons/codec/binary/Base16TestData.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.codec.binary;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Random;
+
+/**
+ * This random data was encoded by OpenSSL. Java had nothing to do with it. This data helps us test interop between
+ * Commons-Codec and OpenSSL.
+ *
+ * @since 1.15
+ */
+public class Base16TestData {
+
+ final static String ENCODED_UTF8_LOWERCASE
+ = "f483cd2b052f74b888029e9cb73d764a2426386b2d5b262f48f79ebee7c386bcdac2ceb9be8ca42a36c88f7dd85936bdc40edcfc51f2a56725ad9850ee89df737244f77049e5f4f847dcc011d8db8f2d61bf8658367113e1625e5cc2c9ff9a7ea81a53b0fa5ea56f03355632d5cd36ff5c320be92003a0af45477d712aff96df3c00476c4d5e063029f5f84c2e02261d8afc6ece7f9c2ccf2ada37b0aa5239dad3fd27b0acf2fa86ef5b3af960042cabe6fd4a2fbf268e8be39d3147e343424b88b907bbaa7d3b0520bd0aa20cacc4bff02e828d1d4cf67360613208fe4656b95edd041d81c8881e7a5d7785544cf [...]
+
+ final static String ENCODED_UTF8_UPPERCASE
+ = "F483CD2B052F74B888029E9CB73D764A2426386B2D5B262F48F79EBEE7C386BCDAC2CEB9BE8CA42A36C88F7DD85936BDC40EDCFC51F2A56725AD9850EE89DF737244F77049E5F4F847DCC011D8DB8F2D61BF8658367113E1625E5CC2C9FF9A7EA81A53B0FA5EA56F03355632D5CD36FF5C320BE92003A0AF45477D712AFF96DF3C00476C4D5E063029F5F84C2E02261D8AFC6ECE7F9C2CCF2ADA37B0AA5239DAD3FD27B0ACF2FA86EF5B3AF960042CABE6FD4A2FBF268E8BE39D3147E343424B88B907BBAA7D3B0520BD0AA20CACC4BFF02E828D1D4CF67360613208FE4656B95EDD041D81C8881E7A5D7785544CF [...]
+
+ final static byte[] DECODED
+ = {-12, -125, -51, 43, 5, 47, 116, -72, -120, 2, -98, -100, -73, 61, 118, 74, 36, 38, 56, 107, 45, 91, 38,
+ 47, 72, -9, -98, -66, -25, -61, -122, -68, -38, -62, -50, -71, -66, -116, -92, 42, 54, -56, -113, 125,
+ -40, 89, 54, -67, -60, 14, -36, -4, 81, -14, -91, 103, 37, -83, -104, 80, -18, -119, -33, 115, 114, 68,
+ -9, 112, 73, -27, -12, -8, 71, -36, -64, 17, -40, -37, -113, 45, 97, -65, -122, 88, 54, 113, 19, -31, 98,
+ 94, 92, -62, -55, -1, -102, 126, -88, 26, 83, -80, -6, 94, -91, 111, 3, 53, 86, 50, -43, -51, 54, -1, 92,
+ 50, 11, -23, 32, 3, -96, -81, 69, 71, 125, 113, 42, -1, -106, -33, 60, 0, 71, 108, 77, 94, 6, 48, 41, -11,
+ -8, 76, 46, 2, 38, 29, -118, -4, 110, -50, 127, -100, 44, -49, 42, -38, 55, -80, -86, 82, 57, -38, -45,
+ -3, 39, -80, -84, -14, -6, -122, -17, 91, 58, -7, 96, 4, 44, -85, -26, -3, 74, 47, -65, 38, -114, -117,
+ -29, -99, 49, 71, -29, 67, 66, 75, -120, -71, 7, -69, -86, 125, 59, 5, 32, -67, 10, -94, 12, -84, -60, -65,
+ -16, 46, -126, -115, 29, 76, -10, 115, 96, 97, 50, 8, -2, 70, 86, -71, 94, -35, 4, 29, -127, -56, -120,
+ 30, 122, 93, 119, -123, 84, 76, -15, -111, 81, -75, -34, 41, -72, 126, -7, 77, -33, 108, -110, 39, -125,
+ -5, 16, 92, -51, -56, 96, 28, -116, 103, -68, 109, -12, 117, -110, -44, -75, 28, 69, -44, 59, 62, -68,
+ 39, -4, -119, 80, 91, 19, -116, 122, -81, -118, 100, -108, -88, 2, -8, -106, -75, -37, 30, -83, 124, -121,
+ 108, -127, 26, -1, -8, 102, -81, -118, 127, -113, -51, 36, -46, 15, 106, -33, -104, 106, -43, -84, -122,
+ 51, -33, 124, -32, 2, -45, 73, -90, 124, 89, -20, -123, 109, -100, 117, 11, 16, -65, 66, -118, -97, -9,
+ 101, 7, -1, 41, 65, 70, 116, -119, 54, 126, 44, 75, 74, 26, -34, -27, 27, 54, -13, -89, -90, 64, 120, 15,
+ -43, 123, 82, -33, 90, -74, 41, -62, 38, -68, 62, -62, 34, 92, 50, 95, -67, -110, -99, -71, -44, -123,
+ 49, 4, 96, 56, 113, 76, 97, -47, -26, -79, -109, 115, -125, 90, 124, 8, -9, -111, 36, -74, 101, -114, 43,
+ 0, -110, 63, 76, 99, 91, 2, 12, -60, 56, -14, -125, 0, 6, -27, 31, 31, -109, -47, -3, 109, 88, -75, -74,
+ 19, 26, -66, 110, 39, 13, -50, 47, 104, -38, 18, 19, 84, 103, 100, -42, 48, 110, 37, 21, -107, 83, -52,
+ -12, 71, 37, -68, -107, -109, 89, -34, -94, -127, 103, -128, -48, -52, 71, 0, 15, 34, 56, -50, 85, -98,
+ 106, -87, -3, 97, -116, -19, 64, -22, -25, -38, -63, 33, -45, 80, 10, -121, -109, 37, -96, 36, 18, -48,
+ 46, 44, -66, 115, -94, 3, -102, -27, -17, -116, -51, 88, -17, 7, -109, 24, 66, 83, -91, 105, -92, -19,
+ 66, -76, 64, -91, 118, -71, 103, -123, 95, 17, -87, -18, -11, 66, -74, 126, 45, 83, -14, 50, 79, 20, 45,
+ -113, -103, 119, -101, -58, -99, 27, -100, -17, -107, 91, -26, -32, -56, 71, 72, 34, 66, 16, 9, -90, 106,
+ -44, -62, -106, 11, 114, -82, -120, -28, -67, 4, -99, 109, -20, -19, 0, -40, -110, -119, 42, -6, 4, -31,
+ 67, 110, -105, 53, 118, 76, 96, -126, -8, -96, 39, -102, 52, 106, 64, 26, -105, -108, -103, -96, -116,
+ 116, 0, -96, 115, 89, 40, -23, -102, -2, -30, 16, 58, -53, -33, 14, 122, -94, 113, -121, 67, -103, -4,
+ -126, 98, -27, 124, -12, 120, -64, -44, 127, 45, -120, 50, 124, -27, 87, -20, -84, 81, -35, 113, -77,
+ -64, -96, -48, -87, -117, -82, 90, -64, -108, -121, 125, -45, -50, -44, -48, -50, 52, -30, -66, -7, 46,
+ -40, -47, 85, -44, -126, -122, 24, -84, 21, 120, 99, -74, 27, 11, -52, 32, -2, 122, -100, -118, 106, -9,
+ -106, 109, -19, 71, 42, 126, 66, -56, 10, -51, -44, 68, 109, -13, 81, -109, 65, 121, 60, -68, -117, 126,
+ -59, 4, -107, -22, 99, -77, 84, 29, 87, 119, -60, 87, 82, -55, -74, 44, -80, 3, 123, -101, 84, -44, 9, 71,
+ 24, 91, 99, 22, -65, 11, -11, -14, -38, -84, 105, -101, -85, -17, 116, -65, 118, -105, 122, -75, 113,
+ -57, -81, -33, -110, 28, 104, -24, -110, -57, -78, 38, -5, -15, -79, 87, 105, 85, 41, -42, -114, -67,
+ -123, 70, 12, 61, 115, 5, 23, -70, 99, 96, -80, 65, -65, 105, -45, -49, 37, -33, -1, 119, -88, 100, 121,
+ -25, -35, -51, 10, 43, -113, 61, 103, 44, 13, 108, 20, 74, 19, 53, 19, 37, -76, 20, -43, -11, 23, -58, -25,
+ -52, 121, -40, -118, 58, 50, 19, -8, -33, -30, -49, -27, -11, -80, 93, -17, 34, 93, 69, 100, 66, -54, 40,
+ 118, 89, -52, -87, 2, 35, -120, 18, 64, 108, 31, -25, 66, 78, 6, -91, -69, -53, 17, 14, -125, 33, -31, -110,
+ 1, 5, -40, 7, 126, -122, 84, -55, -62, -22, 69, -28, 5, 45, -106, 120, 74, 94, 51, 74, 108, -19, -26, -12,
+ 49, 64, 88, 68, 41, -65, 126, 125, -1, -8, -83, -67, 74, 2, -114, -80, -119, -9, -89, -125, 21, 95, 34,
+ -58, -74, 111, -103, 99, 95, 48, 42, 94, -50, -55, -112, -5, -26, 11, -89, -38, -19, 126, 25, 102, 119,
+ 81, -94, 70, -79, 98, 91, -73, 114, 15, 14, 87, -21, -122, -1, -90, 0, 29, -104, -91, -93, -58, -83, -48,
+ -22, 100, -112, -41, 77, 22, -24, 112, -72, 105, 100, 6, -86, -39, 40, -43, 35, -2, 4, -94, 97, -121, 52,
+ -22, 1, 127, -81, -4, -6, -119, 96, 35, -91, 114, 81, 91, 90, -86, -36, 34, -39, 93, -42, 69, 103, -11,
+ 107, -87, 119, -107, -114, -45, -128, -69, 96};
+
+ static byte[] streamToBytes(final InputStream is) throws IOException {
+ final ByteArrayOutputStream os = new ByteArrayOutputStream();
+ final byte[] buf = new byte[4096];
+ int read;
+ while ((read = is.read(buf)) > -1) {
+ os.write(buf, 0, read);
+ }
+ return os.toByteArray();
+ }
+
+ /**
+ * Returns an encoded and decoded copy of the same random data.
+ *
+ * @param size amount of random data to generate and encode
+ * @return two byte[] arrays: [0] = decoded, [1] = encoded
+ */
+ static byte[][] randomData(final int size) {
+ final Random r = new Random();
+ final byte[] decoded = new byte[size];
+ r.nextBytes(decoded);
+ final char[] encodedChars = Hex.encodeHex(decoded);
+ final byte[] encoded = new String(encodedChars).getBytes(Hex.DEFAULT_CHARSET);
+ return new byte[][] {decoded, encoded};
+ }
+}
diff --git a/src/test/java/org/apache/commons/codec/binary/HexTest.java b/src/test/java/org/apache/commons/codec/binary/HexTest.java
index 4c29548..324aaa0 100644
--- a/src/test/java/org/apache/commons/codec/binary/HexTest.java
+++ b/src/test/java/org/apache/commons/codec/binary/HexTest.java
@@ -17,6 +17,7 @@
package org.apache.commons.codec.binary;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -340,6 +341,18 @@ public class HexTest {
checkDecodeHexCharArrayOddCharacters(new char[] { 'A', 'B', 'C', 'D', 'E' });
}
+ @Test(expected = DecoderException.class)
+ public void testDecodeHexCharArrayOutBufferUnderSized() throws DecoderException {
+ final byte[] out = new byte[4];
+ Hex.decodeHex("aabbccddeeff".toCharArray(), out, 0);
+ }
+
+ @Test(expected = DecoderException.class)
+ public void testDecodeHexCharArrayOutBufferUnderSizedByOffset() throws DecoderException {
+ final byte[] out = new byte[6];
+ Hex.decodeHex("aabbccddeeff".toCharArray(), out, 1);
+ }
+
@Test
public void testDecodeHexStringOddCharacters() {
try {
@@ -441,6 +454,27 @@ public class HexTest {
}
@Test
+ public void testEncodeDecodeHexCharArrayRandomToOutput() throws DecoderException, EncoderException {
+ final Random random = new Random();
+ for (int i = 5; i > 0; i--) {
+ final byte[] data = new byte[random.nextInt(10000) + 1];
+ random.nextBytes(data);
+
+ // lower-case
+ final char[] lowerEncodedChars = new char[data.length * 2];
+ Hex.encodeHex(data, 0, data.length, true, lowerEncodedChars, 0);
+ final byte[] decodedLowerCaseBytes = Hex.decodeHex(lowerEncodedChars);
+ assertArrayEquals(data, decodedLowerCaseBytes);
+
+ // upper-case
+ final char[] upperEncodedChars = new char[data.length * 2];
+ Hex.encodeHex(data, 0, data.length, false, upperEncodedChars, 0);
+ final byte[] decodedUpperCaseBytes = Hex.decodeHex(upperEncodedChars);
+ assertArrayEquals(data, decodedUpperCaseBytes);
+ }
+ }
+
+ @Test
public void testEncodeHexByteArrayEmpty() {
assertTrue(Arrays.equals(new char[0], Hex.encodeHex(new byte[0])));
assertTrue(Arrays.equals(new byte[0], new Hex().encode(new byte[0])));
This is an automated email from the ASF dual-hosted git repository.
aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-codec.git
commit a1712d88f39180f5d60f642907843297f4521558
Author: Adam Retter <ad...@googlemail.com>
AuthorDate: Mon Jun 29 21:02:57 2020 +0200
Add missing cases suggested by @aherbert
---
src/test/java/org/apache/commons/codec/binary/Base16Test.java | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/test/java/org/apache/commons/codec/binary/Base16Test.java b/src/test/java/org/apache/commons/codec/binary/Base16Test.java
index 35e4054..299d73a 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base16Test.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base16Test.java
@@ -543,6 +543,7 @@ public class Base16Test {
assertFalse(b16.isInAlphabet((byte) ('0' - 1)));
assertFalse(b16.isInAlphabet((byte) ('9' + 1)));
assertFalse(b16.isInAlphabet((byte) ('a' - 1)));
+ assertFalse(b16.isInAlphabet((byte) ('f' + 1)));
assertFalse(b16.isInAlphabet((byte) ('z' + 1)));
// upper-case
@@ -560,6 +561,7 @@ public class Base16Test {
assertFalse(b16.isInAlphabet((byte) ('9' + 1)));
assertFalse(b16.isInAlphabet((byte) ('A' - 1)));
assertFalse(b16.isInAlphabet((byte) ('F' + 1)));
+ assertFalse(b16.isInAlphabet((byte) ('Z' + 1)));
}
@Test
tags Posted by ah...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-codec.git
commit 919e2f3229d04ff8bbb18de3b0cfb70948092e34
Author: aherbert <ah...@apache.org>
AuthorDate: Tue Jun 30 15:10:15 2020 +0100
Add javadoc <p> tags
---
src/main/java/org/apache/commons/codec/binary/Base16.java | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/main/java/org/apache/commons/codec/binary/Base16.java b/src/main/java/org/apache/commons/codec/binary/Base16.java
index 886b5cd..9ab5fc2 100644
--- a/src/main/java/org/apache/commons/codec/binary/Base16.java
+++ b/src/main/java/org/apache/commons/codec/binary/Base16.java
@@ -25,15 +25,17 @@ import org.apache.commons.codec.CodecPolicy;
* <p>
* This class is thread-safe.
* </p>
- *
+ * <p>
* This implementation strictly follows RFC 4648, and as such unlike
* the {@link Base32} and {@link Base64} implementations,
* it does not ignore invalid alphabet characters or whitespace,
* neither does it offer chunking or padding characters.
- *
+ * </p>
+ * <p>
* The only additional feature above those specified in RFC 4648
* is support for working with a lower-case alphabet in addition
* to the default upper-case alphabet.
+ * </p>
*
* @see <a href="https://tools.ietf.org/html/rfc4648#section-8">RFC 4648 - 8. Base 16 Encoding</a>
*
This is an automated email from the ASF dual-hosted git repository.
aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-codec.git
commit 74343c08c5b1c458c6fd02528bdd6505f142c904
Author: aherbert <ah...@apache.org>
AuthorDate: Tue Jun 30 15:14:35 2020 +0100
CODEC-290: Track changes
---
src/changes/changes.xml | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index aa1c69e..ad0c9a6 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -47,6 +47,7 @@ The <action> type attribute can be add,update,fix,remove.
<action issue="CODEC-280" dev="aherbert" type="update">Base32/Base64/BCodec: Added strict decoding property to control handling of trailing bits. Default lenient mode discards them without error. Strict mode raise an exception.</action>
<action issue="CODEC-289" dev="aherbert" type="update">Base32/Base64 Input/OutputStream: Added strict decoding property to control handling of trailing bits. Default lenient mode discards them without error. Strict mode raise an exception.</action>
<action dev="ggregory" type="update" due-to="Gary Gregory">Update tests from JUnit 4.12 to 4.13.</action>
+ <action issue="CODEC-290" dev="aherbert" due-to="Adam Retter" type="add">Base16Codec and Base16Input/OutputStream</action>
</release>
<release version="1.14" date="2019-12-30" description="Feature and fix release.">
This is an automated email from the ASF dual-hosted git repository.
aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-codec.git
commit 065b10626510274312ff260b4ac1cd9fc964fa24
Author: Adam Retter <ad...@googlemail.com>
AuthorDate: Wed Jun 24 13:05:40 2020 +0200
Address code-review comments by @aherbert
---
.../org/apache/commons/codec/binary/Base16.java | 8 +++---
.../apache/commons/codec/binary/Base16Test.java | 30 ++++++++++++----------
2 files changed, 20 insertions(+), 18 deletions(-)
diff --git a/src/main/java/org/apache/commons/codec/binary/Base16.java b/src/main/java/org/apache/commons/codec/binary/Base16.java
index 5db9043..86ba2cf 100644
--- a/src/main/java/org/apache/commons/codec/binary/Base16.java
+++ b/src/main/java/org/apache/commons/codec/binary/Base16.java
@@ -149,14 +149,14 @@ public class Base16 extends BaseNCodec {
void decode(final byte[] data, int offset, final int length, final Context context) {
if (context.eof || length < 0) {
context.eof = true;
- if (context.ibitWorkArea > 0) {
+ if (context.ibitWorkArea != 0) {
validateTrailingCharacter();
}
return;
}
final int dataLen = Math.min(data.length - offset, length);
- final int availableChars = (context.ibitWorkArea > 0 ? 1 : 0) + dataLen;
+ final int availableChars = (context.ibitWorkArea != 0 ? 1 : 0) + dataLen;
// small optimisation to short-cut the rest of this method when it is fed byte-by-byte
if (availableChars == 1 && availableChars == dataLen) {
@@ -198,7 +198,7 @@ public class Base16 extends BaseNCodec {
private int decodeOctet(final byte octet) {
int decoded = -1;
- if (octet >= 0 && octet < decodeTable.length) {
+ if ((octet & 0xff) < decodeTable.length) {
decoded = decodeTable[octet];
}
@@ -241,7 +241,7 @@ public class Base16 extends BaseNCodec {
*/
@Override
public boolean isInAlphabet(final byte octet) {
- return octet >= 0 && octet < decodeTable.length && decodeTable[octet] != -1;
+ return (octet & 0xff) < decodeTable.length && decodeTable[octet] != -1;
}
/**
diff --git a/src/test/java/org/apache/commons/codec/binary/Base16Test.java b/src/test/java/org/apache/commons/codec/binary/Base16Test.java
index 577a842..0c06553 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base16Test.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base16Test.java
@@ -32,6 +32,7 @@ import java.util.Random;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -116,8 +117,8 @@ public class Base16Test {
@Test
public void testConstructor_LowerCase() {
- final Base16 Base16 = new Base16(true);
- final byte[] encoded = Base16.encode(BaseNTestData.DECODED);
+ final Base16 base16 = new Base16(true);
+ final byte[] encoded = base16.encode(BaseNTestData.DECODED);
final String expectedResult = Base16TestData.ENCODED_UTF8_LOWERCASE;
final String result = StringUtils.newStringUtf8(encoded);
assertEquals("new Base16(true)", expectedResult, result);
@@ -125,11 +126,11 @@ public class Base16Test {
@Test
public void testConstructor_LowerCase_DecodingPolicy() {
- final Base16 Base16 = new Base16(false, CodecPolicy.STRICT);
- final byte[] encoded = Base16.encode(BaseNTestData.DECODED);
+ final Base16 base16 = new Base16(false, CodecPolicy.STRICT);
+ final byte[] encoded = base16.encode(BaseNTestData.DECODED);
final String expectedResult = Base16TestData.ENCODED_UTF8_UPPERCASE;
final String result = StringUtils.newStringUtf8(encoded);
- assertEquals("new Base16(false, CodecPolicy.STRICT)", result, expectedResult);
+ assertEquals("new base16(false, CodecPolicy.STRICT)", result, expectedResult);
}
/**
@@ -435,27 +436,27 @@ public class Base16Test {
@Test
public void testByteToStringVariations() throws DecoderException {
- final Base16 Base16 = new Base16();
+ final Base16 base16 = new Base16();
final byte[] b1 = StringUtils.getBytesUtf8("Hello World");
final byte[] b2 = new byte[0];
final byte[] b3 = null;
- assertEquals("byteToString Hello World", "48656C6C6F20576F726C64", Base16.encodeToString(b1));
+ assertEquals("byteToString Hello World", "48656C6C6F20576F726C64", base16.encodeToString(b1));
assertEquals("byteToString static Hello World", "48656C6C6F20576F726C64", StringUtils.newStringUtf8(new Base16().encode(b1)));
- assertEquals("byteToString \"\"", "", Base16.encodeToString(b2));
+ assertEquals("byteToString \"\"", "", base16.encodeToString(b2));
assertEquals("byteToString static \"\"", "", StringUtils.newStringUtf8(new Base16().encode(b2)));
- assertEquals("byteToString null", null, Base16.encodeToString(b3));
+ assertEquals("byteToString null", null, base16.encodeToString(b3));
assertEquals("byteToString static null", null, StringUtils.newStringUtf8(new Base16().encode(b3)));
}
@Test
public void testStringToByteVariations() throws DecoderException {
- final Base16 Base16 = new Base16();
+ final Base16 base16 = new Base16();
final String s1 = "48656C6C6F20576F726C64";
final String s2 = "";
final String s3 = null;
- assertEquals("StringToByte Hello World", "Hello World", StringUtils.newStringUtf8(Base16.decode(s1)));
+ assertEquals("StringToByte Hello World", "Hello World", StringUtils.newStringUtf8(base16.decode(s1)));
assertEquals("StringToByte Hello World", "Hello World",
StringUtils.newStringUtf8((byte[]) new Base16().decode((Object) s1)));
assertEquals("StringToByte static Hello World", "Hello World",
@@ -587,22 +588,23 @@ public class Base16Test {
@Test
public void testDecodeSingleBytesOptimisation() {
final BaseNCodec.Context context = new BaseNCodec.Context();
- context.ibitWorkArea = 0;
+ assertEquals(0, context.ibitWorkArea);
+ assertNull(context.buffer);
final byte[] data = new byte[1];
final Base16 b16 = new Base16();
- assertEquals(0, context.ibitWorkArea);
data[0] = (byte) 'E';
b16.decode(data, 0, 1, context);
assertEquals(15, context.ibitWorkArea);
+ assertNull(context.buffer);
data[0] = (byte) 'F';
b16.decode(data, 0, 1, context);
assertEquals(0, context.ibitWorkArea);
- assertEquals(-17, context.buffer[0]);
+ assertEquals((byte)0xEF, context.buffer[0]);
}
@Test(expected=IllegalArgumentException.class)
This is an automated email from the ASF dual-hosted git repository.
aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-codec.git
commit e80304ccec2f01aab18a227ac5f2a30393c75d80
Merge: 7118544 74343c0
Author: aherbert <ah...@apache.org>
AuthorDate: Tue Jun 30 15:15:59 2020 +0100
Merge branch 'adamretter-base16'
pom.xml | 7 +
src/changes/changes.xml | 1 +
.../org/apache/commons/codec/binary/Base16.java | 267 +++++++++
.../commons/codec/binary/Base16InputStream.java | 81 +++
.../commons/codec/binary/Base16OutputStream.java | 81 +++
.../org/apache/commons/codec/binary/Base32.java | 2 +-
.../org/apache/commons/codec/binary/Base64.java | 2 +-
.../apache/commons/codec/binary/BaseNCodec.java | 2 +-
.../codec/binary/Base16InputStreamTest.java | 440 +++++++++++++++
.../codec/binary/Base16OutputStreamTest.java | 287 ++++++++++
.../apache/commons/codec/binary/Base16Test.java | 602 +++++++++++++++++++++
.../commons/codec/binary/Base16TestData.java | 33 ++
.../codec/binary/Base32InputStreamTest.java | 41 +-
.../codec/binary/Base32OutputStreamTest.java | 28 +-
.../apache/commons/codec/binary/Base32Test.java | 6 +-
.../commons/codec/binary/Base32TestData.java | 89 ---
.../codec/binary/Base64InputStreamTest.java | 55 +-
.../codec/binary/Base64OutputStreamTest.java | 40 +-
.../apache/commons/codec/binary/Base64Test.java | 17 +-
.../commons/codec/binary/Base64TestData.java | 136 -----
.../{Base64TestData.java => BaseNTestData.java} | 106 ++--
21 files changed, 1932 insertions(+), 391 deletions(-)