You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2023/10/23 12:39:23 UTC

[commons-codec] 01/05: Sort members

This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-codec.git

commit 931bb815b690b098936beca76c600f134027f1bd
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Mon Oct 23 08:33:20 2023 -0400

    Sort members
---
 .../org/apache/commons/codec/binary/Base64.java    |   54 +-
 .../apache/commons/codec/binary/BaseNCodec.java    |  232 +--
 .../java/org/apache/commons/codec/binary/Hex.java  |    4 +-
 .../java/org/apache/commons/codec/cli/Digest.java  |   24 +-
 .../org/apache/commons/codec/digest/Blake3.java    |  670 ++++-----
 .../org/apache/commons/codec/digest/HmacUtils.java |  212 +--
 .../apache/commons/codec/digest/MurmurHash2.java   |  136 +-
 .../apache/commons/codec/digest/MurmurHash3.java   | 1522 ++++++++++----------
 .../org/apache/commons/codec/digest/UnixCrypt.java |   86 +-
 .../org/apache/commons/codec/digest/XXHash32.java  |  140 +-
 .../commons/codec/language/ColognePhonetic.java    |   90 +-
 .../codec/language/DaitchMokotoffSoundex.java      |   46 +-
 .../commons/codec/language/DoubleMetaphone.java    |  466 +++---
 .../apache/commons/codec/language/Metaphone.java   |  150 +-
 .../org/apache/commons/codec/language/Nysiis.java  |    6 +-
 .../commons/codec/language/RefinedSoundex.java     |   12 +-
 .../org/apache/commons/codec/language/Soundex.java |   18 +-
 .../codec/language/bm/BeiderMorseEncoder.java      |   28 +-
 .../org/apache/commons/codec/language/bm/Lang.java |   16 +-
 .../commons/codec/language/bm/Languages.java       |  172 +--
 .../commons/codec/language/bm/PhoneticEngine.java  |   80 +-
 .../org/apache/commons/codec/language/bm/Rule.java |   48 +-
 .../java/org/apache/commons/codec/net/BCodec.java  |  188 +--
 .../org/apache/commons/codec/net/PercentCodec.java |  198 +--
 .../java/org/apache/commons/codec/net/QCodec.java  |  192 +--
 .../commons/codec/net/QuotedPrintableCodec.java    |  444 +++---
 .../org/apache/commons/codec/net/RFC1522Codec.java |  134 +-
 .../org/apache/commons/codec/net/URLCodec.java     |  220 +--
 .../org/apache/commons/codec/CharsetsTest.java     |   12 +-
 .../commons/codec/StringEncoderComparatorTest.java |   18 +-
 .../apache/commons/codec/binary/Base16Test.java    |  388 ++---
 .../codec/binary/Base32InputStreamTest.java        |  124 +-
 .../codec/binary/Base32OutputStreamTest.java       |   70 +-
 .../apache/commons/codec/binary/Base32Test.java    |  278 ++--
 .../commons/codec/binary/Base64Codec13Test.java    |  496 +++----
 .../codec/binary/Base64InputStreamTest.java        |  248 ++--
 .../codec/binary/Base64OutputStreamTest.java       |  100 +-
 .../apache/commons/codec/binary/Base64Test.java    |  610 ++++----
 .../commons/codec/binary/BaseNCodecTest.java       |  446 +++---
 .../apache/commons/codec/binary/BaseNTestData.java |  108 +-
 .../commons/codec/binary/BinaryCodecTest.java      |  714 ++++-----
 .../codec/binary/CharSequenceUtilsTest.java        |   66 +-
 .../org/apache/commons/codec/binary/HexTest.java   |  272 ++--
 .../commons/codec/binary/StringUtilsTest.java      |  112 +-
 .../apache/commons/codec/digest/Apr1CryptTest.java |   42 +-
 .../org/apache/commons/codec/digest/B64Test.java   |   12 +-
 .../apache/commons/codec/digest/Blake3Test.java    |    8 +-
 .../codec/digest/Blake3TestVectorsTest.java        |   44 +-
 .../org/apache/commons/codec/digest/CryptTest.java |   14 +-
 .../apache/commons/codec/digest/Md5CryptTest.java  |   26 +-
 .../commons/codec/digest/MurmurHash2Test.java      |   32 +-
 .../commons/codec/digest/MurmurHash3Test.java      | 1092 +++++++-------
 .../commons/codec/digest/PureJavaCrc32CTest.java   |   36 +-
 .../commons/codec/digest/PureJavaCrc32Test.java    |  478 +++---
 .../commons/codec/digest/Sha256CryptTest.java      |   60 +-
 .../commons/codec/digest/Sha512CryptTest.java      |   58 +-
 .../apache/commons/codec/digest/UnixCryptTest.java |   42 +-
 .../apache/commons/codec/digest/XXHash32Test.java  |   56 +-
 .../codec/language/ColognePhoneticTest.java        |   60 +-
 .../codec/language/DaitchMokotoffSoundexTest.java  |    8 +-
 .../language/MatchRatingApproachEncoderTest.java   |  374 ++---
 .../commons/codec/language/MetaphoneTest.java      |  144 +-
 .../apache/commons/codec/language/SoundexTest.java |   58 +-
 .../bm/CacheSubSequencePerformanceTest.java        |   58 +-
 .../language/bm/PhoneticEngineRegressionTest.java  |  214 +--
 .../org/apache/commons/codec/net/BCodecTest.java   |  112 +-
 .../commons/codec/net/CustomRFC1522Codec.java      |   12 +-
 .../org/apache/commons/codec/net/QCodecTest.java   |  142 +-
 .../codec/net/QuotedPrintableCodecTest.java        |  202 +--
 .../apache/commons/codec/net/RFC1522CodecTest.java |   14 +-
 .../org/apache/commons/codec/net/URLCodecTest.java |  188 +--
 71 files changed, 6618 insertions(+), 6618 deletions(-)

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 b856469d..3521edc2 100644
--- a/src/main/java/org/apache/commons/codec/binary/Base64.java
+++ b/src/main/java/org/apache/commons/codec/binary/Base64.java
@@ -132,33 +132,6 @@ public class Base64 extends BaseNCodec {
     /** Mask used to extract 2 bits, used when decoding final trailing character. */
     private static final int MASK_2BITS = 0x3;
 
-    /**
-     * Encode table to use: either STANDARD or URL_SAFE. Note: the DECODE_TABLE above remains static because it is able
-     * to decode both STANDARD and URL_SAFE streams, but the encodeTable must be a member variable so we can switch
-     * between the two modes.
-     */
-    private final byte[] encodeTable;
-
-    /** Only one decode table currently; keep for consistency with Base32 code. */
-    private final byte[] decodeTable = DECODE_TABLE;
-
-    /**
-     * Line separator for encoding. Not used when decoding. Only used if lineLength &gt; 0.
-     */
-    private final byte[] lineSeparator;
-
-    /**
-     * Convenience variable to help us determine when our buffer is going to run out of room and needs resizing.
-     * {@code decodeSize = 3 + lineSeparator.length;}
-     */
-    private final int decodeSize;
-
-    /**
-     * Convenience variable to help us determine when our buffer is going to run out of room and needs resizing.
-     * {@code encodeSize = 4 + lineSeparator.length;}
-     */
-    private final int encodeSize;
-
     /**
      * Decodes Base64 data into octets.
      * <p>
@@ -441,6 +414,33 @@ public class Base64 extends BaseNCodec {
         return resizedBytes;
     }
 
+    /**
+     * Encode table to use: either STANDARD or URL_SAFE. Note: the DECODE_TABLE above remains static because it is able
+     * to decode both STANDARD and URL_SAFE streams, but the encodeTable must be a member variable so we can switch
+     * between the two modes.
+     */
+    private final byte[] encodeTable;
+
+    /** Only one decode table currently; keep for consistency with Base32 code. */
+    private final byte[] decodeTable = DECODE_TABLE;
+
+    /**
+     * Line separator for encoding. Not used when decoding. Only used if lineLength &gt; 0.
+     */
+    private final byte[] lineSeparator;
+
+    /**
+     * Convenience variable to help us determine when our buffer is going to run out of room and needs resizing.
+     * {@code decodeSize = 3 + lineSeparator.length;}
+     */
+    private final int decodeSize;
+
+    /**
+     * Convenience variable to help us determine when our buffer is going to run out of room and needs resizing.
+     * {@code encodeSize = 4 + lineSeparator.length;}
+     */
+    private final int encodeSize;
+
     /**
      * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
      * <p>
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 551befcd..ef8071de 100644
--- a/src/main/java/org/apache/commons/codec/binary/BaseNCodec.java
+++ b/src/main/java/org/apache/commons/codec/binary/BaseNCodec.java
@@ -51,6 +51,74 @@ import org.apache.commons.codec.EncoderException;
  */
 public abstract class BaseNCodec implements BinaryEncoder, BinaryDecoder {
 
+    /**
+     * Holds thread context so classes can be thread-safe.
+     *
+     * This class is not itself thread-safe; each thread must allocate its own copy.
+     *
+     * @since 1.7
+     */
+    static class Context {
+
+        /**
+         * Placeholder for the bytes we're dealing with for our based logic.
+         * Bitwise operations store and extract the encoding or decoding from this variable.
+         */
+        int ibitWorkArea;
+
+        /**
+         * Placeholder for the bytes we're dealing with for our based logic.
+         * Bitwise operations store and extract the encoding or decoding from this variable.
+         */
+        long lbitWorkArea;
+
+        /**
+         * Buffer for streaming.
+         */
+        byte[] buffer;
+
+        /**
+         * Position where next character should be written in the buffer.
+         */
+        int pos;
+
+        /**
+         * Position where next character should be read from the buffer.
+         */
+        int readPos;
+
+        /**
+         * Boolean flag to indicate the EOF has been reached. Once EOF has been reached, this object becomes useless,
+         * and must be thrown away.
+         */
+        boolean eof;
+
+        /**
+         * Variable tracks how many characters have been written to the current line. Only used when encoding. We use
+         * it to make sure each encoded line never goes beyond lineLength (if lineLength &gt; 0).
+         */
+        int currentLinePos;
+
+        /**
+         * Writes to the buffer only occur after every 3/5 reads when encoding, and every 4/8 reads when decoding. This
+         * variable helps track that.
+         */
+        int modulus;
+
+        /**
+         * Returns a String useful for debugging (especially within a debugger.)
+         *
+         * @return a String useful for debugging.
+         */
+        @SuppressWarnings("boxing") // OK to ignore boxing here
+        @Override
+        public String toString() {
+            return String.format("%s[buffer=%s, currentLinePos=%s, eof=%s, ibitWorkArea=%s, lbitWorkArea=%s, " +
+                    "modulus=%s, pos=%s, readPos=%s]", this.getClass().getSimpleName(), Arrays.toString(buffer),
+                    currentLinePos, eof, ibitWorkArea, lbitWorkArea, modulus, pos, readPos);
+        }
+    }
+
     /**
      * EOF
      *
@@ -123,122 +191,6 @@ public abstract class BaseNCodec implements BinaryEncoder, BinaryDecoder {
      */
     static final byte[] CHUNK_SEPARATOR = {'\r', '\n'};
 
-    /**
-     * @deprecated Use {@link #pad}. Will be removed in 2.0.
-     */
-    @Deprecated
-    protected final byte PAD = PAD_DEFAULT; // instance variable just in case it needs to vary later
-
-    /** Pad byte. Instance variable just in case it needs to vary later. */
-    protected final byte pad;
-
-    /** Number of bytes in each full block of unencoded data, e.g. 4 for Base64 and 5 for Base32 */
-    private final int unencodedBlockSize;
-
-    /** Number of bytes in each full block of encoded data, e.g. 3 for Base64 and 8 for Base32 */
-    private final int encodedBlockSize;
-
-    /**
-     * Chunksize for encoding. Not used when decoding.
-     * A value of zero or less implies no chunking of the encoded data.
-     * Rounded down to the nearest multiple of encodedBlockSize.
-     */
-    protected final int lineLength;
-
-    /**
-     * Size of chunk separator. Not used unless {@link #lineLength} &gt; 0.
-     */
-    private final int chunkSeparatorLength;
-
-    /**
-     * Defines the decoding behavior when the input bytes contain leftover trailing bits that
-     * cannot be created by a valid encoding. These can be bits that are unused from the final
-     * character or entire characters. The default mode is lenient decoding. Set this to
-     * {@code true} to enable strict decoding.
-     * <ul>
-     * <li>Lenient: Any trailing bits are composed into 8-bit bytes where possible.
-     *     The remainder are discarded.
-     * <li>Strict: The decoding will raise an {@link IllegalArgumentException} if trailing bits
-     *     are not part of a valid encoding. Any unused bits from the final character must
-     *     be zero. Impossible counts of entire final characters are not allowed.
-     * </ul>
-     * <p>
-     * When strict decoding is enabled it is expected that the decoded bytes will be re-encoded
-     * to a byte array that matches the original, i.e. no changes occur on the final
-     * character. This requires that the input bytes use the same padding and alphabet
-     * as the encoder.
-     * </p>
-     */
-    private final CodecPolicy decodingPolicy;
-
-    /**
-     * Holds thread context so classes can be thread-safe.
-     *
-     * This class is not itself thread-safe; each thread must allocate its own copy.
-     *
-     * @since 1.7
-     */
-    static class Context {
-
-        /**
-         * Placeholder for the bytes we're dealing with for our based logic.
-         * Bitwise operations store and extract the encoding or decoding from this variable.
-         */
-        int ibitWorkArea;
-
-        /**
-         * Placeholder for the bytes we're dealing with for our based logic.
-         * Bitwise operations store and extract the encoding or decoding from this variable.
-         */
-        long lbitWorkArea;
-
-        /**
-         * Buffer for streaming.
-         */
-        byte[] buffer;
-
-        /**
-         * Position where next character should be written in the buffer.
-         */
-        int pos;
-
-        /**
-         * Position where next character should be read from the buffer.
-         */
-        int readPos;
-
-        /**
-         * Boolean flag to indicate the EOF has been reached. Once EOF has been reached, this object becomes useless,
-         * and must be thrown away.
-         */
-        boolean eof;
-
-        /**
-         * Variable tracks how many characters have been written to the current line. Only used when encoding. We use
-         * it to make sure each encoded line never goes beyond lineLength (if lineLength &gt; 0).
-         */
-        int currentLinePos;
-
-        /**
-         * Writes to the buffer only occur after every 3/5 reads when encoding, and every 4/8 reads when decoding. This
-         * variable helps track that.
-         */
-        int modulus;
-
-        /**
-         * Returns a String useful for debugging (especially within a debugger.)
-         *
-         * @return a String useful for debugging.
-         */
-        @SuppressWarnings("boxing") // OK to ignore boxing here
-        @Override
-        public String toString() {
-            return String.format("%s[buffer=%s, currentLinePos=%s, eof=%s, ibitWorkArea=%s, lbitWorkArea=%s, " +
-                    "modulus=%s, pos=%s, readPos=%s]", this.getClass().getSimpleName(), Arrays.toString(buffer),
-                    currentLinePos, eof, ibitWorkArea, lbitWorkArea, modulus, pos, readPos);
-        }
-    }
-
     /**
      * Create a positive capacity at least as large the minimum required capacity.
      * If the minimum capacity is negative then this throws an OutOfMemoryError as no array
@@ -311,6 +263,54 @@ public abstract class BaseNCodec implements BinaryEncoder, BinaryDecoder {
         return b;
     }
 
+    /**
+     * @deprecated Use {@link #pad}. Will be removed in 2.0.
+     */
+    @Deprecated
+    protected final byte PAD = PAD_DEFAULT; // instance variable just in case it needs to vary later
+
+    /** Pad byte. Instance variable just in case it needs to vary later. */
+    protected final byte pad;
+
+    /** Number of bytes in each full block of unencoded data, e.g. 4 for Base64 and 5 for Base32 */
+    private final int unencodedBlockSize;
+
+    /** Number of bytes in each full block of encoded data, e.g. 3 for Base64 and 8 for Base32 */
+    private final int encodedBlockSize;
+
+    /**
+     * Chunksize for encoding. Not used when decoding.
+     * A value of zero or less implies no chunking of the encoded data.
+     * Rounded down to the nearest multiple of encodedBlockSize.
+     */
+    protected final int lineLength;
+
+    /**
+     * Size of chunk separator. Not used unless {@link #lineLength} &gt; 0.
+     */
+    private final int chunkSeparatorLength;
+
+    /**
+     * Defines the decoding behavior when the input bytes contain leftover trailing bits that
+     * cannot be created by a valid encoding. These can be bits that are unused from the final
+     * character or entire characters. The default mode is lenient decoding. Set this to
+     * {@code true} to enable strict decoding.
+     * <ul>
+     * <li>Lenient: Any trailing bits are composed into 8-bit bytes where possible.
+     *     The remainder are discarded.
+     * <li>Strict: The decoding will raise an {@link IllegalArgumentException} if trailing bits
+     *     are not part of a valid encoding. Any unused bits from the final character must
+     *     be zero. Impossible counts of entire final characters are not allowed.
+     * </ul>
+     * <p>
+     * When strict decoding is enabled it is expected that the decoded bytes will be re-encoded
+     * to a byte array that matches the original, i.e. no changes occur on the final
+     * character. This requires that the input bytes use the same padding and alphabet
+     * as the encoder.
+     * </p>
+     */
+    private final CodecPolicy decodingPolicy;
+
     /**
      * Note {@code lineLength} is rounded down to the nearest multiple of the encoded block size.
      * If {@code chunkSeparatorLength} is zero, then chunking is disabled.
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 61e41ac0..1a859d6c 100644
--- a/src/main/java/org/apache/commons/codec/binary/Hex.java
+++ b/src/main/java/org/apache/commons/codec/binary/Hex.java
@@ -63,8 +63,6 @@ public class Hex implements BinaryEncoder, BinaryDecoder {
     private static final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
             'E', 'F' };
 
-    private final Charset charset;
-
     /**
      * 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
@@ -373,6 +371,8 @@ public class Hex implements BinaryEncoder, BinaryDecoder {
         return digit;
     }
 
+    private final Charset charset;
+
     /**
      * Creates a new codec with the default charset name {@link #DEFAULT_CHARSET}
      */
diff --git a/src/main/java/org/apache/commons/codec/cli/Digest.java b/src/main/java/org/apache/commons/codec/cli/Digest.java
index dce99b6a..e111c353 100644
--- a/src/main/java/org/apache/commons/codec/cli/Digest.java
+++ b/src/main/java/org/apache/commons/codec/cli/Digest.java
@@ -35,10 +35,6 @@ import org.apache.commons.codec.digest.MessageDigestAlgorithms;
  */
 public class Digest {
 
-    private final String algorithm;
-    private final String[] args;
-    private final String[] inputs;
-
     /**
      * Runs the digest algorithm in {@code args[0]} on the file in {@code args[1]}. If there is no {@code args[1]}, use
      * standard input.
@@ -56,6 +52,10 @@ public class Digest {
     public static void main(final String[] args) throws IOException {
         new Digest(args).run();
     }
+    private final String algorithm;
+    private final String[] args;
+
+    private final String[] inputs;
 
     private Digest(final String[] args) {
         if (args == null) {
@@ -101,14 +101,6 @@ public class Digest {
         }
     }
 
-    private void run(final String[] digestAlgorithms) throws IOException {
-        for (final String messageDigestAlgorithm : digestAlgorithms) {
-            if (DigestUtils.isAvailable(messageDigestAlgorithm)) {
-                run(messageDigestAlgorithm + " ", messageDigestAlgorithm);
-            }
-        }
-    }
-
     private void run(final String prefix, final MessageDigest messageDigest) throws IOException {
         if (inputs == null) {
             println(prefix, DigestUtils.digest(messageDigest, System.in));
@@ -143,6 +135,14 @@ public class Digest {
         run(prefix, DigestUtils.getDigest(messageDigestAlgorithm));
     }
 
+    private void run(final String[] digestAlgorithms) throws IOException {
+        for (final String messageDigestAlgorithm : digestAlgorithms) {
+            if (DigestUtils.isAvailable(messageDigestAlgorithm)) {
+                run(messageDigestAlgorithm + " ", messageDigestAlgorithm);
+            }
+        }
+    }
+
     @Override
     public String toString() {
         return String.format("%s %s", super.toString(), Arrays.toString(args));
diff --git a/src/main/java/org/apache/commons/codec/digest/Blake3.java b/src/main/java/org/apache/commons/codec/digest/Blake3.java
index e941c5bf..dcbc6ea8 100644
--- a/src/main/java/org/apache/commons/codec/digest/Blake3.java
+++ b/src/main/java/org/apache/commons/codec/digest/Blake3.java
@@ -75,27 +75,207 @@ import java.util.Objects;
  */
 public final class Blake3 {
 
+    private static final class ChunkState {
+        private int[] chainingValue;
+        private final long chunkCounter;
+        private final int flags;
+
+        private final byte[] block = new byte[BLOCK_LEN];
+        private int blockLength;
+        private int blocksCompressed;
+
+        private ChunkState(final int[] key, final long chunkCounter, final int flags) {
+            chainingValue = key;
+            this.chunkCounter = chunkCounter;
+            this.flags = flags;
+        }
+
+        private int length() {
+            return BLOCK_LEN * blocksCompressed + blockLength;
+        }
+
+        private Output output() {
+            final int[] blockWords = unpackInts(block, BLOCK_INTS);
+            final int outputFlags = flags | startFlag() | CHUNK_END;
+            return new Output(chainingValue, blockWords, chunkCounter, blockLength, outputFlags);
+        }
+
+        private int startFlag() {
+            return blocksCompressed == 0 ? CHUNK_START : 0;
+        }
+
+        private void update(final byte[] input, int offset, int length) {
+            while (length > 0) {
+                if (blockLength == BLOCK_LEN) {
+                    // If the block buffer is full, compress it and clear it. More
+                    // input is coming, so this compression is not CHUNK_END.
+                    final int[] blockWords = unpackInts(block, BLOCK_INTS);
+                    chainingValue = Arrays.copyOf(
+                            compress(chainingValue, blockWords, BLOCK_LEN, chunkCounter, flags | startFlag()),
+                            CHAINING_VALUE_INTS);
+                    blocksCompressed++;
+                    blockLength = 0;
+                    Arrays.fill(block, (byte) 0);
+                }
+
+                final int want = BLOCK_LEN - blockLength;
+                final int take = Math.min(want, length);
+                System.arraycopy(input, offset, block, blockLength, take);
+                blockLength += take;
+                offset += take;
+                length -= take;
+            }
+        }
+    }
+    private static final class EngineState {
+        private final int[] key;
+        private final int flags;
+        // Space for 54 subtree chaining values: 2^54 * CHUNK_LEN = 2^64
+        // No more than 54 entries can ever be added to this stack (after updating 2^64 bytes and not finalizing any)
+        // so we preallocate the stack here. This can be smaller in environments where the data limit is expected to
+        // be much lower.
+        private final int[][] cvStack = new int[54][];
+        private int stackLen;
+        private ChunkState state;
+
+        private EngineState(final int[] key, final int flags) {
+            this.key = key;
+            this.flags = flags;
+            state = new ChunkState(key, 0, flags);
+        }
+
+        // Section 5.1.2 of the BLAKE3 spec explains this algorithm in more detail.
+        private void addChunkCV(final int[] firstCV, final long totalChunks) {
+            // This chunk might complete some subtrees. For each completed subtree,
+            // its left child will be the current top entry in the CV stack, and
+            // its right child will be the current value of `newCV`. Pop each left
+            // child off the stack, merge it with `newCV`, and overwrite `newCV`
+            // with the result. After all these merges, push the final value of
+            // `newCV` onto the stack. The number of completed subtrees is given
+            // by the number of trailing 0-bits in the new total number of chunks.
+            int[] newCV = firstCV;
+            long chunkCounter = totalChunks;
+            while ((chunkCounter & 1) == 0) {
+                newCV = parentChainingValue(popCV(), newCV, key, flags);
+                chunkCounter >>= 1;
+            }
+            pushCV(newCV);
+        }
+
+        private void inputData(final byte[] in, int offset, int length) {
+            while (length > 0) {
+                // If the current chunk is complete, finalize it and reset the
+                // chunk state. More input is coming, so this chunk is not ROOT.
+                if (state.length() == CHUNK_LEN) {
+                    final int[] chunkCV = state.output().chainingValue();
+                    final long totalChunks = state.chunkCounter + 1;
+                    addChunkCV(chunkCV, totalChunks);
+                    state = new ChunkState(key, totalChunks, flags);
+                }
+
+                // Compress input bytes into the current chunk state.
+                final int want = CHUNK_LEN - state.length();
+                final int take = Math.min(want, length);
+                state.update(in, offset, take);
+                offset += take;
+                length -= take;
+            }
+        }
+
+        private void outputHash(final byte[] out, final int offset, final int length) {
+            // Starting with the Output from the current chunk, compute all the
+            // parent chaining values along the right edge of the tree, until we
+            // have the root Output.
+            Output output = state.output();
+            int parentNodesRemaining = stackLen;
+            while (parentNodesRemaining-- > 0) {
+                final int[] parentCV = cvStack[parentNodesRemaining];
+                output = parentOutput(parentCV, output.chainingValue(), key, flags);
+            }
+            output.rootOutputBytes(out, offset, length);
+        }
+
+        private int[] popCV() {
+            return cvStack[--stackLen];
+        }
+
+        private void pushCV(final int[] cv) {
+            cvStack[stackLen++] = cv;
+        }
+
+        private void reset() {
+            stackLen = 0;
+            Arrays.fill(cvStack, null);
+            state = new ChunkState(key, 0, flags);
+        }
+    }
+    /**
+     * Represents the state just prior to either producing an eight word chaining value or any number of output bytes
+     * when the ROOT flag is set.
+     */
+    private static final class Output {
+        private final int[] inputChainingValue;
+        private final int[] blockWords;
+        private final long counter;
+        private final int blockLength;
+        private final int flags;
+
+        private Output(
+                final int[] inputChainingValue, final int[] blockWords, final long counter, final int blockLength,
+                final int flags) {
+            this.inputChainingValue = inputChainingValue;
+            this.blockWords = blockWords;
+            this.counter = counter;
+            this.blockLength = blockLength;
+            this.flags = flags;
+        }
+
+        private int[] chainingValue() {
+            return Arrays
+                    .copyOf(compress(inputChainingValue, blockWords, blockLength, counter, flags), CHAINING_VALUE_INTS);
+        }
+
+        private void rootOutputBytes(final byte[] out, int offset, int length) {
+            int outputBlockCounter = 0;
+            while (length > 0) {
+                int chunkLength = Math.min(OUT_LEN * 2, length);
+                length -= chunkLength;
+                final int[] words =
+                        compress(inputChainingValue, blockWords, blockLength, outputBlockCounter++, flags | ROOT);
+                int wordCounter = 0;
+                while (chunkLength > 0) {
+                    final int wordLength = Math.min(Integer.BYTES, chunkLength);
+                    packInt(words[wordCounter++], out, offset, wordLength);
+                    offset += wordLength;
+                    chunkLength -= wordLength;
+                }
+            }
+        }
+    }
     private static final int BLOCK_LEN = 64;
     private static final int BLOCK_INTS = BLOCK_LEN / Integer.BYTES;
     private static final int KEY_LEN = 32;
     private static final int KEY_INTS = KEY_LEN / Integer.BYTES;
+
     private static final int OUT_LEN = 32;
+
     private static final int CHUNK_LEN = 1024;
     private static final int CHAINING_VALUE_INTS = 8;
-
     /**
      * Standard hash key used for plain hashes; same initialization vector as Blake2s.
      */
     private static final int[] IV =
             { 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 };
-
     // domain flags
     private static final int CHUNK_START = 1;
     private static final int CHUNK_END = 1 << 1;
     private static final int PARENT = 1 << 2;
     private static final int ROOT = 1 << 3;
+
     private static final int KEYED_HASH = 1 << 4;
+
     private static final int DERIVE_KEY_CONTEXT = 1 << 5;
+
     private static final int DERIVE_KEY_MATERIAL = 1 << 6;
 
     /**
@@ -111,97 +291,69 @@ public final class Blake3 {
             { 11, 15, 5, 0, 1, 9, 8, 6, 14, 10, 2, 12, 3, 4, 7, 13 }
     };
 
-    private final EngineState engineState;
+    private static void checkBufferArgs(final byte[] buffer, final int offset, final int length) {
+        Objects.requireNonNull(buffer);
+        if (offset < 0) {
+            throw new IndexOutOfBoundsException("Offset must be non-negative");
+        }
+        if (length < 0) {
+            throw new IndexOutOfBoundsException("Length must be non-negative");
+        }
+        final int bufferLength = buffer.length;
+        if (offset > bufferLength - length) {
+            throw new IndexOutOfBoundsException(
+                    "Offset " + offset + " and length " + length + " out of bounds with buffer length " + bufferLength);
+        }
+    }
 
-    private Blake3(final int[] key, final int flags) {
-        engineState = new EngineState(key, flags);
+    private static int[] compress(
+            final int[] chainingValue, final int[] blockWords, final int blockLength, final long counter,
+            final int flags) {
+        final int[] state = Arrays.copyOf(chainingValue, BLOCK_INTS);
+        System.arraycopy(IV, 0, state, 8, 4);
+        state[12] = (int) counter;
+        state[13] = (int) (counter >> Integer.SIZE);
+        state[14] = blockLength;
+        state[15] = flags;
+        for (int i = 0; i < 7; i++) {
+            final byte[] schedule = MSG_SCHEDULE[i];
+            round(state, blockWords, schedule);
+        }
+        for (int i = 0; i < state.length / 2; i++) {
+            state[i] ^= state[i + 8];
+            state[i + 8] ^= chainingValue[i];
+        }
+        return state;
     }
 
     /**
-     * Resets this instance back to its initial state when it was first constructed.
-     * @return this
+     * The mixing function, G, which mixes either a column or a diagonal.
      */
-    public Blake3 reset() {
-        engineState.reset();
-        return this;
+    private static void g(
+            final int[] state, final int a, final int b, final int c, final int d, final int mx, final int my) {
+        state[a] += state[b] + mx;
+        state[d] = Integer.rotateRight(state[d] ^ state[a], 16);
+        state[c] += state[d];
+        state[b] = Integer.rotateRight(state[b] ^ state[c], 12);
+        state[a] += state[b] + my;
+        state[d] = Integer.rotateRight(state[d] ^ state[a], 8);
+        state[c] += state[d];
+        state[b] = Integer.rotateRight(state[b] ^ state[c], 7);
     }
 
     /**
-     * Updates this hash state using the provided bytes.
+     * Calculates the Blake3 hash of the provided data.
      *
-     * @param in source array to update data from
-     * @return this
-     * @throws NullPointerException if in is null
+     * @param data source array to absorb data from
+     * @return 32-byte hash squeezed from the provided data
+     * @throws NullPointerException if data is null
      */
-    public Blake3 update(final byte[] in) {
-        return update(in, 0, in.length);
+    public static byte[] hash(final byte[] data) {
+        return Blake3.initHash().update(data).doFinalize(OUT_LEN);
     }
 
     /**
-     * Updates this hash state using the provided bytes at an offset.
-     *
-     * @param in     source array to update data from
-     * @param offset where in the array to begin reading bytes
-     * @param length number of bytes to update
-     * @return this
-     * @throws NullPointerException      if in is null
-     * @throws IndexOutOfBoundsException if offset or length are negative or if offset + length is greater than the
-     *                                   length of the provided array
-     */
-    public Blake3 update(final byte[] in, final int offset, final int length) {
-        checkBufferArgs(in, offset, length);
-        engineState.inputData(in, offset, length);
-        return this;
-    }
-
-    /**
-     * Finalizes hash output data that depends on the sequence of updated bytes preceding this invocation and any
-     * previously finalized bytes. Note that this can finalize up to 2<sup>64</sup> bytes per instance.
-     *
-     * @param out destination array to finalize bytes into
-     * @return this
-     * @throws NullPointerException if out is null
-     */
-    public Blake3 doFinalize(final byte[] out) {
-        return doFinalize(out, 0, out.length);
-    }
-
-    /**
-     * Finalizes an arbitrary number of bytes into the provided output array that depends on the sequence of previously
-     * updated and finalized bytes. Note that this can finalize up to 2<sup>64</sup> bytes per instance.
-     *
-     * @param out    destination array to finalize bytes into
-     * @param offset where in the array to begin writing bytes to
-     * @param length number of bytes to finalize
-     * @return this
-     * @throws NullPointerException      if out is null
-     * @throws IndexOutOfBoundsException if offset or length are negative or if offset + length is greater than the
-     *                                   length of the provided array
-     */
-    public Blake3 doFinalize(final byte[] out, final int offset, final int length) {
-        checkBufferArgs(out, offset, length);
-        engineState.outputHash(out, offset, length);
-        return this;
-    }
-
-    /**
-     * Squeezes and returns an arbitrary number of bytes dependent on the sequence of previously absorbed and squeezed bytes.
-     *
-     * @param nrBytes number of bytes to finalize
-     * @return requested number of finalized bytes
-     * @throws IllegalArgumentException if nrBytes is negative
-     */
-    public byte[] doFinalize(final int nrBytes) {
-        if (nrBytes < 0) {
-            throw new IllegalArgumentException("Requested bytes must be non-negative");
-        }
-        final byte[] hash = new byte[nrBytes];
-        doFinalize(hash);
-        return hash;
-    }
-
-    /**
-     * Constructs a fresh Blake3 hash function. The instance returned functions as an arbitrary length message digest.
+     * Constructs a fresh Blake3 hash function. The instance returned functions as an arbitrary length message digest.
      *
      * @return fresh Blake3 instance in hashed mode
      */
@@ -209,23 +361,6 @@ public final class Blake3 {
         return new Blake3(IV, 0);
     }
 
-    /**
-     * Constructs a fresh Blake3 keyed hash function. The instance returned functions as a pseudorandom function (PRF) or as a
-     * message authentication code (MAC).
-     *
-     * @param key 32-byte secret key
-     * @return fresh Blake3 instance in keyed mode using the provided key
-     * @throws NullPointerException     if key is null
-     * @throws IllegalArgumentException if key is not 32 bytes
-     */
-    public static Blake3 initKeyedHash(final byte[] key) {
-        Objects.requireNonNull(key);
-        if (key.length != KEY_LEN) {
-            throw new IllegalArgumentException("Blake3 keys must be 32 bytes");
-        }
-        return new Blake3(unpackInts(key, KEY_INTS), KEYED_HASH);
-    }
-
     /**
      * Constructs a fresh Blake3 key derivation function using the provided key derivation context byte string.
      * The instance returned functions as a key-derivation function which can further absorb additional context data
@@ -245,14 +380,20 @@ public final class Blake3 {
     }
 
     /**
-     * Calculates the Blake3 hash of the provided data.
+     * Constructs a fresh Blake3 keyed hash function. The instance returned functions as a pseudorandom function (PRF) or as a
+     * message authentication code (MAC).
      *
-     * @param data source array to absorb data from
-     * @return 32-byte hash squeezed from the provided data
-     * @throws NullPointerException if data is null
+     * @param key 32-byte secret key
+     * @return fresh Blake3 instance in keyed mode using the provided key
+     * @throws NullPointerException     if key is null
+     * @throws IllegalArgumentException if key is not 32 bytes
      */
-    public static byte[] hash(final byte[] data) {
-        return Blake3.initHash().update(data).doFinalize(OUT_LEN);
+    public static Blake3 initKeyedHash(final byte[] key) {
+        Objects.requireNonNull(key);
+        if (key.length != KEY_LEN) {
+            throw new IllegalArgumentException("Blake3 keys must be 32 bytes");
+        }
+        return new Blake3(unpackInts(key, KEY_INTS), KEYED_HASH);
     }
 
     /**
@@ -267,52 +408,22 @@ public final class Blake3 {
         return Blake3.initKeyedHash(key).update(data).doFinalize(OUT_LEN);
     }
 
-    private static void checkBufferArgs(final byte[] buffer, final int offset, final int length) {
-        Objects.requireNonNull(buffer);
-        if (offset < 0) {
-            throw new IndexOutOfBoundsException("Offset must be non-negative");
-        }
-        if (length < 0) {
-            throw new IndexOutOfBoundsException("Length must be non-negative");
-        }
-        final int bufferLength = buffer.length;
-        if (offset > bufferLength - length) {
-            throw new IndexOutOfBoundsException(
-                    "Offset " + offset + " and length " + length + " out of bounds with buffer length " + bufferLength);
-        }
-    }
-
     private static void packInt(final int value, final byte[] dst, final int off, final int len) {
         for (int i = 0; i < len; i++) {
             dst[off + i] = (byte) (value >>> i * Byte.SIZE);
         }
     }
 
-    private static int unpackInt(final byte[] buf, final int off) {
-        return buf[off] & 0xFF | (buf[off + 1] & 0xFF) << 8 | (buf[off + 2] & 0xFF) << 16 | (buf[off + 3] & 0xFF) << 24;
-    }
-
-    private static int[] unpackInts(final byte[] buf, final int nrInts) {
-        final int[] values = new int[nrInts];
-        for (int i = 0, off = 0; i < nrInts; i++, off += Integer.BYTES) {
-            values[i] = unpackInt(buf, off);
-        }
-        return values;
+    private static int[] parentChainingValue(
+            final int[] leftChildCV, final int[] rightChildCV, final int[] key, final int flags) {
+        return parentOutput(leftChildCV, rightChildCV, key, flags).chainingValue();
     }
 
-    /**
-     * The mixing function, G, which mixes either a column or a diagonal.
-     */
-    private static void g(
-            final int[] state, final int a, final int b, final int c, final int d, final int mx, final int my) {
-        state[a] += state[b] + mx;
-        state[d] = Integer.rotateRight(state[d] ^ state[a], 16);
-        state[c] += state[d];
-        state[b] = Integer.rotateRight(state[b] ^ state[c], 12);
-        state[a] += state[b] + my;
-        state[d] = Integer.rotateRight(state[d] ^ state[a], 8);
-        state[c] += state[d];
-        state[b] = Integer.rotateRight(state[b] ^ state[c], 7);
+    private static Output parentOutput(
+            final int[] leftChildCV, final int[] rightChildCV, final int[] key, final int flags) {
+        final int[] blockWords = Arrays.copyOf(leftChildCV, BLOCK_INTS);
+        System.arraycopy(rightChildCV, 0, blockWords, 8, CHAINING_VALUE_INTS);
+        return new Output(key.clone(), blockWords, 0, BLOCK_LEN, flags | PARENT);
     }
 
     private static void round(final int[] state, final int[] msg, final byte[] schedule) {
@@ -329,216 +440,105 @@ public final class Blake3 {
         g(state, 3, 4, 9, 14, msg[schedule[14]], msg[schedule[15]]);
     }
 
-    private static int[] compress(
-            final int[] chainingValue, final int[] blockWords, final int blockLength, final long counter,
-            final int flags) {
-        final int[] state = Arrays.copyOf(chainingValue, BLOCK_INTS);
-        System.arraycopy(IV, 0, state, 8, 4);
-        state[12] = (int) counter;
-        state[13] = (int) (counter >> Integer.SIZE);
-        state[14] = blockLength;
-        state[15] = flags;
-        for (int i = 0; i < 7; i++) {
-            final byte[] schedule = MSG_SCHEDULE[i];
-            round(state, blockWords, schedule);
-        }
-        for (int i = 0; i < state.length / 2; i++) {
-            state[i] ^= state[i + 8];
-            state[i + 8] ^= chainingValue[i];
-        }
-        return state;
+    private static int unpackInt(final byte[] buf, final int off) {
+        return buf[off] & 0xFF | (buf[off + 1] & 0xFF) << 8 | (buf[off + 2] & 0xFF) << 16 | (buf[off + 3] & 0xFF) << 24;
     }
 
-    private static Output parentOutput(
-            final int[] leftChildCV, final int[] rightChildCV, final int[] key, final int flags) {
-        final int[] blockWords = Arrays.copyOf(leftChildCV, BLOCK_INTS);
-        System.arraycopy(rightChildCV, 0, blockWords, 8, CHAINING_VALUE_INTS);
-        return new Output(key.clone(), blockWords, 0, BLOCK_LEN, flags | PARENT);
+    private static int[] unpackInts(final byte[] buf, final int nrInts) {
+        final int[] values = new int[nrInts];
+        for (int i = 0, off = 0; i < nrInts; i++, off += Integer.BYTES) {
+            values[i] = unpackInt(buf, off);
+        }
+        return values;
     }
 
-    private static int[] parentChainingValue(
-            final int[] leftChildCV, final int[] rightChildCV, final int[] key, final int flags) {
-        return parentOutput(leftChildCV, rightChildCV, key, flags).chainingValue();
+    private final EngineState engineState;
+
+    private Blake3(final int[] key, final int flags) {
+        engineState = new EngineState(key, flags);
     }
 
     /**
-     * Represents the state just prior to either producing an eight word chaining value or any number of output bytes
-     * when the ROOT flag is set.
+     * Finalizes hash output data that depends on the sequence of updated bytes preceding this invocation and any
+     * previously finalized bytes. Note that this can finalize up to 2<sup>64</sup> bytes per instance.
+     *
+     * @param out destination array to finalize bytes into
+     * @return this
+     * @throws NullPointerException if out is null
      */
-    private static final class Output {
-        private final int[] inputChainingValue;
-        private final int[] blockWords;
-        private final long counter;
-        private final int blockLength;
-        private final int flags;
-
-        private Output(
-                final int[] inputChainingValue, final int[] blockWords, final long counter, final int blockLength,
-                final int flags) {
-            this.inputChainingValue = inputChainingValue;
-            this.blockWords = blockWords;
-            this.counter = counter;
-            this.blockLength = blockLength;
-            this.flags = flags;
-        }
-
-        private int[] chainingValue() {
-            return Arrays
-                    .copyOf(compress(inputChainingValue, blockWords, blockLength, counter, flags), CHAINING_VALUE_INTS);
-        }
-
-        private void rootOutputBytes(final byte[] out, int offset, int length) {
-            int outputBlockCounter = 0;
-            while (length > 0) {
-                int chunkLength = Math.min(OUT_LEN * 2, length);
-                length -= chunkLength;
-                final int[] words =
-                        compress(inputChainingValue, blockWords, blockLength, outputBlockCounter++, flags | ROOT);
-                int wordCounter = 0;
-                while (chunkLength > 0) {
-                    final int wordLength = Math.min(Integer.BYTES, chunkLength);
-                    packInt(words[wordCounter++], out, offset, wordLength);
-                    offset += wordLength;
-                    chunkLength -= wordLength;
-                }
-            }
-        }
+    public Blake3 doFinalize(final byte[] out) {
+        return doFinalize(out, 0, out.length);
     }
 
-    private static final class ChunkState {
-        private int[] chainingValue;
-        private final long chunkCounter;
-        private final int flags;
-
-        private final byte[] block = new byte[BLOCK_LEN];
-        private int blockLength;
-        private int blocksCompressed;
-
-        private ChunkState(final int[] key, final long chunkCounter, final int flags) {
-            chainingValue = key;
-            this.chunkCounter = chunkCounter;
-            this.flags = flags;
-        }
-
-        private int length() {
-            return BLOCK_LEN * blocksCompressed + blockLength;
-        }
-
-        private int startFlag() {
-            return blocksCompressed == 0 ? CHUNK_START : 0;
-        }
-
-        private void update(final byte[] input, int offset, int length) {
-            while (length > 0) {
-                if (blockLength == BLOCK_LEN) {
-                    // If the block buffer is full, compress it and clear it. More
-                    // input is coming, so this compression is not CHUNK_END.
-                    final int[] blockWords = unpackInts(block, BLOCK_INTS);
-                    chainingValue = Arrays.copyOf(
-                            compress(chainingValue, blockWords, BLOCK_LEN, chunkCounter, flags | startFlag()),
-                            CHAINING_VALUE_INTS);
-                    blocksCompressed++;
-                    blockLength = 0;
-                    Arrays.fill(block, (byte) 0);
-                }
-
-                final int want = BLOCK_LEN - blockLength;
-                final int take = Math.min(want, length);
-                System.arraycopy(input, offset, block, blockLength, take);
-                blockLength += take;
-                offset += take;
-                length -= take;
-            }
-        }
-
-        private Output output() {
-            final int[] blockWords = unpackInts(block, BLOCK_INTS);
-            final int outputFlags = flags | startFlag() | CHUNK_END;
-            return new Output(chainingValue, blockWords, chunkCounter, blockLength, outputFlags);
-        }
+    /**
+     * Finalizes an arbitrary number of bytes into the provided output array that depends on the sequence of previously
+     * updated and finalized bytes. Note that this can finalize up to 2<sup>64</sup> bytes per instance.
+     *
+     * @param out    destination array to finalize bytes into
+     * @param offset where in the array to begin writing bytes to
+     * @param length number of bytes to finalize
+     * @return this
+     * @throws NullPointerException      if out is null
+     * @throws IndexOutOfBoundsException if offset or length are negative or if offset + length is greater than the
+     *                                   length of the provided array
+     */
+    public Blake3 doFinalize(final byte[] out, final int offset, final int length) {
+        checkBufferArgs(out, offset, length);
+        engineState.outputHash(out, offset, length);
+        return this;
     }
 
-    private static final class EngineState {
-        private final int[] key;
-        private final int flags;
-        // Space for 54 subtree chaining values: 2^54 * CHUNK_LEN = 2^64
-        // No more than 54 entries can ever be added to this stack (after updating 2^64 bytes and not finalizing any)
-        // so we preallocate the stack here. This can be smaller in environments where the data limit is expected to
-        // be much lower.
-        private final int[][] cvStack = new int[54][];
-        private int stackLen;
-        private ChunkState state;
-
-        private EngineState(final int[] key, final int flags) {
-            this.key = key;
-            this.flags = flags;
-            state = new ChunkState(key, 0, flags);
-        }
-
-        private void inputData(final byte[] in, int offset, int length) {
-            while (length > 0) {
-                // If the current chunk is complete, finalize it and reset the
-                // chunk state. More input is coming, so this chunk is not ROOT.
-                if (state.length() == CHUNK_LEN) {
-                    final int[] chunkCV = state.output().chainingValue();
-                    final long totalChunks = state.chunkCounter + 1;
-                    addChunkCV(chunkCV, totalChunks);
-                    state = new ChunkState(key, totalChunks, flags);
-                }
-
-                // Compress input bytes into the current chunk state.
-                final int want = CHUNK_LEN - state.length();
-                final int take = Math.min(want, length);
-                state.update(in, offset, take);
-                offset += take;
-                length -= take;
-            }
-        }
-
-        private void outputHash(final byte[] out, final int offset, final int length) {
-            // Starting with the Output from the current chunk, compute all the
-            // parent chaining values along the right edge of the tree, until we
-            // have the root Output.
-            Output output = state.output();
-            int parentNodesRemaining = stackLen;
-            while (parentNodesRemaining-- > 0) {
-                final int[] parentCV = cvStack[parentNodesRemaining];
-                output = parentOutput(parentCV, output.chainingValue(), key, flags);
-            }
-            output.rootOutputBytes(out, offset, length);
-        }
-
-        private void reset() {
-            stackLen = 0;
-            Arrays.fill(cvStack, null);
-            state = new ChunkState(key, 0, flags);
+    /**
+     * Squeezes and returns an arbitrary number of bytes dependent on the sequence of previously absorbed and squeezed bytes.
+     *
+     * @param nrBytes number of bytes to finalize
+     * @return requested number of finalized bytes
+     * @throws IllegalArgumentException if nrBytes is negative
+     */
+    public byte[] doFinalize(final int nrBytes) {
+        if (nrBytes < 0) {
+            throw new IllegalArgumentException("Requested bytes must be non-negative");
         }
+        final byte[] hash = new byte[nrBytes];
+        doFinalize(hash);
+        return hash;
+    }
 
-        // Section 5.1.2 of the BLAKE3 spec explains this algorithm in more detail.
-        private void addChunkCV(final int[] firstCV, final long totalChunks) {
-            // This chunk might complete some subtrees. For each completed subtree,
-            // its left child will be the current top entry in the CV stack, and
-            // its right child will be the current value of `newCV`. Pop each left
-            // child off the stack, merge it with `newCV`, and overwrite `newCV`
-            // with the result. After all these merges, push the final value of
-            // `newCV` onto the stack. The number of completed subtrees is given
-            // by the number of trailing 0-bits in the new total number of chunks.
-            int[] newCV = firstCV;
-            long chunkCounter = totalChunks;
-            while ((chunkCounter & 1) == 0) {
-                newCV = parentChainingValue(popCV(), newCV, key, flags);
-                chunkCounter >>= 1;
-            }
-            pushCV(newCV);
-        }
+    /**
+     * Resets this instance back to its initial state when it was first constructed.
+     * @return this
+     */
+    public Blake3 reset() {
+        engineState.reset();
+        return this;
+    }
 
-        private void pushCV(final int[] cv) {
-            cvStack[stackLen++] = cv;
-        }
+    /**
+     * Updates this hash state using the provided bytes.
+     *
+     * @param in source array to update data from
+     * @return this
+     * @throws NullPointerException if in is null
+     */
+    public Blake3 update(final byte[] in) {
+        return update(in, 0, in.length);
+    }
 
-        private int[] popCV() {
-            return cvStack[--stackLen];
-        }
+    /**
+     * Updates this hash state using the provided bytes at an offset.
+     *
+     * @param in     source array to update data from
+     * @param offset where in the array to begin reading bytes
+     * @param length number of bytes to update
+     * @return this
+     * @throws NullPointerException      if in is null
+     * @throws IndexOutOfBoundsException if offset or length are negative or if offset + length is greater than the
+     *                                   length of the provided array
+     */
+    public Blake3 update(final byte[] in, final int offset, final int length) {
+        checkBufferArgs(in, offset, length);
+        engineState.inputData(in, offset, length);
+        return this;
     }
 
 }
diff --git a/src/main/java/org/apache/commons/codec/digest/HmacUtils.java b/src/main/java/org/apache/commons/codec/digest/HmacUtils.java
index 21cb7e00..61481c16 100644
--- a/src/main/java/org/apache/commons/codec/digest/HmacUtils.java
+++ b/src/main/java/org/apache/commons/codec/digest/HmacUtils.java
@@ -59,40 +59,6 @@ public final class HmacUtils {
 
     private static final int STREAM_BUFFER_LENGTH = 1024;
 
-    private final Mac mac;
-
-    /**
-     * Returns whether this algorithm is available
-     *
-     * @param name the name to check
-     * @return whether this algorithm is available
-     * @since 1.11
-     */
-    public static boolean isAvailable(final String name) {
-        try {
-            Mac.getInstance(name);
-            return true;
-        } catch (final NoSuchAlgorithmException e) {
-            return false;
-        }
-    }
-
-    /**
-     * Returns whether this algorithm is available
-     *
-     * @param name the name to check
-     * @return whether this algorithm is available
-     * @since 1.11
-     */
-    public static boolean isAvailable(final HmacAlgorithms name) {
-        try {
-            Mac.getInstance(name.getName());
-            return true;
-        } catch (final NoSuchAlgorithmException e) {
-            return false;
-        }
-    }
-
     /**
      * Returns an initialized {@code Mac} for the HmacMD5 algorithm.
      * <p>
@@ -357,8 +323,6 @@ public final class HmacUtils {
         return new HmacUtils(HmacAlgorithms.HMAC_MD5, key).hmacHex(valueToDigest);
     }
 
-    // hmacSha1
-
     /**
      * Returns a HmacSHA1 Message Authentication Code (MAC) for the given key and value.
      *
@@ -415,6 +379,8 @@ public final class HmacUtils {
         return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, key).hmac(valueToDigest);
     }
 
+    // hmacSha1
+
     /**
      * Returns a HmacSHA1 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
      *
@@ -583,8 +549,6 @@ public final class HmacUtils {
         return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmacHex(valueToDigest);
     }
 
-    // hmacSha384
-
     /**
      * Returns a HmacSHA384 Message Authentication Code (MAC) for the given key and value.
      *
@@ -641,6 +605,8 @@ public final class HmacUtils {
         return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmac(valueToDigest);
     }
 
+    // hmacSha384
+
     /**
      * Returns a HmacSHA384 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
      *
@@ -697,8 +663,6 @@ public final class HmacUtils {
         return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, key).hmacHex(valueToDigest);
     }
 
-    // hmacSha512
-
     /**
      * Returns a HmacSHA512 Message Authentication Code (MAC) for the given key and value.
      *
@@ -755,6 +719,8 @@ public final class HmacUtils {
         return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmac(valueToDigest);
     }
 
+    // hmacSha512
+
     /**
      * Returns a HmacSHA512 Message Authentication Code (MAC) as hexadecimal string (lowercase) for the given key and value.
      *
@@ -811,6 +777,38 @@ public final class HmacUtils {
         return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, key).hmacHex(valueToDigest);
     }
 
+    /**
+     * Returns whether this algorithm is available
+     *
+     * @param name the name to check
+     * @return whether this algorithm is available
+     * @since 1.11
+     */
+    public static boolean isAvailable(final HmacAlgorithms name) {
+        try {
+            Mac.getInstance(name.getName());
+            return true;
+        } catch (final NoSuchAlgorithmException e) {
+            return false;
+        }
+    }
+
+    /**
+     * Returns whether this algorithm is available
+     *
+     * @param name the name to check
+     * @return whether this algorithm is available
+     * @since 1.11
+     */
+    public static boolean isAvailable(final String name) {
+        try {
+            Mac.getInstance(name);
+            return true;
+        } catch (final NoSuchAlgorithmException e) {
+            return false;
+        }
+    }
+
     /**
      * Resets and then updates the given {@link Mac} with the value.
      *
@@ -874,6 +872,8 @@ public final class HmacUtils {
         return mac;
     }
 
+    private final Mac mac;
+
     /**
      * Preserves binary compatibility only.
      * As for previous versions does not provide useful behavior
@@ -884,21 +884,17 @@ public final class HmacUtils {
         this(null);
     }
 
-    private HmacUtils(final Mac mac) {
-        this.mac = mac;
-    }
-
     /**
      * Creates an instance using the provided algorithm type.
      *
-     * @param algorithm to use
-     * @param  key the key to use
+     * @param algorithm to use.
+     * @param key the key to use
      * @throws IllegalArgumentException
      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
      * @since 1.11
      */
-    public HmacUtils(final String algorithm, final byte[] key) {
-        this(getInitializedMac(algorithm, key));
+    public HmacUtils(final HmacAlgorithms algorithm, final byte[] key) {
+        this(algorithm.getName(), key);
     }
 
     /**
@@ -910,8 +906,12 @@ public final class HmacUtils {
      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
      * @since 1.11
      */
-    public HmacUtils(final String algorithm, final String key) {
-        this(algorithm, StringUtils.getBytesUtf8(key));
+    public HmacUtils(final HmacAlgorithms algorithm, final String key) {
+        this(algorithm.getName(), StringUtils.getBytesUtf8(key));
+    }
+
+    private HmacUtils(final Mac mac) {
+        this.mac = mac;
     }
 
     /**
@@ -923,21 +923,21 @@ public final class HmacUtils {
      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
      * @since 1.11
      */
-    public HmacUtils(final HmacAlgorithms algorithm, final String key) {
-        this(algorithm.getName(), StringUtils.getBytesUtf8(key));
+    public HmacUtils(final String algorithm, final byte[] key) {
+        this(getInitializedMac(algorithm, key));
     }
 
     /**
      * Creates an instance using the provided algorithm type.
      *
-     * @param algorithm to use.
-     * @param key the key to use
+     * @param algorithm to use
+     * @param  key the key to use
      * @throws IllegalArgumentException
      *             when a {@link NoSuchAlgorithmException} is caught or key is null or key is invalid.
      * @since 1.11
      */
-    public HmacUtils(final HmacAlgorithms algorithm, final byte[] key) {
-        this(algorithm.getName(), key);
+    public HmacUtils(final String algorithm, final String key) {
+        this(algorithm, StringUtils.getBytesUtf8(key));
     }
 
     /**
@@ -955,45 +955,72 @@ public final class HmacUtils {
      * Returns the digest for the input data.
      *
      * @param valueToDigest the input to use
-     * @return the digest as a hexadecimal String
+     * @return the digest as a byte[]
      * @since 1.11
      */
-    public String hmacHex(final byte[] valueToDigest) {
-        return Hex.encodeHexString(hmac(valueToDigest));
+    public byte[] hmac(final ByteBuffer valueToDigest) {
+        mac.update(valueToDigest);
+        return mac.doFinal();
     }
 
     /**
-     * Returns the digest for the input data.
+     * Returns the digest for the file.
      *
-     * @param valueToDigest the input to use, treated as UTF-8
-     * @return the digest as a byte[]
+     * @param valueToDigest the file to use
+     * @return the digest
+     * @throws IOException
+     *             If an I/O error occurs.
      * @since 1.11
      */
-    public byte[] hmac(final String valueToDigest) {
-        return mac.doFinal(StringUtils.getBytesUtf8(valueToDigest));
+    public byte[] hmac(final File valueToDigest) throws IOException {
+        try (final BufferedInputStream stream = new BufferedInputStream(new FileInputStream(valueToDigest))) {
+            return hmac(stream);
+        }
+    }
+
+    /**
+     * Returns the digest for the stream.
+     *
+     * @param valueToDigest
+     *            the data to use
+     *            <p>
+     *            The InputStream must not be null and will not be closed
+     *            </p>
+     * @return the digest
+     * @throws IOException
+     *             If an I/O error occurs.
+     * @since 1.11
+     */
+    public byte[] hmac(final InputStream valueToDigest) throws IOException {
+        final byte[] buffer = new byte[STREAM_BUFFER_LENGTH];
+        int read;
+
+        while ((read = valueToDigest.read(buffer, 0, STREAM_BUFFER_LENGTH) ) > -1) {
+            mac.update(buffer, 0, read);
+        }
+        return mac.doFinal();
     }
 
     /**
      * Returns the digest for the input data.
      *
      * @param valueToDigest the input to use, treated as UTF-8
-     * @return the digest as a hexadecimal String
+     * @return the digest as a byte[]
      * @since 1.11
      */
-    public String hmacHex(final String valueToDigest) {
-        return Hex.encodeHexString(hmac(valueToDigest));
+    public byte[] hmac(final String valueToDigest) {
+        return mac.doFinal(StringUtils.getBytesUtf8(valueToDigest));
     }
 
     /**
      * Returns the digest for the input data.
      *
      * @param valueToDigest the input to use
-     * @return the digest as a byte[]
+     * @return the digest as a hexadecimal String
      * @since 1.11
      */
-    public byte[] hmac(final ByteBuffer valueToDigest) {
-        mac.update(valueToDigest);
-        return mac.doFinal();
+    public String hmacHex(final byte[] valueToDigest) {
+        return Hex.encodeHexString(hmac(valueToDigest));
     }
 
     /**
@@ -1008,26 +1035,16 @@ public final class HmacUtils {
     }
 
     /**
-     * Returns the digest for the stream.
+     * Returns the digest for the file.
      *
-     * @param valueToDigest
-     *            the data to use
-     *            <p>
-     *            The InputStream must not be null and will not be closed
-     *            </p>
-     * @return the digest
+     * @param valueToDigest the file to use
+     * @return the digest as a hexadecimal String
      * @throws IOException
      *             If an I/O error occurs.
      * @since 1.11
      */
-    public byte[] hmac(final InputStream valueToDigest) throws IOException {
-        final byte[] buffer = new byte[STREAM_BUFFER_LENGTH];
-        int read;
-
-        while ((read = valueToDigest.read(buffer, 0, STREAM_BUFFER_LENGTH) ) > -1) {
-            mac.update(buffer, 0, read);
-        }
-        return mac.doFinal();
+    public String hmacHex(final File valueToDigest) throws IOException {
+        return Hex.encodeHexString(hmac(valueToDigest));
     }
 
     /**
@@ -1048,30 +1065,13 @@ public final class HmacUtils {
     }
 
     /**
-     * Returns the digest for the file.
-     *
-     * @param valueToDigest the file to use
-     * @return the digest
-     * @throws IOException
-     *             If an I/O error occurs.
-     * @since 1.11
-     */
-    public byte[] hmac(final File valueToDigest) throws IOException {
-        try (final BufferedInputStream stream = new BufferedInputStream(new FileInputStream(valueToDigest))) {
-            return hmac(stream);
-        }
-    }
-
-    /**
-     * Returns the digest for the file.
+     * Returns the digest for the input data.
      *
-     * @param valueToDigest the file to use
+     * @param valueToDigest the input to use, treated as UTF-8
      * @return the digest as a hexadecimal String
-     * @throws IOException
-     *             If an I/O error occurs.
      * @since 1.11
      */
-    public String hmacHex(final File valueToDigest) throws IOException {
+    public String hmacHex(final String valueToDigest) {
         return Hex.encodeHexString(hmac(valueToDigest));
     }
 
diff --git a/src/main/java/org/apache/commons/codec/digest/MurmurHash2.java b/src/main/java/org/apache/commons/codec/digest/MurmurHash2.java
index 8174d6f8..04038f95 100644
--- a/src/main/java/org/apache/commons/codec/digest/MurmurHash2.java
+++ b/src/main/java/org/apache/commons/codec/digest/MurmurHash2.java
@@ -58,8 +58,54 @@ public final class MurmurHash2 {
     private static final long M64 = 0xc6a4a7935bd1e995L;
     private static final int R64 = 47;
 
-    /** No instance methods. */
-    private MurmurHash2() {
+    /**
+     * Gets the little-endian int from 4 bytes starting at the specified index.
+     *
+     * @param data The data
+     * @param index The index
+     * @return The little-endian int
+     */
+    private static int getLittleEndianInt(final byte[] data, final int index) {
+        return data[index    ] & 0xff |
+               (data[index + 1] & 0xff) <<  8 |
+               (data[index + 2] & 0xff) << 16 |
+               (data[index + 3] & 0xff) << 24;
+    }
+
+    /**
+     * Gets the little-endian long from 8 bytes starting at the specified index.
+     *
+     * @param data The data
+     * @param index The index
+     * @return The little-endian long
+     */
+    private static long getLittleEndianLong(final byte[] data, final int index) {
+        return (long) data[index    ] & 0xff |
+               ((long) data[index + 1] & 0xff) <<  8 |
+               ((long) data[index + 2] & 0xff) << 16 |
+               ((long) data[index + 3] & 0xff) << 24 |
+               ((long) data[index + 4] & 0xff) << 32 |
+               ((long) data[index + 5] & 0xff) << 40 |
+               ((long) data[index + 6] & 0xff) << 48 |
+               ((long) data[index + 7] & 0xff) << 56;
+    }
+
+    /**
+     * Generates a 32-bit hash from byte array with the given length and a default seed value.
+     * This is a helper method that will produce the same result as:
+     *
+     * <pre>
+     * int seed = 0x9747b28c;
+     * int hash = MurmurHash2.hash32(data, length, seed);
+     * </pre>
+     *
+     * @param data The input byte array
+     * @param length The length of the array
+     * @return The 32-bit hash
+     * @see #hash32(byte[], int, int)
+     */
+    public static int hash32(final byte[] data, final int length) {
+        return hash32(data, length, 0x9747b28c);
     }
 
     /**
@@ -109,24 +155,6 @@ public final class MurmurHash2 {
         return h;
     }
 
-    /**
-     * Generates a 32-bit hash from byte array with the given length and a default seed value.
-     * This is a helper method that will produce the same result as:
-     *
-     * <pre>
-     * int seed = 0x9747b28c;
-     * int hash = MurmurHash2.hash32(data, length, seed);
-     * </pre>
-     *
-     * @param data The input byte array
-     * @param length The length of the array
-     * @return The 32-bit hash
-     * @see #hash32(byte[], int, int)
-     */
-    public static int hash32(final byte[] data, final int length) {
-        return hash32(data, length, 0x9747b28c);
-    }
-
     /**
      * Generates a 32-bit hash from a string with a default seed.
      * <p>
@@ -171,6 +199,24 @@ public final class MurmurHash2 {
         return hash32(text.substring(from, from + length));
     }
 
+    /**
+     * Generates a 64-bit hash from byte array with given length and a default seed value.
+     * This is a helper method that will produce the same result as:
+     *
+     * <pre>
+     * int seed = 0xe17a1465;
+     * int hash = MurmurHash2.hash64(data, length, seed);
+     * </pre>
+     *
+     * @param data The input byte array
+     * @param length The length of the array
+     * @return The 64-bit hash
+     * @see #hash64(byte[], int, int)
+     */
+    public static long hash64(final byte[] data, final int length) {
+        return hash64(data, length, 0xe17a1465);
+    }
+
     /**
      * Generates a 64-bit hash from byte array of the given length and seed.
      *
@@ -223,24 +269,6 @@ public final class MurmurHash2 {
         return h;
     }
 
-    /**
-     * Generates a 64-bit hash from byte array with given length and a default seed value.
-     * This is a helper method that will produce the same result as:
-     *
-     * <pre>
-     * int seed = 0xe17a1465;
-     * int hash = MurmurHash2.hash64(data, length, seed);
-     * </pre>
-     *
-     * @param data The input byte array
-     * @param length The length of the array
-     * @return The 64-bit hash
-     * @see #hash64(byte[], int, int)
-     */
-    public static long hash64(final byte[] data, final int length) {
-        return hash64(data, length, 0xe17a1465);
-    }
-
     /**
      * Generates a 64-bit hash from a string with a default seed.
      * <p>
@@ -287,35 +315,7 @@ public final class MurmurHash2 {
         return hash64(text.substring(from, from + length));
     }
 
-    /**
-     * Gets the little-endian int from 4 bytes starting at the specified index.
-     *
-     * @param data The data
-     * @param index The index
-     * @return The little-endian int
-     */
-    private static int getLittleEndianInt(final byte[] data, final int index) {
-        return data[index    ] & 0xff |
-               (data[index + 1] & 0xff) <<  8 |
-               (data[index + 2] & 0xff) << 16 |
-               (data[index + 3] & 0xff) << 24;
-    }
-
-    /**
-     * Gets the little-endian long from 8 bytes starting at the specified index.
-     *
-     * @param data The data
-     * @param index The index
-     * @return The little-endian long
-     */
-    private static long getLittleEndianLong(final byte[] data, final int index) {
-        return (long) data[index    ] & 0xff |
-               ((long) data[index + 1] & 0xff) <<  8 |
-               ((long) data[index + 2] & 0xff) << 16 |
-               ((long) data[index + 3] & 0xff) << 24 |
-               ((long) data[index + 4] & 0xff) << 32 |
-               ((long) data[index + 5] & 0xff) << 40 |
-               ((long) data[index + 6] & 0xff) << 48 |
-               ((long) data[index + 7] & 0xff) << 56;
+    /** No instance methods. */
+    private MurmurHash2() {
     }
 }
diff --git a/src/main/java/org/apache/commons/codec/digest/MurmurHash3.java b/src/main/java/org/apache/commons/codec/digest/MurmurHash3.java
index 24ca412a..ff80c1f9 100644
--- a/src/main/java/org/apache/commons/codec/digest/MurmurHash3.java
+++ b/src/main/java/org/apache/commons/codec/digest/MurmurHash3.java
@@ -57,6 +57,238 @@ import org.apache.commons.codec.binary.StringUtils;
  */
 public final class MurmurHash3 {
 
+    /**
+     * Generates 32-bit hash from input bytes. Bytes can be added incrementally and the new
+     * hash computed.
+     *
+     * <p>This is an implementation of the 32-bit hash function {@code MurmurHash3_x86_32}
+     * from Austin Appleby's original MurmurHash3 {@code c++} code in SMHasher.</p>
+     *
+     * <p>This implementation contains a sign-extension bug in the finalization step of
+     * any bytes left over from dividing the length by 4. This manifests if any of these
+     * bytes are negative.</p>
+     *
+     * @deprecated Use IncrementalHash32x86. This corrects the processing of trailing bytes.
+     */
+    @Deprecated
+    public static class IncrementalHash32 extends IncrementalHash32x86 {
+
+        /**
+         * {@inheritDoc}
+         *
+         * <p>This implementation contains a sign-extension bug in the finalization step of
+         * any bytes left over from dividing the length by 4. This manifests if any of these
+         * bytes are negative.<p>
+         *
+         * @deprecated Use IncrementalHash32x86. This corrects the processing of trailing bytes.
+         */
+        @Override
+        @Deprecated
+        int finalise(final int hash, final int unprocessedLength, final byte[] unprocessed, final int totalLen) {
+            int result = hash;
+            // ************
+            // Note: This fails to apply masking using 0xff to the 3 remaining bytes.
+            // ************
+            int k1 = 0;
+            switch (unprocessedLength) {
+            case 3:
+                k1 ^= unprocessed[2] << 16;
+            case 2:
+                k1 ^= unprocessed[1] << 8;
+            case 1:
+                k1 ^= unprocessed[0];
+
+                // mix functions
+                k1 *= C1_32;
+                k1 = Integer.rotateLeft(k1, R1_32);
+                k1 *= C2_32;
+                result ^= k1;
+            }
+
+            // finalization
+            result ^= totalLen;
+            return fmix32(result);
+        }
+    }
+
+    /**
+     * Generates 32-bit hash from input bytes. Bytes can be added incrementally and the new
+     * hash computed.
+     *
+     * <p>This is an implementation of the 32-bit hash function {@code MurmurHash3_x86_32}
+     * from Austin Appleby's original MurmurHash3 {@code c++} code in SMHasher.</p>
+     *
+     * @since 1.14
+     */
+    public static class IncrementalHash32x86 {
+
+        /** The size of byte blocks that are processed together. */
+        private static final int BLOCK_SIZE = 4;
+
+        /**
+         * Combines the bytes using an Or operation ({@code | } in a little-endian representation
+         * of a 32-bit integer; byte 1 will be the least significant byte, byte 4 the most
+         * significant.
+         *
+         * @param b1 The first byte
+         * @param b2 The second byte
+         * @param b3 The third byte
+         * @param b4 The fourth byte
+         * @return The 32-bit integer
+         */
+        private static int orBytes(final byte b1, final byte b2, final byte b3, final byte b4) {
+            return b1 & 0xff | (b2 & 0xff) << 8 | (b3 & 0xff) << 16 | (b4 & 0xff) << 24;
+        }
+
+        /** Up to 3 unprocessed bytes from input data. */
+        private final byte[] unprocessed = new byte[3];
+
+        /** The number of unprocessed bytes in the tail data. */
+        private int unprocessedLength;
+
+        /** The total number of input bytes added since the start. */
+        private int totalLen;
+
+        /**
+         * The current running hash.
+         * This must be finalised to generate the 32-bit hash value.
+         */
+        private int hash;
+
+        /**
+         * Adds the byte array to the current incremental hash.
+         *
+         * @param data The input byte array
+         * @param offset The offset of data
+         * @param length The length of array
+         */
+        public final void add(final byte[] data, final int offset, final int length) {
+            if (length <= 0) {
+                // Nothing to add
+                return;
+            }
+            totalLen += length;
+
+            // Process the bytes in blocks of 4.
+            // New bytes must be added to any current unprocessed bytes,
+            // then processed in blocks of 4 and the remaining bytes saved:
+            //
+            //    |--|---------------------------|--|
+            // unprocessed
+            //                main block
+            //                                remaining
+
+            // Check if the unprocessed bytes and new bytes can fill a block of 4.
+            // Make this overflow safe in the event that length is Integer.MAX_VALUE.
+            // Equivalent to: (unprocessedLength + length < BLOCK_SIZE)
+            if (unprocessedLength + length - BLOCK_SIZE < 0) {
+                // Not enough so add to the unprocessed bytes
+                System.arraycopy(data, offset, unprocessed, unprocessedLength, length);
+                unprocessedLength += length;
+                return;
+            }
+
+            // Combine unprocessed bytes with new bytes.
+            final int newOffset;
+            final int newLength;
+            if (unprocessedLength > 0) {
+                int k = -1;
+                switch (unprocessedLength) {
+                case 1:
+                    k = orBytes(unprocessed[0], data[offset], data[offset + 1], data[offset + 2]);
+                    break;
+                case 2:
+                    k = orBytes(unprocessed[0], unprocessed[1], data[offset], data[offset + 1]);
+                    break;
+                case 3:
+                    k = orBytes(unprocessed[0], unprocessed[1], unprocessed[2], data[offset]);
+                    break;
+                default:
+                    throw new IllegalStateException("Unprocessed length should be 1, 2, or 3: " + unprocessedLength);
+                }
+                hash = mix32(k, hash);
+                // Update the offset and length
+                final int consumed = BLOCK_SIZE - unprocessedLength;
+                newOffset = offset + consumed;
+                newLength = length - consumed;
+            } else {
+                newOffset = offset;
+                newLength = length;
+            }
+
+            // Main processing of blocks of 4 bytes
+            final int nblocks = newLength >> 2;
+
+            for (int i = 0; i < nblocks; i++) {
+                final int index = newOffset + (i << 2);
+                final int k = getLittleEndianInt(data, index);
+                hash = mix32(k, hash);
+            }
+
+            // Save left-over unprocessed bytes
+            final int consumed = nblocks << 2;
+            unprocessedLength = newLength - consumed;
+            if (unprocessedLength != 0) {
+                System.arraycopy(data, newOffset + consumed, unprocessed, 0, unprocessedLength);
+            }
+        }
+
+        /**
+         * Generates the 32-bit hash value. Repeat calls to this method with no additional data
+         * will generate the same hash value.
+         *
+         * @return The 32-bit hash
+         */
+        public final int end() {
+            // Allow calling end() again after adding no data to return the same result.
+            return finalise(hash, unprocessedLength, unprocessed, totalLen);
+        }
+
+        /**
+         * Finalizes the running hash to the output 32-bit hash by processing remaining bytes
+         * and performing final mixing.
+         *
+         * @param hash The running hash
+         * @param unprocessedLength The number of unprocessed bytes in the tail data.
+         * @param unprocessed Up to 3 unprocessed bytes from input data.
+         * @param totalLen The total number of input bytes added since the start.
+         * @return The 32-bit hash
+         */
+        int finalise(final int hash, final int unprocessedLength, final byte[] unprocessed, final int totalLen) {
+            int result = hash;
+            int k1 = 0;
+            switch (unprocessedLength) {
+            case 3:
+                k1 ^= (unprocessed[2] & 0xff) << 16;
+            case 2:
+                k1 ^= (unprocessed[1] & 0xff) << 8;
+            case 1:
+                k1 ^= unprocessed[0] & 0xff;
+
+                // mix functions
+                k1 *= C1_32;
+                k1 = Integer.rotateLeft(k1, R1_32);
+                k1 *= C2_32;
+                result ^= k1;
+            }
+
+            // finalization
+            result ^= totalLen;
+            return fmix32(result);
+        }
+
+        /**
+         * Starts a new incremental hash.
+         *
+         * @param seed The initial seed value
+         */
+        public final void start(final int seed) {
+            // Reset
+            unprocessedLength = totalLen = 0;
+            this.hash = seed;
+        }
+    }
+
     /**
      * A random number to use for a hash code.
      *
@@ -64,21 +296,19 @@ public final class MurmurHash3 {
      */
     @Deprecated
     public static final long NULL_HASHCODE = 2862933555777941757L;
-
     /**
      * A default seed to use for the murmur hash algorithm.
      * Has the value {@code 104729}.
      */
     public static final int DEFAULT_SEED = 104729;
-
     // Constants for 32-bit variant
     private static final int C1_32 = 0xcc9e2d51;
     private static final int C2_32 = 0x1b873593;
     private static final int R1_32 = 15;
     private static final int R2_32 = 13;
+
     private static final int M_32 = 5;
     private static final int N_32 = 0xe6546b64;
-
     // Constants for 128-bit variant
     private static final long C1 = 0x87c37b91114253d5L;
     private static final long C2 = 0x4cf5ad432745937fL;
@@ -86,290 +316,366 @@ public final class MurmurHash3 {
     private static final int R2 = 27;
     private static final int R3 = 33;
     private static final int M = 5;
+
     private static final int N1 = 0x52dce729;
+
     private static final int N2 = 0x38495ab5;
 
-    /** No instance methods. */
-    private MurmurHash3() {
+    /**
+     * Performs the final avalanche mix step of the 32-bit hash function {@code MurmurHash3_x86_32}.
+     *
+     * @param hash The current hash
+     * @return The final hash
+     */
+    private static int fmix32(int hash) {
+        hash ^= hash >>> 16;
+        hash *= 0x85ebca6b;
+        hash ^= hash >>> 13;
+        hash *= 0xc2b2ae35;
+        hash ^= hash >>> 16;
+        return hash;
     }
 
     /**
-     * Generates 32-bit hash from two longs with a default seed value.
-     * This is a helper method that will produce the same result as:
+     * Performs the final avalanche mix step of the 64-bit hash function {@code MurmurHash3_x64_128}.
      *
-     * <pre>
-     * int offset = 0;
-     * int seed = 104729;
-     * int hash = MurmurHash3.hash32x86(ByteBuffer.allocate(16)
-     *                                            .putLong(data1)
-     *                                            .putLong(data2)
-     *                                            .array(), offset, 16, seed);
-     * </pre>
-     *
-     * @param data1 The first long to hash
-     * @param data2 The second long to hash
-     * @return The 32-bit hash
-     * @see #hash32x86(byte[], int, int, int)
+     * @param hash The current hash
+     * @return The final hash
      */
-    public static int hash32(final long data1, final long data2) {
-        return hash32(data1, data2, DEFAULT_SEED);
+    private static long fmix64(long hash) {
+        hash ^= hash >>> 33;
+        hash *= 0xff51afd7ed558ccdL;
+        hash ^= hash >>> 33;
+        hash *= 0xc4ceb9fe1a85ec53L;
+        hash ^= hash >>> 33;
+        return hash;
     }
 
     /**
-     * Generates 32-bit hash from two longs with the given seed.
-     * This is a helper method that will produce the same result as:
-     *
-     * <pre>
-     * int offset = 0;
-     * int hash = MurmurHash3.hash32x86(ByteBuffer.allocate(16)
-     *                                            .putLong(data1)
-     *                                            .putLong(data2)
-     *                                            .array(), offset, 16, seed);
-     * </pre>
+     * Gets the little-endian int from 4 bytes starting at the specified index.
      *
-     * @param data1 The first long to hash
-     * @param data2 The second long to hash
-     * @param seed The initial seed value
-     * @return The 32-bit hash
-     * @see #hash32x86(byte[], int, int, int)
+     * @param data The data
+     * @param index The index
+     * @return The little-endian int
      */
-    public static int hash32(final long data1, final long data2, final int seed) {
-        int hash = seed;
-        final long r0 = Long.reverseBytes(data1);
-        final long r1 = Long.reverseBytes(data2);
-
-        hash = mix32((int) r0, hash);
-        hash = mix32((int) (r0 >>> 32), hash);
-        hash = mix32((int) r1, hash);
-        hash = mix32((int) (r1 >>> 32), hash);
-
-        hash ^= Long.BYTES * 2;
-        return fmix32(hash);
+    private static int getLittleEndianInt(final byte[] data, final int index) {
+        return data[index    ] & 0xff |
+               (data[index + 1] & 0xff) <<  8 |
+               (data[index + 2] & 0xff) << 16 |
+               (data[index + 3] & 0xff) << 24;
     }
 
     /**
-     * Generates 32-bit hash from a long with a default seed value.
-     * This is a helper method that will produce the same result as:
-     *
-     * <pre>
-     * int offset = 0;
-     * int seed = 104729;
-     * int hash = MurmurHash3.hash32x86(ByteBuffer.allocate(8)
-     *                                            .putLong(data)
-     *                                            .array(), offset, 8, seed);
-     * </pre>
+     * Gets the little-endian long from 8 bytes starting at the specified index.
      *
-     * @param data The long to hash
-     * @return The 32-bit hash
-     * @see #hash32x86(byte[], int, int, int)
+     * @param data The data
+     * @param index The index
+     * @return The little-endian long
      */
-    public static int hash32(final long data) {
-        return hash32(data, DEFAULT_SEED);
+    private static long getLittleEndianLong(final byte[] data, final int index) {
+        return (long) data[index    ] & 0xff |
+               ((long) data[index + 1] & 0xff) <<  8 |
+               ((long) data[index + 2] & 0xff) << 16 |
+               ((long) data[index + 3] & 0xff) << 24 |
+               ((long) data[index + 4] & 0xff) << 32 |
+               ((long) data[index + 5] & 0xff) << 40 |
+               ((long) data[index + 6] & 0xff) << 48 |
+               ((long) data[index + 7] & 0xff) << 56;
     }
 
     /**
-     * Generates 32-bit hash from a long with the given seed.
+     * Generates 128-bit hash from the byte array with a default seed.
      * This is a helper method that will produce the same result as:
      *
      * <pre>
      * int offset = 0;
-     * int hash = MurmurHash3.hash32x86(ByteBuffer.allocate(8)
-     *                                            .putLong(data)
-     *                                            .array(), offset, 8, seed);
+     * int seed = 104729;
+     * int hash = MurmurHash3.hash128(data, offset, data.length, seed);
      * </pre>
      *
-     * @param data The long to hash
-     * @param seed The initial seed value
-     * @return The 32-bit hash
-     * @see #hash32x86(byte[], int, int, int)
+     * <p>Note: The sign extension bug in {@link #hash128(byte[], int, int, int)} does not effect
+     * this result as the default seed is positive.</p>
+     *
+     * @param data The input byte array
+     * @return The 128-bit hash (2 longs)
+     * @see #hash128(byte[], int, int, int)
      */
-    public static int hash32(final long data, final int seed) {
-        int hash = seed;
-        final long r0 = Long.reverseBytes(data);
-
-        hash = mix32((int) r0, hash);
-        hash = mix32((int) (r0 >>> 32), hash);
-
-        hash ^= Long.BYTES;
-        return fmix32(hash);
+    public static long[] hash128(final byte[] data) {
+        return hash128(data, 0, data.length, DEFAULT_SEED);
     }
 
     /**
-     * Generates 32-bit hash from the byte array with a default seed.
-     * This is a helper method that will produce the same result as:
+     * Generates 128-bit hash from the byte array with the given offset, length and seed.
      *
-     * <pre>
-     * int offset = 0;
-     * int seed = 104729;
-     * int hash = MurmurHash3.hash32(data, offset, data.length, seed);
-     * </pre>
+     * <p>This is an implementation of the 128-bit hash function {@code MurmurHash3_x64_128}
+     * from Austin Appleby's original MurmurHash3 {@code c++} code in SMHasher.</p>
      *
-     * <p>This implementation contains a sign-extension bug in the finalization step of
-     * any bytes left over from dividing the length by 4. This manifests if any of these
-     * bytes are negative.</p>
+     * <p>This implementation contains a sign-extension bug in the seed initialization.
+     * This manifests if the seed is negative.</p>
      *
      * @param data The input byte array
-     * @return The 32-bit hash
-     * @see #hash32(byte[], int, int, int)
-     * @deprecated Use {@link #hash32x86(byte[], int, int, int)}. This corrects the processing of trailing bytes.
+     * @param offset The first element of array
+     * @param length The length of array
+     * @param seed The initial seed value
+     * @return The 128-bit hash (2 longs)
+     * @deprecated Use {@link #hash128x64(byte[], int, int, int)}. This corrects the seed initialization.
      */
     @Deprecated
-    public static int hash32(final byte[] data) {
-        return hash32(data, 0, data.length, DEFAULT_SEED);
+    public static long[] hash128(final byte[] data, final int offset, final int length, final int seed) {
+        // ************
+        // Note: This deliberately fails to apply masking using 0xffffffffL to the seed
+        // to maintain behavioral compatibility with the original version.
+        // The implicit conversion to a long will extend a negative sign
+        // bit through the upper 32-bits of the long seed. These should be zero.
+        // ************
+        return hash128x64Internal(data, offset, length, seed);
     }
 
     /**
-     * Generates 32-bit hash from a string with a default seed.
+     * Generates 128-bit hash from a string with a default seed.
      * <p>
      * Before 1.14 the string was converted using default encoding.
      * Since 1.14 the string is converted to bytes using UTF-8 encoding.
      * </p>
+     * <p>
      * This is a helper method that will produce the same result as:
+     * </p>
      *
      * <pre>
      * int offset = 0;
      * int seed = 104729;
      * byte[] bytes = data.getBytes(StandardCharsets.UTF_8);
-     * int hash = MurmurHash3.hash32(bytes, offset, bytes.length, seed);
+     * int hash = MurmurHash3.hash128(bytes, offset, bytes.length, seed);
      * </pre>
      *
-     * <p>This implementation contains a sign-extension bug in the finalization step of
-     * any bytes left over from dividing the length by 4. This manifests if any of these
-     * bytes are negative.</p>
+     * <p>Note: The sign extension bug in {@link #hash128(byte[], int, int, int)} does not effect
+     * this result as the default seed is positive.</p>
      *
-     * @param data The input string
-     * @return The 32-bit hash
-     * @see #hash32(byte[], int, int, int)
-     * @deprecated Use {@link #hash32x86(byte[], int, int, int)} with the bytes returned from
-     * {@link String#getBytes(java.nio.charset.Charset)}. This corrects the processing of trailing bytes.
+     * @param data The input String
+     * @return The 128-bit hash (2 longs)
+     * @see #hash128(byte[], int, int, int)
+     * @deprecated Use {@link #hash128x64(byte[])} using the bytes returned from
+     * {@link String#getBytes(java.nio.charset.Charset)}.
      */
     @Deprecated
-    public static int hash32(final String data) {
+    public static long[] hash128(final String data) {
         final byte[] bytes = StringUtils.getBytesUtf8(data);
-        return hash32(bytes, 0, bytes.length, DEFAULT_SEED);
+        return hash128(bytes, 0, bytes.length, DEFAULT_SEED);
     }
 
     /**
-     * Generates 32-bit hash from the byte array with the given length and a default seed.
+     * Generates 128-bit hash from the byte array with a seed of zero.
      * This is a helper method that will produce the same result as:
      *
      * <pre>
      * int offset = 0;
-     * int seed = 104729;
-     * int hash = MurmurHash3.hash32(data, offset, length, seed);
+     * int seed = 0;
+     * int hash = MurmurHash3.hash128x64(data, offset, data.length, seed);
      * </pre>
      *
-     * <p>This implementation contains a sign-extension bug in the finalization step of
-     * any bytes left over from dividing the length by 4. This manifests if any of these
-     * bytes are negative.</p>
-     *
      * @param data The input byte array
-     * @param length The length of array
-     * @return The 32-bit hash
-     * @see #hash32(byte[], int, int, int)
-     * @deprecated Use {@link #hash32x86(byte[], int, int, int)}. This corrects the processing of trailing bytes.
+     * @return The 128-bit hash (2 longs)
+     * @see #hash128x64(byte[], int, int, int)
+     * @since 1.14
      */
-    @Deprecated
-    public static int hash32(final byte[] data, final int length) {
-        return hash32(data, length, DEFAULT_SEED);
+    public static long[] hash128x64(final byte[] data) {
+        return hash128x64(data, 0, data.length, 0);
     }
 
     /**
-     * Generates 32-bit hash from the byte array with the given length and seed. This is a
-     * helper method that will produce the same result as:
-     *
-     * <pre>
-     * int offset = 0;
-     * int hash = MurmurHash3.hash32(data, offset, length, seed);
-     * </pre>
+     * Generates 128-bit hash from the byte array with the given offset, length and seed.
      *
-     * <p>This implementation contains a sign-extension bug in the finalization step of
-     * any bytes left over from dividing the length by 4. This manifests if any of these
-     * bytes are negative.</p>
+     * <p>This is an implementation of the 128-bit hash function {@code MurmurHash3_x64_128}
+     * from Austin Appleby's original MurmurHash3 {@code c++} code in SMHasher.</p>
      *
      * @param data The input byte array
+     * @param offset The first element of array
      * @param length The length of array
      * @param seed The initial seed value
-     * @return The 32-bit hash
-     * @see #hash32(byte[], int, int, int)
-     * @deprecated Use {@link #hash32x86(byte[], int, int, int)}. This corrects the processing of trailing bytes.
+     * @return The 128-bit hash (2 longs)
+     * @since 1.14
      */
-    @Deprecated
-    public static int hash32(final byte[] data, final int length, final int seed) {
-        return hash32(data, 0, length, seed);
+    public static long[] hash128x64(final byte[] data, final int offset, final int length, final int seed) {
+        // Use an unsigned 32-bit integer as the seed
+        return hash128x64Internal(data, offset, length, seed & 0xffffffffL);
     }
 
     /**
-     * Generates 32-bit hash from the byte array with the given offset, length and seed.
+     * Generates 128-bit hash from the byte array with the given offset, length and seed.
      *
-     * <p>This is an implementation of the 32-bit hash function {@code MurmurHash3_x86_32}
+     * <p>This is an implementation of the 128-bit hash function {@code MurmurHash3_x64_128}
      * from Austin Appleby's original MurmurHash3 {@code c++} code in SMHasher.</p>
      *
-     * <p>This implementation contains a sign-extension bug in the finalization step of
-     * any bytes left over from dividing the length by 4. This manifests if any of these
-     * bytes are negative.</p>
-     *
      * @param data The input byte array
-     * @param offset The offset of data
+     * @param offset The first element of array
      * @param length The length of array
      * @param seed The initial seed value
-     * @return The 32-bit hash
-     * @deprecated Use {@link #hash32x86(byte[], int, int, int)}. This corrects the processing of trailing bytes.
+     * @return The 128-bit hash (2 longs)
      */
-    @Deprecated
-    public static int hash32(final byte[] data, final int offset, final int length, final int seed) {
-        int hash = seed;
-        final int nblocks = length >> 2;
+    private static long[] hash128x64Internal(final byte[] data, final int offset, final int length, final long seed) {
+        long h1 = seed;
+        long h2 = seed;
+        final int nblocks = length >> 4;
 
         // body
         for (int i = 0; i < nblocks; i++) {
-            final int index = offset + (i << 2);
-            final int k = getLittleEndianInt(data, index);
-            hash = mix32(k, hash);
-        }
+            final int index = offset + (i << 4);
+            long k1 = getLittleEndianLong(data, index);
+            long k2 = getLittleEndianLong(data, index + 8);
 
-        // tail
-        // ************
-        // Note: This fails to apply masking using 0xff to the 3 remaining bytes.
-        // ************
-        final int index = offset + (nblocks << 2);
-        int k1 = 0;
-        switch (offset + length - index) {
+            // mix functions for k1
+            k1 *= C1;
+            k1 = Long.rotateLeft(k1, R1);
+            k1 *= C2;
+            h1 ^= k1;
+            h1 = Long.rotateLeft(h1, R2);
+            h1 += h2;
+            h1 = h1 * M + N1;
+
+            // mix functions for k2
+            k2 *= C2;
+            k2 = Long.rotateLeft(k2, R3);
+            k2 *= C1;
+            h2 ^= k2;
+            h2 = Long.rotateLeft(h2, R1);
+            h2 += h1;
+            h2 = h2 * M + N2;
+        }
+
+        // tail
+        long k1 = 0;
+        long k2 = 0;
+        final int index = offset + (nblocks << 4);
+        switch (offset + length - index) {
+        case 15:
+            k2 ^= ((long) data[index + 14] & 0xff) << 48;
+        case 14:
+            k2 ^= ((long) data[index + 13] & 0xff) << 40;
+        case 13:
+            k2 ^= ((long) data[index + 12] & 0xff) << 32;
+        case 12:
+            k2 ^= ((long) data[index + 11] & 0xff) << 24;
+        case 11:
+            k2 ^= ((long) data[index + 10] & 0xff) << 16;
+        case 10:
+            k2 ^= ((long) data[index + 9] & 0xff) << 8;
+        case 9:
+            k2 ^= data[index + 8] & 0xff;
+            k2 *= C2;
+            k2 = Long.rotateLeft(k2, R3);
+            k2 *= C1;
+            h2 ^= k2;
+
+        case 8:
+            k1 ^= ((long) data[index + 7] & 0xff) << 56;
+        case 7:
+            k1 ^= ((long) data[index + 6] & 0xff) << 48;
+        case 6:
+            k1 ^= ((long) data[index + 5] & 0xff) << 40;
+        case 5:
+            k1 ^= ((long) data[index + 4] & 0xff) << 32;
+        case 4:
+            k1 ^= ((long) data[index + 3] & 0xff) << 24;
         case 3:
-            k1 ^= data[index + 2] << 16;
+            k1 ^= ((long) data[index + 2] & 0xff) << 16;
         case 2:
-            k1 ^= data[index + 1] << 8;
+            k1 ^= ((long) data[index + 1] & 0xff) << 8;
         case 1:
-            k1 ^= data[index];
-
-            // mix functions
-            k1 *= C1_32;
-            k1 = Integer.rotateLeft(k1, R1_32);
-            k1 *= C2_32;
-            hash ^= k1;
+            k1 ^= data[index] & 0xff;
+            k1 *= C1;
+            k1 = Long.rotateLeft(k1, R1);
+            k1 *= C2;
+            h1 ^= k1;
         }
 
-        hash ^= length;
-        return fmix32(hash);
+        // finalization
+        h1 ^= length;
+        h2 ^= length;
+
+        h1 += h2;
+        h2 += h1;
+
+        h1 = fmix64(h1);
+        h2 = fmix64(h2);
+
+        h1 += h2;
+        h2 += h1;
+
+        return new long[] { h1, h2 };
     }
 
     /**
-     * Generates 32-bit hash from the byte array with a seed of zero.
+     * Generates 32-bit hash from the byte array with a default seed.
      * This is a helper method that will produce the same result as:
      *
      * <pre>
      * int offset = 0;
-     * int seed = 0;
-     * int hash = MurmurHash3.hash32x86(data, offset, data.length, seed);
+     * int seed = 104729;
+     * int hash = MurmurHash3.hash32(data, offset, data.length, seed);
      * </pre>
      *
+     * <p>This implementation contains a sign-extension bug in the finalization step of
+     * any bytes left over from dividing the length by 4. This manifests if any of these
+     * bytes are negative.</p>
+     *
      * @param data The input byte array
      * @return The 32-bit hash
-     * @see #hash32x86(byte[], int, int, int)
-     * @since 1.14
+     * @see #hash32(byte[], int, int, int)
+     * @deprecated Use {@link #hash32x86(byte[], int, int, int)}. This corrects the processing of trailing bytes.
      */
-    public static int hash32x86(final byte[] data) {
-        return hash32x86(data, 0, data.length, 0);
+    @Deprecated
+    public static int hash32(final byte[] data) {
+        return hash32(data, 0, data.length, DEFAULT_SEED);
+    }
+
+    /**
+     * Generates 32-bit hash from the byte array with the given length and a default seed.
+     * This is a helper method that will produce the same result as:
+     *
+     * <pre>
+     * int offset = 0;
+     * int seed = 104729;
+     * int hash = MurmurHash3.hash32(data, offset, length, seed);
+     * </pre>
+     *
+     * <p>This implementation contains a sign-extension bug in the finalization step of
+     * any bytes left over from dividing the length by 4. This manifests if any of these
+     * bytes are negative.</p>
+     *
+     * @param data The input byte array
+     * @param length The length of array
+     * @return The 32-bit hash
+     * @see #hash32(byte[], int, int, int)
+     * @deprecated Use {@link #hash32x86(byte[], int, int, int)}. This corrects the processing of trailing bytes.
+     */
+    @Deprecated
+    public static int hash32(final byte[] data, final int length) {
+        return hash32(data, length, DEFAULT_SEED);
+    }
+
+    /**
+     * Generates 32-bit hash from the byte array with the given length and seed. This is a
+     * helper method that will produce the same result as:
+     *
+     * <pre>
+     * int offset = 0;
+     * int hash = MurmurHash3.hash32(data, offset, length, seed);
+     * </pre>
+     *
+     * <p>This implementation contains a sign-extension bug in the finalization step of
+     * any bytes left over from dividing the length by 4. This manifests if any of these
+     * bytes are negative.</p>
+     *
+     * @param data The input byte array
+     * @param length The length of array
+     * @param seed The initial seed value
+     * @return The 32-bit hash
+     * @see #hash32(byte[], int, int, int)
+     * @deprecated Use {@link #hash32x86(byte[], int, int, int)}. This corrects the processing of trailing bytes.
+     */
+    @Deprecated
+    public static int hash32(final byte[] data, final int length, final int seed) {
+        return hash32(data, 0, length, seed);
     }
 
     /**
@@ -378,14 +684,19 @@ public final class MurmurHash3 {
      * <p>This is an implementation of the 32-bit hash function {@code MurmurHash3_x86_32}
      * from Austin Appleby's original MurmurHash3 {@code c++} code in SMHasher.</p>
      *
+     * <p>This implementation contains a sign-extension bug in the finalization step of
+     * any bytes left over from dividing the length by 4. This manifests if any of these
+     * bytes are negative.</p>
+     *
      * @param data The input byte array
      * @param offset The offset of data
      * @param length The length of array
      * @param seed The initial seed value
      * @return The 32-bit hash
-     * @since 1.14
+     * @deprecated Use {@link #hash32x86(byte[], int, int, int)}. This corrects the processing of trailing bytes.
      */
-    public static int hash32x86(final byte[] data, final int offset, final int length, final int seed) {
+    @Deprecated
+    public static int hash32(final byte[] data, final int offset, final int length, final int seed) {
         int hash = seed;
         final int nblocks = length >> 2;
 
@@ -397,15 +708,18 @@ public final class MurmurHash3 {
         }
 
         // tail
+        // ************
+        // Note: This fails to apply masking using 0xff to the 3 remaining bytes.
+        // ************
         final int index = offset + (nblocks << 2);
         int k1 = 0;
         switch (offset + length - index) {
         case 3:
-            k1 ^= (data[index + 2] & 0xff) << 16;
+            k1 ^= data[index + 2] << 16;
         case 2:
-            k1 ^= (data[index + 1] & 0xff) << 8;
+            k1 ^= data[index + 1] << 8;
         case 1:
-            k1 ^= data[index] & 0xff;
+            k1 ^= data[index];
 
             // mix functions
             k1 *= C1_32;
@@ -419,137 +733,200 @@ public final class MurmurHash3 {
     }
 
     /**
-     * Generates 64-bit hash from a long with a default seed.
-     *
-     * <p><strong>This is not part of the original MurmurHash3 {@code c++} implementation.</strong></p>
-     *
-     * <p>This is a Murmur3-like 64-bit variant.
-     * The method does not produce the same result as either half of the hash bytes from
-     * {@linkplain #hash128x64(byte[])} with the same byte data from the {@code long}.
-     * This method will be removed in a future release.</p>
-     *
-     * <p>Note: The sign extension bug in {@link #hash64(byte[], int, int, int)} does not effect
-     * this result as the default seed is positive.</p>
-     *
-     * <p>This is a helper method that will produce the same result as:</p>
+     * Generates 32-bit hash from a long with a default seed value.
+     * This is a helper method that will produce the same result as:
      *
      * <pre>
      * int offset = 0;
      * int seed = 104729;
-     * long hash = MurmurHash3.hash64(ByteBuffer.allocate(8)
-     *                                          .putLong(data)
-     *                                          .array(), offset, 8, seed);
+     * int hash = MurmurHash3.hash32x86(ByteBuffer.allocate(8)
+     *                                            .putLong(data)
+     *                                            .array(), offset, 8, seed);
      * </pre>
      *
      * @param data The long to hash
-     * @return The 64-bit hash
-     * @see #hash64(byte[], int, int, int)
-     * @deprecated Not part of the MurmurHash3 implementation.
-     * Use half of the hash bytes from {@link #hash128x64(byte[])} with the bytes from the {@code long}.
+     * @return The 32-bit hash
+     * @see #hash32x86(byte[], int, int, int)
      */
-    @Deprecated
-    public static long hash64(final long data) {
-        long hash = DEFAULT_SEED;
-        long k = Long.reverseBytes(data);
-        // mix functions
-        k *= C1;
-        k = Long.rotateLeft(k, R1);
-        k *= C2;
-        hash ^= k;
-        hash = Long.rotateLeft(hash, R2) * M + N1;
-        // finalization
-        hash ^= Long.BYTES;
-        hash = fmix64(hash);
-        return hash;
+    public static int hash32(final long data) {
+        return hash32(data, DEFAULT_SEED);
     }
 
     /**
-     * Generates 64-bit hash from an int with a default seed.
-     *
-     * <p><strong>This is not part of the original MurmurHash3 {@code c++} implementation.</strong></p>
-     *
-     * <p>This is a Murmur3-like 64-bit variant.
-     * The method does not produce the same result as either half of the hash bytes from
-     * {@linkplain #hash128x64(byte[])} with the same byte data from the {@code int}.
-     * This method will be removed in a future release.</p>
-     *
-     * <p>Note: The sign extension bug in {@link #hash64(byte[], int, int, int)} does not effect
-     * this result as the default seed is positive.</p>
-     *
-     * <p>This is a helper method that will produce the same result as:</p>
+     * Generates 32-bit hash from a long with the given seed.
+     * This is a helper method that will produce the same result as:
      *
      * <pre>
      * int offset = 0;
-     * int seed = 104729;
-     * long hash = MurmurHash3.hash64(ByteBuffer.allocate(4)
-     *                                          .putInt(data)
-     *                                          .array(), offset, 4, seed);
+     * int hash = MurmurHash3.hash32x86(ByteBuffer.allocate(8)
+     *                                            .putLong(data)
+     *                                            .array(), offset, 8, seed);
      * </pre>
      *
-     * @param data The int to hash
-     * @return The 64-bit hash
-     * @see #hash64(byte[], int, int, int)
-     * @deprecated Not part of the MurmurHash3 implementation.
-     * Use half of the hash bytes from {@link #hash128x64(byte[])} with the bytes from the {@code int}.
+     * @param data The long to hash
+     * @param seed The initial seed value
+     * @return The 32-bit hash
+     * @see #hash32x86(byte[], int, int, int)
      */
-    @Deprecated
-    public static long hash64(final int data) {
-        long k1 = Integer.reverseBytes(data) & -1L >>> 32;
-        long hash = DEFAULT_SEED;
-        k1 *= C1;
-        k1 = Long.rotateLeft(k1, R1);
-        k1 *= C2;
-        hash ^= k1;
-        // finalization
-        hash ^= Integer.BYTES;
-        hash = fmix64(hash);
-        return hash;
+    public static int hash32(final long data, final int seed) {
+        int hash = seed;
+        final long r0 = Long.reverseBytes(data);
+
+        hash = mix32((int) r0, hash);
+        hash = mix32((int) (r0 >>> 32), hash);
+
+        hash ^= Long.BYTES;
+        return fmix32(hash);
     }
 
     /**
-     * Generates 64-bit hash from a short with a default seed.
+     * Generates 32-bit hash from two longs with a default seed value.
+     * This is a helper method that will produce the same result as:
      *
-     * <p><strong>This is not part of the original MurmurHash3 {@code c++} implementation.</strong></p>
+     * <pre>
+     * int offset = 0;
+     * int seed = 104729;
+     * int hash = MurmurHash3.hash32x86(ByteBuffer.allocate(16)
+     *                                            .putLong(data1)
+     *                                            .putLong(data2)
+     *                                            .array(), offset, 16, seed);
+     * </pre>
      *
-     * <p>This is a Murmur3-like 64-bit variant.
-     * The method does not produce the same result as either half of the hash bytes from
-     * {@linkplain #hash128x64(byte[])} with the same byte data from the {@code short}.
-     * This method will be removed in a future release.</p>
+     * @param data1 The first long to hash
+     * @param data2 The second long to hash
+     * @return The 32-bit hash
+     * @see #hash32x86(byte[], int, int, int)
+     */
+    public static int hash32(final long data1, final long data2) {
+        return hash32(data1, data2, DEFAULT_SEED);
+    }
+
+    /**
+     * Generates 32-bit hash from two longs with the given seed.
+     * This is a helper method that will produce the same result as:
      *
-     * <p>Note: The sign extension bug in {@link #hash64(byte[], int, int, int)} does not effect
-     * this result as the default seed is positive.</p>
+     * <pre>
+     * int offset = 0;
+     * int hash = MurmurHash3.hash32x86(ByteBuffer.allocate(16)
+     *                                            .putLong(data1)
+     *                                            .putLong(data2)
+     *                                            .array(), offset, 16, seed);
+     * </pre>
      *
-     * <p>This is a helper method that will produce the same result as:</p>
+     * @param data1 The first long to hash
+     * @param data2 The second long to hash
+     * @param seed The initial seed value
+     * @return The 32-bit hash
+     * @see #hash32x86(byte[], int, int, int)
+     */
+    public static int hash32(final long data1, final long data2, final int seed) {
+        int hash = seed;
+        final long r0 = Long.reverseBytes(data1);
+        final long r1 = Long.reverseBytes(data2);
+
+        hash = mix32((int) r0, hash);
+        hash = mix32((int) (r0 >>> 32), hash);
+        hash = mix32((int) r1, hash);
+        hash = mix32((int) (r1 >>> 32), hash);
+
+        hash ^= Long.BYTES * 2;
+        return fmix32(hash);
+    }
+
+    /**
+     * Generates 32-bit hash from a string with a default seed.
+     * <p>
+     * Before 1.14 the string was converted using default encoding.
+     * Since 1.14 the string is converted to bytes using UTF-8 encoding.
+     * </p>
+     * This is a helper method that will produce the same result as:
      *
      * <pre>
      * int offset = 0;
      * int seed = 104729;
-     * long hash = MurmurHash3.hash64(ByteBuffer.allocate(2)
-     *                                          .putShort(data)
-     *                                          .array(), offset, 2, seed);
+     * byte[] bytes = data.getBytes(StandardCharsets.UTF_8);
+     * int hash = MurmurHash3.hash32(bytes, offset, bytes.length, seed);
      * </pre>
      *
-     * @param data The short to hash
-     * @return The 64-bit hash
-     * @see #hash64(byte[], int, int, int)
-     * @deprecated Not part of the MurmurHash3 implementation.
-     * Use half of the hash bytes from {@link #hash128x64(byte[])} with the bytes from the {@code short}.
+     * <p>This implementation contains a sign-extension bug in the finalization step of
+     * any bytes left over from dividing the length by 4. This manifests if any of these
+     * bytes are negative.</p>
+     *
+     * @param data The input string
+     * @return The 32-bit hash
+     * @see #hash32(byte[], int, int, int)
+     * @deprecated Use {@link #hash32x86(byte[], int, int, int)} with the bytes returned from
+     * {@link String#getBytes(java.nio.charset.Charset)}. This corrects the processing of trailing bytes.
      */
     @Deprecated
-    public static long hash64(final short data) {
-        long hash = DEFAULT_SEED;
-        long k1 = 0;
-        k1 ^= ((long) data & 0xff) << 8;
-        k1 ^= (long) ((data & 0xFF00) >> 8) & 0xff;
-        k1 *= C1;
-        k1 = Long.rotateLeft(k1, R1);
-        k1 *= C2;
-        hash ^= k1;
+    public static int hash32(final String data) {
+        final byte[] bytes = StringUtils.getBytesUtf8(data);
+        return hash32(bytes, 0, bytes.length, DEFAULT_SEED);
+    }
 
-        // finalization
-        hash ^= Short.BYTES;
-        hash = fmix64(hash);
-        return hash;
+    /**
+     * Generates 32-bit hash from the byte array with a seed of zero.
+     * This is a helper method that will produce the same result as:
+     *
+     * <pre>
+     * int offset = 0;
+     * int seed = 0;
+     * int hash = MurmurHash3.hash32x86(data, offset, data.length, seed);
+     * </pre>
+     *
+     * @param data The input byte array
+     * @return The 32-bit hash
+     * @see #hash32x86(byte[], int, int, int)
+     * @since 1.14
+     */
+    public static int hash32x86(final byte[] data) {
+        return hash32x86(data, 0, data.length, 0);
+    }
+
+    /**
+     * Generates 32-bit hash from the byte array with the given offset, length and seed.
+     *
+     * <p>This is an implementation of the 32-bit hash function {@code MurmurHash3_x86_32}
+     * from Austin Appleby's original MurmurHash3 {@code c++} code in SMHasher.</p>
+     *
+     * @param data The input byte array
+     * @param offset The offset of data
+     * @param length The length of array
+     * @param seed The initial seed value
+     * @return The 32-bit hash
+     * @since 1.14
+     */
+    public static int hash32x86(final byte[] data, final int offset, final int length, final int seed) {
+        int hash = seed;
+        final int nblocks = length >> 2;
+
+        // body
+        for (int i = 0; i < nblocks; i++) {
+            final int index = offset + (i << 2);
+            final int k = getLittleEndianInt(data, index);
+            hash = mix32(k, hash);
+        }
+
+        // tail
+        final int index = offset + (nblocks << 2);
+        int k1 = 0;
+        switch (offset + length - index) {
+        case 3:
+            k1 ^= (data[index + 2] & 0xff) << 16;
+        case 2:
+            k1 ^= (data[index + 1] & 0xff) << 8;
+        case 1:
+            k1 ^= data[index] & 0xff;
+
+            // mix functions
+            k1 *= C1_32;
+            k1 = Integer.rotateLeft(k1, R1_32);
+            k1 *= C2_32;
+            hash ^= k1;
+        }
+
+        hash ^= length;
+        return fmix32(hash);
     }
 
     /**
@@ -698,256 +1075,137 @@ public final class MurmurHash3 {
     }
 
     /**
-     * Generates 128-bit hash from the byte array with a default seed.
-     * This is a helper method that will produce the same result as:
+     * Generates 64-bit hash from an int with a default seed.
      *
-     * <pre>
-     * int offset = 0;
-     * int seed = 104729;
-     * int hash = MurmurHash3.hash128(data, offset, data.length, seed);
-     * </pre>
+     * <p><strong>This is not part of the original MurmurHash3 {@code c++} implementation.</strong></p>
      *
-     * <p>Note: The sign extension bug in {@link #hash128(byte[], int, int, int)} does not effect
+     * <p>This is a Murmur3-like 64-bit variant.
+     * The method does not produce the same result as either half of the hash bytes from
+     * {@linkplain #hash128x64(byte[])} with the same byte data from the {@code int}.
+     * This method will be removed in a future release.</p>
+     *
+     * <p>Note: The sign extension bug in {@link #hash64(byte[], int, int, int)} does not effect
      * this result as the default seed is positive.</p>
      *
-     * @param data The input byte array
-     * @return The 128-bit hash (2 longs)
-     * @see #hash128(byte[], int, int, int)
-     */
-    public static long[] hash128(final byte[] data) {
-        return hash128(data, 0, data.length, DEFAULT_SEED);
-    }
-
-    /**
-     * Generates 128-bit hash from the byte array with a seed of zero.
-     * This is a helper method that will produce the same result as:
+     * <p>This is a helper method that will produce the same result as:</p>
      *
      * <pre>
      * int offset = 0;
-     * int seed = 0;
-     * int hash = MurmurHash3.hash128x64(data, offset, data.length, seed);
+     * int seed = 104729;
+     * long hash = MurmurHash3.hash64(ByteBuffer.allocate(4)
+     *                                          .putInt(data)
+     *                                          .array(), offset, 4, seed);
      * </pre>
      *
-     * @param data The input byte array
-     * @return The 128-bit hash (2 longs)
-     * @see #hash128x64(byte[], int, int, int)
-     * @since 1.14
+     * @param data The int to hash
+     * @return The 64-bit hash
+     * @see #hash64(byte[], int, int, int)
+     * @deprecated Not part of the MurmurHash3 implementation.
+     * Use half of the hash bytes from {@link #hash128x64(byte[])} with the bytes from the {@code int}.
      */
-    public static long[] hash128x64(final byte[] data) {
-        return hash128x64(data, 0, data.length, 0);
+    @Deprecated
+    public static long hash64(final int data) {
+        long k1 = Integer.reverseBytes(data) & -1L >>> 32;
+        long hash = DEFAULT_SEED;
+        k1 *= C1;
+        k1 = Long.rotateLeft(k1, R1);
+        k1 *= C2;
+        hash ^= k1;
+        // finalization
+        hash ^= Integer.BYTES;
+        hash = fmix64(hash);
+        return hash;
     }
 
     /**
-     * Generates 128-bit hash from a string with a default seed.
-     * <p>
-     * Before 1.14 the string was converted using default encoding.
-     * Since 1.14 the string is converted to bytes using UTF-8 encoding.
-     * </p>
-     * <p>
-     * This is a helper method that will produce the same result as:
-     * </p>
+     * Generates 64-bit hash from a long with a default seed.
      *
-     * <pre>
-     * int offset = 0;
-     * int seed = 104729;
-     * byte[] bytes = data.getBytes(StandardCharsets.UTF_8);
-     * int hash = MurmurHash3.hash128(bytes, offset, bytes.length, seed);
-     * </pre>
+     * <p><strong>This is not part of the original MurmurHash3 {@code c++} implementation.</strong></p>
      *
-     * <p>Note: The sign extension bug in {@link #hash128(byte[], int, int, int)} does not effect
+     * <p>This is a Murmur3-like 64-bit variant.
+     * The method does not produce the same result as either half of the hash bytes from
+     * {@linkplain #hash128x64(byte[])} with the same byte data from the {@code long}.
+     * This method will be removed in a future release.</p>
+     *
+     * <p>Note: The sign extension bug in {@link #hash64(byte[], int, int, int)} does not effect
      * this result as the default seed is positive.</p>
      *
-     * @param data The input String
-     * @return The 128-bit hash (2 longs)
-     * @see #hash128(byte[], int, int, int)
-     * @deprecated Use {@link #hash128x64(byte[])} using the bytes returned from
-     * {@link String#getBytes(java.nio.charset.Charset)}.
-     */
-    @Deprecated
-    public static long[] hash128(final String data) {
-        final byte[] bytes = StringUtils.getBytesUtf8(data);
-        return hash128(bytes, 0, bytes.length, DEFAULT_SEED);
-    }
-
-    /**
-     * Generates 128-bit hash from the byte array with the given offset, length and seed.
-     *
-     * <p>This is an implementation of the 128-bit hash function {@code MurmurHash3_x64_128}
-     * from Austin Appleby's original MurmurHash3 {@code c++} code in SMHasher.</p>
+     * <p>This is a helper method that will produce the same result as:</p>
      *
-     * <p>This implementation contains a sign-extension bug in the seed initialization.
-     * This manifests if the seed is negative.</p>
+     * <pre>
+     * int offset = 0;
+     * int seed = 104729;
+     * long hash = MurmurHash3.hash64(ByteBuffer.allocate(8)
+     *                                          .putLong(data)
+     *                                          .array(), offset, 8, seed);
+     * </pre>
      *
-     * @param data The input byte array
-     * @param offset The first element of array
-     * @param length The length of array
-     * @param seed The initial seed value
-     * @return The 128-bit hash (2 longs)
-     * @deprecated Use {@link #hash128x64(byte[], int, int, int)}. This corrects the seed initialization.
+     * @param data The long to hash
+     * @return The 64-bit hash
+     * @see #hash64(byte[], int, int, int)
+     * @deprecated Not part of the MurmurHash3 implementation.
+     * Use half of the hash bytes from {@link #hash128x64(byte[])} with the bytes from the {@code long}.
      */
     @Deprecated
-    public static long[] hash128(final byte[] data, final int offset, final int length, final int seed) {
-        // ************
-        // Note: This deliberately fails to apply masking using 0xffffffffL to the seed
-        // to maintain behavioral compatibility with the original version.
-        // The implicit conversion to a long will extend a negative sign
-        // bit through the upper 32-bits of the long seed. These should be zero.
-        // ************
-        return hash128x64Internal(data, offset, length, seed);
+    public static long hash64(final long data) {
+        long hash = DEFAULT_SEED;
+        long k = Long.reverseBytes(data);
+        // mix functions
+        k *= C1;
+        k = Long.rotateLeft(k, R1);
+        k *= C2;
+        hash ^= k;
+        hash = Long.rotateLeft(hash, R2) * M + N1;
+        // finalization
+        hash ^= Long.BYTES;
+        hash = fmix64(hash);
+        return hash;
     }
 
     /**
-     * Generates 128-bit hash from the byte array with the given offset, length and seed.
+     * Generates 64-bit hash from a short with a default seed.
      *
-     * <p>This is an implementation of the 128-bit hash function {@code MurmurHash3_x64_128}
-     * from Austin Appleby's original MurmurHash3 {@code c++} code in SMHasher.</p>
+     * <p><strong>This is not part of the original MurmurHash3 {@code c++} implementation.</strong></p>
      *
-     * @param data The input byte array
-     * @param offset The first element of array
-     * @param length The length of array
-     * @param seed The initial seed value
-     * @return The 128-bit hash (2 longs)
-     * @since 1.14
-     */
-    public static long[] hash128x64(final byte[] data, final int offset, final int length, final int seed) {
-        // Use an unsigned 32-bit integer as the seed
-        return hash128x64Internal(data, offset, length, seed & 0xffffffffL);
-    }
-
-    /**
-     * Generates 128-bit hash from the byte array with the given offset, length and seed.
+     * <p>This is a Murmur3-like 64-bit variant.
+     * The method does not produce the same result as either half of the hash bytes from
+     * {@linkplain #hash128x64(byte[])} with the same byte data from the {@code short}.
+     * This method will be removed in a future release.</p>
      *
-     * <p>This is an implementation of the 128-bit hash function {@code MurmurHash3_x64_128}
-     * from Austin Appleby's original MurmurHash3 {@code c++} code in SMHasher.</p>
+     * <p>Note: The sign extension bug in {@link #hash64(byte[], int, int, int)} does not effect
+     * this result as the default seed is positive.</p>
      *
-     * @param data The input byte array
-     * @param offset The first element of array
-     * @param length The length of array
-     * @param seed The initial seed value
-     * @return The 128-bit hash (2 longs)
+     * <p>This is a helper method that will produce the same result as:</p>
+     *
+     * <pre>
+     * int offset = 0;
+     * int seed = 104729;
+     * long hash = MurmurHash3.hash64(ByteBuffer.allocate(2)
+     *                                          .putShort(data)
+     *                                          .array(), offset, 2, seed);
+     * </pre>
+     *
+     * @param data The short to hash
+     * @return The 64-bit hash
+     * @see #hash64(byte[], int, int, int)
+     * @deprecated Not part of the MurmurHash3 implementation.
+     * Use half of the hash bytes from {@link #hash128x64(byte[])} with the bytes from the {@code short}.
      */
-    private static long[] hash128x64Internal(final byte[] data, final int offset, final int length, final long seed) {
-        long h1 = seed;
-        long h2 = seed;
-        final int nblocks = length >> 4;
-
-        // body
-        for (int i = 0; i < nblocks; i++) {
-            final int index = offset + (i << 4);
-            long k1 = getLittleEndianLong(data, index);
-            long k2 = getLittleEndianLong(data, index + 8);
-
-            // mix functions for k1
-            k1 *= C1;
-            k1 = Long.rotateLeft(k1, R1);
-            k1 *= C2;
-            h1 ^= k1;
-            h1 = Long.rotateLeft(h1, R2);
-            h1 += h2;
-            h1 = h1 * M + N1;
-
-            // mix functions for k2
-            k2 *= C2;
-            k2 = Long.rotateLeft(k2, R3);
-            k2 *= C1;
-            h2 ^= k2;
-            h2 = Long.rotateLeft(h2, R1);
-            h2 += h1;
-            h2 = h2 * M + N2;
-        }
-
-        // tail
+    @Deprecated
+    public static long hash64(final short data) {
+        long hash = DEFAULT_SEED;
         long k1 = 0;
-        long k2 = 0;
-        final int index = offset + (nblocks << 4);
-        switch (offset + length - index) {
-        case 15:
-            k2 ^= ((long) data[index + 14] & 0xff) << 48;
-        case 14:
-            k2 ^= ((long) data[index + 13] & 0xff) << 40;
-        case 13:
-            k2 ^= ((long) data[index + 12] & 0xff) << 32;
-        case 12:
-            k2 ^= ((long) data[index + 11] & 0xff) << 24;
-        case 11:
-            k2 ^= ((long) data[index + 10] & 0xff) << 16;
-        case 10:
-            k2 ^= ((long) data[index + 9] & 0xff) << 8;
-        case 9:
-            k2 ^= data[index + 8] & 0xff;
-            k2 *= C2;
-            k2 = Long.rotateLeft(k2, R3);
-            k2 *= C1;
-            h2 ^= k2;
-
-        case 8:
-            k1 ^= ((long) data[index + 7] & 0xff) << 56;
-        case 7:
-            k1 ^= ((long) data[index + 6] & 0xff) << 48;
-        case 6:
-            k1 ^= ((long) data[index + 5] & 0xff) << 40;
-        case 5:
-            k1 ^= ((long) data[index + 4] & 0xff) << 32;
-        case 4:
-            k1 ^= ((long) data[index + 3] & 0xff) << 24;
-        case 3:
-            k1 ^= ((long) data[index + 2] & 0xff) << 16;
-        case 2:
-            k1 ^= ((long) data[index + 1] & 0xff) << 8;
-        case 1:
-            k1 ^= data[index] & 0xff;
-            k1 *= C1;
-            k1 = Long.rotateLeft(k1, R1);
-            k1 *= C2;
-            h1 ^= k1;
-        }
+        k1 ^= ((long) data & 0xff) << 8;
+        k1 ^= (long) ((data & 0xFF00) >> 8) & 0xff;
+        k1 *= C1;
+        k1 = Long.rotateLeft(k1, R1);
+        k1 *= C2;
+        hash ^= k1;
 
         // finalization
-        h1 ^= length;
-        h2 ^= length;
-
-        h1 += h2;
-        h2 += h1;
-
-        h1 = fmix64(h1);
-        h2 = fmix64(h2);
-
-        h1 += h2;
-        h2 += h1;
-
-        return new long[] { h1, h2 };
-    }
-
-    /**
-     * Gets the little-endian long from 8 bytes starting at the specified index.
-     *
-     * @param data The data
-     * @param index The index
-     * @return The little-endian long
-     */
-    private static long getLittleEndianLong(final byte[] data, final int index) {
-        return (long) data[index    ] & 0xff |
-               ((long) data[index + 1] & 0xff) <<  8 |
-               ((long) data[index + 2] & 0xff) << 16 |
-               ((long) data[index + 3] & 0xff) << 24 |
-               ((long) data[index + 4] & 0xff) << 32 |
-               ((long) data[index + 5] & 0xff) << 40 |
-               ((long) data[index + 6] & 0xff) << 48 |
-               ((long) data[index + 7] & 0xff) << 56;
-    }
-
-    /**
-     * Gets the little-endian int from 4 bytes starting at the specified index.
-     *
-     * @param data The data
-     * @param index The index
-     * @return The little-endian int
-     */
-    private static int getLittleEndianInt(final byte[] data, final int index) {
-        return data[index    ] & 0xff |
-               (data[index + 1] & 0xff) <<  8 |
-               (data[index + 2] & 0xff) << 16 |
-               (data[index + 3] & 0xff) << 24;
+        hash ^= Short.BYTES;
+        hash = fmix64(hash);
+        return hash;
     }
 
     /**
@@ -965,265 +1223,7 @@ public final class MurmurHash3 {
         return Integer.rotateLeft(hash, R2_32) * M_32 + N_32;
     }
 
-    /**
-     * Performs the final avalanche mix step of the 32-bit hash function {@code MurmurHash3_x86_32}.
-     *
-     * @param hash The current hash
-     * @return The final hash
-     */
-    private static int fmix32(int hash) {
-        hash ^= hash >>> 16;
-        hash *= 0x85ebca6b;
-        hash ^= hash >>> 13;
-        hash *= 0xc2b2ae35;
-        hash ^= hash >>> 16;
-        return hash;
-    }
-
-    /**
-     * Performs the final avalanche mix step of the 64-bit hash function {@code MurmurHash3_x64_128}.
-     *
-     * @param hash The current hash
-     * @return The final hash
-     */
-    private static long fmix64(long hash) {
-        hash ^= hash >>> 33;
-        hash *= 0xff51afd7ed558ccdL;
-        hash ^= hash >>> 33;
-        hash *= 0xc4ceb9fe1a85ec53L;
-        hash ^= hash >>> 33;
-        return hash;
-    }
-
-    /**
-     * Generates 32-bit hash from input bytes. Bytes can be added incrementally and the new
-     * hash computed.
-     *
-     * <p>This is an implementation of the 32-bit hash function {@code MurmurHash3_x86_32}
-     * from Austin Appleby's original MurmurHash3 {@code c++} code in SMHasher.</p>
-     *
-     * @since 1.14
-     */
-    public static class IncrementalHash32x86 {
-
-        /** The size of byte blocks that are processed together. */
-        private static final int BLOCK_SIZE = 4;
-
-        /** Up to 3 unprocessed bytes from input data. */
-        private final byte[] unprocessed = new byte[3];
-
-        /** The number of unprocessed bytes in the tail data. */
-        private int unprocessedLength;
-
-        /** The total number of input bytes added since the start. */
-        private int totalLen;
-
-        /**
-         * The current running hash.
-         * This must be finalised to generate the 32-bit hash value.
-         */
-        private int hash;
-
-        /**
-         * Starts a new incremental hash.
-         *
-         * @param seed The initial seed value
-         */
-        public final void start(final int seed) {
-            // Reset
-            unprocessedLength = totalLen = 0;
-            this.hash = seed;
-        }
-
-        /**
-         * Adds the byte array to the current incremental hash.
-         *
-         * @param data The input byte array
-         * @param offset The offset of data
-         * @param length The length of array
-         */
-        public final void add(final byte[] data, final int offset, final int length) {
-            if (length <= 0) {
-                // Nothing to add
-                return;
-            }
-            totalLen += length;
-
-            // Process the bytes in blocks of 4.
-            // New bytes must be added to any current unprocessed bytes,
-            // then processed in blocks of 4 and the remaining bytes saved:
-            //
-            //    |--|---------------------------|--|
-            // unprocessed
-            //                main block
-            //                                remaining
-
-            // Check if the unprocessed bytes and new bytes can fill a block of 4.
-            // Make this overflow safe in the event that length is Integer.MAX_VALUE.
-            // Equivalent to: (unprocessedLength + length < BLOCK_SIZE)
-            if (unprocessedLength + length - BLOCK_SIZE < 0) {
-                // Not enough so add to the unprocessed bytes
-                System.arraycopy(data, offset, unprocessed, unprocessedLength, length);
-                unprocessedLength += length;
-                return;
-            }
-
-            // Combine unprocessed bytes with new bytes.
-            final int newOffset;
-            final int newLength;
-            if (unprocessedLength > 0) {
-                int k = -1;
-                switch (unprocessedLength) {
-                case 1:
-                    k = orBytes(unprocessed[0], data[offset], data[offset + 1], data[offset + 2]);
-                    break;
-                case 2:
-                    k = orBytes(unprocessed[0], unprocessed[1], data[offset], data[offset + 1]);
-                    break;
-                case 3:
-                    k = orBytes(unprocessed[0], unprocessed[1], unprocessed[2], data[offset]);
-                    break;
-                default:
-                    throw new IllegalStateException("Unprocessed length should be 1, 2, or 3: " + unprocessedLength);
-                }
-                hash = mix32(k, hash);
-                // Update the offset and length
-                final int consumed = BLOCK_SIZE - unprocessedLength;
-                newOffset = offset + consumed;
-                newLength = length - consumed;
-            } else {
-                newOffset = offset;
-                newLength = length;
-            }
-
-            // Main processing of blocks of 4 bytes
-            final int nblocks = newLength >> 2;
-
-            for (int i = 0; i < nblocks; i++) {
-                final int index = newOffset + (i << 2);
-                final int k = getLittleEndianInt(data, index);
-                hash = mix32(k, hash);
-            }
-
-            // Save left-over unprocessed bytes
-            final int consumed = nblocks << 2;
-            unprocessedLength = newLength - consumed;
-            if (unprocessedLength != 0) {
-                System.arraycopy(data, newOffset + consumed, unprocessed, 0, unprocessedLength);
-            }
-        }
-
-        /**
-         * Generates the 32-bit hash value. Repeat calls to this method with no additional data
-         * will generate the same hash value.
-         *
-         * @return The 32-bit hash
-         */
-        public final int end() {
-            // Allow calling end() again after adding no data to return the same result.
-            return finalise(hash, unprocessedLength, unprocessed, totalLen);
-        }
-
-        /**
-         * Finalizes the running hash to the output 32-bit hash by processing remaining bytes
-         * and performing final mixing.
-         *
-         * @param hash The running hash
-         * @param unprocessedLength The number of unprocessed bytes in the tail data.
-         * @param unprocessed Up to 3 unprocessed bytes from input data.
-         * @param totalLen The total number of input bytes added since the start.
-         * @return The 32-bit hash
-         */
-        int finalise(final int hash, final int unprocessedLength, final byte[] unprocessed, final int totalLen) {
-            int result = hash;
-            int k1 = 0;
-            switch (unprocessedLength) {
-            case 3:
-                k1 ^= (unprocessed[2] & 0xff) << 16;
-            case 2:
-                k1 ^= (unprocessed[1] & 0xff) << 8;
-            case 1:
-                k1 ^= unprocessed[0] & 0xff;
-
-                // mix functions
-                k1 *= C1_32;
-                k1 = Integer.rotateLeft(k1, R1_32);
-                k1 *= C2_32;
-                result ^= k1;
-            }
-
-            // finalization
-            result ^= totalLen;
-            return fmix32(result);
-        }
-
-        /**
-         * Combines the bytes using an Or operation ({@code | } in a little-endian representation
-         * of a 32-bit integer; byte 1 will be the least significant byte, byte 4 the most
-         * significant.
-         *
-         * @param b1 The first byte
-         * @param b2 The second byte
-         * @param b3 The third byte
-         * @param b4 The fourth byte
-         * @return The 32-bit integer
-         */
-        private static int orBytes(final byte b1, final byte b2, final byte b3, final byte b4) {
-            return b1 & 0xff | (b2 & 0xff) << 8 | (b3 & 0xff) << 16 | (b4 & 0xff) << 24;
-        }
-    }
-
-    /**
-     * Generates 32-bit hash from input bytes. Bytes can be added incrementally and the new
-     * hash computed.
-     *
-     * <p>This is an implementation of the 32-bit hash function {@code MurmurHash3_x86_32}
-     * from Austin Appleby's original MurmurHash3 {@code c++} code in SMHasher.</p>
-     *
-     * <p>This implementation contains a sign-extension bug in the finalization step of
-     * any bytes left over from dividing the length by 4. This manifests if any of these
-     * bytes are negative.</p>
-     *
-     * @deprecated Use IncrementalHash32x86. This corrects the processing of trailing bytes.
-     */
-    @Deprecated
-    public static class IncrementalHash32 extends IncrementalHash32x86 {
-
-        /**
-         * {@inheritDoc}
-         *
-         * <p>This implementation contains a sign-extension bug in the finalization step of
-         * any bytes left over from dividing the length by 4. This manifests if any of these
-         * bytes are negative.<p>
-         *
-         * @deprecated Use IncrementalHash32x86. This corrects the processing of trailing bytes.
-         */
-        @Override
-        @Deprecated
-        int finalise(final int hash, final int unprocessedLength, final byte[] unprocessed, final int totalLen) {
-            int result = hash;
-            // ************
-            // Note: This fails to apply masking using 0xff to the 3 remaining bytes.
-            // ************
-            int k1 = 0;
-            switch (unprocessedLength) {
-            case 3:
-                k1 ^= unprocessed[2] << 16;
-            case 2:
-                k1 ^= unprocessed[1] << 8;
-            case 1:
-                k1 ^= unprocessed[0];
-
-                // mix functions
-                k1 *= C1_32;
-                k1 = Integer.rotateLeft(k1, R1_32);
-                k1 *= C2_32;
-                result ^= k1;
-            }
-
-            // finalization
-            result ^= totalLen;
-            return fmix32(result);
-        }
+    /** No instance methods. */
+    private MurmurHash3() {
     }
 }
diff --git a/src/main/java/org/apache/commons/codec/digest/UnixCrypt.java b/src/main/java/org/apache/commons/codec/digest/UnixCrypt.java
index cb814246..8d83a6a7 100644
--- a/src/main/java/org/apache/commons/codec/digest/UnixCrypt.java
+++ b/src/main/java/org/apache/commons/codec/digest/UnixCrypt.java
@@ -172,6 +172,49 @@ public class UnixCrypt {
                     0x8000020, 0x208000, 32800, 0x8008020, 0x8200000, 32, 0x8208000, 0x208020, 0, 0x8000000,
                     0x8200020, 32768, 0x208020 } };
 
+    private static int[] body(final int[] schedule, final int eSwap0, final int eSwap1) {
+        int left = 0;
+        int right = 0;
+        int t = 0;
+        for (int j = 0; j < 25; j++) {
+            for (int i = 0; i < 32; i += 4) {
+                left = dEncrypt(left, right, i, eSwap0, eSwap1, schedule);
+                right = dEncrypt(right, left, i + 2, eSwap0, eSwap1, schedule);
+            }
+            t = left;
+            left = right;
+            right = t;
+        }
+
+        t = right;
+        right = left >>> 1 | left << 31;
+        left = t >>> 1 | t << 31;
+        final int[] results = new int[2];
+        permOp(right, left, 1, 0x55555555, results);
+        right = results[0];
+        left = results[1];
+        permOp(left, right, 8, 0xff00ff, results);
+        left = results[0];
+        right = results[1];
+        permOp(right, left, 2, 0x33333333, results);
+        right = results[0];
+        left = results[1];
+        permOp(left, right, 16, 65535, results);
+        left = results[0];
+        right = results[1];
+        permOp(right, left, 4, 0xf0f0f0f, results);
+        right = results[0];
+        left = results[1];
+        final int[] out = new int[2];
+        out[0] = left;
+        out[1] = right;
+        return out;
+    }
+
+    private static int byteToUnsigned(final byte b) {
+        return b & 0xff;
+    }
+
     /**
      * Generates a crypt(3) compatible hash using the DES algorithm.
      * <p>
@@ -285,49 +328,6 @@ public class UnixCrypt {
         return crypt(original.getBytes(StandardCharsets.UTF_8), salt);
     }
 
-    private static int[] body(final int[] schedule, final int eSwap0, final int eSwap1) {
-        int left = 0;
-        int right = 0;
-        int t = 0;
-        for (int j = 0; j < 25; j++) {
-            for (int i = 0; i < 32; i += 4) {
-                left = dEncrypt(left, right, i, eSwap0, eSwap1, schedule);
-                right = dEncrypt(right, left, i + 2, eSwap0, eSwap1, schedule);
-            }
-            t = left;
-            left = right;
-            right = t;
-        }
-
-        t = right;
-        right = left >>> 1 | left << 31;
-        left = t >>> 1 | t << 31;
-        final int[] results = new int[2];
-        permOp(right, left, 1, 0x55555555, results);
-        right = results[0];
-        left = results[1];
-        permOp(left, right, 8, 0xff00ff, results);
-        left = results[0];
-        right = results[1];
-        permOp(right, left, 2, 0x33333333, results);
-        right = results[0];
-        left = results[1];
-        permOp(left, right, 16, 65535, results);
-        left = results[0];
-        right = results[1];
-        permOp(right, left, 4, 0xf0f0f0f, results);
-        right = results[0];
-        left = results[1];
-        final int[] out = new int[2];
-        out[0] = left;
-        out[1] = right;
-        return out;
-    }
-
-    private static int byteToUnsigned(final byte b) {
-        return b & 0xff;
-    }
-
     private static int dEncrypt(int el, final int r, final int s, final int e0, final int e1, final int[] sArr) {
         int v = r ^ r >>> 16;
         int u = v & e0;
diff --git a/src/main/java/org/apache/commons/codec/digest/XXHash32.java b/src/main/java/org/apache/commons/codec/digest/XXHash32.java
index c11d3638..f2d4af8d 100644
--- a/src/main/java/org/apache/commons/codec/digest/XXHash32.java
+++ b/src/main/java/org/apache/commons/codec/digest/XXHash32.java
@@ -46,14 +46,28 @@ public class XXHash32 implements Checksum {
     private static final int PRIME4 =  668265263;
     private static final int PRIME5 =  374761393;
 
+    /**
+     * Gets the little-endian int from 4 bytes starting at the specified index.
+     *
+     * @param buffer The data
+     * @param idx The index
+     * @return The little-endian int
+     */
+    private static int getInt(final byte[] buffer, final int idx) {
+        return buffer[idx    ] & 0xff |
+               (buffer[idx + 1] & 0xff) <<  8 |
+               (buffer[idx + 2] & 0xff) << 16 |
+               (buffer[idx + 3] & 0xff) << 24;
+    }
     private final byte[] oneByte = new byte[1];
     private final int[] state = new int[4];
     // Note: the code used to use ByteBuffer but the manual method is 50% faster
     // See: http://gitbox.apache.org/repos/asf/commons-compress/diff/2f56fb5c
     private final byte[] buffer = new byte[BUF_SIZE];
-    private final int seed;
 
+    private final int seed;
     private int totalLen;
+
     private int pos;
 
     /** Set to true when the state array has been updated since the last reset. */
@@ -75,61 +89,6 @@ public class XXHash32 implements Checksum {
         initializeState();
     }
 
-    @Override
-    public void reset() {
-        initializeState();
-        totalLen = 0;
-        pos = 0;
-        stateUpdated = false;
-    }
-
-    @Override
-    public void update(final int b) {
-        oneByte[0] = (byte) (b & 0xff);
-        update(oneByte, 0, 1);
-    }
-
-    @Override
-    public void update(final byte[] b, int off, final int len) {
-        if (len <= 0) {
-            return;
-        }
-        totalLen += len;
-
-        final int end = off + len;
-
-        // Check if the unprocessed bytes and new bytes can fill a block of 16.
-        // Make this overflow safe in the event that len is Integer.MAX_VALUE.
-        // Equivalent to: (pos + len < BUF_SIZE)
-        if (pos + len - BUF_SIZE < 0) {
-            System.arraycopy(b, off, buffer, pos, len);
-            pos += len;
-            return;
-        }
-
-        // Process left-over bytes with new bytes
-        if (pos > 0) {
-            final int size = BUF_SIZE - pos;
-            System.arraycopy(b, off, buffer, pos, size);
-            process(buffer, 0);
-            off += size;
-        }
-
-        final int limit = end - BUF_SIZE;
-        while (off <= limit) {
-            process(b, off);
-            off += BUF_SIZE;
-        }
-
-        // Handle left-over bytes
-        if (off < end) {
-            pos = end - off;
-            System.arraycopy(b, off, buffer, 0, pos);
-        } else {
-            pos = 0;
-        }
-    }
-
     @Override
     public long getValue() {
         int hash;
@@ -163,20 +122,6 @@ public class XXHash32 implements Checksum {
         return hash & 0xffffffffL;
     }
 
-    /**
-     * Gets the little-endian int from 4 bytes starting at the specified index.
-     *
-     * @param buffer The data
-     * @param idx The index
-     * @return The little-endian int
-     */
-    private static int getInt(final byte[] buffer, final int idx) {
-        return buffer[idx    ] & 0xff |
-               (buffer[idx + 1] & 0xff) <<  8 |
-               (buffer[idx + 2] & 0xff) << 16 |
-               (buffer[idx + 3] & 0xff) << 24;
-    }
-
     private void initializeState() {
         state[0] = seed + PRIME1 + PRIME2;
         state[1] = seed + PRIME2;
@@ -203,4 +148,59 @@ public class XXHash32 implements Checksum {
 
         stateUpdated = true;
     }
+
+    @Override
+    public void reset() {
+        initializeState();
+        totalLen = 0;
+        pos = 0;
+        stateUpdated = false;
+    }
+
+    @Override
+    public void update(final byte[] b, int off, final int len) {
+        if (len <= 0) {
+            return;
+        }
+        totalLen += len;
+
+        final int end = off + len;
+
+        // Check if the unprocessed bytes and new bytes can fill a block of 16.
+        // Make this overflow safe in the event that len is Integer.MAX_VALUE.
+        // Equivalent to: (pos + len < BUF_SIZE)
+        if (pos + len - BUF_SIZE < 0) {
+            System.arraycopy(b, off, buffer, pos, len);
+            pos += len;
+            return;
+        }
+
+        // Process left-over bytes with new bytes
+        if (pos > 0) {
+            final int size = BUF_SIZE - pos;
+            System.arraycopy(b, off, buffer, pos, size);
+            process(buffer, 0);
+            off += size;
+        }
+
+        final int limit = end - BUF_SIZE;
+        while (off <= limit) {
+            process(b, off);
+            off += BUF_SIZE;
+        }
+
+        // Handle left-over bytes
+        if (off < end) {
+            pos = end - off;
+            System.arraycopy(b, off, buffer, 0, pos);
+        } else {
+            pos = 0;
+        }
+    }
+
+    @Override
+    public void update(final int b) {
+        oneByte[0] = (byte) (b & 0xff);
+        update(oneByte, 0, 1);
+    }
 }
diff --git a/src/main/java/org/apache/commons/codec/language/ColognePhonetic.java b/src/main/java/org/apache/commons/codec/language/ColognePhonetic.java
index bd1c59cf..0a7b6271 100644
--- a/src/main/java/org/apache/commons/codec/language/ColognePhonetic.java
+++ b/src/main/java/org/apache/commons/codec/language/ColognePhonetic.java
@@ -182,19 +182,6 @@ import org.apache.commons.codec.StringEncoder;
  */
 public class ColognePhonetic implements StringEncoder {
 
-    // Predefined char arrays for better performance and less GC load
-    private static final char[] AEIJOUY = { 'A', 'E', 'I', 'J', 'O', 'U', 'Y' };
-    private static final char[] CSZ = { 'C', 'S', 'Z' };
-    private static final char[] FPVW = { 'F', 'P', 'V', 'W' };
-    private static final char[] GKQ = { 'G', 'K', 'Q' };
-    private static final char[] CKQ = { 'C', 'K', 'Q' };
-    private static final char[] AHKLOQRUX = { 'A', 'H', 'K', 'L', 'O', 'Q', 'R', 'U', 'X' };
-    private static final char[] SZ = { 'S', 'Z' };
-    private static final char[] AHKOQUX = { 'A', 'H', 'K', 'O', 'Q', 'U', 'X' };
-    private static final char[] DTX = { 'D', 'T', 'X' };
-
-    private static final char CHAR_IGNORE = '-';    // is this character to be ignored?
-
     /**
      * This class is not thread-safe; the field {@link #length} is mutable.
      * However, it is not shared between threads, as it is constructed on demand
@@ -218,6 +205,10 @@ public class ColognePhonetic implements StringEncoder {
 
         protected abstract char[] copyData(int start, int length);
 
+        public boolean isEmpty() {
+            return length() == 0;
+        }
+
         public int length() {
             return length;
         }
@@ -226,12 +217,34 @@ public class ColognePhonetic implements StringEncoder {
         public String toString() {
             return new String(copyData(0, length));
         }
+    }
+    private class CologneInputBuffer extends CologneBuffer {
 
-        public boolean isEmpty() {
-            return length() == 0;
+        public CologneInputBuffer(final char[] data) {
+            super(data);
+        }
+
+        @Override
+        protected char[] copyData(final int start, final int length) {
+            final char[] newData = new char[length];
+            System.arraycopy(data, data.length - this.length + start, newData, 0, length);
+            return newData;
+        }
+
+        public char getNextChar() {
+            return data[getNextPos()];
+        }
+
+        protected int getNextPos() {
+            return data.length - length;
         }
-    }
 
+        public char removeNext() {
+            final char ch = getNextChar();
+            length--;
+            return ch;
+        }
+    }
     private class CologneOutputBuffer extends CologneBuffer {
 
         private char lastCode;
@@ -241,6 +254,11 @@ public class ColognePhonetic implements StringEncoder {
             lastCode = '/'; // impossible value
         }
 
+        @Override
+        protected char[] copyData(final int start, final int length) {
+            return Arrays.copyOfRange(data, start, length);
+        }
+
         /**
          * Stores the next code in the output buffer, keeping track of the previous code.
          * '0' is only stored if it is the first entry.
@@ -256,40 +274,22 @@ public class ColognePhonetic implements StringEncoder {
             }
             lastCode = code;
         }
-
-        @Override
-        protected char[] copyData(final int start, final int length) {
-            return Arrays.copyOfRange(data, start, length);
-        }
     }
+    // Predefined char arrays for better performance and less GC load
+    private static final char[] AEIJOUY = { 'A', 'E', 'I', 'J', 'O', 'U', 'Y' };
+    private static final char[] CSZ = { 'C', 'S', 'Z' };
+    private static final char[] FPVW = { 'F', 'P', 'V', 'W' };
+    private static final char[] GKQ = { 'G', 'K', 'Q' };
+    private static final char[] CKQ = { 'C', 'K', 'Q' };
+    private static final char[] AHKLOQRUX = { 'A', 'H', 'K', 'L', 'O', 'Q', 'R', 'U', 'X' };
 
-    private class CologneInputBuffer extends CologneBuffer {
-
-        public CologneInputBuffer(final char[] data) {
-            super(data);
-        }
-
-        @Override
-        protected char[] copyData(final int start, final int length) {
-            final char[] newData = new char[length];
-            System.arraycopy(data, data.length - this.length + start, newData, 0, length);
-            return newData;
-        }
+    private static final char[] SZ = { 'S', 'Z' };
 
-        public char getNextChar() {
-            return data[getNextPos()];
-        }
+    private static final char[] AHKOQUX = { 'A', 'H', 'K', 'O', 'Q', 'U', 'X' };
 
-        protected int getNextPos() {
-            return data.length - length;
-        }
+    private static final char[] DTX = { 'D', 'T', 'X' };
 
-        public char removeNext() {
-            final char ch = getNextChar();
-            length--;
-            return ch;
-        }
-    }
+    private static final char CHAR_IGNORE = '-';    // is this character to be ignored?
 
     /*
      * Returns whether the array contains the key, or not.
diff --git a/src/main/java/org/apache/commons/codec/language/DaitchMokotoffSoundex.java b/src/main/java/org/apache/commons/codec/language/DaitchMokotoffSoundex.java
index 96390df4..79d4680c 100644
--- a/src/main/java/org/apache/commons/codec/language/DaitchMokotoffSoundex.java
+++ b/src/main/java/org/apache/commons/codec/language/DaitchMokotoffSoundex.java
@@ -69,29 +69,6 @@ import org.apache.commons.codec.StringEncoder;
  */
 public class DaitchMokotoffSoundex implements StringEncoder {
 
-    private static final String COMMENT = "//";
-
-    private static final String DOUBLE_QUOTE = "\"";
-
-    private static final String MULTILINE_COMMENT_END = "*/";
-
-    private static final String MULTILINE_COMMENT_START = "/*";
-
-    /** The resource file containing the replacement and folding rules */
-    private static final String RESOURCE_FILE = "org/apache/commons/codec/language/dmrules.txt";
-
-    /** The code length of a DM soundex value. */
-    private static final int MAX_LENGTH = 6;
-
-    /** Transformation rules indexed by the first character of their pattern. */
-    private static final Map<Character, List<Rule>> RULES = new HashMap<>();
-
-    /** Folding rules. */
-    private static final Map<Character, Character> FOLDINGS = new HashMap<>();
-
-    /** Whether to use ASCII folding prior to encoding. */
-    private final boolean folding;
-
     /**
      * Inner class representing a branch during DM soundex encoding.
      */
@@ -227,6 +204,26 @@ public class DaitchMokotoffSoundex implements StringEncoder {
         }
     }
 
+    private static final String COMMENT = "//";
+
+    private static final String DOUBLE_QUOTE = "\"";
+
+    private static final String MULTILINE_COMMENT_END = "*/";
+
+    private static final String MULTILINE_COMMENT_START = "/*";
+
+    /** The resource file containing the replacement and folding rules */
+    private static final String RESOURCE_FILE = "org/apache/commons/codec/language/dmrules.txt";
+
+    /** The code length of a DM soundex value. */
+    private static final int MAX_LENGTH = 6;
+
+    /** Transformation rules indexed by the first character of their pattern. */
+    private static final Map<Character, List<Rule>> RULES = new HashMap<>();
+
+    /** Folding rules. */
+    private static final Map<Character, Character> FOLDINGS = new HashMap<>();
+
     static {
         try (final Scanner scanner = new Scanner(Resources.getInputStream(RESOURCE_FILE), CharEncoding.UTF_8)) {
             parseRules(scanner, RESOURCE_FILE, RULES, FOLDINGS);
@@ -323,6 +320,9 @@ public class DaitchMokotoffSoundex implements StringEncoder {
         return str;
     }
 
+    /** Whether to use ASCII folding prior to encoding. */
+    private final boolean folding;
+
     /**
      * Creates a new instance with ASCII-folding enabled.
      */
diff --git a/src/main/java/org/apache/commons/codec/language/DoubleMetaphone.java b/src/main/java/org/apache/commons/codec/language/DoubleMetaphone.java
index 4c11b2cb..44a68977 100644
--- a/src/main/java/org/apache/commons/codec/language/DoubleMetaphone.java
+++ b/src/main/java/org/apache/commons/codec/language/DoubleMetaphone.java
@@ -36,11 +36,87 @@ import org.apache.commons.codec.binary.StringUtils;
  */
 public class DoubleMetaphone implements StringEncoder {
 
+    /**
+     * Inner class for storing results, since there is the optional alternate encoding.
+     */
+    public class DoubleMetaphoneResult {
+
+        private final StringBuilder primary = new StringBuilder(getMaxCodeLen());
+        private final StringBuilder alternate = new StringBuilder(getMaxCodeLen());
+        private final int maxLength;
+
+        public DoubleMetaphoneResult(final int maxLength) {
+            this.maxLength = maxLength;
+        }
+
+        public void append(final char value) {
+            appendPrimary(value);
+            appendAlternate(value);
+        }
+
+        public void append(final char primary, final char alternate) {
+            appendPrimary(primary);
+            appendAlternate(alternate);
+        }
+
+        public void append(final String value) {
+            appendPrimary(value);
+            appendAlternate(value);
+        }
+
+        public void append(final String primary, final String alternate) {
+            appendPrimary(primary);
+            appendAlternate(alternate);
+        }
+
+        public void appendAlternate(final char value) {
+            if (this.alternate.length() < this.maxLength) {
+                this.alternate.append(value);
+            }
+        }
+
+        public void appendAlternate(final String value) {
+            final int addChars = this.maxLength - this.alternate.length();
+            if (value.length() <= addChars) {
+                this.alternate.append(value);
+            } else {
+                this.alternate.append(value, 0, addChars);
+            }
+        }
+
+        public void appendPrimary(final char value) {
+            if (this.primary.length() < this.maxLength) {
+                this.primary.append(value);
+            }
+        }
+
+        public void appendPrimary(final String value) {
+            final int addChars = this.maxLength - this.primary.length();
+            if (value.length() <= addChars) {
+                this.primary.append(value);
+            } else {
+                this.primary.append(value, 0, addChars);
+            }
+        }
+
+        public String getAlternate() {
+            return this.alternate.toString();
+        }
+
+        public String getPrimary() {
+            return this.primary.toString();
+        }
+
+        public boolean isComplete() {
+            return this.primary.length() >= this.maxLength &&
+                   this.alternate.length() >= this.maxLength;
+        }
+    }
+
     /**
      * "Vowels" to test for
      */
     private static final String VOWELS = "AEIOUY";
-
     /**
      * Prefixes when present which are not pronounced
      */
@@ -50,14 +126,133 @@ public class DoubleMetaphone implements StringEncoder {
         { "L", "R", "N", "M", "B", "H", "F", "V", "W", " " };
     private static final String[] ES_EP_EB_EL_EY_IB_IL_IN_IE_EI_ER =
         { "ES", "EP", "EB", "EL", "EY", "IB", "IL", "IN", "IE", "EI", "ER" };
+
     private static final String[] L_T_K_S_N_M_B_Z =
         { "L", "T", "K", "S", "N", "M", "B", "Z" };
 
+    /*
+     * Determines whether {@code value} contains any of the criteria starting at index {@code start} and
+     * matching up to length {@code length}.
+     */
+    protected static boolean contains(final String value, final int start, final int length,
+                                      final String... criteria) {
+        boolean result = false;
+        if (start >= 0 && start + length <= value.length()) {
+            final String target = value.substring(start, start + length);
+
+            for (final String element : criteria) {
+                if (target.equals(element)) {
+                    result = true;
+                    break;
+                }
+            }
+        }
+        return result;
+    }
+
     /**
      * Maximum length of an encoding, default is 4
      */
     private int maxCodeLen = 4;
 
+    /*
+     * Gets the character at index {@code index} if available, otherwise
+     * it returns {@code Character.MIN_VALUE} so that there is some sort
+     * of default.
+     */
+    protected char charAt(final String value, final int index) {
+        if (index < 0 || index >= value.length()) {
+            return Character.MIN_VALUE;
+        }
+        return value.charAt(index);
+    }
+
+    /**
+     * Cleans the input.
+     */
+    private String cleanInput(String input) {
+        if (input == null) {
+            return null;
+        }
+        input = input.trim();
+        if (input.isEmpty()) {
+            return null;
+        }
+        return input.toUpperCase(java.util.Locale.ENGLISH);
+    }
+
+    /**
+     * Complex condition 0 for 'C'.
+     */
+    private boolean conditionC0(final String value, final int index) {
+        if (contains(value, index, 4, "CHIA")) {
+            return true;
+        }
+        if (index <= 1) {
+            return false;
+        }
+        if (isVowel(charAt(value, index - 2))) {
+            return false;
+        }
+        if (!contains(value, index - 1, 3, "ACH")) {
+            return false;
+        }
+        final char c = charAt(value, index + 2);
+        return c != 'I' && c != 'E' ||
+                contains(value, index - 2, 6, "BACHER", "MACHER");
+    }
+
+    /**
+     * Complex condition 0 for 'CH'.
+     */
+    private boolean conditionCH0(final String value, final int index) {
+        if (index != 0) {
+            return false;
+        }
+        if (!contains(value, index + 1, 5, "HARAC", "HARIS") &&
+                   !contains(value, index + 1, 3, "HOR", "HYM", "HIA", "HEM")) {
+            return false;
+        }
+        return !contains(value, 0, 5, "CHORE");
+    }
+
+    /**
+     * Complex condition 1 for 'CH'.
+     */
+    private boolean conditionCH1(final String value, final int index) {
+        return contains(value, 0, 4, "VAN ", "VON ") || contains(value, 0, 3, "SCH") ||
+                contains(value, index - 2, 6, "ORCHES", "ARCHIT", "ORCHID") ||
+                contains(value, index + 2, 1, "T", "S") ||
+                (contains(value, index - 1, 1, "A", "O", "U", "E") || index == 0) &&
+                 (contains(value, index + 2, 1, L_R_N_M_B_H_F_V_W_SPACE) || index + 1 == value.length() - 1);
+    }
+
+    /**
+     * Complex condition 0 for 'L'.
+     */
+    private boolean conditionL0(final String value, final int index) {
+        if (index == value.length() - 3 &&
+            contains(value, index - 1, 4, "ILLO", "ILLA", "ALLE")) {
+            return true;
+        }
+        return (contains(value, value.length() - 2, 2, "AS", "OS") ||
+                contains(value, value.length() - 1, 1, "A", "O")) &&
+                contains(value, index - 1, 4, "ALLE");
+    }
+
+    //-- BEGIN HANDLERS --//
+
+    /**
+     * Complex condition 0 for 'M'.
+     */
+    private boolean conditionM0(final String value, final int index) {
+        if (charAt(value, index + 1) == 'M') {
+            return true;
+        }
+        return contains(value, index - 1, 3, "UMB") &&
+               (index + 1 == value.length() - 1 || contains(value, index + 2, 2, "ER"));
+    }
+
     /**
      * Encode a value with Double Metaphone.
      *
@@ -209,34 +404,6 @@ public class DoubleMetaphone implements StringEncoder {
         return doubleMetaphone(value);
     }
 
-    /**
-     * Check if the Double Metaphone values of two {@code String} values
-     * are equal.
-     *
-     * @param value1 The left-hand side of the encoded {@link String#equals(Object)}.
-     * @param value2 The right-hand side of the encoded {@link String#equals(Object)}.
-     * @return {@code true} if the encoded {@code String}s are equal;
-     *          {@code false} otherwise.
-     * @see #isDoubleMetaphoneEqual(String,String,boolean)
-     */
-    public boolean isDoubleMetaphoneEqual(final String value1, final String value2) {
-        return isDoubleMetaphoneEqual(value1, value2, false);
-    }
-
-    /**
-     * Check if the Double Metaphone values of two {@code String} values
-     * are equal, optionally using the alternate value.
-     *
-     * @param value1 The left-hand side of the encoded {@link String#equals(Object)}.
-     * @param value2 The right-hand side of the encoded {@link String#equals(Object)}.
-     * @param alternate use the alternate value if {@code true}.
-     * @return {@code true} if the encoded {@code String}s are equal;
-     *          {@code false} otherwise.
-     */
-    public boolean isDoubleMetaphoneEqual(final String value1, final String value2, final boolean alternate) {
-        return StringUtils.equals(doubleMetaphone(value1, alternate), doubleMetaphone(value2, alternate));
-    }
-
     /**
      * Returns the maxCodeLen.
      * @return int
@@ -245,16 +412,6 @@ public class DoubleMetaphone implements StringEncoder {
         return this.maxCodeLen;
     }
 
-    /**
-     * Sets the maxCodeLen.
-     * @param maxCodeLen The maxCodeLen to set
-     */
-    public void setMaxCodeLen(final int maxCodeLen) {
-        this.maxCodeLen = maxCodeLen;
-    }
-
-    //-- BEGIN HANDLERS --//
-
     /**
      * Handles 'A', 'E', 'I', 'O', 'U', and 'Y' cases.
      */
@@ -584,6 +741,8 @@ public class DoubleMetaphone implements StringEncoder {
         return charAt(value, index + 1) == 'R' ? index + 2 : index + 1;
     }
 
+    //-- BEGIN CONDITIONS --//
+
     /**
      * Handles 'S' cases.
      */
@@ -738,6 +897,8 @@ public class DoubleMetaphone implements StringEncoder {
         return index;
     }
 
+    //-- BEGIN HELPER FUNCTIONS --//
+
     /**
      * Handles 'Z' cases.
      */
@@ -759,94 +920,32 @@ public class DoubleMetaphone implements StringEncoder {
         return index;
     }
 
-    //-- BEGIN CONDITIONS --//
-
-    /**
-     * Complex condition 0 for 'C'.
-     */
-    private boolean conditionC0(final String value, final int index) {
-        if (contains(value, index, 4, "CHIA")) {
-            return true;
-        }
-        if (index <= 1) {
-            return false;
-        }
-        if (isVowel(charAt(value, index - 2))) {
-            return false;
-        }
-        if (!contains(value, index - 1, 3, "ACH")) {
-            return false;
-        }
-        final char c = charAt(value, index + 2);
-        return c != 'I' && c != 'E' ||
-                contains(value, index - 2, 6, "BACHER", "MACHER");
-    }
-
     /**
-     * Complex condition 0 for 'CH'.
-     */
-    private boolean conditionCH0(final String value, final int index) {
-        if (index != 0) {
-            return false;
-        }
-        if (!contains(value, index + 1, 5, "HARAC", "HARIS") &&
-                   !contains(value, index + 1, 3, "HOR", "HYM", "HIA", "HEM")) {
-            return false;
-        }
-        return !contains(value, 0, 5, "CHORE");
-    }
-
-    /**
-     * Complex condition 1 for 'CH'.
-     */
-    private boolean conditionCH1(final String value, final int index) {
-        return contains(value, 0, 4, "VAN ", "VON ") || contains(value, 0, 3, "SCH") ||
-                contains(value, index - 2, 6, "ORCHES", "ARCHIT", "ORCHID") ||
-                contains(value, index + 2, 1, "T", "S") ||
-                (contains(value, index - 1, 1, "A", "O", "U", "E") || index == 0) &&
-                 (contains(value, index + 2, 1, L_R_N_M_B_H_F_V_W_SPACE) || index + 1 == value.length() - 1);
-    }
-
-    /**
-     * Complex condition 0 for 'L'.
-     */
-    private boolean conditionL0(final String value, final int index) {
-        if (index == value.length() - 3 &&
-            contains(value, index - 1, 4, "ILLO", "ILLA", "ALLE")) {
-            return true;
-        }
-        return (contains(value, value.length() - 2, 2, "AS", "OS") ||
-                contains(value, value.length() - 1, 1, "A", "O")) &&
-                contains(value, index - 1, 4, "ALLE");
-    }
-
-    /**
-     * Complex condition 0 for 'M'.
-     */
-    private boolean conditionM0(final String value, final int index) {
-        if (charAt(value, index + 1) == 'M') {
-            return true;
-        }
-        return contains(value, index - 1, 3, "UMB") &&
-               (index + 1 == value.length() - 1 || contains(value, index + 2, 2, "ER"));
-    }
-
-    //-- BEGIN HELPER FUNCTIONS --//
-
-    /**
-     * Determines whether or not a value is of slavo-germanic origin. A value is
-     * of slavo-germanic origin if it contians any of 'W', 'K', 'CZ', or 'WITZ'.
+     * Check if the Double Metaphone values of two {@code String} values
+     * are equal.
+     *
+     * @param value1 The left-hand side of the encoded {@link String#equals(Object)}.
+     * @param value2 The right-hand side of the encoded {@link String#equals(Object)}.
+     * @return {@code true} if the encoded {@code String}s are equal;
+     *          {@code false} otherwise.
+     * @see #isDoubleMetaphoneEqual(String,String,boolean)
      */
-    private boolean isSlavoGermanic(final String value) {
-        return value.indexOf('W') > -1 || value.indexOf('K') > -1 ||
-                value.contains("CZ") || value.contains("WITZ");
+    public boolean isDoubleMetaphoneEqual(final String value1, final String value2) {
+        return isDoubleMetaphoneEqual(value1, value2, false);
     }
 
     /**
-     * Determines whether or not a character is a vowel or not
+     * Check if the Double Metaphone values of two {@code String} values
+     * are equal, optionally using the alternate value.
+     *
+     * @param value1 The left-hand side of the encoded {@link String#equals(Object)}.
+     * @param value2 The right-hand side of the encoded {@link String#equals(Object)}.
+     * @param alternate use the alternate value if {@code true}.
+     * @return {@code true} if the encoded {@code String}s are equal;
+     *          {@code false} otherwise.
      */
-    private boolean isVowel(final char ch) {
-        return VOWELS.indexOf(ch) != -1;
+    public boolean isDoubleMetaphoneEqual(final String value1, final String value2, final boolean alternate) {
+        return StringUtils.equals(doubleMetaphone(value1, alternate), doubleMetaphone(value2, alternate));
     }
 
     /**
@@ -866,127 +965,28 @@ public class DoubleMetaphone implements StringEncoder {
     }
 
     /**
-     * Cleans the input.
-     */
-    private String cleanInput(String input) {
-        if (input == null) {
-            return null;
-        }
-        input = input.trim();
-        if (input.isEmpty()) {
-            return null;
-        }
-        return input.toUpperCase(java.util.Locale.ENGLISH);
-    }
-
-    /*
-     * Gets the character at index {@code index} if available, otherwise
-     * it returns {@code Character.MIN_VALUE} so that there is some sort
-     * of default.
+     * Determines whether or not a value is of slavo-germanic origin. A value is
+     * of slavo-germanic origin if it contians any of 'W', 'K', 'CZ', or 'WITZ'.
      */
-    protected char charAt(final String value, final int index) {
-        if (index < 0 || index >= value.length()) {
-            return Character.MIN_VALUE;
-        }
-        return value.charAt(index);
+    private boolean isSlavoGermanic(final String value) {
+        return value.indexOf('W') > -1 || value.indexOf('K') > -1 ||
+                value.contains("CZ") || value.contains("WITZ");
     }
 
-    /*
-     * Determines whether {@code value} contains any of the criteria starting at index {@code start} and
-     * matching up to length {@code length}.
+    /**
+     * Determines whether or not a character is a vowel or not
      */
-    protected static boolean contains(final String value, final int start, final int length,
-                                      final String... criteria) {
-        boolean result = false;
-        if (start >= 0 && start + length <= value.length()) {
-            final String target = value.substring(start, start + length);
-
-            for (final String element : criteria) {
-                if (target.equals(element)) {
-                    result = true;
-                    break;
-                }
-            }
-        }
-        return result;
+    private boolean isVowel(final char ch) {
+        return VOWELS.indexOf(ch) != -1;
     }
 
     //-- BEGIN INNER CLASSES --//
 
     /**
-     * Inner class for storing results, since there is the optional alternate encoding.
+     * Sets the maxCodeLen.
+     * @param maxCodeLen The maxCodeLen to set
      */
-    public class DoubleMetaphoneResult {
-
-        private final StringBuilder primary = new StringBuilder(getMaxCodeLen());
-        private final StringBuilder alternate = new StringBuilder(getMaxCodeLen());
-        private final int maxLength;
-
-        public DoubleMetaphoneResult(final int maxLength) {
-            this.maxLength = maxLength;
-        }
-
-        public void append(final char value) {
-            appendPrimary(value);
-            appendAlternate(value);
-        }
-
-        public void append(final char primary, final char alternate) {
-            appendPrimary(primary);
-            appendAlternate(alternate);
-        }
-
-        public void appendPrimary(final char value) {
-            if (this.primary.length() < this.maxLength) {
-                this.primary.append(value);
-            }
-        }
-
-        public void appendAlternate(final char value) {
-            if (this.alternate.length() < this.maxLength) {
-                this.alternate.append(value);
-            }
-        }
-
-        public void append(final String value) {
-            appendPrimary(value);
-            appendAlternate(value);
-        }
-
-        public void append(final String primary, final String alternate) {
-            appendPrimary(primary);
-            appendAlternate(alternate);
-        }
-
-        public void appendPrimary(final String value) {
-            final int addChars = this.maxLength - this.primary.length();
-            if (value.length() <= addChars) {
-                this.primary.append(value);
-            } else {
-                this.primary.append(value, 0, addChars);
-            }
-        }
-
-        public void appendAlternate(final String value) {
-            final int addChars = this.maxLength - this.alternate.length();
-            if (value.length() <= addChars) {
-                this.alternate.append(value);
-            } else {
-                this.alternate.append(value, 0, addChars);
-            }
-        }
-
-        public String getPrimary() {
-            return this.primary.toString();
-        }
-
-        public String getAlternate() {
-            return this.alternate.toString();
-        }
-
-        public boolean isComplete() {
-            return this.primary.length() >= this.maxLength &&
-                   this.alternate.length() >= this.maxLength;
-        }
+    public void setMaxCodeLen(final int maxCodeLen) {
+        this.maxCodeLen = maxCodeLen;
     }
 }
diff --git a/src/main/java/org/apache/commons/codec/language/Metaphone.java b/src/main/java/org/apache/commons/codec/language/Metaphone.java
index ff23ac59..bf055587 100644
--- a/src/main/java/org/apache/commons/codec/language/Metaphone.java
+++ b/src/main/java/org/apache/commons/codec/language/Metaphone.java
@@ -74,6 +74,81 @@ public class Metaphone implements StringEncoder {
      */
     private int maxCodeLen = 4;
 
+    /**
+     * Encodes an Object using the metaphone algorithm.  This method
+     * is provided in order to satisfy the requirements of the
+     * Encoder interface, and will throw an EncoderException if the
+     * supplied object is not of type java.lang.String.
+     *
+     * @param obj Object to encode
+     * @return An object (or type java.lang.String) containing the
+     *         metaphone code which corresponds to the String supplied.
+     * @throws EncoderException if the parameter supplied is not
+     *                          of type java.lang.String
+     */
+    @Override
+    public Object encode(final Object obj) throws EncoderException {
+        if (!(obj instanceof String)) {
+            throw new EncoderException("Parameter supplied to Metaphone encode is not of type java.lang.String");
+        }
+        return metaphone((String) obj);
+    }
+
+    /**
+     * Encodes a String using the Metaphone algorithm.
+     *
+     * @param str String object to encode
+     * @return The metaphone code corresponding to the String supplied
+     */
+    @Override
+    public String encode(final String str) {
+        return metaphone(str);
+    }
+
+    /**
+     * Returns the maxCodeLen.
+     * @return int
+     */
+    public int getMaxCodeLen() { return this.maxCodeLen; }
+
+    private boolean isLastChar(final int wdsz, final int n) {
+        return n + 1 == wdsz;
+    }
+
+    /**
+     * Tests is the metaphones of two strings are identical.
+     *
+     * @param str1 First of two strings to compare
+     * @param str2 Second of two strings to compare
+     * @return {@code true} if the metaphones of these strings are identical,
+     *        {@code false} otherwise.
+     */
+    public boolean isMetaphoneEqual(final String str1, final String str2) {
+        return metaphone(str1).equals(metaphone(str2));
+    }
+
+    private boolean isNextChar(final StringBuilder string, final int index, final char c) {
+        boolean matches = false;
+        if (index >= 0 &&
+            index < string.length() - 1 ) {
+            matches = string.charAt(index + 1) == c;
+        }
+        return matches;
+    }
+
+    private boolean isPreviousChar(final StringBuilder string, final int index, final char c) {
+        boolean matches = false;
+        if (index > 0 &&
+            index < string.length() ) {
+            matches = string.charAt(index - 1) == c;
+        }
+        return matches;
+    }
+
+    private boolean isVowel(final StringBuilder string, final int index) {
+        return VOWELS.indexOf(string.charAt(index)) >= 0;
+    }
+
     /**
      * Find the metaphone value of a String. This is similar to the
      * soundex algorithm, but better at finding similar sounding words.
@@ -306,28 +381,6 @@ public class Metaphone implements StringEncoder {
         return code.toString();
     }
 
-    private boolean isVowel(final StringBuilder string, final int index) {
-        return VOWELS.indexOf(string.charAt(index)) >= 0;
-    }
-
-    private boolean isPreviousChar(final StringBuilder string, final int index, final char c) {
-        boolean matches = false;
-        if (index > 0 &&
-            index < string.length() ) {
-            matches = string.charAt(index - 1) == c;
-        }
-        return matches;
-    }
-
-    private boolean isNextChar(final StringBuilder string, final int index, final char c) {
-        boolean matches = false;
-        if (index >= 0 &&
-            index < string.length() - 1 ) {
-            matches = string.charAt(index + 1) == c;
-        }
-        return matches;
-    }
-
     private boolean regionMatch(final StringBuilder string, final int index, final String test) {
         boolean matches = false;
         if (index >= 0 && index + test.length() - 1 < string.length()) {
@@ -337,59 +390,6 @@ public class Metaphone implements StringEncoder {
         return matches;
     }
 
-    private boolean isLastChar(final int wdsz, final int n) {
-        return n + 1 == wdsz;
-    }
-
-    /**
-     * Encodes an Object using the metaphone algorithm.  This method
-     * is provided in order to satisfy the requirements of the
-     * Encoder interface, and will throw an EncoderException if the
-     * supplied object is not of type java.lang.String.
-     *
-     * @param obj Object to encode
-     * @return An object (or type java.lang.String) containing the
-     *         metaphone code which corresponds to the String supplied.
-     * @throws EncoderException if the parameter supplied is not
-     *                          of type java.lang.String
-     */
-    @Override
-    public Object encode(final Object obj) throws EncoderException {
-        if (!(obj instanceof String)) {
-            throw new EncoderException("Parameter supplied to Metaphone encode is not of type java.lang.String");
-        }
-        return metaphone((String) obj);
-    }
-
-    /**
-     * Encodes a String using the Metaphone algorithm.
-     *
-     * @param str String object to encode
-     * @return The metaphone code corresponding to the String supplied
-     */
-    @Override
-    public String encode(final String str) {
-        return metaphone(str);
-    }
-
-    /**
-     * Tests is the metaphones of two strings are identical.
-     *
-     * @param str1 First of two strings to compare
-     * @param str2 Second of two strings to compare
-     * @return {@code true} if the metaphones of these strings are identical,
-     *        {@code false} otherwise.
-     */
-    public boolean isMetaphoneEqual(final String str1, final String str2) {
-        return metaphone(str1).equals(metaphone(str2));
-    }
-
-    /**
-     * Returns the maxCodeLen.
-     * @return int
-     */
-    public int getMaxCodeLen() { return this.maxCodeLen; }
-
     /**
      * Sets the maxCodeLen.
      * @param maxCodeLen The maxCodeLen to set
diff --git a/src/main/java/org/apache/commons/codec/language/Nysiis.java b/src/main/java/org/apache/commons/codec/language/Nysiis.java
index 36b42412..969c6a58 100644
--- a/src/main/java/org/apache/commons/codec/language/Nysiis.java
+++ b/src/main/java/org/apache/commons/codec/language/Nysiis.java
@@ -92,9 +92,6 @@ public class Nysiis implements StringEncoder {
     private static final char SPACE = ' ';
     private static final int TRUE_LENGTH = 6;
 
-    /** Indicates the strict mode. */
-    private final boolean strict;
-
     /**
      * Tests if the given character is a vowel.
      *
@@ -174,6 +171,9 @@ public class Nysiis implements StringEncoder {
         return new char[] { curr };
     }
 
+    /** Indicates the strict mode. */
+    private final boolean strict;
+
     /**
      * Creates an instance of the {@link Nysiis} encoder with strict mode (original form),
      * i.e. encoded strings have a maximum length of 6.
diff --git a/src/main/java/org/apache/commons/codec/language/RefinedSoundex.java b/src/main/java/org/apache/commons/codec/language/RefinedSoundex.java
index 56cd0b42..30c7df91 100644
--- a/src/main/java/org/apache/commons/codec/language/RefinedSoundex.java
+++ b/src/main/java/org/apache/commons/codec/language/RefinedSoundex.java
@@ -55,6 +55,12 @@ public class RefinedSoundex implements StringEncoder {
      */
     private static final char[] US_ENGLISH_MAPPING = US_ENGLISH_MAPPING_STRING.toCharArray();
 
+    /**
+     * This static variable contains an instance of the RefinedSoundex using
+     * the US_ENGLISH mapping.
+     */
+    public static final RefinedSoundex US_ENGLISH = new RefinedSoundex();
+
     /**
      * Every letter of the alphabet is "mapped" to a numerical value. This char
      * array holds the values to which each letter is mapped. This
@@ -62,12 +68,6 @@ public class RefinedSoundex implements StringEncoder {
      */
     private final char[] soundexMapping;
 
-    /**
-     * This static variable contains an instance of the RefinedSoundex using
-     * the US_ENGLISH mapping.
-     */
-    public static final RefinedSoundex US_ENGLISH = new RefinedSoundex();
-
      /**
      * Creates an instance of the RefinedSoundex object using the default US
      * English mapping.
diff --git a/src/main/java/org/apache/commons/codec/language/Soundex.java b/src/main/java/org/apache/commons/codec/language/Soundex.java
index 8905555d..2a00cddc 100644
--- a/src/main/java/org/apache/commons/codec/language/Soundex.java
+++ b/src/main/java/org/apache/commons/codec/language/Soundex.java
@@ -164,15 +164,6 @@ public class Soundex implements StringEncoder {
         this.specialCaseHW = !hasMarker(this.soundexMapping);
     }
 
-    private boolean hasMarker(final char[] mapping) {
-        for(final char ch : mapping) {
-            if (ch == SILENT_MARKER) {
-                return true;
-            }
-        }
-        return false;
-    }
-
     /**
      * Creates a refined soundex instance using a custom mapping. This constructor can be used to customize the mapping,
      * and/or possibly provide an internationalized mapping for a non-Western character set.
@@ -272,6 +263,15 @@ public class Soundex implements StringEncoder {
         return this.maxLength;
     }
 
+    private boolean hasMarker(final char[] mapping) {
+        for(final char ch : mapping) {
+            if (ch == SILENT_MARKER) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     /**
      * Maps the given upper-case character to its Soundex code.
      *
diff --git a/src/main/java/org/apache/commons/codec/language/bm/BeiderMorseEncoder.java b/src/main/java/org/apache/commons/codec/language/bm/BeiderMorseEncoder.java
index 21ae48c6..1cac30a0 100644
--- a/src/main/java/org/apache/commons/codec/language/bm/BeiderMorseEncoder.java
+++ b/src/main/java/org/apache/commons/codec/language/bm/BeiderMorseEncoder.java
@@ -143,6 +143,20 @@ public class BeiderMorseEncoder implements StringEncoder {
                                          this.engine.getMaxPhonemes());
     }
 
+    /**
+     * Sets the number of maximum of phonemes that shall be considered by the engine.
+     *
+     * @param maxPhonemes
+     *            the maximum number of phonemes returned by the engine
+     * @since 1.7
+     */
+    public void setMaxPhonemes(final int maxPhonemes) {
+        this.engine = new PhoneticEngine(this.engine.getNameType(),
+                                         this.engine.getRuleType(),
+                                         this.engine.isConcat(),
+                                         maxPhonemes);
+    }
+
     /**
      * Sets the type of name. Use {@link NameType#GENERIC} unless you specifically want phonetic encodings
      * optimized for Ashkenazi or Sephardic Jewish family names.
@@ -170,18 +184,4 @@ public class BeiderMorseEncoder implements StringEncoder {
                                          this.engine.getMaxPhonemes());
     }
 
-    /**
-     * Sets the number of maximum of phonemes that shall be considered by the engine.
-     *
-     * @param maxPhonemes
-     *            the maximum number of phonemes returned by the engine
-     * @since 1.7
-     */
-    public void setMaxPhonemes(final int maxPhonemes) {
-        this.engine = new PhoneticEngine(this.engine.getNameType(),
-                                         this.engine.getRuleType(),
-                                         this.engine.isConcat(),
-                                         maxPhonemes);
-    }
-
 }
diff --git a/src/main/java/org/apache/commons/codec/language/bm/Lang.java b/src/main/java/org/apache/commons/codec/language/bm/Lang.java
index 05bb751a..734f668d 100644
--- a/src/main/java/org/apache/commons/codec/language/bm/Lang.java
+++ b/src/main/java/org/apache/commons/codec/language/bm/Lang.java
@@ -83,14 +83,6 @@ public class Lang {
     // guessing rules, perhaps by marking it protected and allowing sub-classing. However, the vast majority of users
     // should be strongly encouraged to use the static factory {@code instance} method to get their Lang instances.
 
-    private static final Map<NameType, Lang> LANGS = new EnumMap<>(NameType.class);
-
-    private static final String LANGUAGE_RULES_RN = "org/apache/commons/codec/language/bm/%s_lang.txt";
-
-    private final Languages languages;
-
-    private final List<LangRule> rules;
-
     private static final class LangRule {
         private final boolean acceptOnMatch;
         private final Set<String> languages;
@@ -107,6 +99,10 @@ public class Lang {
         }
     }
 
+    private static final Map<NameType, Lang> LANGS = new EnumMap<>(NameType.class);
+
+    private static final String LANGUAGE_RULES_RN = "org/apache/commons/codec/language/bm/%s_lang.txt";
+
     static {
         for (final NameType s : NameType.values()) {
             LANGS.put(s, loadFromResource(String.format(LANGUAGE_RULES_RN, s.getName()), Languages.getInstance(s)));
@@ -185,6 +181,10 @@ public class Lang {
         return new Lang(rules, languages);
     }
 
+    private final Languages languages;
+
+    private final List<LangRule> rules;
+
     private Lang(final List<LangRule> rules, final Languages languages) {
         this.rules = Collections.unmodifiableList(rules);
         this.languages = languages;
diff --git a/src/main/java/org/apache/commons/codec/language/bm/Languages.java b/src/main/java/org/apache/commons/codec/language/bm/Languages.java
index a06d44cf..c0f366f4 100644
--- a/src/main/java/org/apache/commons/codec/language/bm/Languages.java
+++ b/src/main/java/org/apache/commons/codec/language/bm/Languages.java
@@ -65,67 +65,116 @@ public class Languages {
     // languages, and a second part that provides instance methods for accessing
     // this set for supported languages.
 
-    public static final String ANY = "any";
+    /**
+     * A set of languages.
+     */
+    public static abstract class LanguageSet {
 
-    private static final Map<NameType, Languages> LANGUAGES = new EnumMap<>(NameType.class);
+        public static LanguageSet from(final Set<String> langs) {
+            return langs.isEmpty() ? NO_LANGUAGES : new SomeLanguages(langs);
+        }
+
+        public abstract boolean contains(String language);
+
+        public abstract String getAny();
+
+        public abstract boolean isEmpty();
+
+        public abstract boolean isSingleton();
+
+        abstract LanguageSet merge(LanguageSet other);
+
+        public abstract LanguageSet restrictTo(LanguageSet other);
+    }
 
     /**
-     * No languages at all.
+     * Some languages, explicitly enumerated.
      */
-    public static final LanguageSet NO_LANGUAGES = new LanguageSet() {
+    public static final class SomeLanguages extends LanguageSet {
+        private final Set<String> languages;
+
+        private SomeLanguages(final Set<String> languages) {
+            this.languages = Collections.unmodifiableSet(languages);
+        }
+
         @Override
         public boolean contains(final String language) {
-            return false;
+            return this.languages.contains(language);
         }
 
         @Override
         public String getAny() {
-            throw new NoSuchElementException("Can't fetch any language from the empty language set.");
+            return this.languages.iterator().next();
+        }
+
+        public Set<String> getLanguages() {
+            return this.languages;
         }
 
         @Override
         public boolean isEmpty() {
-            return true;
+            return this.languages.isEmpty();
         }
 
         @Override
         public boolean isSingleton() {
-            return false;
+            return this.languages.size() == 1;
         }
 
         @Override
-        public LanguageSet restrictTo(final LanguageSet other) {
-            return this;
+        public LanguageSet merge(final LanguageSet other) {
+            if (other == NO_LANGUAGES) {
+                return this;
+            }
+            if (other == ANY_LANGUAGE) {
+                return other;
+            }
+            final SomeLanguages someLanguages = (SomeLanguages) other;
+            final Set<String> set = new HashSet<>(languages);
+            set.addAll(someLanguages.languages);
+            return from(set);
         }
 
         @Override
-        public LanguageSet merge(final LanguageSet other) {
-            return other;
+        public LanguageSet restrictTo(final LanguageSet other) {
+            if (other == NO_LANGUAGES) {
+                return other;
+            }
+            if (other == ANY_LANGUAGE) {
+                return this;
+            }
+            final SomeLanguages someLanguages = (SomeLanguages) other;
+            return from(languages.stream().filter(lang -> someLanguages.languages.contains(lang)).collect(Collectors.toSet()));
         }
 
         @Override
         public String toString() {
-            return "NO_LANGUAGES";
+            return "Languages(" + languages.toString() + ")";
         }
-    };
+
+    }
+
+    public static final String ANY = "any";
+
+    private static final Map<NameType, Languages> LANGUAGES = new EnumMap<>(NameType.class);
 
     /**
-     * Any/all languages.
+     * No languages at all.
      */
-    public static final LanguageSet ANY_LANGUAGE = new LanguageSet() {
+    public static final LanguageSet NO_LANGUAGES = new LanguageSet() {
         @Override
         public boolean contains(final String language) {
-            return true;
+            return false;
         }
 
         @Override
         public String getAny() {
-            throw new NoSuchElementException("Can't fetch any language from the any language set.");
+            throw new NoSuchElementException("Can't fetch any language from the empty language set.");
         }
 
         @Override
         public boolean isEmpty() {
-            return false;
+            return true;
         }
 
         @Override
@@ -134,111 +183,60 @@ public class Languages {
         }
 
         @Override
-        public LanguageSet restrictTo(final LanguageSet other) {
+        public LanguageSet merge(final LanguageSet other) {
             return other;
         }
 
         @Override
-        public LanguageSet merge(final LanguageSet other) {
-            return other;
+        public LanguageSet restrictTo(final LanguageSet other) {
+            return this;
         }
 
         @Override
         public String toString() {
-            return "ANY_LANGUAGE";
+            return "NO_LANGUAGES";
         }
     };
 
-    private final Set<String> languages;
-
     /**
-     * A set of languages.
-     */
-    public static abstract class LanguageSet {
-
-        public static LanguageSet from(final Set<String> langs) {
-            return langs.isEmpty() ? NO_LANGUAGES : new SomeLanguages(langs);
-        }
-
-        public abstract boolean contains(String language);
-
-        public abstract String getAny();
-
-        public abstract boolean isEmpty();
-
-        public abstract boolean isSingleton();
-
-        public abstract LanguageSet restrictTo(LanguageSet other);
-
-        abstract LanguageSet merge(LanguageSet other);
-    }
-
-    /**
-     * Some languages, explicitly enumerated.
+     * Any/all languages.
      */
-    public static final class SomeLanguages extends LanguageSet {
-        private final Set<String> languages;
-
-        private SomeLanguages(final Set<String> languages) {
-            this.languages = Collections.unmodifiableSet(languages);
-        }
-
+    public static final LanguageSet ANY_LANGUAGE = new LanguageSet() {
         @Override
         public boolean contains(final String language) {
-            return this.languages.contains(language);
+            return true;
         }
 
         @Override
         public String getAny() {
-            return this.languages.iterator().next();
-        }
-
-        public Set<String> getLanguages() {
-            return this.languages;
+            throw new NoSuchElementException("Can't fetch any language from the any language set.");
         }
 
         @Override
         public boolean isEmpty() {
-            return this.languages.isEmpty();
+            return false;
         }
 
         @Override
         public boolean isSingleton() {
-            return this.languages.size() == 1;
+            return false;
         }
 
         @Override
-        public LanguageSet restrictTo(final LanguageSet other) {
-            if (other == NO_LANGUAGES) {
-                return other;
-            }
-            if (other == ANY_LANGUAGE) {
-                return this;
-            }
-            final SomeLanguages someLanguages = (SomeLanguages) other;
-            return from(languages.stream().filter(lang -> someLanguages.languages.contains(lang)).collect(Collectors.toSet()));
+        public LanguageSet merge(final LanguageSet other) {
+            return other;
         }
 
         @Override
-        public LanguageSet merge(final LanguageSet other) {
-            if (other == NO_LANGUAGES) {
-                return this;
-            }
-            if (other == ANY_LANGUAGE) {
-                return other;
-            }
-            final SomeLanguages someLanguages = (SomeLanguages) other;
-            final Set<String> set = new HashSet<>(languages);
-            set.addAll(someLanguages.languages);
-            return from(set);
+        public LanguageSet restrictTo(final LanguageSet other) {
+            return other;
         }
 
         @Override
         public String toString() {
-            return "Languages(" + languages.toString() + ")";
+            return "ANY_LANGUAGE";
         }
-
-    }
+    };
 
     static {
         for (final NameType s : NameType.values()) {
@@ -276,6 +274,8 @@ public class Languages {
         return String.format("org/apache/commons/codec/language/bm/%s_languages.txt", nameType.getName());
     }
 
+    private final Set<String> languages;
+
     private Languages(final Set<String> languages) {
         this.languages = languages;
     }
diff --git a/src/main/java/org/apache/commons/codec/language/bm/PhoneticEngine.java b/src/main/java/org/apache/commons/codec/language/bm/PhoneticEngine.java
index 85fa753a..ef69a2a4 100644
--- a/src/main/java/org/apache/commons/codec/language/bm/PhoneticEngine.java
+++ b/src/main/java/org/apache/commons/codec/language/bm/PhoneticEngine.java
@@ -55,34 +55,6 @@ import org.apache.commons.codec.language.bm.Rule.Phoneme;
  */
 public class PhoneticEngine {
 
-    private static final int DEFAULT_MAX_PHONEMES = 20;
-
-    private static final Map<NameType, Set<String>> NAME_PREFIXES = new EnumMap<>(NameType.class);
-
-    private final Lang lang;
-
-    private final NameType nameType;
-
-    private final RuleType ruleType;
-
-    private final boolean concat;
-
-    private final int maxPhonemes;
-
-    static {
-        NAME_PREFIXES.put(NameType.ASHKENAZI,
-                Collections.unmodifiableSet(
-                        new HashSet<>(Arrays.asList("bar", "ben", "da", "de", "van", "von"))));
-        NAME_PREFIXES.put(NameType.SEPHARDIC,
-                Collections.unmodifiableSet(
-                        new HashSet<>(Arrays.asList("al", "el", "da", "dal", "de", "del", "dela", "de la",
-                                                          "della", "des", "di", "do", "dos", "du", "van", "von"))));
-        NAME_PREFIXES.put(NameType.GENERIC,
-                Collections.unmodifiableSet(
-                        new HashSet<>(Arrays.asList("da", "dal", "de", "del", "dela", "de la", "della",
-                                                          "des", "di", "do", "dos", "du", "van", "von"))));
-    }
-
     /**
      * Utility for manipulating a set of phonemes as they are being built up. Not intended for use outside
      * this package, and probably not outside the {@link PhoneticEngine} class.
@@ -91,8 +63,6 @@ public class PhoneticEngine {
      */
     static final class PhonemeBuilder {
 
-        private final Set<Rule.Phoneme> phonemes;
-
         /**
          * An empty builder where all phonemes must come from some set of languages. This will contain a single
          * phoneme of zero characters. This can then be appended to. This should be the only way to create a new
@@ -105,6 +75,8 @@ public class PhoneticEngine {
             return new PhonemeBuilder(new Rule.Phoneme("", languages));
         }
 
+        private final Set<Rule.Phoneme> phonemes;
+
         private PhonemeBuilder(final Rule.Phoneme phoneme) {
             this.phonemes = new LinkedHashSet<>();
             this.phonemes.add(phoneme);
@@ -251,6 +223,24 @@ public class PhoneticEngine {
         }
     }
 
+    private static final int DEFAULT_MAX_PHONEMES = 20;
+
+    private static final Map<NameType, Set<String>> NAME_PREFIXES = new EnumMap<>(NameType.class);
+
+    static {
+        NAME_PREFIXES.put(NameType.ASHKENAZI,
+                Collections.unmodifiableSet(
+                        new HashSet<>(Arrays.asList("bar", "ben", "da", "de", "van", "von"))));
+        NAME_PREFIXES.put(NameType.SEPHARDIC,
+                Collections.unmodifiableSet(
+                        new HashSet<>(Arrays.asList("al", "el", "da", "dal", "de", "del", "dela", "de la",
+                                                          "della", "des", "di", "do", "dos", "du", "van", "von"))));
+        NAME_PREFIXES.put(NameType.GENERIC,
+                Collections.unmodifiableSet(
+                        new HashSet<>(Arrays.asList("da", "dal", "de", "del", "dela", "de la", "della",
+                                                          "des", "di", "do", "dos", "du", "van", "von"))));
+    }
+
     /**
      * Joins some strings with an internal separator.
      *
@@ -262,6 +252,16 @@ public class PhoneticEngine {
         return strings.stream().collect(Collectors.joining(sep));
     }
 
+    private final Lang lang;
+
+    private final NameType nameType;
+
+    private final RuleType ruleType;
+
+    private final boolean concat;
+
+    private final int maxPhonemes;
+
     /**
      * Generates a new, fully-configured phonetic engine.
      *
@@ -466,6 +466,16 @@ public class PhoneticEngine {
         return this.lang;
     }
 
+    /**
+     * Gets the maximum number of phonemes the engine will calculate for a given input.
+     *
+     * @return the maximum number of phonemes
+     * @since 1.7
+     */
+    public int getMaxPhonemes() {
+        return this.maxPhonemes;
+    }
+
     /**
      * Gets the NameType being used.
      *
@@ -492,14 +502,4 @@ public class PhoneticEngine {
     public boolean isConcat() {
         return this.concat;
     }
-
-    /**
-     * Gets the maximum number of phonemes the engine will calculate for a given input.
-     *
-     * @return the maximum number of phonemes
-     * @since 1.7
-     */
-    public int getMaxPhonemes() {
-        return this.maxPhonemes;
-    }
 }
diff --git a/src/main/java/org/apache/commons/codec/language/bm/Rule.java b/src/main/java/org/apache/commons/codec/language/bm/Rule.java
index 620195d7..028a22f4 100644
--- a/src/main/java/org/apache/commons/codec/language/bm/Rule.java
+++ b/src/main/java/org/apache/commons/codec/language/bm/Rule.java
@@ -84,32 +84,8 @@ import org.apache.commons.codec.language.bm.Languages.LanguageSet;
  */
 public class Rule {
 
-    public static final RPattern ALL_STRINGS_RMATCHER = input -> true;
-
-    public static final String ALL = "ALL";
-
-    private static final String DOUBLE_QUOTE = "\"";
-
-    private static final String HASH_INCLUDE = "#include";
-
-    private static final int HASH_INCLUDE_LENGTH = HASH_INCLUDE.length();
-
-    private static final Map<NameType, Map<RuleType, Map<String, Map<String, List<Rule>>>>> RULES =
-            new EnumMap<>(NameType.class);
-
-    private final RPattern lContext;
-
-    private final String pattern;
-
-    private final PhonemeExpr phoneme;
-
-    private final RPattern rContext;
-
     public static final class Phoneme implements PhonemeExpr {
 
-        private final StringBuilder phonemeText;
-        private final Languages.LanguageSet languages;
-
         public static final Comparator<Phoneme> COMPARATOR = (o1, o2) -> {
             final int o1Length = o1.phonemeText.length();
             final int o2Length = o2.phonemeText.length();
@@ -129,6 +105,9 @@ public class Rule {
 
             return 0;
         };
+        private final StringBuilder phonemeText;
+
+        private final Languages.LanguageSet languages;
 
         public Phoneme(final CharSequence phonemeText, final Languages.LanguageSet languages) {
             this.phonemeText = new StringBuilder(phonemeText);
@@ -218,6 +197,19 @@ public class Rule {
         boolean isMatch(CharSequence input);
     }
 
+    public static final RPattern ALL_STRINGS_RMATCHER = input -> true;
+
+    public static final String ALL = "ALL";
+
+    private static final String DOUBLE_QUOTE = "\"";
+
+    private static final String HASH_INCLUDE = "#include";
+
+    private static final int HASH_INCLUDE_LENGTH = HASH_INCLUDE.length();
+
+    private static final Map<NameType, Map<RuleType, Map<String, Map<String, List<Rule>>>>> RULES =
+            new EnumMap<>(NameType.class);
+
     static {
         for (final NameType s : NameType.values()) {
             final Map<RuleType, Map<String, Map<String, List<Rule>>>> rts =
@@ -579,6 +571,14 @@ public class Rule {
         return str;
     }
 
+    private final RPattern lContext;
+
+    private final String pattern;
+
+    private final PhonemeExpr phoneme;
+
+    private final RPattern rContext;
+
     /**
      * Creates a new rule.
      *
diff --git a/src/main/java/org/apache/commons/codec/net/BCodec.java b/src/main/java/org/apache/commons/codec/net/BCodec.java
index 943f2ea8..481cd1e0 100644
--- a/src/main/java/org/apache/commons/codec/net/BCodec.java
+++ b/src/main/java/org/apache/commons/codec/net/BCodec.java
@@ -114,30 +114,49 @@ public class BCodec extends RFC1522Codec implements StringEncoder, StringDecoder
     }
 
     /**
-     * Returns true if decoding behavior is strict. Decoding will raise a
-     * {@link DecoderException} if trailing bits are not part of a valid Base64 encoding.
-     *
-     * <p>The default is false for lenient encoding. Decoding will compose trailing bits
-     * into 8-bit bytes and discard the remainder.
+     * Decodes a Base64 object into its original form. Escaped characters are converted back to their original
+     * representation.
      *
-     * @return true if using strict decoding
-     * @since 1.15
+     * @param value
+     *            Base64 object to convert into its original form
+     * @return original object
+     * @throws DecoderException
+     *             Thrown if the argument is not a {@code String}. Thrown if a failure condition is encountered
+     *             during the decode process.
      */
-    public boolean isStrictDecoding() {
-        return decodingPolicy == CodecPolicy.STRICT;
-    }
-
     @Override
-    protected String getEncoding() {
-        return "B";
+    public Object decode(final Object value) throws DecoderException {
+        if (value == null) {
+            return null;
+        }
+        if (value instanceof String) {
+            return decode((String) value);
+        }
+        throw new DecoderException("Objects of type " +
+              value.getClass().getName() +
+              " cannot be decoded using BCodec");
     }
 
+    /**
+     * Decodes a Base64 string into its original form. Escaped characters are converted back to their original
+     * representation.
+     *
+     * @param value
+     *            Base64 string to convert into its original form
+     * @return original string
+     * @throws DecoderException
+     *             A decoder exception is thrown if a failure condition is encountered during the decode process.
+     */
     @Override
-    protected byte[] doEncoding(final byte[] bytes) {
-        if (bytes == null) {
+    public String decode(final String value) throws DecoderException {
+        if (value == null) {
             return null;
         }
-        return Base64.encodeBase64(bytes);
+        try {
+            return this.decodeText(value);
+        } catch (final UnsupportedEncodingException | IllegalArgumentException e) {
+            throw new DecoderException(e.getMessage(), e);
+        }
     }
 
     @Override
@@ -148,45 +167,34 @@ public class BCodec extends RFC1522Codec implements StringEncoder, StringDecoder
         return new Base64(0, BaseNCodec.getChunkSeparator(), false, decodingPolicy).decode(bytes);
     }
 
-    /**
-     * Encodes a string into its Base64 form using the specified Charset. Unsafe characters are escaped.
-     *
-     * @param strSource
-     *            string to convert to Base64 form
-     * @param sourceCharset
-     *            the Charset for {@code value}
-     * @return Base64 string
-     * @throws EncoderException
-     *             thrown if a failure condition is encountered during the encoding process.
-     * @since 1.7
-     */
-    public String encode(final String strSource, final Charset sourceCharset) throws EncoderException {
-        if (strSource == null) {
+    @Override
+    protected byte[] doEncoding(final byte[] bytes) {
+        if (bytes == null) {
             return null;
         }
-        return encodeText(strSource, sourceCharset);
+        return Base64.encodeBase64(bytes);
     }
 
     /**
-     * Encodes a string into its Base64 form using the specified Charset. Unsafe characters are escaped.
+     * Encodes an object into its Base64 form using the default Charset. Unsafe characters are escaped.
      *
-     * @param strSource
-     *            string to convert to Base64 form
-     * @param sourceCharset
-     *            the Charset for {@code value}
-     * @return Base64 string
+     * @param value
+     *            object to convert to Base64 form
+     * @return Base64 object
      * @throws EncoderException
      *             thrown if a failure condition is encountered during the encoding process.
      */
-    public String encode(final String strSource, final String sourceCharset) throws EncoderException {
-        if (strSource == null) {
+    @Override
+    public Object encode(final Object value) throws EncoderException {
+        if (value == null) {
             return null;
         }
-        try {
-            return this.encodeText(strSource, sourceCharset);
-        } catch (final UnsupportedEncodingException e) {
-            throw new EncoderException(e.getMessage(), e);
+        if (value instanceof String) {
+            return encode((String) value);
         }
+        throw new EncoderException("Objects of type " +
+              value.getClass().getName() +
+              " cannot be encoded using BCodec");
     }
 
     /**
@@ -207,71 +215,44 @@ public class BCodec extends RFC1522Codec implements StringEncoder, StringDecoder
     }
 
     /**
-     * Decodes a Base64 string into its original form. Escaped characters are converted back to their original
-     * representation.
-     *
-     * @param value
-     *            Base64 string to convert into its original form
-     * @return original string
-     * @throws DecoderException
-     *             A decoder exception is thrown if a failure condition is encountered during the decode process.
-     */
-    @Override
-    public String decode(final String value) throws DecoderException {
-        if (value == null) {
-            return null;
-        }
-        try {
-            return this.decodeText(value);
-        } catch (final UnsupportedEncodingException | IllegalArgumentException e) {
-            throw new DecoderException(e.getMessage(), e);
-        }
-    }
-
-    /**
-     * Encodes an object into its Base64 form using the default Charset. Unsafe characters are escaped.
+     * Encodes a string into its Base64 form using the specified Charset. Unsafe characters are escaped.
      *
-     * @param value
-     *            object to convert to Base64 form
-     * @return Base64 object
+     * @param strSource
+     *            string to convert to Base64 form
+     * @param sourceCharset
+     *            the Charset for {@code value}
+     * @return Base64 string
      * @throws EncoderException
      *             thrown if a failure condition is encountered during the encoding process.
+     * @since 1.7
      */
-    @Override
-    public Object encode(final Object value) throws EncoderException {
-        if (value == null) {
+    public String encode(final String strSource, final Charset sourceCharset) throws EncoderException {
+        if (strSource == null) {
             return null;
         }
-        if (value instanceof String) {
-            return encode((String) value);
-        }
-        throw new EncoderException("Objects of type " +
-              value.getClass().getName() +
-              " cannot be encoded using BCodec");
+        return encodeText(strSource, sourceCharset);
     }
 
     /**
-     * Decodes a Base64 object into its original form. Escaped characters are converted back to their original
-     * representation.
+     * Encodes a string into its Base64 form using the specified Charset. Unsafe characters are escaped.
      *
-     * @param value
-     *            Base64 object to convert into its original form
-     * @return original object
-     * @throws DecoderException
-     *             Thrown if the argument is not a {@code String}. Thrown if a failure condition is encountered
-     *             during the decode process.
+     * @param strSource
+     *            string to convert to Base64 form
+     * @param sourceCharset
+     *            the Charset for {@code value}
+     * @return Base64 string
+     * @throws EncoderException
+     *             thrown if a failure condition is encountered during the encoding process.
      */
-    @Override
-    public Object decode(final Object value) throws DecoderException {
-        if (value == null) {
+    public String encode(final String strSource, final String sourceCharset) throws EncoderException {
+        if (strSource == null) {
             return null;
         }
-        if (value instanceof String) {
-            return decode((String) value);
+        try {
+            return this.encodeText(strSource, sourceCharset);
+        } catch (final UnsupportedEncodingException e) {
+            throw new EncoderException(e.getMessage(), e);
         }
-        throw new DecoderException("Objects of type " +
-              value.getClass().getName() +
-              " cannot be decoded using BCodec");
     }
 
     /**
@@ -292,4 +273,23 @@ public class BCodec extends RFC1522Codec implements StringEncoder, StringDecoder
     public String getDefaultCharset() {
         return this.charset.name();
     }
+
+    @Override
+    protected String getEncoding() {
+        return "B";
+    }
+
+    /**
+     * Returns true if decoding behavior is strict. Decoding will raise a
+     * {@link DecoderException} if trailing bits are not part of a valid Base64 encoding.
+     *
+     * <p>The default is false for lenient encoding. Decoding will compose trailing bits
+     * into 8-bit bytes and discard the remainder.
+     *
+     * @return true if using strict decoding
+     * @since 1.15
+     */
+    public boolean isStrictDecoding() {
+        return decodingPolicy == CodecPolicy.STRICT;
+    }
 }
diff --git a/src/main/java/org/apache/commons/codec/net/PercentCodec.java b/src/main/java/org/apache/commons/codec/net/PercentCodec.java
index 31288642..8e515381 100644
--- a/src/main/java/org/apache/commons/codec/net/PercentCodec.java
+++ b/src/main/java/org/apache/commons/codec/net/PercentCodec.java
@@ -83,52 +83,65 @@ public class PercentCodec implements BinaryEncoder, BinaryDecoder {
         insertAlwaysEncodeChars(alwaysEncodeChars);
     }
 
-    /**
-     * Adds the byte array into a BitSet for faster lookup
-     *
-     * @param alwaysEncodeCharsArray
-     */
-    private void insertAlwaysEncodeChars(final byte[] alwaysEncodeCharsArray) {
-        if (alwaysEncodeCharsArray != null) {
-            for (final byte b : alwaysEncodeCharsArray) {
-                insertAlwaysEncodeChar(b);
+    private boolean canEncode(final byte c) {
+        return !isAsciiChar(c) || inAlwaysEncodeCharsRange(c) && alwaysEncodeChars.get(c);
+    }
+
+    private boolean containsSpace(final byte[] bytes) {
+        for (final byte b : bytes) {
+            if (b == ' ') {
+                return true;
             }
         }
-        insertAlwaysEncodeChar(ESCAPE_CHAR);
+        return false;
     }
 
     /**
-     * Inserts a single character into a BitSet and maintains the min and max of the characters of the
-     * {@code BitSet alwaysEncodeChars} in order to avoid look-ups when a byte is out of this range.
-     *
-     * @param b the byte that is candidate for min and max limit
+     * Decode bytes encoded with Percent-Encoding based on RFC 3986. The reverse process is performed in order to
+     * decode the encoded characters to Unicode.
      */
-    private void insertAlwaysEncodeChar(final byte b) {
-        this.alwaysEncodeChars.set(b);
-        if (b < alwaysEncodeCharsMin) {
-            alwaysEncodeCharsMin = b;
+    @Override
+    public byte[] decode(final byte[] bytes) throws DecoderException {
+        if (bytes == null) {
+            return null;
         }
-        if (b > alwaysEncodeCharsMax) {
-            alwaysEncodeCharsMax = b;
+
+        final ByteBuffer buffer = ByteBuffer.allocate(expectedDecodingBytes(bytes));
+        for (int i = 0; i < bytes.length; i++) {
+            final byte b = bytes[i];
+            if (b == ESCAPE_CHAR) {
+                try {
+                    final int u = Utils.digit16(bytes[++i]);
+                    final int l = Utils.digit16(bytes[++i]);
+                    buffer.put((byte) ((u << 4) + l));
+                } catch (final ArrayIndexOutOfBoundsException e) {
+                    throw new DecoderException("Invalid percent decoding: ", e);
+                }
+            } else if (plusForSpace && b == '+') {
+                buffer.put((byte) ' ');
+            } else {
+                buffer.put(b);
+            }
         }
+        return buffer.array();
     }
 
     /**
-     * Percent-Encoding based on RFC 3986. The non US-ASCII characters are encoded, as well as the
-     * US-ASCII characters that are configured to be always encoded.
+     * Decodes a byte[] Object, whose bytes are encoded with Percent-Encoding.
+     *
+     * @param obj the object to decode
+     * @return the decoding result byte[] as Object
+     * @throws DecoderException if the object is not a byte array
      */
     @Override
-    public byte[] encode(final byte[] bytes) throws EncoderException {
-        if (bytes == null) {
+    public Object decode(final Object obj) throws DecoderException {
+        if (obj == null) {
             return null;
         }
-
-        final int expectedEncodingBytes = expectedEncodingBytes(bytes);
-        final boolean willEncode = expectedEncodingBytes != bytes.length;
-        if (willEncode || plusForSpace && containsSpace(bytes)) {
-            return doEncode(bytes, expectedEncodingBytes, willEncode);
+        if (obj instanceof byte[]) {
+            return decode((byte[]) obj);
         }
-        return bytes;
+        throw new DecoderException("Objects of type " + obj.getClass().getName() + " cannot be Percent decoded");
     }
 
     private byte[] doEncode(final byte[] bytes, final int expectedLength, final boolean willEncode) {
@@ -153,63 +166,40 @@ public class PercentCodec implements BinaryEncoder, BinaryDecoder {
         return buffer.array();
     }
 
-    private int expectedEncodingBytes(final byte[] bytes) {
-        int byteCount = 0;
-        for (final byte b : bytes) {
-            byteCount += canEncode(b) ? 3: 1;
+    /**
+     * Percent-Encoding based on RFC 3986. The non US-ASCII characters are encoded, as well as the
+     * US-ASCII characters that are configured to be always encoded.
+     */
+    @Override
+    public byte[] encode(final byte[] bytes) throws EncoderException {
+        if (bytes == null) {
+            return null;
         }
-        return byteCount;
-    }
 
-    private boolean containsSpace(final byte[] bytes) {
-        for (final byte b : bytes) {
-            if (b == ' ') {
-                return true;
-            }
+        final int expectedEncodingBytes = expectedEncodingBytes(bytes);
+        final boolean willEncode = expectedEncodingBytes != bytes.length;
+        if (willEncode || plusForSpace && containsSpace(bytes)) {
+            return doEncode(bytes, expectedEncodingBytes, willEncode);
         }
-        return false;
-    }
-
-    private boolean canEncode(final byte c) {
-        return !isAsciiChar(c) || inAlwaysEncodeCharsRange(c) && alwaysEncodeChars.get(c);
-    }
-
-    private boolean inAlwaysEncodeCharsRange(final byte c) {
-        return c >= alwaysEncodeCharsMin && c <= alwaysEncodeCharsMax;
-    }
-
-    private boolean isAsciiChar(final byte c) {
-        return c >= 0;
+        return bytes;
     }
 
     /**
-     * Decode bytes encoded with Percent-Encoding based on RFC 3986. The reverse process is performed in order to
-     * decode the encoded characters to Unicode.
+     * Encodes an object into using the Percent-Encoding. Only byte[] objects are accepted.
+     *
+     * @param obj the object to encode
+     * @return the encoding result byte[] as Object
+     * @throws EncoderException if the object is not a byte array
      */
     @Override
-    public byte[] decode(final byte[] bytes) throws DecoderException {
-        if (bytes == null) {
+    public Object encode(final Object obj) throws EncoderException {
+        if (obj == null) {
             return null;
         }
-
-        final ByteBuffer buffer = ByteBuffer.allocate(expectedDecodingBytes(bytes));
-        for (int i = 0; i < bytes.length; i++) {
-            final byte b = bytes[i];
-            if (b == ESCAPE_CHAR) {
-                try {
-                    final int u = Utils.digit16(bytes[++i]);
-                    final int l = Utils.digit16(bytes[++i]);
-                    buffer.put((byte) ((u << 4) + l));
-                } catch (final ArrayIndexOutOfBoundsException e) {
-                    throw new DecoderException("Invalid percent decoding: ", e);
-                }
-            } else if (plusForSpace && b == '+') {
-                buffer.put((byte) ' ');
-            } else {
-                buffer.put(b);
-            }
+        if (obj instanceof byte[]) {
+            return encode((byte[]) obj);
         }
-        return buffer.array();
+        throw new EncoderException("Objects of type " + obj.getClass().getName() + " cannot be Percent encoded");
     }
 
     private int expectedDecodingBytes(final byte[] bytes) {
@@ -222,39 +212,49 @@ public class PercentCodec implements BinaryEncoder, BinaryDecoder {
         return byteCount;
     }
 
+    private int expectedEncodingBytes(final byte[] bytes) {
+        int byteCount = 0;
+        for (final byte b : bytes) {
+            byteCount += canEncode(b) ? 3: 1;
+        }
+        return byteCount;
+    }
+
+    private boolean inAlwaysEncodeCharsRange(final byte c) {
+        return c >= alwaysEncodeCharsMin && c <= alwaysEncodeCharsMax;
+    }
+
     /**
-     * Encodes an object into using the Percent-Encoding. Only byte[] objects are accepted.
+     * Inserts a single character into a BitSet and maintains the min and max of the characters of the
+     * {@code BitSet alwaysEncodeChars} in order to avoid look-ups when a byte is out of this range.
      *
-     * @param obj the object to encode
-     * @return the encoding result byte[] as Object
-     * @throws EncoderException if the object is not a byte array
+     * @param b the byte that is candidate for min and max limit
      */
-    @Override
-    public Object encode(final Object obj) throws EncoderException {
-        if (obj == null) {
-            return null;
+    private void insertAlwaysEncodeChar(final byte b) {
+        this.alwaysEncodeChars.set(b);
+        if (b < alwaysEncodeCharsMin) {
+            alwaysEncodeCharsMin = b;
         }
-        if (obj instanceof byte[]) {
-            return encode((byte[]) obj);
+        if (b > alwaysEncodeCharsMax) {
+            alwaysEncodeCharsMax = b;
         }
-        throw new EncoderException("Objects of type " + obj.getClass().getName() + " cannot be Percent encoded");
     }
 
     /**
-     * Decodes a byte[] Object, whose bytes are encoded with Percent-Encoding.
+     * Adds the byte array into a BitSet for faster lookup
      *
-     * @param obj the object to decode
-     * @return the decoding result byte[] as Object
-     * @throws DecoderException if the object is not a byte array
+     * @param alwaysEncodeCharsArray
      */
-    @Override
-    public Object decode(final Object obj) throws DecoderException {
-        if (obj == null) {
-            return null;
-        }
-        if (obj instanceof byte[]) {
-            return decode((byte[]) obj);
+    private void insertAlwaysEncodeChars(final byte[] alwaysEncodeCharsArray) {
+        if (alwaysEncodeCharsArray != null) {
+            for (final byte b : alwaysEncodeCharsArray) {
+                insertAlwaysEncodeChar(b);
+            }
         }
-        throw new DecoderException("Objects of type " + obj.getClass().getName() + " cannot be Percent decoded");
+        insertAlwaysEncodeChar(ESCAPE_CHAR);
+    }
+
+    private boolean isAsciiChar(final byte c) {
+        return c >= 0;
     }
 }
diff --git a/src/main/java/org/apache/commons/codec/net/QCodec.java b/src/main/java/org/apache/commons/codec/net/QCodec.java
index 6717cf78..e5b4c215 100644
--- a/src/main/java/org/apache/commons/codec/net/QCodec.java
+++ b/src/main/java/org/apache/commons/codec/net/QCodec.java
@@ -51,15 +51,11 @@ import org.apache.commons.codec.StringEncoder;
  * @since 1.3
  */
 public class QCodec extends RFC1522Codec implements StringEncoder, StringDecoder {
-    /**
-     * The default Charset used for string decoding and encoding.
-     */
-    private final Charset charset;
-
     /**
      * BitSet of printable characters as defined in RFC 1522.
      */
     private static final BitSet PRINTABLE_CHARS = new BitSet(256);
+
     // Static initializer for printable chars collection
     static {
         // alpha characters
@@ -103,11 +99,15 @@ public class QCodec extends RFC1522Codec implements StringEncoder, StringDecoder
         PRINTABLE_CHARS.set('}');
         PRINTABLE_CHARS.set('~');
     }
-
     private static final byte SPACE = 32;
 
     private static final byte UNDERSCORE = 95;
 
+    /**
+     * The default Charset used for string decoding and encoding.
+     */
+    private final Charset charset;
+
     private boolean encodeBlanks = false;
 
     /**
@@ -144,25 +144,50 @@ public class QCodec extends RFC1522Codec implements StringEncoder, StringDecoder
         this(Charset.forName(charsetName));
     }
 
+    /**
+     * Decodes a quoted-printable object into its original form. Escaped characters are converted back to their original
+     * representation.
+     *
+     * @param obj
+     *            quoted-printable object to convert into its original form
+     * @return original object
+     * @throws DecoderException
+     *             Thrown if the argument is not a {@code String}. Thrown if a failure condition is encountered
+     *             during the decode process.
+     */
     @Override
-    protected String getEncoding() {
-        return "Q";
+    public Object decode(final Object obj) throws DecoderException {
+        if (obj == null) {
+            return null;
+        }
+        if (obj instanceof String) {
+            return decode((String) obj);
+        }
+        throw new DecoderException("Objects of type " +
+              obj.getClass().getName() +
+              " cannot be decoded using Q codec");
     }
 
+    /**
+     * Decodes a quoted-printable string into its original form. Escaped characters are converted back to their original
+     * representation.
+     *
+     * @param str
+     *            quoted-printable string to convert into its original form
+     * @return original string
+     * @throws DecoderException
+     *             A decoder exception is thrown if a failure condition is encountered during the decode process.
+     */
     @Override
-    protected byte[] doEncoding(final byte[] bytes) {
-        if (bytes == null) {
+    public String decode(final String str) throws DecoderException {
+        if (str == null) {
             return null;
         }
-        final byte[] data = QuotedPrintableCodec.encodeQuotedPrintable(PRINTABLE_CHARS, bytes);
-        if (this.encodeBlanks) {
-            for (int i = 0; i < data.length; i++) {
-                if (data[i] == SPACE) {
-                    data[i] = UNDERSCORE;
-                }
-            }
+        try {
+            return decodeText(str);
+        } catch (final UnsupportedEncodingException e) {
+            throw new DecoderException(e.getMessage(), e);
         }
-        return data;
     }
 
     @Override
@@ -192,45 +217,42 @@ public class QCodec extends RFC1522Codec implements StringEncoder, StringDecoder
         return QuotedPrintableCodec.decodeQuotedPrintable(bytes);
     }
 
-    /**
-     * Encodes a string into its quoted-printable form using the specified Charset. Unsafe characters are escaped.
-     *
-     * @param sourceStr
-     *            string to convert to quoted-printable form
-     * @param sourceCharset
-     *            the Charset for sourceStr
-     * @return quoted-printable string
-     * @throws EncoderException
-     *             thrown if a failure condition is encountered during the encoding process.
-     * @since 1.7
-     */
-    public String encode(final String sourceStr, final Charset sourceCharset) throws EncoderException {
-        if (sourceStr == null) {
+    @Override
+    protected byte[] doEncoding(final byte[] bytes) {
+        if (bytes == null) {
             return null;
         }
-        return encodeText(sourceStr, sourceCharset);
+        final byte[] data = QuotedPrintableCodec.encodeQuotedPrintable(PRINTABLE_CHARS, bytes);
+        if (this.encodeBlanks) {
+            for (int i = 0; i < data.length; i++) {
+                if (data[i] == SPACE) {
+                    data[i] = UNDERSCORE;
+                }
+            }
+        }
+        return data;
     }
 
     /**
-     * Encodes a string into its quoted-printable form using the specified Charset. Unsafe characters are escaped.
+     * Encodes an object into its quoted-printable form using the default Charset. Unsafe characters are escaped.
      *
-     * @param sourceStr
-     *            string to convert to quoted-printable form
-     * @param sourceCharset
-     *            the Charset for sourceStr
-     * @return quoted-printable string
+     * @param obj
+     *            object to convert to quoted-printable form
+     * @return quoted-printable object
      * @throws EncoderException
      *             thrown if a failure condition is encountered during the encoding process.
      */
-    public String encode(final String sourceStr, final String sourceCharset) throws EncoderException {
-        if (sourceStr == null) {
+    @Override
+    public Object encode(final Object obj) throws EncoderException {
+        if (obj == null) {
             return null;
         }
-        try {
-            return encodeText(sourceStr, sourceCharset);
-        } catch (final UnsupportedEncodingException e) {
-            throw new EncoderException(e.getMessage(), e);
+        if (obj instanceof String) {
+            return encode((String) obj);
         }
+        throw new EncoderException("Objects of type " +
+              obj.getClass().getName() +
+              " cannot be encoded using Q codec");
     }
 
     /**
@@ -251,71 +273,44 @@ public class QCodec extends RFC1522Codec implements StringEncoder, StringDecoder
     }
 
     /**
-     * Decodes a quoted-printable string into its original form. Escaped characters are converted back to their original
-     * representation.
-     *
-     * @param str
-     *            quoted-printable string to convert into its original form
-     * @return original string
-     * @throws DecoderException
-     *             A decoder exception is thrown if a failure condition is encountered during the decode process.
-     */
-    @Override
-    public String decode(final String str) throws DecoderException {
-        if (str == null) {
-            return null;
-        }
-        try {
-            return decodeText(str);
-        } catch (final UnsupportedEncodingException e) {
-            throw new DecoderException(e.getMessage(), e);
-        }
-    }
-
-    /**
-     * Encodes an object into its quoted-printable form using the default Charset. Unsafe characters are escaped.
+     * Encodes a string into its quoted-printable form using the specified Charset. Unsafe characters are escaped.
      *
-     * @param obj
-     *            object to convert to quoted-printable form
-     * @return quoted-printable object
+     * @param sourceStr
+     *            string to convert to quoted-printable form
+     * @param sourceCharset
+     *            the Charset for sourceStr
+     * @return quoted-printable string
      * @throws EncoderException
      *             thrown if a failure condition is encountered during the encoding process.
+     * @since 1.7
      */
-    @Override
-    public Object encode(final Object obj) throws EncoderException {
-        if (obj == null) {
+    public String encode(final String sourceStr, final Charset sourceCharset) throws EncoderException {
+        if (sourceStr == null) {
             return null;
         }
-        if (obj instanceof String) {
-            return encode((String) obj);
-        }
-        throw new EncoderException("Objects of type " +
-              obj.getClass().getName() +
-              " cannot be encoded using Q codec");
+        return encodeText(sourceStr, sourceCharset);
     }
 
     /**
-     * Decodes a quoted-printable object into its original form. Escaped characters are converted back to their original
-     * representation.
+     * Encodes a string into its quoted-printable form using the specified Charset. Unsafe characters are escaped.
      *
-     * @param obj
-     *            quoted-printable object to convert into its original form
-     * @return original object
-     * @throws DecoderException
-     *             Thrown if the argument is not a {@code String}. Thrown if a failure condition is encountered
-     *             during the decode process.
+     * @param sourceStr
+     *            string to convert to quoted-printable form
+     * @param sourceCharset
+     *            the Charset for sourceStr
+     * @return quoted-printable string
+     * @throws EncoderException
+     *             thrown if a failure condition is encountered during the encoding process.
      */
-    @Override
-    public Object decode(final Object obj) throws DecoderException {
-        if (obj == null) {
+    public String encode(final String sourceStr, final String sourceCharset) throws EncoderException {
+        if (sourceStr == null) {
             return null;
         }
-        if (obj instanceof String) {
-            return decode((String) obj);
+        try {
+            return encodeText(sourceStr, sourceCharset);
+        } catch (final UnsupportedEncodingException e) {
+            throw new EncoderException(e.getMessage(), e);
         }
-        throw new DecoderException("Objects of type " +
-              obj.getClass().getName() +
-              " cannot be decoded using Q codec");
     }
 
     /**
@@ -337,6 +332,11 @@ public class QCodec extends RFC1522Codec implements StringEncoder, StringDecoder
         return this.charset.name();
     }
 
+    @Override
+    protected String getEncoding() {
+        return "Q";
+    }
+
     /**
      * Tests if optional transformation of SPACE characters is to be used
      *
diff --git a/src/main/java/org/apache/commons/codec/net/QuotedPrintableCodec.java b/src/main/java/org/apache/commons/codec/net/QuotedPrintableCodec.java
index 51487161..b6eea3ec 100644
--- a/src/main/java/org/apache/commons/codec/net/QuotedPrintableCodec.java
+++ b/src/main/java/org/apache/commons/codec/net/QuotedPrintableCodec.java
@@ -69,16 +69,6 @@ import org.apache.commons.codec.binary.StringUtils;
  * @since 1.3
  */
 public class QuotedPrintableCodec implements BinaryEncoder, BinaryDecoder, StringEncoder, StringDecoder {
-    /**
-     * The default Charset used for string decoding and encoding.
-     */
-    private final Charset charset;
-
-    /**
-     * Indicates whether soft line breaks shall be used during encoding (rule #3-5).
-     */
-    private final boolean strict;
-
     /**
      * BitSet of printable characters as defined in RFC 1521.
      */
@@ -113,102 +103,44 @@ public class QuotedPrintableCodec implements BinaryEncoder, BinaryDecoder, Strin
     }
 
     /**
-     * Default constructor, assumes default Charset of {@link StandardCharsets#UTF_8}
-     */
-    public QuotedPrintableCodec() {
-        this(StandardCharsets.UTF_8, false);
-    }
-
-    /**
-     * Constructor which allows for the selection of the strict mode.
-     *
-     * @param strict
-     *            if {@code true}, soft line breaks will be used
-     * @since 1.10
-     */
-    public QuotedPrintableCodec(final boolean strict) {
-        this(StandardCharsets.UTF_8, strict);
-    }
-
-    /**
-     * Constructor which allows for the selection of a default Charset.
-     *
-     * @param charset
-     *            the default string Charset to use.
-     * @since 1.7
-     */
-    public QuotedPrintableCodec(final Charset charset) {
-        this(charset, false);
-    }
-
-    /**
-     * Constructor which allows for the selection of a default Charset and strict mode.
-     *
-     * @param charset
-     *            the default string Charset to use.
-     * @param strict
-     *            if {@code true}, soft line breaks will be used
-     * @since 1.10
-     */
-    public QuotedPrintableCodec(final Charset charset, final boolean strict) {
-        this.charset = charset;
-        this.strict = strict;
-    }
-
-    /**
-     * Constructor which allows for the selection of a default Charset.
-     *
-     * @param charsetName
-     *            the default string Charset to use.
-     * @throws UnsupportedCharsetException
-     *             If no support for the named Charset is available
-     *             in this instance of the Java virtual machine
-     * @throws IllegalArgumentException
-     *             If the given charsetName is null
-     * @throws IllegalCharsetNameException
-     *             If the given Charset name is illegal
-     *
-     * @since 1.7 throws UnsupportedCharsetException if the named Charset is unavailable
-     */
-    public QuotedPrintableCodec(final String charsetName)
-            throws IllegalCharsetNameException, IllegalArgumentException, UnsupportedCharsetException {
-        this(Charset.forName(charsetName), false);
-    }
-
-    /**
-     * Encodes byte into its quoted-printable representation.
-     *
-     * @param b
-     *            byte to encode
-     * @param buffer
-     *            the buffer to write to
-     * @return The number of bytes written to the {@code buffer}
-     */
-    private static final int encodeQuotedPrintable(final int b, final ByteArrayOutputStream buffer) {
-        buffer.write(ESCAPE_CHAR);
-        final char hex1 = Utils.hexDigit(b >> 4);
-        final char hex2 = Utils.hexDigit(b);
-        buffer.write(hex1);
-        buffer.write(hex2);
-        return 3;
-    }
-
-    /**
-     * Return the byte at position {@code index} of the byte array and
-     * make sure it is unsigned.
+     * Decodes an array quoted-printable characters into an array of original bytes. Escaped characters are converted
+     * back to their original representation.
+     * <p>
+     * This function fully implements the quoted-printable encoding specification (rule #1 through rule #5) as
+     * defined in RFC 1521.
+     * </p>
      *
-     * @param index
-     *            position in the array
      * @param bytes
-     *            the byte array
-     * @return the unsigned octet at position {@code index} from the array
+     *            array of quoted-printable characters
+     * @return array of original bytes
+     * @throws DecoderException
+     *             Thrown if quoted-printable decoding is unsuccessful
      */
-    private static int getUnsignedOctet(final int index, final byte[] bytes) {
-        int b = bytes[index];
-        if (b < 0) {
-            b = 256 + b;
+    public static final byte[] decodeQuotedPrintable(final byte[] bytes) throws DecoderException {
+        if (bytes == null) {
+            return null;
         }
-        return b;
+        final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+        for (int i = 0; i < bytes.length; i++) {
+            final int b = bytes[i];
+            if (b == ESCAPE_CHAR) {
+                try {
+                    // if the next octet is a CR we have found a soft line break
+                    if (bytes[++i] == CR) {
+                        continue;
+                    }
+                    final int u = Utils.digit16(bytes[i]);
+                    final int l = Utils.digit16(bytes[++i]);
+                    buffer.write((char) ((u << 4) + l));
+                } catch (final ArrayIndexOutOfBoundsException e) {
+                    throw new DecoderException("Invalid quoted-printable encoding", e);
+                }
+            } else if (b != CR && b != LF) {
+                // every other octet is appended except for CR & LF
+                buffer.write(b);
+            }
+        }
+        return buffer.toByteArray();
     }
 
     /**
@@ -231,17 +163,6 @@ public class QuotedPrintableCodec implements BinaryEncoder, BinaryDecoder, Strin
         return 1;
     }
 
-    /**
-     * Checks whether the given byte is whitespace.
-     *
-     * @param b
-     *            byte to be checked
-     * @return {@code true} if the byte is either a space or tab character
-     */
-    private static boolean isWhitespace(final int b) {
-        return b == SPACE || b == TAB;
-    }
-
     /**
      * Encodes an array of bytes into an array of quoted-printable 7-bit characters. Unsafe characters are escaped.
      * <p>
@@ -344,61 +265,123 @@ public class QuotedPrintableCodec implements BinaryEncoder, BinaryDecoder, Strin
     }
 
     /**
-     * Decodes an array quoted-printable characters into an array of original bytes. Escaped characters are converted
-     * back to their original representation.
-     * <p>
-     * This function fully implements the quoted-printable encoding specification (rule #1 through rule #5) as
-     * defined in RFC 1521.
-     * </p>
+     * Encodes byte into its quoted-printable representation.
      *
+     * @param b
+     *            byte to encode
+     * @param buffer
+     *            the buffer to write to
+     * @return The number of bytes written to the {@code buffer}
+     */
+    private static final int encodeQuotedPrintable(final int b, final ByteArrayOutputStream buffer) {
+        buffer.write(ESCAPE_CHAR);
+        final char hex1 = Utils.hexDigit(b >> 4);
+        final char hex2 = Utils.hexDigit(b);
+        buffer.write(hex1);
+        buffer.write(hex2);
+        return 3;
+    }
+
+    /**
+     * Return the byte at position {@code index} of the byte array and
+     * make sure it is unsigned.
+     *
+     * @param index
+     *            position in the array
      * @param bytes
-     *            array of quoted-printable characters
-     * @return array of original bytes
-     * @throws DecoderException
-     *             Thrown if quoted-printable decoding is unsuccessful
+     *            the byte array
+     * @return the unsigned octet at position {@code index} from the array
      */
-    public static final byte[] decodeQuotedPrintable(final byte[] bytes) throws DecoderException {
-        if (bytes == null) {
-            return null;
-        }
-        final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
-        for (int i = 0; i < bytes.length; i++) {
-            final int b = bytes[i];
-            if (b == ESCAPE_CHAR) {
-                try {
-                    // if the next octet is a CR we have found a soft line break
-                    if (bytes[++i] == CR) {
-                        continue;
-                    }
-                    final int u = Utils.digit16(bytes[i]);
-                    final int l = Utils.digit16(bytes[++i]);
-                    buffer.write((char) ((u << 4) + l));
-                } catch (final ArrayIndexOutOfBoundsException e) {
-                    throw new DecoderException("Invalid quoted-printable encoding", e);
-                }
-            } else if (b != CR && b != LF) {
-                // every other octet is appended except for CR & LF
-                buffer.write(b);
-            }
+    private static int getUnsignedOctet(final int index, final byte[] bytes) {
+        int b = bytes[index];
+        if (b < 0) {
+            b = 256 + b;
         }
-        return buffer.toByteArray();
+        return b;
     }
 
     /**
-     * Encodes an array of bytes into an array of quoted-printable 7-bit characters. Unsafe characters are escaped.
-     * <p>
-     * Depending on the selection of the {@code strict} parameter, this function either implements the full ruleset
-     * or only a subset of quoted-printable encoding specification (rule #1 and rule #2) as defined in
-     * RFC 1521 and is suitable for encoding binary data and unformatted text.
-     * </p>
+     * Checks whether the given byte is whitespace.
      *
-     * @param bytes
-     *            array of bytes to be encoded
-     * @return array of bytes containing quoted-printable data
+     * @param b
+     *            byte to be checked
+     * @return {@code true} if the byte is either a space or tab character
      */
-    @Override
-    public byte[] encode(final byte[] bytes) {
-        return encodeQuotedPrintable(PRINTABLE_CHARS, bytes, strict);
+    private static boolean isWhitespace(final int b) {
+        return b == SPACE || b == TAB;
+    }
+
+    /**
+     * The default Charset used for string decoding and encoding.
+     */
+    private final Charset charset;
+
+    /**
+     * Indicates whether soft line breaks shall be used during encoding (rule #3-5).
+     */
+    private final boolean strict;
+
+    /**
+     * Default constructor, assumes default Charset of {@link StandardCharsets#UTF_8}
+     */
+    public QuotedPrintableCodec() {
+        this(StandardCharsets.UTF_8, false);
+    }
+
+    /**
+     * Constructor which allows for the selection of the strict mode.
+     *
+     * @param strict
+     *            if {@code true}, soft line breaks will be used
+     * @since 1.10
+     */
+    public QuotedPrintableCodec(final boolean strict) {
+        this(StandardCharsets.UTF_8, strict);
+    }
+
+    /**
+     * Constructor which allows for the selection of a default Charset.
+     *
+     * @param charset
+     *            the default string Charset to use.
+     * @since 1.7
+     */
+    public QuotedPrintableCodec(final Charset charset) {
+        this(charset, false);
+    }
+
+    /**
+     * Constructor which allows for the selection of a default Charset and strict mode.
+     *
+     * @param charset
+     *            the default string Charset to use.
+     * @param strict
+     *            if {@code true}, soft line breaks will be used
+     * @since 1.10
+     */
+    public QuotedPrintableCodec(final Charset charset, final boolean strict) {
+        this.charset = charset;
+        this.strict = strict;
+    }
+
+    /**
+     * Constructor which allows for the selection of a default Charset.
+     *
+     * @param charsetName
+     *            the default string Charset to use.
+     * @throws UnsupportedCharsetException
+     *             If no support for the named Charset is available
+     *             in this instance of the Java virtual machine
+     * @throws IllegalArgumentException
+     *             If the given charsetName is null
+     * @throws IllegalCharsetNameException
+     *             If the given Charset name is illegal
+     *
+     * @since 1.7 throws UnsupportedCharsetException if the named Charset is unavailable
+     */
+    public QuotedPrintableCodec(final String charsetName)
+            throws IllegalCharsetNameException, IllegalArgumentException, UnsupportedCharsetException {
+        this(Charset.forName(charsetName), false);
     }
 
     /**
@@ -421,24 +404,46 @@ public class QuotedPrintableCodec implements BinaryEncoder, BinaryDecoder, Strin
     }
 
     /**
-     * Encodes a string into its quoted-printable form using the default string Charset. Unsafe characters are escaped.
-     * <p>
-     * Depending on the selection of the {@code strict} parameter, this function either implements the full ruleset
-     * or only a subset of quoted-printable encoding specification (rule #1 and rule #2) as defined in
-     * RFC 1521 and is suitable for encoding binary data and unformatted text.
-     * </p>
+     * Decodes a quoted-printable object into its original form. Escaped characters are converted back to their original
+     * representation.
      *
-     * @param sourceStr
-     *            string to convert to quoted-printable form
-     * @return quoted-printable string
-     * @throws EncoderException
-     *             Thrown if quoted-printable encoding is unsuccessful
+     * @param obj
+     *            quoted-printable object to convert into its original form
+     * @return original object
+     * @throws DecoderException
+     *             Thrown if the argument is not a {@code String} or {@code byte[]}. Thrown if a failure
+     *             condition is encountered during the decode process.
+     */
+    @Override
+    public Object decode(final Object obj) throws DecoderException {
+        if (obj == null) {
+            return null;
+        }
+        if (obj instanceof byte[]) {
+            return decode((byte[]) obj);
+        }
+        if (obj instanceof String) {
+            return decode((String) obj);
+        }
+        throw new DecoderException("Objects of type " +
+              obj.getClass().getName() +
+              " cannot be quoted-printable decoded");
+    }
+
+    /**
+     * Decodes a quoted-printable string into its original form using the default string Charset. Escaped characters are
+     * converted back to their original representation.
      *
+     * @param sourceStr
+     *            quoted-printable string to convert into its original form
+     * @return original string
+     * @throws DecoderException
+     *             Thrown if quoted-printable decoding is unsuccessful. Thrown if Charset is not supported.
      * @see #getCharset()
      */
     @Override
-    public String encode(final String sourceStr) throws EncoderException {
-        return this.encode(sourceStr, getCharset());
+    public String decode(final String sourceStr) throws DecoderException {
+        return this.decode(sourceStr, this.getCharset());
     }
 
     /**
@@ -484,19 +489,20 @@ public class QuotedPrintableCodec implements BinaryEncoder, BinaryDecoder, Strin
     }
 
     /**
-     * Decodes a quoted-printable string into its original form using the default string Charset. Escaped characters are
-     * converted back to their original representation.
+     * Encodes an array of bytes into an array of quoted-printable 7-bit characters. Unsafe characters are escaped.
+     * <p>
+     * Depending on the selection of the {@code strict} parameter, this function either implements the full ruleset
+     * or only a subset of quoted-printable encoding specification (rule #1 and rule #2) as defined in
+     * RFC 1521 and is suitable for encoding binary data and unformatted text.
+     * </p>
      *
-     * @param sourceStr
-     *            quoted-printable string to convert into its original form
-     * @return original string
-     * @throws DecoderException
-     *             Thrown if quoted-printable decoding is unsuccessful. Thrown if Charset is not supported.
-     * @see #getCharset()
+     * @param bytes
+     *            array of bytes to be encoded
+     * @return array of bytes containing quoted-printable data
      */
     @Override
-    public String decode(final String sourceStr) throws DecoderException {
-        return this.decode(sourceStr, this.getCharset());
+    public byte[] encode(final byte[] bytes) {
+        return encodeQuotedPrintable(PRINTABLE_CHARS, bytes, strict);
     }
 
     /**
@@ -526,49 +532,24 @@ public class QuotedPrintableCodec implements BinaryEncoder, BinaryDecoder, Strin
     }
 
     /**
-     * Decodes a quoted-printable object into its original form. Escaped characters are converted back to their original
-     * representation.
-     *
-     * @param obj
-     *            quoted-printable object to convert into its original form
-     * @return original object
-     * @throws DecoderException
-     *             Thrown if the argument is not a {@code String} or {@code byte[]}. Thrown if a failure
-     *             condition is encountered during the decode process.
-     */
-    @Override
-    public Object decode(final Object obj) throws DecoderException {
-        if (obj == null) {
-            return null;
-        }
-        if (obj instanceof byte[]) {
-            return decode((byte[]) obj);
-        }
-        if (obj instanceof String) {
-            return decode((String) obj);
-        }
-        throw new DecoderException("Objects of type " +
-              obj.getClass().getName() +
-              " cannot be quoted-printable decoded");
-    }
-
-    /**
-     * Gets the default Charset name used for string decoding and encoding.
+     * Encodes a string into its quoted-printable form using the default string Charset. Unsafe characters are escaped.
+     * <p>
+     * Depending on the selection of the {@code strict} parameter, this function either implements the full ruleset
+     * or only a subset of quoted-printable encoding specification (rule #1 and rule #2) as defined in
+     * RFC 1521 and is suitable for encoding binary data and unformatted text.
+     * </p>
      *
-     * @return the default Charset name
-     * @since 1.7
-     */
-    public Charset getCharset() {
-        return this.charset;
-    }
-
-    /**
-     * Gets the default Charset name used for string decoding and encoding.
+     * @param sourceStr
+     *            string to convert to quoted-printable form
+     * @return quoted-printable string
+     * @throws EncoderException
+     *             Thrown if quoted-printable encoding is unsuccessful
      *
-     * @return the default Charset name
+     * @see #getCharset()
      */
-    public String getDefaultCharset() {
-        return this.charset.name();
+    @Override
+    public String encode(final String sourceStr) throws EncoderException {
+        return this.encode(sourceStr, getCharset());
     }
 
     /**
@@ -615,4 +596,23 @@ public class QuotedPrintableCodec implements BinaryEncoder, BinaryDecoder, Strin
         }
         return StringUtils.newStringUsAscii(encode(sourceStr.getBytes(sourceCharset)));
     }
+
+    /**
+     * Gets the default Charset name used for string decoding and encoding.
+     *
+     * @return the default Charset name
+     * @since 1.7
+     */
+    public Charset getCharset() {
+        return this.charset;
+    }
+
+    /**
+     * Gets the default Charset name used for string decoding and encoding.
+     *
+     * @return the default Charset name
+     */
+    public String getDefaultCharset() {
+        return this.charset.name();
+    }
 }
diff --git a/src/main/java/org/apache/commons/codec/net/RFC1522Codec.java b/src/main/java/org/apache/commons/codec/net/RFC1522Codec.java
index 2a16aa38..dfd77d1c 100644
--- a/src/main/java/org/apache/commons/codec/net/RFC1522Codec.java
+++ b/src/main/java/org/apache/commons/codec/net/RFC1522Codec.java
@@ -51,63 +51,6 @@ abstract class RFC1522Codec {
     /** Postfix. */
     protected static final String PREFIX = "=?";
 
-    /**
-     * Applies an RFC 1522 compliant encoding scheme to the given string of text with the given charset.
-     * <p>
-     * This method constructs the "encoded-word" header common to all the RFC 1522 codecs and then invokes
-     * {@link #doEncoding(byte[])}  method of a concrete class to perform the specific encoding.
-     * </p>
-     *
-     * @param text
-     *            a string to encode
-     * @param charset
-     *            a charset to be used
-     * @return RFC 1522 compliant "encoded-word"
-     * @throws EncoderException
-     *             thrown if there is an error condition during the Encoding process.
-     * @see Charset
-     */
-    protected String encodeText(final String text, final Charset charset) throws EncoderException {
-        if (text == null) {
-            return null;
-        }
-        final StringBuilder buffer = new StringBuilder();
-        buffer.append(PREFIX);
-        buffer.append(charset);
-        buffer.append(SEP);
-        buffer.append(this.getEncoding());
-        buffer.append(SEP);
-        buffer.append(StringUtils.newStringUsAscii(this.doEncoding(text.getBytes(charset))));
-        buffer.append(POSTFIX);
-        return buffer.toString();
-    }
-
-    /**
-     * Applies an RFC 1522 compliant encoding scheme to the given string of text with the given charset.
-     * <p>
-     * This method constructs the "encoded-word" header common to all the RFC 1522 codecs and then invokes
-     * {@link #doEncoding(byte[])}  method of a concrete class to perform the specific encoding.
-     * </p>
-     *
-     * @param text
-     *            a string to encode
-     * @param charsetName
-     *            the charset to use
-     * @return RFC 1522 compliant "encoded-word"
-     * @throws EncoderException
-     *             thrown if there is an error condition during the Encoding process.
-     * @throws UnsupportedEncodingException
-     *             if charset is not available
-     * @see Charset
-     */
-    protected String encodeText(final String text, final String charsetName)
-            throws EncoderException, UnsupportedEncodingException {
-        if (text == null) {
-            return null;
-        }
-        return this.encodeText(text, Charset.forName(charsetName));
-    }
-
     /**
      * Applies an RFC 1522 compliant decoding scheme to the given string of text.
      * <p>
@@ -158,11 +101,15 @@ abstract class RFC1522Codec {
     }
 
     /**
-     * Returns the codec name (referred to as encoding in the RFC 1522).
+     * Decodes an array of bytes using the defined encoding scheme.
      *
-     * @return name of the codec
+     * @param bytes
+     *            Data to be decoded
+     * @return a byte array that contains decoded data
+     * @throws DecoderException
+     *             A decoder exception is thrown if a Decoder encounters a failure condition during the decode process.
      */
-    protected abstract String getEncoding();
+    protected abstract byte[] doDecoding(byte[] bytes) throws DecoderException;
 
     /**
      * Encodes an array of bytes using the defined encoding scheme.
@@ -176,13 +123,66 @@ abstract class RFC1522Codec {
     protected abstract byte[] doEncoding(byte[] bytes) throws EncoderException;
 
     /**
-     * Decodes an array of bytes using the defined encoding scheme.
+     * Applies an RFC 1522 compliant encoding scheme to the given string of text with the given charset.
+     * <p>
+     * This method constructs the "encoded-word" header common to all the RFC 1522 codecs and then invokes
+     * {@link #doEncoding(byte[])}  method of a concrete class to perform the specific encoding.
+     * </p>
      *
-     * @param bytes
-     *            Data to be decoded
-     * @return a byte array that contains decoded data
-     * @throws DecoderException
-     *             A decoder exception is thrown if a Decoder encounters a failure condition during the decode process.
+     * @param text
+     *            a string to encode
+     * @param charset
+     *            a charset to be used
+     * @return RFC 1522 compliant "encoded-word"
+     * @throws EncoderException
+     *             thrown if there is an error condition during the Encoding process.
+     * @see Charset
      */
-    protected abstract byte[] doDecoding(byte[] bytes) throws DecoderException;
+    protected String encodeText(final String text, final Charset charset) throws EncoderException {
+        if (text == null) {
+            return null;
+        }
+        final StringBuilder buffer = new StringBuilder();
+        buffer.append(PREFIX);
+        buffer.append(charset);
+        buffer.append(SEP);
+        buffer.append(this.getEncoding());
+        buffer.append(SEP);
+        buffer.append(StringUtils.newStringUsAscii(this.doEncoding(text.getBytes(charset))));
+        buffer.append(POSTFIX);
+        return buffer.toString();
+    }
+
+    /**
+     * Applies an RFC 1522 compliant encoding scheme to the given string of text with the given charset.
+     * <p>
+     * This method constructs the "encoded-word" header common to all the RFC 1522 codecs and then invokes
+     * {@link #doEncoding(byte[])}  method of a concrete class to perform the specific encoding.
+     * </p>
+     *
+     * @param text
+     *            a string to encode
+     * @param charsetName
+     *            the charset to use
+     * @return RFC 1522 compliant "encoded-word"
+     * @throws EncoderException
+     *             thrown if there is an error condition during the Encoding process.
+     * @throws UnsupportedEncodingException
+     *             if charset is not available
+     * @see Charset
+     */
+    protected String encodeText(final String text, final String charsetName)
+            throws EncoderException, UnsupportedEncodingException {
+        if (text == null) {
+            return null;
+        }
+        return this.encodeText(text, Charset.forName(charsetName));
+    }
+
+    /**
+     * Returns the codec name (referred to as encoding in the RFC 1522).
+     *
+     * @return name of the codec
+     */
+    protected abstract String getEncoding();
 }
diff --git a/src/main/java/org/apache/commons/codec/net/URLCodec.java b/src/main/java/org/apache/commons/codec/net/URLCodec.java
index d5809f3b..26ef3493 100644
--- a/src/main/java/org/apache/commons/codec/net/URLCodec.java
+++ b/src/main/java/org/apache/commons/codec/net/URLCodec.java
@@ -48,14 +48,6 @@ import org.apache.commons.codec.binary.StringUtils;
  */
 public class URLCodec implements BinaryEncoder, BinaryDecoder, StringEncoder, StringDecoder {
 
-    /**
-     * The default charset used for string decoding and encoding.
-     *
-     * @deprecated TODO: This field will be changed to a private final Charset in 2.0. (CODEC-126)
-     */
-    @Deprecated
-    protected volatile String charset; // added volatile: see CODEC-232
-
     /**
      * Release 1.5 made this field final.
      */
@@ -97,23 +89,41 @@ public class URLCodec implements BinaryEncoder, BinaryDecoder, StringEncoder, St
         WWW_FORM_URL = (BitSet) WWW_FORM_URL_SAFE.clone();
     }
 
-
-    /**
-     * Default constructor.
-     */
-    public URLCodec() {
-        this(CharEncoding.UTF_8);
-    }
-
     /**
-     * Constructor which allows for the selection of a default charset.
+     * Decodes an array of URL safe 7-bit characters into an array of original bytes. Escaped characters are converted
+     * back to their original representation.
      *
-     * @param charset the default string charset to use.
+     * @param bytes
+     *            array of URL safe characters
+     * @return array of original bytes
+     * @throws DecoderException
+     *             Thrown if URL decoding is unsuccessful
      */
-    public URLCodec(final String charset) {
-        this.charset = charset;
+    public static final byte[] decodeUrl(final byte[] bytes) throws DecoderException {
+        if (bytes == null) {
+            return null;
+        }
+        final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+        for (int i = 0; i < bytes.length; i++) {
+            final int b = bytes[i];
+            if (b == '+') {
+                buffer.write(' ');
+            } else if (b == ESCAPE_CHAR) {
+                try {
+                    final int u = Utils.digit16(bytes[++i]);
+                    final int l = Utils.digit16(bytes[++i]);
+                    buffer.write((char) ((u << 4) + l));
+                } catch (final ArrayIndexOutOfBoundsException e) {
+                    throw new DecoderException("Invalid URL encoding: ", e);
+                }
+            } else {
+                buffer.write(b);
+            }
+        }
+        return buffer.toByteArray();
     }
 
+
     /**
      * Encodes an array of bytes into an array of URL safe 7-bit characters. Unsafe characters are escaped.
      *
@@ -154,52 +164,29 @@ public class URLCodec implements BinaryEncoder, BinaryDecoder, StringEncoder, St
     }
 
     /**
-     * Decodes an array of URL safe 7-bit characters into an array of original bytes. Escaped characters are converted
-     * back to their original representation.
+     * The default charset used for string decoding and encoding.
      *
-     * @param bytes
-     *            array of URL safe characters
-     * @return array of original bytes
-     * @throws DecoderException
-     *             Thrown if URL decoding is unsuccessful
+     * @deprecated TODO: This field will be changed to a private final Charset in 2.0. (CODEC-126)
      */
-    public static final byte[] decodeUrl(final byte[] bytes) throws DecoderException {
-        if (bytes == null) {
-            return null;
-        }
-        final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
-        for (int i = 0; i < bytes.length; i++) {
-            final int b = bytes[i];
-            if (b == '+') {
-                buffer.write(' ');
-            } else if (b == ESCAPE_CHAR) {
-                try {
-                    final int u = Utils.digit16(bytes[++i]);
-                    final int l = Utils.digit16(bytes[++i]);
-                    buffer.write((char) ((u << 4) + l));
-                } catch (final ArrayIndexOutOfBoundsException e) {
-                    throw new DecoderException("Invalid URL encoding: ", e);
-                }
-            } else {
-                buffer.write(b);
-            }
-        }
-        return buffer.toByteArray();
+    @Deprecated
+    protected volatile String charset; // added volatile: see CODEC-232
+
+    /**
+     * Default constructor.
+     */
+    public URLCodec() {
+        this(CharEncoding.UTF_8);
     }
 
     /**
-     * Encodes an array of bytes into an array of URL safe 7-bit characters. Unsafe characters are escaped.
+     * Constructor which allows for the selection of a default charset.
      *
-     * @param bytes
-     *            array of bytes to convert to URL safe characters
-     * @return array of bytes containing URL safe characters
+     * @param charset the default string charset to use.
      */
-    @Override
-    public byte[] encode(final byte[] bytes) {
-        return encodeUrl(WWW_FORM_URL_SAFE, bytes);
+    public URLCodec(final String charset) {
+        this.charset = charset;
     }
 
-
     /**
      * Decodes an array of URL safe 7-bit characters into an array of original bytes. Escaped characters are converted
      * back to their original representation.
@@ -215,48 +202,55 @@ public class URLCodec implements BinaryEncoder, BinaryDecoder, StringEncoder, St
         return decodeUrl(bytes);
     }
 
+
     /**
-     * Encodes a string into its URL safe form using the specified string charset. Unsafe characters are escaped.
+     * Decodes a URL safe object into its original form. Escaped characters are converted back to their original
+     * representation.
      *
-     * @param str
-     *            string to convert to a URL safe form
-     * @param charsetName
-     *            the charset for str
-     * @return URL safe string
-     * @throws UnsupportedEncodingException
-     *             Thrown if charset is not supported
+     * @param obj
+     *            URL safe object to convert into its original form
+     * @return original object
+     * @throws DecoderException
+     *             Thrown if the argument is not a {@code String} or {@code byte[]}. Thrown if a failure
+     *             condition is encountered during the decode process.
      */
-    public String encode(final String str, final String charsetName) throws UnsupportedEncodingException {
-        if (str == null) {
+    @Override
+    public Object decode(final Object obj) throws DecoderException {
+        if (obj == null) {
             return null;
         }
-        return StringUtils.newStringUsAscii(encode(str.getBytes(charsetName)));
+        if (obj instanceof byte[]) {
+            return decode((byte[]) obj);
+        }
+        if (obj instanceof String) {
+            return decode((String) obj);
+        }
+        throw new DecoderException("Objects of type " + obj.getClass().getName() + " cannot be URL decoded");
     }
 
     /**
-     * Encodes a string into its URL safe form using the default string charset. Unsafe characters are escaped.
+     * Decodes a URL safe string into its original form using the default string charset. Escaped characters are
+     * converted back to their original representation.
      *
      * @param str
-     *            string to convert to a URL safe form
-     * @return URL safe string
-     * @throws EncoderException
-     *             Thrown if URL encoding is unsuccessful
-     *
+     *            URL safe string to convert into its original form
+     * @return original string
+     * @throws DecoderException
+     *             Thrown if URL decoding is unsuccessful
      * @see #getDefaultCharset()
      */
     @Override
-    public String encode(final String str) throws EncoderException {
+    public String decode(final String str) throws DecoderException {
         if (str == null) {
             return null;
         }
         try {
-            return encode(str, getDefaultCharset());
+            return decode(str, getDefaultCharset());
         } catch (final UnsupportedEncodingException e) {
-            throw new EncoderException(e.getMessage(), e);
+            throw new DecoderException(e.getMessage(), e);
         }
     }
 
-
     /**
      * Decodes a URL safe string into its original form using the specified encoding. Escaped characters are converted
      * back to their original representation.
@@ -279,27 +273,17 @@ public class URLCodec implements BinaryEncoder, BinaryDecoder, StringEncoder, St
         return new String(decode(StringUtils.getBytesUsAscii(str)), charsetName);
     }
 
+
     /**
-     * Decodes a URL safe string into its original form using the default string charset. Escaped characters are
-     * converted back to their original representation.
+     * Encodes an array of bytes into an array of URL safe 7-bit characters. Unsafe characters are escaped.
      *
-     * @param str
-     *            URL safe string to convert into its original form
-     * @return original string
-     * @throws DecoderException
-     *             Thrown if URL decoding is unsuccessful
-     * @see #getDefaultCharset()
+     * @param bytes
+     *            array of bytes to convert to URL safe characters
+     * @return array of bytes containing URL safe characters
      */
     @Override
-    public String decode(final String str) throws DecoderException {
-        if (str == null) {
-            return null;
-        }
-        try {
-            return decode(str, getDefaultCharset());
-        } catch (final UnsupportedEncodingException e) {
-            throw new DecoderException(e.getMessage(), e);
-        }
+    public byte[] encode(final byte[] bytes) {
+        return encodeUrl(WWW_FORM_URL_SAFE, bytes);
     }
 
     /**
@@ -326,28 +310,44 @@ public class URLCodec implements BinaryEncoder, BinaryDecoder, StringEncoder, St
     }
 
     /**
-     * Decodes a URL safe object into its original form. Escaped characters are converted back to their original
-     * representation.
+     * Encodes a string into its URL safe form using the default string charset. Unsafe characters are escaped.
      *
-     * @param obj
-     *            URL safe object to convert into its original form
-     * @return original object
-     * @throws DecoderException
-     *             Thrown if the argument is not a {@code String} or {@code byte[]}. Thrown if a failure
-     *             condition is encountered during the decode process.
+     * @param str
+     *            string to convert to a URL safe form
+     * @return URL safe string
+     * @throws EncoderException
+     *             Thrown if URL encoding is unsuccessful
+     *
+     * @see #getDefaultCharset()
      */
     @Override
-    public Object decode(final Object obj) throws DecoderException {
-        if (obj == null) {
+    public String encode(final String str) throws EncoderException {
+        if (str == null) {
             return null;
         }
-        if (obj instanceof byte[]) {
-            return decode((byte[]) obj);
+        try {
+            return encode(str, getDefaultCharset());
+        } catch (final UnsupportedEncodingException e) {
+            throw new EncoderException(e.getMessage(), e);
         }
-        if (obj instanceof String) {
-            return decode((String) obj);
+    }
+
+    /**
+     * Encodes a string into its URL safe form using the specified string charset. Unsafe characters are escaped.
+     *
+     * @param str
+     *            string to convert to a URL safe form
+     * @param charsetName
+     *            the charset for str
+     * @return URL safe string
+     * @throws UnsupportedEncodingException
+     *             Thrown if charset is not supported
+     */
+    public String encode(final String str, final String charsetName) throws UnsupportedEncodingException {
+        if (str == null) {
+            return null;
         }
-        throw new DecoderException("Objects of type " + obj.getClass().getName() + " cannot be URL decoded");
+        return StringUtils.newStringUsAscii(encode(str.getBytes(charsetName)));
     }
 
     /**
diff --git a/src/test/java/org/apache/commons/codec/CharsetsTest.java b/src/test/java/org/apache/commons/codec/CharsetsTest.java
index c2aa9edc..834413c4 100644
--- a/src/test/java/org/apache/commons/codec/CharsetsTest.java
+++ b/src/test/java/org/apache/commons/codec/CharsetsTest.java
@@ -29,6 +29,12 @@ import org.junit.jupiter.api.Test;
  */
 public class CharsetsTest {
 
+    @SuppressWarnings("deprecation")
+    @Test
+    public void testIso8859_1() {
+        assertEquals("ISO-8859-1", Charsets.ISO_8859_1.name());
+    }
+
     @Test
     public void testToCharset() {
         assertEquals(Charset.defaultCharset(), Charsets.toCharset((String) null));
@@ -37,12 +43,6 @@ public class CharsetsTest {
         assertEquals(StandardCharsets.UTF_8, Charsets.toCharset(StandardCharsets.UTF_8));
     }
 
-    @SuppressWarnings("deprecation")
-    @Test
-    public void testIso8859_1() {
-        assertEquals("ISO-8859-1", Charsets.ISO_8859_1.name());
-    }
-
     @SuppressWarnings("deprecation")
     @Test
     public void testUsAscii() {
diff --git a/src/test/java/org/apache/commons/codec/StringEncoderComparatorTest.java b/src/test/java/org/apache/commons/codec/StringEncoderComparatorTest.java
index b8495090..930aeb94 100644
--- a/src/test/java/org/apache/commons/codec/StringEncoderComparatorTest.java
+++ b/src/test/java/org/apache/commons/codec/StringEncoderComparatorTest.java
@@ -32,15 +32,6 @@ import org.junit.jupiter.api.Test;
  */
 public class StringEncoderComparatorTest {
 
-    @Test
-    public void testComparatorWithSoundex() throws Exception {
-        final StringEncoderComparator sCompare =
-            new StringEncoderComparator( new Soundex() );
-
-        assertEquals(0, sCompare.compare("O'Brien", "O'Brian"),
-                "O'Brien and O'Brian didn't come out with the same Soundex, something must be wrong here");
-    }
-
     @SuppressWarnings("unchecked") // cannot easily avoid this warning
     @Test
     public void testComparatorWithDoubleMetaphone() throws Exception {
@@ -71,4 +62,13 @@ public class StringEncoderComparatorTest {
                 "Trying to compare objects that make no sense to the underlying encoder" +
                         " should return a zero compare code");
     }
+
+    @Test
+    public void testComparatorWithSoundex() throws Exception {
+        final StringEncoderComparator sCompare =
+            new StringEncoderComparator( new Soundex() );
+
+        assertEquals(0, sCompare.compare("O'Brien", "O'Brian"),
+                "O'Brien and O'Brian didn't come out with the same Soundex, something must be wrong here");
+    }
 }
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 6afdcb93..53856f0a 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base16Test.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base16Test.java
@@ -45,6 +45,12 @@ public class Base16Test {
 
     private final Random random = new Random();
 
+    @Test
+    public void checkEncodeLengthBounds() {
+        final Base16 base16 = new Base16();
+        assertThrows(IllegalArgumentException.class, () -> base16.encode(new byte[10], 0, 1 << 30));
+    }
+
     /**
      * @return Returns the random.
      */
@@ -67,11 +73,6 @@ public class Base16Test {
         assertEquals(content, decodedContent, "decoding hello world");
     }
 
-    @Test
-    public void testBase16AtBufferStart() {
-        testBase16InBuffer(0, 100);
-    }
-
     @Test
     public void testBase16AtBufferEnd() {
         testBase16InBuffer(100, 0);
@@ -82,6 +83,11 @@ public class Base16Test {
         testBase16InBuffer(100, 100);
     }
 
+    @Test
+    public void testBase16AtBufferStart() {
+        testBase16InBuffer(0, 100);
+    }
+
     private void testBase16InBuffer(final int startPasSize, final int endPadSize) {
         final String content = "Hello World";
         final String encodedContent;
@@ -93,6 +99,21 @@ public class Base16Test {
         assertEquals("48656C6C6F20576F726C64", encodedContent, "encoding hello world");
     }
 
+    @Test
+    public void testByteToStringVariations() {
+        final Base16 base16 = new Base16();
+        final byte[] b1 = StringUtils.getBytesUtf8("Hello World");
+        final byte[] b2 = {};
+        final byte[] b3 = null;
+
+        assertEquals("48656C6C6F20576F726C64", base16.encodeToString(b1), "byteToString Hello World");
+        assertEquals("48656C6C6F20576F726C64", StringUtils.newStringUtf8(new Base16().encode(b1)), "byteToString static Hello World");
+        assertEquals("", base16.encodeToString(b2), "byteToString \"\"");
+        assertEquals("", StringUtils.newStringUtf8(new Base16().encode(b2)), "byteToString static \"\"");
+        assertNull(base16.encodeToString(b3), "byteToString null");
+        assertNull(StringUtils.newStringUtf8(new Base16().encode(b3)), "byteToString static null");
+    }
+
     /**
      * isBase16 throws RuntimeException on some
      * non-Base16 bytes
@@ -104,15 +125,6 @@ public class Base16Test {
         assertThrows(RuntimeException.class, () -> b16.decode(x));
     }
 
-    @Test
-    public void testConstructors() {
-        new Base16();
-        new Base16(false);
-        new Base16(true);
-        new Base16(false, CodecPolicy.LENIENT);
-        new Base16(false, CodecPolicy.STRICT);
-    }
-
     @Test
     public void testConstructor_LowerCase() {
         final Base16 base16 = new Base16(true);
@@ -131,6 +143,67 @@ public class Base16Test {
         assertEquals(result, expectedResult, "new base16(false, CodecPolicy.STRICT)");
     }
 
+    @Test
+    public void testConstructors() {
+        new Base16();
+        new Base16(false);
+        new Base16(true);
+        new Base16(false, CodecPolicy.LENIENT);
+        new Base16(false, CodecPolicy.STRICT);
+    }
+
+    @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);
+    }
+
+    @Test
+    public void testDecodeSingleBytesOptimisation() {
+        final BaseNCodec.Context context = new BaseNCodec.Context();
+        assertEquals(0, context.ibitWorkArea);
+        assertNull(context.buffer);
+
+        final byte[] data = new byte[1];
+
+        final Base16 b16 = new Base16();
+
+        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((byte)0xEF, context.buffer[0]);
+    }
+
     /**
      * Test encode and decode of empty byte array.
      */
@@ -175,6 +248,53 @@ public class Base16Test {
         }
     }
 
+    @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
+        b16 = new Base16(true);
+        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) ('f' + 1)));
+        assertFalse(b16.isInAlphabet((byte) ('z' + 1)));
+
+        // upper-case
+        b16 = new Base16(false);
+        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)));
+        assertFalse(b16.isInAlphabet((byte) ('Z' + 1)));
+    }
+
     @Test
     public void testKnownDecodings() {
         assertEquals("The quick brown fox jumped over the lazy dogs.", new String(new Base16(true).decode(
@@ -205,6 +325,17 @@ public class Base16Test {
         assertEquals("78797a7a7921", new String(new Base16(true).encode("xyzzy!".getBytes(CHARSET_UTF8))));
     }
 
+    @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, CodecPolicy.LENIENT);
+        assertEquals(CodecPolicy.LENIENT, b16.getCodecPolicy());
+
+        final byte[] decoded = b16.decode(StringUtils.getBytesUtf8(encoded));
+        assertArrayEquals(new byte[] {(byte)0xaa, (byte)0xbb, (byte)0xcc, (byte)0xdd}, decoded);
+    }
+
     @Test
     public void testNonBase16Test() {
         final byte[] invalidEncodedChars = { '/', ':', '@', 'G', '%', '`', 'g' };
@@ -234,6 +365,12 @@ public class Base16Test {
         assertEquals(original, dest, "dest string does not equal original");
     }
 
+    @Test
+    public void testObjectEncode() {
+        final Base16 b16 = new Base16();
+        assertEquals(new String(b16.encode("Hello World".getBytes(CHARSET_UTF8))), "48656C6C6F20576F726C64");
+    }
+
     @Test
     public void testObjectEncodeWithInvalidParameter() {
         assertThrows(EncoderException.class, () -> new Base16().encode("Yadayadayada"));
@@ -252,9 +389,24 @@ public class Base16Test {
     }
 
     @Test
-    public void testObjectEncode() {
-        final Base16 b16 = new Base16();
-        assertEquals(new String(b16.encode("Hello World".getBytes(CHARSET_UTF8))), "48656C6C6F20576F726C64");
+    public void testOddEvenDecoding() {
+        final String encoded = "4142434445";
+
+        final BaseNCodec.Context context = new BaseNCodec.Context();
+        final Base16 base16 = new Base16();
+
+        final byte[] encodedBytes = StringUtils.getBytesUtf8(encoded);
+
+        // pass odd, then even, then odd amount of data
+        base16.decode(encodedBytes, 0, 3, context);
+        base16.decode(encodedBytes, 3, 4, context);
+        base16.decode(encodedBytes, 7, 3, context);
+
+        final byte[] decodedBytes = new byte[context.pos];
+        System.arraycopy(context.buffer, context.readPos, decodedBytes, 0, decodedBytes.length);
+        final String decoded = StringUtils.newStringUtf8(decodedBytes);
+
+        assertEquals("ABCDE", decoded);
     }
 
     @Test
@@ -397,38 +549,12 @@ public class Base16Test {
     }
 
     @Test
-    public void testTriplets() {
-        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
-    public void testByteToStringVariations() {
-        final Base16 base16 = new Base16();
-        final byte[] b1 = StringUtils.getBytesUtf8("Hello World");
-        final byte[] b2 = {};
-        final byte[] b3 = null;
+    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
 
-        assertEquals("48656C6C6F20576F726C64", base16.encodeToString(b1), "byteToString Hello World");
-        assertEquals("48656C6C6F20576F726C64", StringUtils.newStringUtf8(new Base16().encode(b1)), "byteToString static Hello World");
-        assertEquals("", base16.encodeToString(b2), "byteToString \"\"");
-        assertEquals("", StringUtils.newStringUtf8(new Base16().encode(b2)), "byteToString static \"\"");
-        assertNull(base16.encodeToString(b3), "byteToString null");
-        assertNull(StringUtils.newStringUtf8(new Base16().encode(b3)), "byteToString static null");
+        final Base16 b16 = new Base16(true, CodecPolicy.STRICT);
+        assertEquals(CodecPolicy.STRICT, b16.getCodecPolicy());
+        assertThrows(IllegalArgumentException.class, () -> b16.decode(StringUtils.getBytesUtf8(encoded)));
     }
 
     @Test
@@ -447,6 +573,26 @@ public class Base16Test {
         assertNull(StringUtils.newStringUtf8(new Base16().decode(s3)), "StringToByte static null");
     }
 
+    @Test
+    public void testTriplets() {
+        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 })));
+    }
+
     private String toString(final byte[] data) {
         final StringBuilder buf = new StringBuilder();
         for (int i = 0; i < data.length; i++) {
@@ -457,150 +603,4 @@ public class Base16Test {
         }
         return buf.toString();
     }
-
-    @Test
-    public void checkEncodeLengthBounds() {
-        final Base16 base16 = new Base16();
-        assertThrows(IllegalArgumentException.class, () -> base16.encode(new byte[10], 0, 1 << 30));
-    }
-
-    @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
-        b16 = new Base16(true);
-        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) ('f' + 1)));
-        assertFalse(b16.isInAlphabet((byte) ('z' + 1)));
-
-        // upper-case
-        b16 = new Base16(false);
-        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)));
-        assertFalse(b16.isInAlphabet((byte) ('Z' + 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);
-    }
-
-    @Test
-    public void testDecodeSingleBytesOptimisation() {
-        final BaseNCodec.Context context = new BaseNCodec.Context();
-        assertEquals(0, context.ibitWorkArea);
-        assertNull(context.buffer);
-
-        final byte[] data = new byte[1];
-
-        final Base16 b16 = new Base16();
-
-        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((byte)0xEF, context.buffer[0]);
-    }
-
-    @Test
-    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, CodecPolicy.STRICT);
-        assertEquals(CodecPolicy.STRICT, b16.getCodecPolicy());
-        assertThrows(IllegalArgumentException.class, () -> 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, CodecPolicy.LENIENT);
-        assertEquals(CodecPolicy.LENIENT, b16.getCodecPolicy());
-
-        final byte[] decoded = b16.decode(StringUtils.getBytesUtf8(encoded));
-        assertArrayEquals(new byte[] {(byte)0xaa, (byte)0xbb, (byte)0xcc, (byte)0xdd}, decoded);
-    }
-
-    @Test
-    public void testOddEvenDecoding() {
-        final String encoded = "4142434445";
-
-        final BaseNCodec.Context context = new BaseNCodec.Context();
-        final Base16 base16 = new Base16();
-
-        final byte[] encodedBytes = StringUtils.getBytesUtf8(encoded);
-
-        // pass odd, then even, then odd amount of data
-        base16.decode(encodedBytes, 0, 3, context);
-        base16.decode(encodedBytes, 3, 4, context);
-        base16.decode(encodedBytes, 7, 3, context);
-
-        final byte[] decodedBytes = new byte[context.pos];
-        System.arraycopy(context.buffer, context.readPos, decodedBytes, 0, decodedBytes.length);
-        final String decoded = StringUtils.newStringUtf8(decodedBytes);
-
-        assertEquals("ABCDE", decoded);
-    }
 }
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 06248f61..81e17d24 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base32InputStreamTest.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base32InputStreamTest.java
@@ -42,36 +42,30 @@ public class Base32InputStreamTest {
     private static final String STRING_FIXTURE = "Hello World";
 
     /**
-     * Tests the problem reported in CODEC-130. Missing / wrong implementation of skip.
+     * Tests skipping past the end of a stream.
+     *
+     * @throws Throwable
+     *             for some failure scenarios.
      */
     @Test
-    public void testCodec130() throws IOException {
-        final ByteArrayOutputStream bos = new ByteArrayOutputStream();
-        try (final Base32OutputStream base32os = new Base32OutputStream(bos)) {
-            base32os.write(StringUtils.getBytesUtf8(STRING_FIXTURE));
+    public void testAvailable() throws Throwable {
+        final InputStream ins = new ByteArrayInputStream(StringUtils.getBytesIso8859_1(ENCODED_FOO));
+        try (final Base32InputStream b32stream = new Base32InputStream(ins)) {
+            assertEquals(1, b32stream.available());
+            assertEquals(3, b32stream.skip(10));
+            // End of stream reached
+            assertEquals(0, b32stream.available());
+            assertEquals(-1, b32stream.read());
+            assertEquals(-1, b32stream.read());
+            assertEquals(0, b32stream.available());
         }
-
-        final ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
-        final Base32InputStream ins = new Base32InputStream(bis);
-
-        // we skip the first character read from the reader
-        ins.skip(1);
-        final byte[] decodedBytes = BaseNTestData.streamToBytes(ins, new byte[64]);
-        final String str = StringUtils.newStringUtf8(decodedBytes);
-
-        assertEquals(STRING_FIXTURE.substring(1), str);
     }
 
-    /**
-     * Tests the bug reported in CODEC-105. Bad interactions with InputStream when reading one byte at a time.
-     */
-    @Test
-    public void testCodec105() throws IOException {
-        try (final Base32InputStream in = new Base32InputStream(new Codec105ErrorInputStream(), true, 0, null)) {
-            for (int i = 0; i < 5; i++) {
-                in.read();
-            }
-        }
+    private void testBase32EmptyInputStream(final int chuckSize) throws Exception {
+        final byte[] emptyEncoded = {};
+        final byte[] emptyDecoded = {};
+        testByteByByte(emptyEncoded, emptyDecoded, chuckSize, CRLF);
+        testByChunk(emptyEncoded, emptyDecoded, chuckSize, CRLF);
     }
 
     // /**
@@ -140,26 +134,6 @@ public class Base32InputStreamTest {
     // );
     // }
 
-    /**
-     * Tests skipping past the end of a stream.
-     *
-     * @throws Throwable
-     *             for some failure scenarios.
-     */
-    @Test
-    public void testAvailable() throws Throwable {
-        final InputStream ins = new ByteArrayInputStream(StringUtils.getBytesIso8859_1(ENCODED_FOO));
-        try (final Base32InputStream b32stream = new Base32InputStream(ins)) {
-            assertEquals(1, b32stream.available());
-            assertEquals(3, b32stream.skip(10));
-            // End of stream reached
-            assertEquals(0, b32stream.available());
-            assertEquals(-1, b32stream.read());
-            assertEquals(-1, b32stream.read());
-            assertEquals(0, b32stream.available());
-        }
-    }
-
     /**
      * Tests the Base32InputStream implementation against empty input.
      *
@@ -182,13 +156,6 @@ public class Base32InputStreamTest {
         testBase32EmptyInputStream(BaseNCodec.PEM_CHUNK_SIZE);
     }
 
-    private void testBase32EmptyInputStream(final int chuckSize) throws Exception {
-        final byte[] emptyEncoded = {};
-        final byte[] emptyDecoded = {};
-        testByteByByte(emptyEncoded, emptyDecoded, chuckSize, CRLF);
-        testByChunk(emptyEncoded, emptyDecoded, chuckSize, CRLF);
-    }
-
     /**
      * Tests the Base32InputStream implementation.
      *
@@ -377,6 +344,39 @@ public class Base32InputStreamTest {
         assertArrayEquals(decoded, output, "Streaming base32 wrap-wrap-wrap!");
     }
 
+    /**
+     * Tests the bug reported in CODEC-105. Bad interactions with InputStream when reading one byte at a time.
+     */
+    @Test
+    public void testCodec105() throws IOException {
+        try (final Base32InputStream in = new Base32InputStream(new Codec105ErrorInputStream(), true, 0, null)) {
+            for (int i = 0; i < 5; i++) {
+                in.read();
+            }
+        }
+    }
+
+    /**
+     * Tests the problem reported in CODEC-130. Missing / wrong implementation of skip.
+     */
+    @Test
+    public void testCodec130() throws IOException {
+        final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        try (final Base32OutputStream base32os = new Base32OutputStream(bos)) {
+            base32os.write(StringUtils.getBytesUtf8(STRING_FIXTURE));
+        }
+
+        final ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
+        final Base32InputStream ins = new Base32InputStream(bis);
+
+        // we skip the first character read from the reader
+        ins.skip(1);
+        final byte[] decodedBytes = BaseNTestData.streamToBytes(ins, new byte[64]);
+        final String str = StringUtils.newStringUtf8(decodedBytes);
+
+        assertEquals(STRING_FIXTURE.substring(1), str);
+    }
+
     /**
      * Tests markSupported.
      *
@@ -446,38 +446,38 @@ public class Base32InputStreamTest {
     }
 
     /**
-     * Tests skipping as a noop
+     * Tests skipping number of characters larger than the internal buffer.
      *
      * @throws Throwable
      *             for some failure scenarios.
      */
     @Test
-    public void testSkipNone() throws Throwable {
+    public void testSkipBig() throws Throwable {
         final InputStream ins = new ByteArrayInputStream(StringUtils.getBytesIso8859_1(ENCODED_FOO));
         try (final Base32InputStream b32stream = new Base32InputStream(ins)) {
-            final byte[] actualBytes = new byte[6];
-            assertEquals(0, b32stream.skip(0));
-            b32stream.read(actualBytes, 0, actualBytes.length);
-            assertArrayEquals(actualBytes, new byte[] { 102, 111, 111, 0, 0, 0 });
+            assertEquals(3, b32stream.skip(1024));
             // End of stream reached
             assertEquals(-1, b32stream.read());
+            assertEquals(-1, b32stream.read());
         }
     }
 
     /**
-     * Tests skipping number of characters larger than the internal buffer.
+     * Tests skipping as a noop
      *
      * @throws Throwable
      *             for some failure scenarios.
      */
     @Test
-    public void testSkipBig() throws Throwable {
+    public void testSkipNone() throws Throwable {
         final InputStream ins = new ByteArrayInputStream(StringUtils.getBytesIso8859_1(ENCODED_FOO));
         try (final Base32InputStream b32stream = new Base32InputStream(ins)) {
-            assertEquals(3, b32stream.skip(1024));
+            final byte[] actualBytes = new byte[6];
+            assertEquals(0, b32stream.skip(0));
+            b32stream.read(actualBytes, 0, actualBytes.length);
+            assertArrayEquals(actualBytes, new byte[] { 102, 111, 111, 0, 0, 0 });
             // End of stream reached
             assertEquals(-1, b32stream.read());
-            assertEquals(-1, b32stream.read());
         }
     }
 
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 8cb10449..d935e7d7 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base32OutputStreamTest.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base32OutputStreamTest.java
@@ -60,6 +60,13 @@ public class Base32OutputStreamTest {
 //    }
 
 
+    private void testBase32EmptyOutputStream(final int chunkSize) throws Exception {
+        final byte[] emptyEncoded = {};
+        final byte[] emptyDecoded = {};
+        testByteByByte(emptyEncoded, emptyDecoded, chunkSize, CR_LF);
+        testByChunk(emptyEncoded, emptyDecoded, chunkSize, CR_LF);
+    }
+
     /**
      * Test the Base32OutputStream implementation against empty input.
      *
@@ -82,13 +89,6 @@ public class Base32OutputStreamTest {
         testBase32EmptyOutputStream(BaseNCodec.PEM_CHUNK_SIZE);
     }
 
-    private void testBase32EmptyOutputStream(final int chunkSize) throws Exception {
-        final byte[] emptyEncoded = {};
-        final byte[] emptyDecoded = {};
-        testByteByByte(emptyEncoded, emptyDecoded, chunkSize, CR_LF);
-        testByChunk(emptyEncoded, emptyDecoded, chunkSize, CR_LF);
-    }
-
     /**
      * Test the Base32OutputStream implementation
      *
@@ -276,6 +276,34 @@ public class Base32OutputStreamTest {
         assertArrayEquals(decoded, output, "Streaming byte-by-byte Base32 wrap-wrap-wrap!");
     }
 
+    /**
+     * Test strict decoding.
+     *
+     * @throws Exception
+     *             for some failure scenarios.
+     */
+    @Test
+    public void testStrictDecoding() throws Exception {
+        for (final String s : Base32Test.BASE32_IMPOSSIBLE_CASES) {
+            final byte[] encoded = StringUtils.getBytesUtf8(s);
+            ByteArrayOutputStream bout = new ByteArrayOutputStream();
+            try (Base32OutputStream out = new Base32OutputStream(bout, false)) {
+                // Default is lenient decoding; it should not throw
+                assertFalse(out.isStrictDecoding());
+                out.write(encoded);
+                out.close();
+                assertTrue(bout.size() > 0);
+
+                // Strict decoding should throw
+                bout = new ByteArrayOutputStream();
+                try (final Base32OutputStream out2 = new Base32OutputStream(bout, false, 0, null, CodecPolicy.STRICT)) {
+                    assertTrue(out2.isStrictDecoding());
+                    assertThrows(IllegalArgumentException.class, () -> out2.write(encoded));
+                }
+            }
+        }
+    }
+
     /**
      * Tests Base32OutputStream.write for expected IndexOutOfBoundsException conditions.
      *
@@ -307,32 +335,4 @@ public class Base32OutputStreamTest {
             assertThrows(NullPointerException.class, () -> out.write(null, 0, 0));
         }
     }
-
-    /**
-     * Test strict decoding.
-     *
-     * @throws Exception
-     *             for some failure scenarios.
-     */
-    @Test
-    public void testStrictDecoding() throws Exception {
-        for (final String s : Base32Test.BASE32_IMPOSSIBLE_CASES) {
-            final byte[] encoded = StringUtils.getBytesUtf8(s);
-            ByteArrayOutputStream bout = new ByteArrayOutputStream();
-            try (Base32OutputStream out = new Base32OutputStream(bout, false)) {
-                // Default is lenient decoding; it should not throw
-                assertFalse(out.isStrictDecoding());
-                out.write(encoded);
-                out.close();
-                assertTrue(bout.size() > 0);
-
-                // Strict decoding should throw
-                bout = new ByteArrayOutputStream();
-                try (final Base32OutputStream out2 = new Base32OutputStream(bout, false, 0, null, CodecPolicy.STRICT)) {
-                    assertTrue(out2.isStrictDecoding());
-                    assertThrows(IllegalArgumentException.class, () -> out2.write(encoded));
-                }
-            }
-        }
-    }
 }
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 d0c892c2..6c059c31 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base32Test.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base32Test.java
@@ -138,9 +138,57 @@ public class Base32Test {
         {"foobar" ,"MZXW6YTBOI%%%%%%"},
     };
 
-    @Test
-    public void testBase32AtBufferStart() {
-        testBase32InBuffer(0, 100);
+    /**
+     * Test base 32 decoding of the final trailing bits. Trailing encoded bytes
+     * cannot fit exactly into 5-bit characters so the last character has a limited
+     * alphabet where the final bits are zero. This asserts that illegal final
+     * characters throw an exception when decoding.
+     *
+     * @param nbits the number of trailing bits (must be a factor of 5 and {@code <40})
+     */
+    private static void assertBase32DecodingOfTrailingBits(final int nbits) {
+        // Requires strict decoding
+        final Base32 codec = new Base32(0, null, false, BaseNCodec.PAD_DEFAULT, CodecPolicy.STRICT);
+        assertTrue(codec.isStrictDecoding());
+        assertEquals(CodecPolicy.STRICT, codec.getCodecPolicy());
+        // A lenient decoder should not re-encode to the same bytes
+        final Base32 defaultCodec = new Base32();
+        assertFalse(defaultCodec.isStrictDecoding());
+        assertEquals(CodecPolicy.LENIENT, defaultCodec.getCodecPolicy());
+
+        // Create the encoded bytes. The first characters must be valid so fill with 'zero'
+        // then pad to the block size.
+        final int length = nbits / 5;
+        final byte[] encoded = new byte[8];
+        Arrays.fill(encoded, 0, length, ENCODE_TABLE[0]);
+        Arrays.fill(encoded, length, encoded.length, (byte) '=');
+        // Compute how many bits would be discarded from 8-bit bytes
+        final int discard = nbits % 8;
+        final int emptyBitsMask = (1 << discard) - 1;
+        // Special case when an impossible number of trailing characters
+        final boolean invalid = length == 1 || length == 3 || length == 6;
+        // Enumerate all 32 possible final characters in the last position
+        final int last = length - 1;
+        for (int i = 0; i < 32; i++) {
+            encoded[last] = ENCODE_TABLE[i];
+            // If the lower bits are set we expect an exception. This is not a valid
+            // final character.
+            if (invalid || (i & emptyBitsMask) != 0) {
+                assertThrows(IllegalArgumentException.class, () -> codec.decode(encoded), "Final base-32 digit should not be allowed");
+                // The default lenient mode should decode this
+                final byte[] decoded = defaultCodec.decode(encoded);
+                // Re-encoding should not match the original array as it was invalid
+                assertFalse(Arrays.equals(encoded, defaultCodec.encode(decoded)));
+            } else {
+                // Otherwise this should decode
+                final byte[] decoded = codec.decode(encoded);
+                // Compute the bits that were encoded. This should match the final decoded byte.
+                final int bitsEncoded = i >> discard;
+                assertEquals(bitsEncoded, decoded[decoded.length - 1], "Invalid decoding of last character");
+                // Re-encoding should match the original array (requires the same padding character)
+                assertArrayEquals(encoded, codec.encode(decoded));
+            }
+        }
     }
 
     @Test
@@ -153,13 +201,30 @@ public class Base32Test {
         testBase32InBuffer(100, 100);
     }
 
-    private void testBase32InBuffer(final int startPasSize, final int endPadSize) {
+    @Test
+    public void testBase32AtBufferStart() {
+        testBase32InBuffer(0, 100);
+    }
+
+    @Test
+    public void testBase32BinarySamples() throws Exception {
         final Base32 codec = new Base32();
-        for (final String[] element : BASE32_TEST_CASES) {
-            final byte[] bytes = element[0].getBytes(CHARSET_UTF8);
-            byte[] buffer = ArrayUtils.addAll(bytes, new byte[endPadSize]);
-            buffer = ArrayUtils.addAll(new byte[startPasSize], buffer);
-            assertEquals(element[1], StringUtils.newStringUtf8(codec.encode(buffer, startPasSize, bytes.length)));
+        for (final Object[] element : BASE32_BINARY_TEST_CASES) {
+            final String expected;
+            if (element.length > 2) {
+                expected = (String)element[2];
+            } else {
+                expected = (String)element[1];
+            }
+                assertEquals(expected.toUpperCase(), codec.encodeAsString((byte[])element[0]));
+        }
+    }
+
+    @Test
+    public void testBase32BinarySamplesReverse() throws Exception {
+        final Base32 codec = new Base32();
+        for (final Object[] element : BASE32_BINARY_TEST_CASES) {
+            assertArrayEquals((byte[])element[0], codec.decode((String)element[1]));
         }
     }
 
@@ -171,6 +236,47 @@ public class Base32Test {
         }
     }
 
+    @Test
+    public void testBase32DecodingOfTrailing10Bits() {
+        assertBase32DecodingOfTrailingBits(10);
+    }
+
+    @Test
+    public void testBase32DecodingOfTrailing15Bits() {
+        assertBase32DecodingOfTrailingBits(15);
+    }
+
+    @Test
+    public void testBase32DecodingOfTrailing20Bits() {
+        assertBase32DecodingOfTrailingBits(20);
+    }
+
+    @Test
+    public void testBase32DecodingOfTrailing25Bits() {
+        assertBase32DecodingOfTrailingBits(25);
+    }
+
+    @Test
+    public void testBase32DecodingOfTrailing30Bits() {
+        assertBase32DecodingOfTrailingBits(30);
+    }
+
+    @Test
+    public void testBase32DecodingOfTrailing35Bits() {
+        assertBase32DecodingOfTrailingBits(35);
+    }
+
+    @Test
+    public void testBase32DecodingOfTrailing5Bits() {
+        assertBase32DecodingOfTrailingBits(5);
+    }
+
+    @Test
+    public void testBase32HexImpossibleSamples() {
+        testImpossibleCases(new Base32(0, null, true, BaseNCodec.PAD_DEFAULT, CodecPolicy.STRICT),
+            BASE32HEX_IMPOSSIBLE_CASES);
+    }
+
     @Test
     public void testBase32HexSamples() throws Exception {
         final Base32 codec = new Base32(true);
@@ -196,32 +302,33 @@ public class Base32Test {
     }
 
     @Test
-    public void testBase32Samples() throws Exception {
-        final Base32 codec = new Base32();
-        for (final String[] element : BASE32_TEST_CASES) {
-                assertEquals(element[1], codec.encodeAsString(element[0].getBytes(CHARSET_UTF8)));
-        }
+    public void testBase32ImpossibleChunked() {
+        testImpossibleCases(
+            new Base32(20, BaseNCodec.CHUNK_SEPARATOR, false, BaseNCodec.PAD_DEFAULT, CodecPolicy.STRICT),
+            BASE32_IMPOSSIBLE_CASES_CHUNKED);
     }
 
     @Test
-    public void testBase32BinarySamples() throws Exception {
+    public void testBase32ImpossibleSamples() {
+        testImpossibleCases(new Base32(0, null, false, BaseNCodec.PAD_DEFAULT, CodecPolicy.STRICT),
+            BASE32_IMPOSSIBLE_CASES);
+    }
+
+    private void testBase32InBuffer(final int startPasSize, final int endPadSize) {
         final Base32 codec = new Base32();
-        for (final Object[] element : BASE32_BINARY_TEST_CASES) {
-            final String expected;
-            if (element.length > 2) {
-                expected = (String)element[2];
-            } else {
-                expected = (String)element[1];
-            }
-                assertEquals(expected.toUpperCase(), codec.encodeAsString((byte[])element[0]));
+        for (final String[] element : BASE32_TEST_CASES) {
+            final byte[] bytes = element[0].getBytes(CHARSET_UTF8);
+            byte[] buffer = ArrayUtils.addAll(bytes, new byte[endPadSize]);
+            buffer = ArrayUtils.addAll(new byte[startPasSize], buffer);
+            assertEquals(element[1], StringUtils.newStringUtf8(codec.encode(buffer, startPasSize, bytes.length)));
         }
     }
 
     @Test
-    public void testBase32BinarySamplesReverse() throws Exception {
+    public void testBase32Samples() throws Exception {
         final Base32 codec = new Base32();
-        for (final Object[] element : BASE32_BINARY_TEST_CASES) {
-            assertArrayEquals((byte[])element[0], codec.decode((String)element[1]));
+        for (final String[] element : BASE32_TEST_CASES) {
+                assertEquals(element[1], codec.encodeAsString(element[0].getBytes(CHARSET_UTF8)));
         }
     }
 
@@ -282,6 +389,12 @@ public class Base32Test {
         assertNull(new Base32().decode((byte[]) null), "empty Base32 encode");
     }
 
+    private void testImpossibleCases(final Base32 codec, final String[] impossible_cases) {
+        for (final String impossible : impossible_cases) {
+            assertThrows(IllegalArgumentException.class, () -> codec.decode(impossible));
+        }
+    }
+
     @Test
     public void testIsInAlphabet() {
         // invalid bounds
@@ -379,117 +492,4 @@ public class Base32Test {
             }
         }
     }
-
-    @Test
-    public void testBase32ImpossibleSamples() {
-        testImpossibleCases(new Base32(0, null, false, BaseNCodec.PAD_DEFAULT, CodecPolicy.STRICT),
-            BASE32_IMPOSSIBLE_CASES);
-    }
-
-    @Test
-    public void testBase32ImpossibleChunked() {
-        testImpossibleCases(
-            new Base32(20, BaseNCodec.CHUNK_SEPARATOR, false, BaseNCodec.PAD_DEFAULT, CodecPolicy.STRICT),
-            BASE32_IMPOSSIBLE_CASES_CHUNKED);
-    }
-
-    @Test
-    public void testBase32HexImpossibleSamples() {
-        testImpossibleCases(new Base32(0, null, true, BaseNCodec.PAD_DEFAULT, CodecPolicy.STRICT),
-            BASE32HEX_IMPOSSIBLE_CASES);
-    }
-
-    private void testImpossibleCases(final Base32 codec, final String[] impossible_cases) {
-        for (final String impossible : impossible_cases) {
-            assertThrows(IllegalArgumentException.class, () -> codec.decode(impossible));
-        }
-    }
-
-    @Test
-    public void testBase32DecodingOfTrailing5Bits() {
-        assertBase32DecodingOfTrailingBits(5);
-    }
-
-    @Test
-    public void testBase32DecodingOfTrailing10Bits() {
-        assertBase32DecodingOfTrailingBits(10);
-    }
-
-    @Test
-    public void testBase32DecodingOfTrailing15Bits() {
-        assertBase32DecodingOfTrailingBits(15);
-    }
-
-    @Test
-    public void testBase32DecodingOfTrailing20Bits() {
-        assertBase32DecodingOfTrailingBits(20);
-    }
-
-    @Test
-    public void testBase32DecodingOfTrailing25Bits() {
-        assertBase32DecodingOfTrailingBits(25);
-    }
-
-    @Test
-    public void testBase32DecodingOfTrailing30Bits() {
-        assertBase32DecodingOfTrailingBits(30);
-    }
-
-    @Test
-    public void testBase32DecodingOfTrailing35Bits() {
-        assertBase32DecodingOfTrailingBits(35);
-    }
-
-    /**
-     * Test base 32 decoding of the final trailing bits. Trailing encoded bytes
-     * cannot fit exactly into 5-bit characters so the last character has a limited
-     * alphabet where the final bits are zero. This asserts that illegal final
-     * characters throw an exception when decoding.
-     *
-     * @param nbits the number of trailing bits (must be a factor of 5 and {@code <40})
-     */
-    private static void assertBase32DecodingOfTrailingBits(final int nbits) {
-        // Requires strict decoding
-        final Base32 codec = new Base32(0, null, false, BaseNCodec.PAD_DEFAULT, CodecPolicy.STRICT);
-        assertTrue(codec.isStrictDecoding());
-        assertEquals(CodecPolicy.STRICT, codec.getCodecPolicy());
-        // A lenient decoder should not re-encode to the same bytes
-        final Base32 defaultCodec = new Base32();
-        assertFalse(defaultCodec.isStrictDecoding());
-        assertEquals(CodecPolicy.LENIENT, defaultCodec.getCodecPolicy());
-
-        // Create the encoded bytes. The first characters must be valid so fill with 'zero'
-        // then pad to the block size.
-        final int length = nbits / 5;
-        final byte[] encoded = new byte[8];
-        Arrays.fill(encoded, 0, length, ENCODE_TABLE[0]);
-        Arrays.fill(encoded, length, encoded.length, (byte) '=');
-        // Compute how many bits would be discarded from 8-bit bytes
-        final int discard = nbits % 8;
-        final int emptyBitsMask = (1 << discard) - 1;
-        // Special case when an impossible number of trailing characters
-        final boolean invalid = length == 1 || length == 3 || length == 6;
-        // Enumerate all 32 possible final characters in the last position
-        final int last = length - 1;
-        for (int i = 0; i < 32; i++) {
-            encoded[last] = ENCODE_TABLE[i];
-            // If the lower bits are set we expect an exception. This is not a valid
-            // final character.
-            if (invalid || (i & emptyBitsMask) != 0) {
-                assertThrows(IllegalArgumentException.class, () -> codec.decode(encoded), "Final base-32 digit should not be allowed");
-                // The default lenient mode should decode this
-                final byte[] decoded = defaultCodec.decode(encoded);
-                // Re-encoding should not match the original array as it was invalid
-                assertFalse(Arrays.equals(encoded, defaultCodec.encode(decoded)));
-            } else {
-                // Otherwise this should decode
-                final byte[] decoded = codec.decode(encoded);
-                // Compute the bits that were encoded. This should match the final decoded byte.
-                final int bitsEncoded = i >> discard;
-                assertEquals(bitsEncoded, decoded[decoded.length - 1], "Invalid decoding of last character");
-                // Re-encoding should match the original array (requires the same padding character)
-                assertArrayEquals(encoded, codec.encode(decoded));
-            }
-        }
-    }
 }
diff --git a/src/test/java/org/apache/commons/codec/binary/Base64Codec13Test.java b/src/test/java/org/apache/commons/codec/binary/Base64Codec13Test.java
index f194848a..f6f319a3 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base64Codec13Test.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base64Codec13Test.java
@@ -45,106 +45,106 @@ public class Base64Codec13Test {
         initBYTES();
     }
 
-    /* These strings were generated from random byte[] arrays fed into commons-codec-1.3.jar */
-    private static void initSTRINGS() {
-        final String[] s = STRINGS;
-        s[0] = "";
-        s[1] = "uA==";
-        s[2] = "z9w=";
-        s[3] = "TQ+Z";
-        s[4] = "bhjUYA==";
-        s[5] = "1cO9td8=";
-        s[6] = "sMxHoJf5";
-        s[7] = "jQcPlDsZzw==";
-        s[8] = "TAaPnfW/CYU=";
-        s[9] = "cXTZuwzXPONS";
-        s[10] = "Ltn/ZTV4IjT6OA==";
-        s[11] = "6fh+jdU31SOmWrc=";
-        s[12] = "E/5MoD4qCvDuTcFA";
-        s[13] = "2n9YyfCMyMXembtssQ==";
-        s[14] = "qBka3Bq6V31HmcmHjkY=";
-        s[15] = "WvyZe6kQ8py7m25ucawJ";
-        s[16] = "oYpxMy6BSpZXhVpOR6dXmA==";
-        s[63] = "yexFaNKaP+VkVwEUvxQXbC0HSCi/srOY7c036lT25frs4xjIvp214JHCg7OL/XZW3IMe6CDgSMCaaI91eRgM";
-        s[64] = "vkqgnuJ3plxNtoveiMJuYLN6wZQLpb3Fg48/zHkdFuDucuMKWVRO/niFRgKsFqcxq6VgCxwQbePiP9sRnxz7wg==";
-        s[65] = "YHks3GCb2uVF47Y2tCieiDGJ879Rm5dBhQhQizYhfWOo+BrB2/K+E7wZWTid14lMpM60+5C0N9JNKAcBESeqZZI=";
-        s[66] = "z8551jmQp/Qs95tw226+HCHWruKx/JvfBCfQ5p0fF77mkSpp66E552ik2gycrBBsMC/NbznAgTZoMzZxehfJwu49";
-        s[67] = "VsR2whqq/qQm342+TNz1lgOZMoWbpCz+kj2zflq0nx7S/ReEVPUJcqgMtVzrr2FVQPfBAH5VRjR+hkxwv4bssQms8Q==";
-        s[68] = "5xmIp8dUJZzkisIkuEPsnPXvzDeMo48qWFfHIn2av3jr5qoZHCs0LfNEyepC3v2sa0nCU0FlqsmDyTI5/2jt5zsLtV0=";
-        s[69] = "tGEgXjglUB9NbCtiS88AetLtRqhCAnhzOUKVgvbJZHqOA6x8uOorA1t3NcaIA00ZqbPYALu4LzIm4i4lAL9QgiH/Jg7b";
-        s[70] = "gFtxEhYJahDmU5dpudYs6ZTsqAx+s2j+06A0zeyb3U7nhZFsbkCDlds0EYUoqerZqZPm7F6CDOOD3dU7nYmelE0DxyMO9A==";
-        s[71] = "j/h/1JygYA5bjttxzQxr5gBtgh+AYVozhF4WgvcU/g49v0hUy6FdhfZewGK+Phtzj7RabI5p2zXyzvkmLQdFhdI5Um4O5sw=";
-        s[72] = "m+kYVGojIR5pgbz7pGJm2g+3qqk7fhl3cowa2eVrhki7WofyywnRezqTxOkBgVFz6nKs8qxpbbbzALctcPeMsp9dpXUfuUJr";
-        s[73] = "pPaGnMr0UYmldnJVk/F+3WCJJ1r2otvD5KJdt2u1RnS6LwhHhwLCqfW8O/QEg43WdxKomGL/JM33tn/B9pMPoIU0QTGjq2GRow==";
-        s[74] = "mOxzGyym6T/BxCV5nSiIYMlfAUmCN7gt7+ZTMg1kd8Ptirk+JF5dk8USbWBu/9ZvNg5ZuiJCeGwfaVpqpZ3K9ySF7C87Jvu1RUE=";
-        s[75] = "VYLOIE4DnhxJn3FKS/2RHHHYLlZiGVdV/k4uBbtAYHUSTpRzaaYPGNAVjdNwbTHIihmeuk/5YQUy8NFsxIom+Li7bnWiBoHKBPP7";
-        s[76] = "7foMpJ0TknCatjUiSxtnuKSiz4Qvl/idWY9UKiTljoQHZ+C8bcUscnI/bZr13e6AvyUh47MlpdGvzIm05qUdMWWLoZJOaGYvDmvrWQ==";
-        s[77] = "jxQSGiFs+b1TfE4lDUAPUPJ0SWeUgl03rK6auieWJcarDIHM97gGOHMmyHudRMqkZmIkxYRgYgCCUg/JeU91OZD3tL4U+wNhShywe88=";
-        s[78] = "UGmH/gl7t3Dk801vRhRDEbgsfShtHZ1gZQn4KNZ5Qsw3WiGjW0ImInVHa+LSHBzLUjwC0Z3nXO4i4+CiKYqAspOViE6WqVUY8ZSV0Og4";
-        s[79] = "wdEoYmJuRng2z2IkAiSgJ1CW2VE7H7oXpYWEFFO8nG0bZn7PHhT8KyhaO2ridl8eUEysja0VXFDyQqSgZnvdUKrCGepWGZbw0/0bDws3Ag==";
-        s[80] = "5kZqgrUbt+rN5BWAddeUtm9TGT43vYpB6PeyQwTyy9Vbr0+U/4Qzy0Iw37Ra293HmkmpgQzuScVpcIiFGXPAFWwToR+bovwu7aXji/FnMwk=";
-        s[81] = "E467MMmJbmwv8Omc2TdcyMr/30B8izWbf+CAuJtw67b1g9trhC6n4GYnXjeW9DYvmWoIJPx0zvU/Q+gqv0cteg2bx9P2mrgMDARb6egowqjx";
-        s[82] = "Vpt8hYb4jx1F+7REX7K65v6eO5F1GDg/K8SVLWDSp0srupYEQkBVRxnB9dmhSo9XHpz4C8pRl8r82fxXZummEf4U2Oh0Dip5rnNtDL+IJvL8lQ==";
-        s[121] = "hf69xr9mtFf4N3j2uA9MgLL5Zy94Hjv+VQi94+LS8972JJgDHCQOwP5whdQkV+SJpXkiyHGaSsQ4fhepPwzuZcEpYER+beny1j+M0HSZe36MdRIhlTqno+4qsXckL0CjXsYkJJM0NAfOYjHAus5G1bgi9VhmiMfAMA==";
-        s[122] = "yKzTh5hPp9/PBeZtrZXsFHAR9ywOM3hRaBDkgG9E09wFW8MZD0xMGegcp0QrTJcP8QYOaYhTDVimPqsNTVOmjdjkvS+2WhjJW4mVOXQ8KID91yaBtPo+DStL5GMgctcP5MoVf1Vp8w/mYtofqbllfDm5NfYzh2A7ijY=";
-        s[123] = "csFmwvDzoO4IO6ySDA4B2V7emEetAwCgO66zzlfWb3KDrPfFZc3Jgr4+dlaUkEIDHYeLHETdTssWOl2KrPHBEsULpDTR+3OhurXb1Qr2NvHiHFuqT3Geb6EYw2albfTmXxch82ablt4WKl4qPcSey54v6tsCuUuZzrkt";
-        s[124] = "5InxvKwpoCV7EK78OzU/tL9/NmK14Prw9tOCAyK+xpUNLZriuVEVdgpoZ05rliufaUDGHH8dPAem8G9DN/VOPktB6vXKtc2kMUgnMTiZwv/UVd+xyqnT8PLEdNQ8rCWxyiCcLdXFf0+xcE7qCcwzC+D7+cRW+i6dnpZkyw==";
-        s[125] = "cEx7oTsSHWUFPj92cstdy5wGbRcxH+VRWN8kaNTTCPWqSckyU9Xk/jj5/gj9DFwjfsCSp60xutf4/rFanjtwqtRg6dJLP4JAgpOKswDlHi6Vt7zF/w7HidMf2sdtlsqzayZmT2Hn7iOo3CExzr5Z5JfmMFAX8R9peUN4t5U=";
-        s[126] = "AeXetVbj+7mmGiCs3BGUSZDLlq2odMsN8JAHQM64Cly8y5jw75PpISocWRFFQmmXYP7ckKmtuhIvD69HtZxGhNRsl1l1gXzKFhsWykcRtG87F8sS1Uv/i6QvGiRIDVEGGIzWrzRIISkBb9wCxJ2HESfleWwrz/GqryjoN26B";
-        s[127] = "aj1/8/+U8VO3D2iAwvQXZ4H0KwtuzDm4JCC8+22ccqk+UzKvqjGs87XngwfsMfSkeGVAi6VB6tfNJTjYctaj7R8dwh2PIfLSrvaphw4wNB2REjplnPojoOb9bNUNtUvdK3b1bArOWugIRJWLnMl72yEHFb1iBfBmn7uIa7KT2Q==";
-        s[128] = "kiMuF/1CMRlgoS/uLKn1mNZFZNHJNkRQnivOrzj8HQAagwzvTXvsGgI9hXX3qaeZL9/x/Oq+Y5F6Dh+wXo+0kp6JagFjvbTJcQSowFzIwg7/V9sans0NE0Ejow5BfZKvihFI46sHiALl1qzoXqLQq+5fZGIFRyyY8wFW1uiNu9k=";
-        s[129] = "YXmCWhiNz4/IhyxQIYjgNvjX+XwDiPTSBMaFELm5X8Y4knGRnkF4/zix8l9wHBb+7Cgfrr46rF7eiIzaAFLjLjjewy63duBJiVbEWjqFO0fu6T9iIjuEaF2sTppvuZNPHx80vN+HLAnAVmgFESw5APXWn15dizvuUfVHd5isCqbA";
-        s[130] = "GJfUoBivW5uqDpUxTRfjGWNYfN3/dTFtdRqCIH5L2c1nWX0dgY3ba1+fW/YX1Oh5aw4lC6BIiiThjJoV1VrNnlXzbcUcMy+GsDUUB8Qe8lBvfe/t4RmNPB0hVgrS89ntbuU0SsCmWw+9DqM3nidPebANKERig1zZTBBKgpVf7HPFCA==";
-        s[131] = "eTerNs7dOqJAxAxcMQRnUDc2cBj2x0jU1g1D3G+b22kDz7JBzOy/mxhGXAQ3130lavWMhImSBkReU+z0A13EYVMUv9PFzD747KCvns+SCo52YNHB0896b4l47q8hu8jsD17TZ2uWWJhS4cNnSE1jeM6NoXGKvf90yxfzwucNYc4RdaQ=";
-        s[132] = "lbrGsjbzE521q8tzVHV7vcTPchUnzI/UfeR2R+cmOa29YljPWLht9Wx2JrjiKv4Of5nXe7kvhi+LYUuFVqgaqIFhC/PLbqOFiT2VZcXorToaRT9CLiqV5b6nHN/Txz6SI7MiD3hnk7psDbglPOo+ytqc9sFHj7UkR1ZctQjwFYwJjlxf";
-        s[133] = "mQwAPzYzfxz9FXEiZ6M8u1oN3EJbFYmNVfpm+j0DqgU+OPI4URHBIrF4xvdMvAPn0WuarbQy/ZVN0eKL7S4K3Mvan0flAwaZdI+e5HpkfxOoGTp8Dk5EFTXjmZ/s+GonePEQEGNVPL1WYoD6xXqAAvMLKtyrFcpoiGS9eDBlsZDQzPzz/g==";
-        s[134] = "3G6d12UY4l5W7Nnw0BL0HnViVg9SdEuLMqeZwy0RlJR/Ytcgd/mIxIuXXAlGhvhoX6Xc2BGU7RpTi1jYKzA86yul0j96dbcE4OtrP9lUBJlcY9eWz59dvLqKxwt3cEOBwrPf69MHuIa256es3AOCobfC8RQScW0PQ0QUa1VHB/eXSsVTSWg=";
-        s[135] = "AxgrZKTFk5JvLC3DBACHwp266FxKI/yn9F+1tYkzL57RVs5HCJYS47VuG0T0E2wqzHqcLKPQMZWU7vbRoyMGNL3ZtaHoZqTqcq9KWtODC+OnEvSS7+1P4SmQDuyL2MJ/eJABJKNcu1K/Lk0buAaO0FvX6OGBcPzu1+dv/ZkwuORK07qRnxqQ";
-        s[136] = "atkG8l2U/Nnm+zLu7zjenrfcAVQJMUqHimFZ3cQfaUp4qyrFn1UiwZ33j66Vt63eVaT/FXx+LlEnsHn6ATPBMp3iEYoBJYyNpjz/zROhBbcznQAMdWUTcyKInvnG3x6ExgBXpyqfxxp/Pm8by7LlSUT5MKHdcu+TEfUXRokCr2iPnt7NYsNDfA==";
-        s[137] = "dciU1mSHGcBxOAVBgJx75J6DaQdBZfTIzQ04WhkkdRMupOZWSnv19xhz8hiO+ZnbBtDJuO5rHsUGzH/jYacfZyCQ924roRvkh3T1yxsLq3abZJUCD9HYnPTELVhv1+cEF4aoO3vGOu2FpfLUn5QTd0PozsIqcqZVB2V57B7DjfizUe3D8Yf5Vco=";
-        s[138] = "dgR1PPacBvtILBmg33s9KWtuc67ndh3rCHZ/lIN7sENgbFqJQy5DC3XIeHTV7oWd+tJQaXxoC71/SU7Rz6OClAMKXLbMz8U6RPiqn3M7MRCQcDfNjA5cCNknXT9Ehz/IZF/7lcWrwxBKYm4B98lPkpZtR2QHndiQ3venzWrP0P5y27mReaFuaJ++";
-        s[139] = "1Q8rfp1HuGsxurTgGMakxj5SwNF7EixXxVPnfGADWDcygh5C1BMXqiL1AuVXOVFOsaydfLWGC8Kbh/JiL6H+12lYrNGUT9yJRIzRDi4XylMnrYwBtwCJjoHSi4exz5K2ih54utVAuzXZg6mnc9ied/mNRjj9d2HFD5mv0w/qTN/WFxEmtuZM/nMMag==";
-        s[140] = "w01TnPP/F3Vni3fBdV32Bnbb4J1FcbaE+Xn44no5ug77U8FS1gSm3LqJ8yTyXduzl5v2dwBEfziEfTuyqgeLLsCYTBjXmYOIHQosEl6DyAknu4XK52eQW+Fes9eSs2Nq+G4aaR4y4leeFNmCoZ9BQmAAZr0LFkqnvqaKmBVgcgxPs7/8SQHnpqvaU6Y=";
-        s[141] = "OfzIF38Tp5g1W5eVbrkrMe0Mm7e0wBYg5hVvLpn/5MW5OFcmRDuBp15ayRBnJ1sBI93+CNl0LwP8Q0z9IXFjTER5gHZ1KfG8NV+oacKNG7aYrbUftkSL/oPfRNPez6U0FuWgvVrXUB6cwKTWvwb9KoD7s6AGYRdH50ZgJdBniFD7dKoOQnJ/ECuTUXI+";
-        s[142] = "4hoX0sjqlkSJPUq627iJkNYRbtD+V2qErCuTikaeRDEZvVHWvzdvwj4W1xxJjz+yHAN6z2EjCWidcSsVgTejQ1bH8uTzJgh/zq3yGUSsJoJWrecqxsge8bEBjkm+qUO8G3kAnC6FMjJ2NYQeXf6OK6OgsqyJwlHPTyAms2/IoYTB4iEqgIFG/2fNEJEIag==";
-        s[143] = "M/dy14xNbZMRfHiKKFdmD/OrEB+8MexrRO8mMh0i5LrNA5WUtLXdwUfAysYmal94MSoNJfgmwGCoqNwlWZBW1kpQaPdqsrn2cvc6JcZW9FlOx07DERJGbZ6l6ofbzZWgF+yf+hvT6jnJvXBVCTT3lfO3qo4leNuEJwsuU6erXGC3Ch53uPtGIrdDUpcX6/U=";
-        s[144] = "GgLr2hd3nK64IZv0JksKAT/yJNQ38ayuWyBnWLjXbEmT048UDppsrrnP6hikRo5v2TlHGhD2dcwG9NLK3Ph8IoIo9Wf2vZWBB+SMI9FpgZxBWLEjwHbOWsHaEQMVsQfk38EWQP0Fr6VyMKlEQfpsRkuCpp1KxscaxK7g5BgXUlb0a2x0F+C9hEB0OVPsj4JN";
-        s[145] = "W9lKcLDqNGQAG/sKQNaRmeOUmLJ7GcMNqBaGZ659Rnjr6RTrfnmkp5Z9meALnwXoHjPjzSQDJnVYsY+xyMnuPgl6gMVAhAm+XprYVpsne4vt+7ojUqavVPBqLy5dtnhp1qfcnAiV5cZhHXX7NbxkUOzptjEGCQjnhSH4rPbZtgoIWE8Z6boF3l/thLnFX+AiiQ==";
-        s[146] = "iYLn5h9lIhD/x9moaPRnTX6mJEJKThg4WXxS7IrR2zblH26uOkINz0dJNTJVets0ZNYDnsnT7J2iI3Y6hTVWPGoYU49J3B2LhCREs0DZQ3C7080FtiOcfHbfBLNn0DyCK1LeAC7YB/bNdiyhLqH8fKl+0+KhiPDIUBJY2e7IbZR/9t0sxJbIXx6cRvI5AXex12o=";
-        s[147] = "SlRJEc7npTUvQq8SgBYKmVY/3wHYp2gsDxafN/JLUuEqEjmWMtW7fxASi+ePX4gmJJqLhD5t+AZxiCwYK3L3ceuJx4TiqVgJz8d6sc7fgWXluh1K+BcGPbZ7+Cq4Vsga7JEBVekviEZ5Ah4apNr8RkB7oMOUVPGxRcyyaVE4zBW+scA6c1yi/HQXddQ9rWyLUsVo";
-        s[148] = "AAlbGR6ekLOzx4hpqZTUqVUQ0FL2CFpgCMOp6CuuUzkSnWXpUjvOiSDkNPgoTPgpgmg3uYvMsX43mkPGUGC9awDThXyGQh6u3WfWtmhiPRqXnjFek+EPd0LYXps71non6C9m7nUlYNWzBJ1YzrzWjlB5LLPBN8bsZG6RbdZkYMxJ9J5ta/c30m8wDDNuTm0nEE0ZVQ==";
-        s[149] = "nWWbBhzObqwEFh/TiKREcsqLYbRjIcZflJpol16Mi4YDL6EZri22qRnTgrBtIY+HieTYWuLaCSk/B9WcYujoS6Jb5dyg3FQ6XF9bYaNQGx2w8DHgx0k2nqH/0U1sAU0kft32aD2orqCMIprbO1WJIt2auRnvcOTFoOax926nAkxvR3nrFVDevFjDbugpWHkGwic6G7o=";
-        s[150] = "WNk1Rn2qtG+gk0AEewrgo+aRbNrG4CgQpOR8Uo7c2m2XQY8MVDu4uRA6rzYGGdgqTcICKky9MvHeJeNWVAXOxmA4EdXQ2xItFJdQtxBt56cad9FBXXsz21yVsPr5d453abi7T3XfHVTToekiOlxAJs+bpat9cFRbIdHghO9wc/ucoArT53vpYsnyeVnmZG2PX48lXpNS";
-        s[151] = "wVmiO6mdf2aahrJlcmnBD0Qa58y8AvzXtJ54ImxgPLPn0NCQIrmUxzNZNTODE3WO6kZMECaT/REqT3PoOBp9stCHCFNXOM7979J44C1ZRU0yPCha00kQZBF5EmcLitVCz10tP8gG1fiIvMjwpd2ZTOaY4/g4NeJHLjJPll0c5nbH7n4v+1I+xG7/7k7G6N8sp21pbgpTYA==";
-        s[152] = "OoiVZosI+KG0EZTu+WpH7kKISxmO1zRYaSPMBMW0AyRiC2iZVEkOMiKn12XPqIDSW/kVA58cvv/ysTAzKLTu78Uo+sVcJe3AtLdgeA9vORFELTP4v9DQ/mAmehe3N8xk+VTLY6xHWi6f4j9cTDW/BDyJSDRY00oYoHlvnjgHo4CHBo0sMGgX3CwcnK2hpMFVtB/3qPl6v2w=";
-        s[153] = "97ZVsTYwD8VrgN1FOIRZ8jm8OMgrxG3o1aJoYtPVWXp9cjjlgXqTMZVsoWr3pr7pudw+LYo1Ejz3JpiUPHqWcZ2PWrWs7PR1akYGuwdCBHYvCGTcZYFe/yu1AB8w5zYsl1eJR45g0u1DlXfx5BUAUzc4yJDjc48Ls62bn8t0EJ7+30sWwifqKuz2EHpsqp1j/iMlwzKJGjGE";
-        s[154] = "0NSYKTvBKKInwL9PJ/pWUWVX4gjF3igsA2qqQMsRew0lI1LcCB18eGCYk0AnyUCe99w5lWHGFUMMeH6DZciAylWGeDn19JdzVOTevBWk3LIujI1GvsEB3oVqf2Zl9IZeDGCT4+bQKBWvgcXHjysZfnn/5z9Xz06qrPqac5LfS36fDcwnkrUYQWDsL2Ike32ALmOnkcDjNq1BoA==";
-        s[155] = "5ok+rYI4LCgGa2psGUN/fdkT2gQEToB9HRiFXQpe2YcQvEN2z7YlJCETx4jSWw06p5Y8tZcp08moKNYwUJ40DvPpGlDG+wUpFhC4kkfo6vj6TrCj5yoWJi5D+qdgH2T0JeWM80cYN0bsOsetdaqNhDONlYXZ2lVYkyVS/wzw8K5xX87EWktwOwFq/yYhuWCYJ9GZL7QuDipJjEE=";
-        s[156] = "KHzTalU9wPSnIjh5g0eHi1HUaFufxJpXpjDe0N3wEKINqbgzhbj3Kf4qWjb2d1A+0Mlu9tYF/kA9ONjda5jYfRgCHm5mUrjU0TAyT7EQFZ2u6WFK/sFHP++ycJQk8k7KLPUWA5OWScy1EO+dYF4d0r6K5O+7H/rpknxN6M9FlP8sH83DXK1Sd+UXL32D+4flF580FaZ5B3Tkx3dH";
-        s[157] = "RrJVxIKoDXtCviWMv/SXMO42Dn6UWOKDy2hh2ASXssT0e+G6m7F1230iJWlEN0wBR8p+BlTdBhQrn25098P3K16rBmZpzw/5dmesIJxhYPaM4GiaOgztFjuScTgkmV0Jl/vZ9eCXdEVNISeXkIixM4pssTFuUV7PY/Upzdj55rDKGLr1eT7AFVSNP30PhL8zZs8MANqKBeKBBDvtww==";
-        s[158] = "sy4t5rFA75GRBE+Dqa9sQxjPluKt/JnEY54guHnKqccmx3HGiyJ0jUA+et4XO8Xg69wCA9xVxJZQL73z80mVfIf43HIKOxgxT2IjG7EKMOD/qx6NnMTve4BryggLtbLQUeRfhriQeY7h65tD9ierhccXoXDpGnmBn9m2BQP78y+Qhc4eIsa3LcxbQJUIwvURjFp/rgMD7lhOLboa/2Y=";
-        s[159] = "Zs/BfFoWImYau2dZLb7JneeTQp7sQ06yonEq0Ya4BNOJGy/5dGH42ozt0PpP2IZ/S58X7esVgc6jA1y3Bcxj3MPoDjQJSZHFEtR3G31T8eF5OpPVC4dw9s9clllM05tvcemssLdcd85UP/xBaDrmpAl8ZDSc73zflK3nJw8e0HQFYntNnlZPFyyyBLHnLycb6Jlvq7F2OqrZR+FXZnL3";
-        s[160] = "hdeDJuRnmb8q9EYec8+futT/CvqhpqoUdtmG6E31RrYJDs96M5Wfng90IEqrncZe4rVYDocRZK23dvqtJaPhTUBXXh42IyMlUnro69KI+075FvYYwgVaUd10r7ExWM5Z7DCQ2x8Tm1meK2YCTPkF1VXXexl1UjYCnRQuQxppdophMwroJK8VqlJbFFslchTSBFuI7wgcdy+f/LHMbMsusQ==";
-        s[161] = "ClCCOv0mD9//LR0OisHfamxcTvmlwMLgAIQt3hbOjRPkXwEgaDzP0u6LN8BNwdOVw+LhrbzMI8zQzHvo7mGPkQICeeim/x+xmGPQtmWnXxCWiL1uf/8eR5Wuy9Er8skTB8rG4/ubb2ssvCkubObPAkMSOgFnX9UtxnCN4+nMNV2vvn4xMTSvvQyYWewfnlNkflTyva1epE9RVW2RqRtJikY=";
-        s[162] = "Fs+AmFCnUr/imw8D0GpNidIP9qwW8yRAzmtqPS+vT6n5U4YFQcpgbznrYO4TPqkVF2oz1mpgLYIgx/u2XsrtljGX46LfY8OyUPaw4/da38QGngoIlS2cN01cgN3efSjMlnZFo1x8T9p0Nn1IgRgevOd5ezVUL7WdY7eeiE1pXXcGBgDYn7NDQph0dC6HDlBiS95bDFcZ+6FYigE4WybpsOHL";
-        s[163] = "wgO4DdGZy9g13IuOhkJGJcToyLuCBVm9T/c8qY4NOheVU1NW2g8sPIo+RiEsSST8sx6+Jh/A/kaCxYvJ9CsgnBjZMMWRsd383HZAoJtkxwKvyoeXzzD+puFvqKQBEKrlBEwffXhLDoFQAW2ycYtBGztl0GsUtoOob2nv7ienx1xD6KNZNaxYx2ObRAYS/e8LS3pg5dku9MPBp1X12m8ZIXRAaw==";
-        s[164] = "EkXt02SaRUIjFmoLxyO6N+giL4iA4fY0Exao+mjgEfZ+Wv6w95GXHBI1xlYMVLkOcnu9nescvcXQH0OrqL9uforEUTGTSg2ci67m4GrwAryMy+5eUo77Q5GpWKfsg8nDbD8a3gUI/9EE0sCNp7tMaKwoJ56cxhbG3TJYpqWTpq3/S3q76x+3ETL+zxh6EMh8MJPfWcIxlDS7evKqdPgS00KgUtk=";
-        s[165] = "OuBqx5LFJroRbDn41+4azFHlKgw6bMgbsRGaK9UnPvi5xfmV4SLQ2YzIhopGi1F57L6vKukaW0XlFk/Ff5Td5IMC7U+kvXKlf8fGIIQ8FaHI0vbIX89OJlBqlICqftSNiVRxtaE+aCh0rBoDfgPwuC8qBC20I1O3ZLuKfeUVGkMOLEWeZLS6mmcn3cSERj9o/dEl8QYwQvhH+VG6YWF//yki1Vu8";
-        s[166] = "SO/vDsqZDdImOdH19sZI7FUVhlx1EI0XRr8ArTuAG5F8LDK76Bct2C7fXTUowilXnJWhQxvbGiulkUGSuVjVP12zac9bShRpr1L3ucde7n1f9y/NcHJCwdqTLq7RYygItQ4ppQGiP9jXf2Dn/qmVZZTh+SY3AZCIS+OVo2LAiYJHWnzzoX8Zt+dOYiOA/ZQKZieVJlc8ks+2xqYPD55eH0btZn5hzA==";
-        s[167] = "tZL/qACMO9SzmgJhWQMsbKgE5lPAEbxn3NR7504ilgArR8j7uv1KF46uQyjrkEnyBormYB/6nLGlHht62IQftMYf5gHpHFfTvukRKF8728yIYAAYHPQ/WjHzHdVSqUJqF2a8RE6SvvY+KSKWLMU3hjn1f6dqX599hYD7AnbPGTpFKDU5sLFOXbuynU1sPUhP+a4Hev9yNU6atLDo4CkX/Yq3FbpWVuQ=";
-        s[168] = "GRe7uF1wH5/71B3vmGF+pN3H9PKO1tLwsnb0D4/Pm7Pu5KAe4OfelkfFIBgyjuoZrpeEkGZnb+qf+Kn7Kt1hDwYr/Mb9ewuwOXsbIpLQMgfh0I5XsPrWocduVzn+u/cm3cr0Z11zsx0AZjTqvslACkDqiquY41JhtGdc22RCvIYom2l+zzMIMyCPsHeCSB1MBu8EWK3iP7SD3dWttwzMg0xanoPDgk0U";
-        s[169] = "8BDFu+29lptlGSjcZe7ghWaUgIzbuUpM5XDFbtJVQPEd3bAE0cGRlQE9EhKXi5J/IskYNrQ357tBhA+UNDNXCibT2AZGpzWAcwE6dP+14FuRL5Gxqh/teuPYKr5IIn7M3SbgOychZzLI7HGCvVhBUiJBu8orI3WmAIVcUhAsMGHsFveck/ZCXQA+Uq/WVnW1VNs6hSmIhsAFc51qsmsQK07z2Wptx4rRjw==";
-        s[170] = "siPSXD4u36WYtTvvDzRlFPiuZMnRczrL3eA15955JDCc6/V2Cvu6m/HPO6JxogxO0aYTZ5tejYDOIZgBy40DgUZMqPJ2IpYjsmUbjjJU8u/OpwhMon525m3v0EYlvyj2Qp3pwFKDkvncK3aNjN3KaaX6HuIy6kyqsDl0BTEnB5iJyHLRBCkeznTK019u48Yfsrz2oGuZcWzNj5/vKMdxQPiyJ9EHyox8Ark=";
-        s[171] = "+/14PnFQVZ7BTHKUvkTtRrYS7WnPND5gZ5byMhUrDLkJa6UPBV7z0nrDMifEo/dQfUq3EjCiG6xGVhrUvAzgxqOQZTW1Y9p9M0KWW+E0XvCQppHFpuMqF1vYsF0OD6AMiE9JtGnWs3JcaWP/XBF/CvhQlFGbHi3fbrD/haTEBnmpJWBgMdKribdbXHtBSFZ2MzCX2eDtxoDdRdEVGs4v/q8gVBS+WsnZ3TTF";
-        s[172] = "31I1ja+B+aopKkztGzJYvJEWAshyoAAV5yve4LnP0kdImUQaVETSuo5CDIYr7zM8MCD1eYPpLicmGnA+C927o9QGAVL3ctO/DCWhNinW7NmeYIM+o4diKBkDPjHmSWa+nq4nr+gOap4CtwL2wW2B5Yqt26pKgN9uAU5CmTL26hYFgMEOZfrkQ7XdYGy2CN8RJLmjeSFVVNBG/FTaK7tpuy0LQSkko6wczBYGeg==";
-        s[173] = "XbRfDqGe3eeI1tHx8UnPneDB57N8VeSSzXzVCNSgxOEfd6d/un5CDxHG+m4w3tIbtSky4R2+zMF+S5cRvTOwZ/veegYtLKTxA0mVedWLFkfh/v4NgPJ+NEU+cylbSSZLAeBofDvoJwnYKujN2KFa8PGAxr3Y8ry3qdkS8Ob1ZiHYAmLvKS9sGb/vjTvRy+a4Q7kOepsm7PYisinKelBAvDnjli6/lOutGrenjX4=";
-        s[174] = "jGEj/AaBefac9uOcmGuO9nH+N+zMsC4qAe6ZUEMMIXdTGnSWl7Xt0/nKqyOj3ZH249HwkJ8bn5C+0bzOpQ1eA3PxEq6RfKMrjHJPJmTZXrSESTjfj3oNLU/CqqDOqd8znTgN6nvnUdCeStLMh9bmWF1+0G11nDwg6GQWWQ0zjVDTq5j7ocXcFOyUcu0cyl5YDcUP0i2mA2JullInU2uBte7nToeSGB3FJxKueBbv";
-        s[175] = "RAzNCxlP2S/8LfbGtlSDShox8cSgmJMOc2xPFs8egZVJiwlmnS3aBWKPRbbxkZiVVYlu4GNJNwbocc6dgrl28HXAsYikE5wwoQ1MeOJWU3zzFiYENh7SLBQfjVPQHucctr8P6Rl7YL5wHc+aC+m92R3bnzm5rp1PeHm7uzy2iUUN0cgfbwJ4FrpXhVMTsAUpTbg1+037EWcGOuxir4dG2xBfgOwa+ejFHkw7y0LWRw==";
-        s[176] = "08hmZptBGKKqR6Qz9GNc2Wk1etgU/KogbiPQmAh5IXlTBc97DuEToL4Bb889nfObVQ/WelmiCS8wEjSBdmnlkkU7/b5UT3P4k1pB6ZxPH9Qldj5aazkA/yCb0kzDfJlcdFOh1eAcu5LvwTXOizmPwsDvJEnOkaDZrKESZshsHU2A6Mx6awk9/orf6iBlJHQIIH3l4o3b1gx2TNb/hUgdAlwtQDhvKO3skB0PS+rcWAw=";
-        s[177] = "0GhrgbSSHPLWtyS2mnSxrNAj/dyrFQcxIgPjT7+78SZ1ZTGc03vsmlZ4Z/bOO84E9yKblaI5dSHVXrx57L0kikL8tgKCsAkUNO3l/4zv5FfCrRTgGx4sFTFB1NNcLcwagkvFzde764DjYmj4YZhYsXSZCVKi0uu5M8fpgGDZ9UMSFR008cbhaIoFLWSANqiNJYSvTQZhGWfLtIPGLN+gIOMcaKhx1b5vg6OYSz6ScAM/";
-        s[178] = "2VGiMV/f2hNZAjw3fdeHx/wRIVzeP018lZynzwSySG/zQBxyRmi3YmKVZmh3aJunuiqmvdt0kJ6lX7M8BajYHPCBkqJOx8oPJ/K1oADxVgnavZ69dKYrSy9/Pm6sHxjFrdSz9TelUK9sgoFTWS6GxgzWEqXRBDDpGUnsNbSEcWLPKVLNNoYAcltY98JZaNSZBXcpa9FeSN7sVU43q2IEcDx3ZkJzRJpl/lb7n+ivMwX/OQ==";
-        s[179] = "iMSCh1m5vct3C7LEn5wKRYtalzvG6pKahG19rTb6Z9q7+buDsML5yM6NqDvoVxt3Dv7KRwdS3xG/Pyb7bJGvQ2a4FhRnTa4HvPvl3cpJdMgCCvsXeXXoML4pHzFlpP0bNsMoupmhQ0khAW51PAr4B165u1y5ULpruxE+dGx/HJUQyMfGhOSZ5jDKKxD5TNYQkDEY28Xqln6Fj8duzQLzMIgSoD8KGZKD8jm6/f8Vwvf43NE=";
-        s[180] = "hN4+x/sK9FRZn5llaw7/XDGwht3BcIxAFP4JoGqVQCw8c5IOlSqKEOViYss1mnvko6kVrc2iMEA8h8RssJ4dJBpFDZ/bkehCyhQmWpspZtAvRN59mj6nx0SBglYGccPyrn3e0uvvGJ5nYmjTA7gqB0Y+FFGAYwgAO345ipxTrMFsnJ8a913GzpobJdcHiw5hfqYK2iqo8STzVljaGMc5WSzP69vFDTHSS39YSfbE890TPBgm";
+    /* Here are the randomly generated byte[] arrays we generated to exercise commons-codec-1.3.jar */
+    private static void initBYTES() {
+        final byte[][] b = BYTES;
+        b[0] = new byte[]{};
+        b[1] = new byte[]{-72};
+        b[2] = new byte[]{-49, -36};
+        b[3] = new byte[]{77, 15, -103};
+        b[4] = new byte[]{110, 24, -44, 96};
+        b[5] = new byte[]{-43, -61, -67, -75, -33};
+        b[6] = new byte[]{-80, -52, 71, -96, -105, -7};
+        b[7] = new byte[]{-115, 7, 15, -108, 59, 25, -49};
+        b[8] = new byte[]{76, 6, -113, -99, -11, -65, 9, -123};
+        b[9] = new byte[]{113, 116, -39, -69, 12, -41, 60, -29, 82};
+        b[10] = new byte[]{46, -39, -1, 101, 53, 120, 34, 52, -6, 56};
+        b[11] = new byte[]{-23, -8, 126, -115, -43, 55, -43, 35, -90, 90, -73};
+        b[12] = new byte[]{19, -2, 76, -96, 62, 42, 10, -16, -18, 77, -63, 64};
+        b[13] = new byte[]{-38, 127, 88, -55, -16, -116, -56, -59, -34, -103, -69, 108, -79};
+        b[14] = new byte[]{-88, 25, 26, -36, 26, -70, 87, 125, 71, -103, -55, -121, -114, 70};
+        b[15] = new byte[]{90, -4, -103, 123, -87, 16, -14, -100, -69, -101, 110, 110, 113, -84, 9};
+        b[16] = new byte[]{-95, -118, 113, 51, 46, -127, 74, -106, 87, -123, 90, 78, 71, -89, 87, -104};
+        b[63] = new byte[]{-55, -20, 69, 104, -46, -102, 63, -27, 100, 87, 1, 20, -65, 20, 23, 108, 45, 7, 72, 40, -65, -78, -77, -104, -19, -51, 55, -22, 84, -10, -27, -6, -20, -29, 24, -56, -66, -99, -75, -32, -111, -62, -125, -77, -117, -3, 118, 86, -36, -125, 30, -24, 32, -32, 72, -64, -102, 104, -113, 117, 121, 24, 12};
+        b[64] = new byte[]{-66, 74, -96, -98, -30, 119, -90, 92, 77, -74, -117, -34, -120, -62, 110, 96, -77, 122, -63, -108, 11, -91, -67, -59, -125, -113, 63, -52, 121, 29, 22, -32, -18, 114, -29, 10, 89, 84, 78, -2, 120, -123, 70, 2, -84, 22, -89, 49, -85, -91, 96, 11, 28, 16, 109, -29, -30, 63, -37, 17, -97, 28, -5, -62};
+        b[65] = new byte[]{96, 121, 44, -36, 96, -101, -38, -27, 69, -29, -74, 54, -76, 40, -98, -120, 49, -119, -13, -65, 81, -101, -105, 65, -123, 8, 80, -117, 54, 33, 125, 99, -88, -8, 26, -63, -37, -14, -66, 19, -68, 25, 89, 56, -99, -41, -119, 76, -92, -50, -76, -5, -112, -76, 55, -46, 77, 40, 7, 1, 17, 39, -86, 101, -110};
+        b[66] = new byte[]{-49, -50, 121, -42, 57, -112, -89, -12, 44, -9, -101, 112, -37, 110, -66, 28, 33, -42, -82, -30, -79, -4, -101, -33, 4, 39, -48, -26, -99, 31, 23, -66, -26, -111, 42, 105, -21, -95, 57, -25, 104, -92, -38, 12, -100, -84, 16, 108, 48, 47, -51, 111, 57, -64, -127, 54, 104, 51, 54, 113, 122, 23, -55, -62, -18, 61};
+        b[67] = new byte[]{86, -60, 118, -62, 26, -86, -2, -92, 38, -33, -115, -66, 76, -36, -11, -106, 3, -103, 50, -123, -101, -92, 44, -2, -110, 61, -77, 126, 90, -76, -97, 30, -46, -3, 23, -124, 84, -11, 9, 114, -88, 12, -75, 92, -21, -81, 97, 85, 64, -9, -63, 0, 126, 85, 70, 52, 126, -122, 76, 112, -65, -122, -20, -79, 9, -84, -15};
+        b[68] = new byte[]{-25, 25, -120, -89, -57, 84, 37, -100, -28, -118, -62, 36, -72, 67, -20, -100, -11, -17, -52, 55, -116, -93, -113, 42, 88, 87, -57, 34, 125, -102, -65, 120, -21, -26, -86, 25, 28, 43, 52, 45, -13, 68, -55, -22, 66, -34, -3, -84, 107, 73, -62, 83, 65, 101, -86, -55, -125, -55, 50, 57, -1, 104, -19, -25, 59, 11, -75, 93};
+        b[69] = new byte[]{-76, 97, 32, 94, 56, 37, 80, 31, 77, 108, 43, 98, 75, -49, 0, 122, -46, -19, 70, -88, 66, 2, 120, 115, 57, 66, -107, -126, -10, -55, 100, 122, -114, 3, -84, 124, -72, -22, 43, 3, 91, 119, 53, -58, -120, 3, 77, 25, -87, -77, -40, 0, -69, -72, 47, 50, 38, -30, 46, 37, 0, -65, 80, -126, 33, -1, 38, 14, -37};
+        b[70] = new byte[]{-128, 91, 113, 18, 22, 9, 106, 16, -26, 83, -105, 105, -71, -42, 44, -23, -108, -20, -88, 12, 126, -77, 104, -2, -45, -96, 52, -51, -20, -101, -35, 78, -25, -123, -111, 108, 110, 64, -125, -107, -37, 52, 17, -123, 40, -87, -22, -39, -87, -109, -26, -20, 94, -126, 12, -29, -125, -35, -43, 59, -99, -119, -98, -108, 77, 3, -57, 35, 14, -12};
+        b[71] = new byte[]{-113, -8, 127, -44, -100, -96, 96, 14, 91, -114, -37, 113, -51, 12, 107, -26, 0, 109, -126, 31, -128, 97, 90, 51, -124, 94, 22, -126, -9, 20, -2, 14, 61, -65, 72, 84, -53, -95, 93, -123, -10, 94, -64, 98, -66, 62, 27, 115, -113, -76, 90, 108, -114, 105, -37, 53, -14, -50, -7, 38, 45, 7, 69, -123, -46, 57, 82, 110, 14, -26, -52};
+        b[72] = new byte[]{-101, -23, 24, 84, 106, 35, 33, 30, 105, -127, -68, -5, -92, 98, 102, -38, 15, -73, -86, -87, 59, 126, 25, 119, 114, -116, 26, -39, -27, 107, -122, 72, -69, 90, -121, -14, -53, 9, -47, 123, 58, -109, -60, -23, 1, -127, 81, 115, -22, 114, -84, -14, -84, 105, 109, -74, -13, 0, -73, 45, 112, -9, -116, -78, -97, 93, -91, 117, 31, -71, 66, 107};
+        b[73] = new byte[]{-92, -10, -122, -100, -54, -12, 81, -119, -91, 118, 114, 85, -109, -15, 126, -35, 96, -119, 39, 90, -10, -94, -37, -61, -28, -94, 93, -73, 107, -75, 70, 116, -70, 47, 8, 71, -121, 2, -62, -87, -11, -68, 59, -12, 4, -125, -115, -42, 119, 18, -88, -104, 98, -1, 36, -51, -9, -74, 127, -63, -10, -109, 15, -96, -123, 52, 65, 49, -93, -85, 97, -111, -93};
+        b[74] = new byte[]{-104, -20, 115, 27, 44, -90, -23, 63, -63, -60, 37, 121, -99, 40, -120, 96, -55, 95, 1, 73, -126, 55, -72, 45, -17, -26, 83, 50, 13, 100, 119, -61, -19, -118, -71, 62, 36, 94, 93, -109, -59, 18, 109, 96, 110, -1, -42, 111, 54, 14, 89, -70, 34, 66, 120, 108, 31, 105, 90, 106, -91, -99, -54, -9, 36, -123, -20, 47, 59, 38, -5, -75, 69, 65};
+        b[75] = new byte[]{85, -126, -50, 32, 78, 3, -98, 28, 73, -97, 113, 74, 75, -3, -111, 28, 113, -40, 46, 86, 98, 25, 87, 85, -2, 78, 46, 5, -69, 64, 96, 117, 18, 78, -108, 115, 105, -90, 15, 24, -48, 21, -115, -45, 112, 109, 49, -56, -118, 25, -98, -70, 79, -7, 97, 5, 50, -16, -47, 108, -60, -118, 38, -8, -72, -69, 110, 117, -94, 6, -127, -54, 4, -13, -5};
+        b[76] = new byte[]{-19, -6, 12, -92, -99, 19, -110, 112, -102, -74, 53, 34, 75, 27, 103, -72, -92, -94, -49, -124, 47, -105, -8, -99, 89, -113, 84, 42, 36, -27, -114, -124, 7, 103, -32, -68, 109, -59, 44, 114, 114, 63, 109, -102, -11, -35, -18, -128, -65, 37, 33, -29, -77, 37, -91, -47, -81, -52, -119, -76, -26, -91, 29, 49, 101, -117, -95, -110, 78, 104, 102, 47, 14, 107, -21, 89};
+        b[77] = new byte[]{-113, 20, 18, 26, 33, 108, -7, -67, 83, 124, 78, 37, 13, 64, 15, 80, -14, 116, 73, 103, -108, -126, 93, 55, -84, -82, -102, -70, 39, -106, 37, -58, -85, 12, -127, -52, -9, -72, 6, 56, 115, 38, -56, 123, -99, 68, -54, -92, 102, 98, 36, -59, -124, 96, 98, 0, -126, 82, 15, -55, 121, 79, 117, 57, -112, -9, -76, -66, 20, -5, 3, 97, 74, 28, -80, 123, -49};
+        b[78] = new byte[]{80, 105, -121, -2, 9, 123, -73, 112, -28, -13, 77, 111, 70, 20, 67, 17, -72, 44, 125, 40, 109, 29, -99, 96, 101, 9, -8, 40, -42, 121, 66, -52, 55, 90, 33, -93, 91, 66, 38, 34, 117, 71, 107, -30, -46, 28, 28, -53, 82, 60, 2, -47, -99, -25, 92, -18, 34, -29, -32, -94, 41, -118, -128, -78, -109, -107, -120, 78, -106, -87, 85, 24, -15, -108, -107, -48, -24, 56};
+        b[79] = new byte[]{-63, -47, 40, 98, 98, 110, 70, 120, 54, -49, 98, 36, 2, 36, -96, 39, 80, -106, -39, 81, 59, 31, -70, 23, -91, -123, -124, 20, 83, -68, -100, 109, 27, 102, 126, -49, 30, 20, -4, 43, 40, 90, 59, 106, -30, 118, 95, 30, 80, 76, -84, -115, -83, 21, 92, 80, -14, 66, -92, -96, 102, 123, -35, 80, -86, -62, 25, -22, 86, 25, -106, -16, -45, -3, 27, 15, 11, 55, 2};
+        b[80] = new byte[]{-26, 70, 106, -126, -75, 27, -73, -22, -51, -28, 21, -128, 117, -41, -108, -74, 111, 83, 25, 62, 55, -67, -118, 65, -24, -9, -78, 67, 4, -14, -53, -43, 91, -81, 79, -108, -1, -124, 51, -53, 66, 48, -33, -76, 90, -37, -35, -57, -102, 73, -87, -127, 12, -18, 73, -59, 105, 112, -120, -123, 25, 115, -64, 21, 108, 19, -95, 31, -101, -94, -4, 46, -19, -91, -29, -117, -15, 103, 51, 9};
+        b[81] = new byte[]{19, -114, -69, 48, -55, -119, 110, 108, 47, -16, -23, -100, -39, 55, 92, -56, -54, -1, -33, 64, 124, -117, 53, -101, 127, -32, -128, -72, -101, 112, -21, -74, -11, -125, -37, 107, -124, 46, -89, -32, 102, 39, 94, 55, -106, -12, 54, 47, -103, 106, 8, 36, -4, 116, -50, -11, 63, 67, -24, 42, -65, 71, 45, 122, 13, -101, -57, -45, -10, -102, -72, 12, 12, 4, 91, -23, -24, 40, -62, -88, -15};
+        b[82] = new byte[]{86, -101, 124, -123, -122, -8, -113, 29, 69, -5, -76, 68, 95, -78, -70, -26, -2, -98, 59, -111, 117, 24, 56, 63, 43, -60, -107, 45, 96, -46, -89, 75, 43, -70, -106, 4, 66, 64, 85, 71, 25, -63, -11, -39, -95, 74, -113, 87, 30, -100, -8, 11, -54, 81, -105, -54, -4, -39, -4, 87, 102, -23, -90, 17, -2, 20, -40, -24, 116, 14, 42, 121, -82, 115, 109, 12, -65, -120, 38, -14, -4, -107};
+        b[121] = new byte[]{-123, -2, -67, -58, -65, 102, -76, 87, -8, 55, 120, -10, -72, 15, 76, -128, -78, -7, 103, 47, 120, 30, 59, -2, 85, 8, -67, -29, -30, -46, -13, -34, -10, 36, -104, 3, 28, 36, 14, -64, -2, 112, -123, -44, 36, 87, -28, -119, -91, 121, 34, -56, 113, -102, 74, -60, 56, 126, 23, -87, 63, 12, -18, 101, -63, 41, 96, 68, 126, 109, -23, -14, -42, 63, -116, -48, 116, -103, 123, 126, -116, 117, 18, 33, -107, 58, -89, -93, -18, 42, -79, 119, 36, 47, 64, -93, 94, -58, 36, 3 [...]
+        b[122] = new byte[]{-56, -84, -45, -121, -104, 79, -89, -33, -49, 5, -26, 109, -83, -107, -20, 20, 112, 17, -9, 44, 14, 51, 120, 81, 104, 16, -28, -128, 111, 68, -45, -36, 5, 91, -61, 25, 15, 76, 76, 25, -24, 28, -89, 68, 43, 76, -105, 15, -15, 6, 14, 105, -120, 83, 13, 88, -90, 62, -85, 13, 77, 83, -90, -115, -40, -28, -67, 47, -74, 90, 24, -55, 91, -119, -107, 57, 116, 60, 40, -128, -3, -41, 38, -127, -76, -6, 62, 13, 43, 75, -28, 99, 32, 114, -41, 15, -28, -54, 21, 127, 85, 10 [...]
+        b[123] = new byte[]{114, -63, 102, -62, -16, -13, -96, -18, 8, 59, -84, -110, 12, 14, 1, -39, 94, -34, -104, 71, -83, 3, 0, -96, 59, -82, -77, -50, 87, -42, 111, 114, -125, -84, -9, -59, 101, -51, -55, -126, -66, 62, 118, 86, -108, -112, 66, 3, 29, -121, -117, 28, 68, -35, 78, -53, 22, 58, 93, -118, -84, -15, -63, 18, -59, 11, -92, 52, -47, -5, 115, -95, -70, -75, -37, -43, 10, -10, 54, -15, -30, 28, 91, -86, 79, 113, -98, 111, -95, 24, -61, 102, -91, 109, -12, -26, 95, 23, 33, - [...]
+        b[124] = new byte[]{-28, -119, -15, -68, -84, 41, -96, 37, 123, 16, -82, -4, 59, 53, 63, -76, -65, 127, 54, 98, -75, -32, -6, -16, -10, -45, -126, 3, 34, -66, -58, -107, 13, 45, -102, -30, -71, 81, 21, 118, 10, 104, 103, 78, 107, -106, 43, -97, 105, 64, -58, 28, 127, 29, 60, 7, -90, -16, 111, 67, 55, -11, 78, 62, 75, 65, -22, -11, -54, -75, -51, -92, 49, 72, 39, 49, 56, -103, -62, -1, -44, 85, -33, -79, -54, -87, -45, -16, -14, -60, 116, -44, 60, -84, 37, -79, -54, 32, -100, 45,  [...]
+        b[125] = new byte[]{112, 76, 123, -95, 59, 18, 29, 101, 5, 62, 63, 118, 114, -53, 93, -53, -100, 6, 109, 23, 49, 31, -27, 81, 88, -33, 36, 104, -44, -45, 8, -11, -86, 73, -55, 50, 83, -43, -28, -2, 56, -7, -2, 8, -3, 12, 92, 35, 126, -64, -110, -89, -83, 49, -70, -41, -8, -2, -79, 90, -98, 59, 112, -86, -44, 96, -23, -46, 75, 63, -126, 64, -126, -109, -118, -77, 0, -27, 30, 46, -107, -73, -68, -59, -1, 14, -57, -119, -45, 31, -38, -57, 109, -106, -54, -77, 107, 38, 102, 79, 97, - [...]
+        b[126] = new byte[]{1, -27, -34, -75, 86, -29, -5, -71, -90, 26, 32, -84, -36, 17, -108, 73, -112, -53, -106, -83, -88, 116, -53, 13, -16, -112, 7, 64, -50, -72, 10, 92, -68, -53, -104, -16, -17, -109, -23, 33, 42, 28, 89, 17, 69, 66, 105, -105, 96, -2, -36, -112, -87, -83, -70, 18, 47, 15, -81, 71, -75, -100, 70, -124, -44, 108, -105, 89, 117, -127, 124, -54, 22, 27, 22, -54, 71, 17, -76, 111, 59, 23, -53, 18, -43, 75, -1, -117, -92, 47, 26, 36, 72, 13, 81, 6, 24, -116, -42, -81 [...]
+        b[127] = new byte[]{106, 61, 127, -13, -1, -108, -15, 83, -73, 15, 104, -128, -62, -12, 23, 103, -127, -12, 43, 11, 110, -52, 57, -72, 36, 32, -68, -5, 109, -100, 114, -87, 62, 83, 50, -81, -86, 49, -84, -13, -75, -25, -125, 7, -20, 49, -12, -92, 120, 101, 64, -117, -91, 65, -22, -41, -51, 37, 56, -40, 114, -42, -93, -19, 31, 29, -62, 29, -113, 33, -14, -46, -82, -10, -87, -121, 14, 48, 52, 29, -111, 18, 58, 101, -100, -6, 35, -96, -26, -3, 108, -43, 13, -75, 75, -35, 43, 118, -1 [...]
+        b[128] = new byte[]{-110, 35, 46, 23, -3, 66, 49, 25, 96, -95, 47, -18, 44, -87, -11, -104, -42, 69, 100, -47, -55, 54, 68, 80, -98, 43, -50, -81, 56, -4, 29, 0, 26, -125, 12, -17, 77, 123, -20, 26, 2, 61, -123, 117, -9, -87, -89, -103, 47, -33, -15, -4, -22, -66, 99, -111, 122, 14, 31, -80, 94, -113, -76, -110, -98, -119, 106, 1, 99, -67, -76, -55, 113, 4, -88, -64, 92, -56, -62, 14, -1, 87, -37, 26, -98, -51, 13, 19, 65, 35, -93, 14, 65, 125, -110, -81, -118, 17, 72, -29, -85,  [...]
+        b[129] = new byte[]{97, 121, -126, 90, 24, -115, -49, -113, -56, -121, 44, 80, 33, -120, -32, 54, -8, -41, -7, 124, 3, -120, -12, -46, 4, -58, -123, 16, -71, -71, 95, -58, 56, -110, 113, -111, -98, 65, 120, -1, 56, -79, -14, 95, 112, 28, 22, -2, -20, 40, 31, -82, -66, 58, -84, 94, -34, -120, -116, -38, 0, 82, -29, 46, 56, -34, -61, 46, -73, 118, -32, 73, -119, 86, -60, 90, 58, -123, 59, 71, -18, -23, 63, 98, 34, 59, -124, 104, 93, -84, 78, -102, 111, -71, -109, 79, 31, 31, 52, -6 [...]
+        b[130] = new byte[]{24, -105, -44, -96, 24, -81, 91, -101, -86, 14, -107, 49, 77, 23, -29, 25, 99, 88, 124, -35, -1, 117, 49, 109, 117, 26, -126, 32, 126, 75, -39, -51, 103, 89, 125, 29, -127, -115, -37, 107, 95, -97, 91, -10, 23, -44, -24, 121, 107, 14, 37, 11, -96, 72, -118, 36, -31, -116, -102, 21, -43, 90, -51, -98, 85, -13, 109, -59, 28, 51, 47, -122, -80, 53, 20, 7, -60, 30, -14, 80, 111, 125, -17, -19, -31, 25, -115, 60, 29, 33, 86, 10, -46, -13, -39, -19, 110, -27, 52, 74 [...]
+        b[131] = new byte[]{121, 55, -85, 54, -50, -35, 58, -94, 64, -60, 12, 92, 49, 4, 103, 80, 55, 54, 112, 24, -10, -57, 72, -44, -42, 13, 67, -36, 111, -101, -37, 105, 3, -49, -78, 65, -52, -20, -65, -101, 24, 70, 92, 4, 55, -41, 125, 37, 106, -11, -116, -124, -119, -110, 6, 68, 94, 83, -20, -12, 3, 93, -60, 97, 83, 20, -65, -45, -59, -52, 62, -8, -20, -96, -81, -98, -49, -110, 10, -114, 118, 96, -47, -63, -45, -49, 122, 111, -119, 120, -18, -81, 33, -69, -56, -20, 15, 94, -45, 103, [...]
+        b[132] = new byte[]{-107, -70, -58, -78, 54, -13, 19, -99, -75, -85, -53, 115, 84, 117, 123, -67, -60, -49, 114, 21, 39, -52, -113, -44, 125, -28, 118, 71, -25, 38, 57, -83, -67, 98, 88, -49, 88, -72, 109, -11, 108, 118, 38, -72, -30, 42, -2, 14, 127, -103, -41, 123, -71, 47, -122, 47, -117, 97, 75, -123, 86, -88, 26, -88, -127, 97, 11, -13, -53, 110, -93, -123, -119, 61, -107, 101, -59, -24, -83, 58, 26, 69, 63, 66, 46, 42, -107, -27, -66, -89, 28, -33, -45, -57, 62, -110, 35, - [...]
+        b[133] = new byte[]{-103, 12, 0, 63, 54, 51, 127, 28, -3, 21, 113, 34, 103, -93, 60, -69, 90, 13, -36, 66, 91, 21, -119, -115, 85, -6, 102, -6, 61, 3, -86, 5, 62, 56, -14, 56, 81, 17, -63, 34, -79, 120, -58, -9, 76, -68, 3, -25, -47, 107, -102, -83, -76, 50, -3, -107, 77, -47, -30, -117, -19, 46, 10, -36, -53, -38, -97, 71, -27, 3, 6, -103, 116, -113, -98, -28, 122, 100, 127, 19, -88, 25, 58, 124, 14, 78, 68, 21, 53, -29, -103, -97, -20, -8, 106, 39, 120, -15, 16, 16, 99, 85, 60, [...]
+        b[134] = new byte[]{-36, 110, -99, -41, 101, 24, -30, 94, 86, -20, -39, -16, -48, 18, -12, 30, 117, 98, 86, 15, 82, 116, 75, -117, 50, -89, -103, -61, 45, 17, -108, -108, 127, 98, -41, 32, 119, -7, -120, -60, -117, -105, 92, 9, 70, -122, -8, 104, 95, -91, -36, -40, 17, -108, -19, 26, 83, -117, 88, -40, 43, 48, 60, -21, 43, -91, -46, 63, 122, 117, -73, 4, -32, -21, 107, 63, -39, 84, 4, -103, 92, 99, -41, -106, -49, -97, 93, -68, -70, -118, -57, 11, 119, 112, 67, -127, -62, -77, -3 [...]
+        b[135] = new byte[]{3, 24, 43, 100, -92, -59, -109, -110, 111, 44, 45, -61, 4, 0, -121, -62, -99, -70, -24, 92, 74, 35, -4, -89, -12, 95, -75, -75, -119, 51, 47, -98, -47, 86, -50, 71, 8, -106, 18, -29, -75, 110, 27, 68, -12, 19, 108, 42, -52, 122, -100, 44, -93, -48, 49, -107, -108, -18, -10, -47, -93, 35, 6, 52, -67, -39, -75, -95, -24, 102, -92, -22, 114, -81, 74, 90, -45, -125, 11, -29, -89, 18, -12, -110, -17, -19, 79, -31, 41, -112, 14, -20, -117, -40, -62, 127, 120, -112,  [...]
+        b[136] = new byte[]{106, -39, 6, -14, 93, -108, -4, -39, -26, -5, 50, -18, -17, 56, -34, -98, -73, -36, 1, 84, 9, 49, 74, -121, -118, 97, 89, -35, -60, 31, 105, 74, 120, -85, 42, -59, -97, 85, 34, -63, -99, -9, -113, -82, -107, -73, -83, -34, 85, -92, -1, 21, 124, 126, 46, 81, 39, -80, 121, -6, 1, 51, -63, 50, -99, -30, 17, -118, 1, 37, -116, -115, -90, 60, -1, -51, 19, -95, 5, -73, 51, -99, 0, 12, 117, 101, 19, 115, 34, -120, -98, -7, -58, -33, 30, -124, -58, 0, 87, -89, 42, -97 [...]
+        b[137] = new byte[]{117, -56, -108, -42, 100, -121, 25, -64, 113, 56, 5, 65, -128, -100, 123, -28, -98, -125, 105, 7, 65, 101, -12, -56, -51, 13, 56, 90, 25, 36, 117, 19, 46, -92, -26, 86, 74, 123, -11, -9, 24, 115, -14, 24, -114, -7, -103, -37, 6, -48, -55, -72, -18, 107, 30, -59, 6, -52, 127, -29, 97, -89, 31, 103, 32, -112, -9, 110, 43, -95, 27, -28, -121, 116, -11, -53, 27, 11, -85, 118, -101, 100, -107, 2, 15, -47, -40, -100, -12, -60, 45, 88, 111, -41, -25, 4, 23, -122, -88 [...]
+        b[138] = new byte[]{118, 4, 117, 60, -10, -100, 6, -5, 72, 44, 25, -96, -33, 123, 61, 41, 107, 110, 115, -82, -25, 118, 29, -21, 8, 118, 127, -108, -125, 123, -80, 67, 96, 108, 90, -119, 67, 46, 67, 11, 117, -56, 120, 116, -43, -18, -123, -99, -6, -46, 80, 105, 124, 104, 11, -67, 127, 73, 78, -47, -49, -93, -126, -108, 3, 10, 92, -74, -52, -49, -59, 58, 68, -8, -86, -97, 115, 59, 49, 16, -112, 112, 55, -51, -116, 14, 92, 8, -39, 39, 93, 63, 68, -121, 63, -56, 100, 95, -5, -107, - [...]
+        b[139] = new byte[]{-43, 15, 43, 126, -99, 71, -72, 107, 49, -70, -76, -32, 24, -58, -92, -58, 62, 82, -64, -47, 123, 18, 44, 87, -59, 83, -25, 124, 96, 3, 88, 55, 50, -126, 30, 66, -44, 19, 23, -86, 34, -11, 2, -27, 87, 57, 81, 78, -79, -84, -99, 124, -75, -122, 11, -62, -101, -121, -14, 98, 47, -95, -2, -41, 105, 88, -84, -47, -108, 79, -36, -119, 68, -116, -47, 14, 46, 23, -54, 83, 39, -83, -116, 1, -73, 0, -119, -114, -127, -46, -117, -121, -79, -49, -110, -74, -118, 30, 120, [...]
+        b[140] = new byte[]{-61, 77, 83, -100, -13, -1, 23, 117, 103, -117, 119, -63, 117, 93, -10, 6, 118, -37, -32, -99, 69, 113, -74, -124, -7, 121, -8, -30, 122, 57, -70, 14, -5, 83, -63, 82, -42, 4, -90, -36, -70, -119, -13, 36, -14, 93, -37, -77, -105, -101, -10, 119, 0, 68, 127, 56, -124, 125, 59, -78, -86, 7, -117, 46, -64, -104, 76, 24, -41, -103, -125, -120, 29, 10, 44, 18, 94, -125, -56, 9, 39, -69, -123, -54, -25, 103, -112, 91, -31, 94, -77, -41, -110, -77, 99, 106, -8, 110, [...]
+        b[141] = new byte[]{57, -4, -56, 23, 127, 19, -89, -104, 53, 91, -105, -107, 110, -71, 43, 49, -19, 12, -101, -73, -76, -64, 22, 32, -26, 21, 111, 46, -103, -1, -28, -59, -71, 56, 87, 38, 68, 59, -127, -89, 94, 90, -55, 16, 103, 39, 91, 1, 35, -35, -2, 8, -39, 116, 47, 3, -4, 67, 76, -3, 33, 113, 99, 76, 68, 121, -128, 118, 117, 41, -15, -68, 53, 95, -88, 105, -62, -115, 27, -74, -104, -83, -75, 31, -74, 68, -117, -2, -125, -33, 68, -45, -34, -49, -91, 52, 22, -27, -96, -67, 90,  [...]
+        b[142] = new byte[]{-30, 26, 23, -46, -56, -22, -106, 68, -119, 61, 74, -70, -37, -72, -119, -112, -42, 17, 110, -48, -2, 87, 106, -124, -84, 43, -109, -118, 70, -98, 68, 49, 25, -67, 81, -42, -65, 55, 111, -62, 62, 22, -41, 28, 73, -113, 63, -78, 28, 3, 122, -49, 97, 35, 9, 104, -99, 113, 43, 21, -127, 55, -93, 67, 86, -57, -14, -28, -13, 38, 8, 127, -50, -83, -14, 25, 68, -84, 38, -126, 86, -83, -25, 42, -58, -56, 30, -15, -79, 1, -114, 73, -66, -87, 67, -68, 27, 121, 0, -100,  [...]
+        b[143] = new byte[]{51, -9, 114, -41, -116, 77, 109, -109, 17, 124, 120, -118, 40, 87, 102, 15, -13, -85, 16, 31, -68, 49, -20, 107, 68, -17, 38, 50, 29, 34, -28, -70, -51, 3, -107, -108, -76, -75, -35, -63, 71, -64, -54, -58, 38, 106, 95, 120, 49, 42, 13, 37, -8, 38, -64, 96, -88, -88, -36, 37, 89, -112, 86, -42, 74, 80, 104, -9, 106, -78, -71, -10, 114, -9, 58, 37, -58, 86, -12, 89, 78, -57, 78, -61, 17, 18, 70, 109, -98, -91, -22, -121, -37, -51, -107, -96, 23, -20, -97, -6, 2 [...]
+        b[144] = new byte[]{26, 2, -21, -38, 23, 119, -100, -82, -72, 33, -101, -12, 38, 75, 10, 1, 63, -14, 36, -44, 55, -15, -84, -82, 91, 32, 103, 88, -72, -41, 108, 73, -109, -45, -113, 20, 14, -102, 108, -82, -71, -49, -22, 24, -92, 70, -114, 111, -39, 57, 71, 26, 16, -10, 117, -52, 6, -12, -46, -54, -36, -8, 124, 34, -126, 40, -11, 103, -10, -67, -107, -127, 7, -28, -116, 35, -47, 105, -127, -100, 65, 88, -79, 35, -64, 118, -50, 90, -63, -38, 17, 3, 21, -79, 7, -28, -33, -63, 22, 6 [...]
+        b[145] = new byte[]{91, -39, 74, 112, -80, -22, 52, 100, 0, 27, -5, 10, 64, -42, -111, -103, -29, -108, -104, -78, 123, 25, -61, 13, -88, 22, -122, 103, -82, 125, 70, 120, -21, -23, 20, -21, 126, 121, -92, -89, -106, 125, -103, -32, 11, -97, 5, -24, 30, 51, -29, -51, 36, 3, 38, 117, 88, -79, -113, -79, -56, -55, -18, 62, 9, 122, -128, -59, 64, -124, 9, -66, 94, -102, -40, 86, -101, 39, 123, -117, -19, -5, -70, 35, 82, -90, -81, 84, -16, 106, 47, 46, 93, -74, 120, 105, -42, -89, - [...]
+        b[146] = new byte[]{-119, -126, -25, -26, 31, 101, 34, 16, -1, -57, -39, -88, 104, -12, 103, 77, 126, -90, 36, 66, 74, 78, 24, 56, 89, 124, 82, -20, -118, -47, -37, 54, -27, 31, 110, -82, 58, 66, 13, -49, 71, 73, 53, 50, 85, 122, -37, 52, 100, -42, 3, -98, -55, -45, -20, -99, -94, 35, 118, 58, -123, 53, 86, 60, 106, 24, 83, -113, 73, -36, 29, -117, -124, 36, 68, -77, 64, -39, 67, 112, -69, -45, -51, 5, -74, 35, -100, 124, 118, -33, 4, -77, 103, -48, 60, -126, 43, 82, -34, 0, 46,  [...]
+        b[147] = new byte[]{74, 84, 73, 17, -50, -25, -91, 53, 47, 66, -81, 18, -128, 22, 10, -103, 86, 63, -33, 1, -40, -89, 104, 44, 15, 22, -97, 55, -14, 75, 82, -31, 42, 18, 57, -106, 50, -43, -69, 127, 16, 18, -117, -25, -113, 95, -120, 38, 36, -102, -117, -124, 62, 109, -8, 6, 113, -120, 44, 24, 43, 114, -9, 113, -21, -119, -57, -124, -30, -87, 88, 9, -49, -57, 122, -79, -50, -33, -127, 101, -27, -70, 29, 74, -8, 23, 6, 61, -74, 123, -8, 42, -72, 86, -56, 26, -20, -111, 1, 85, -23, [...]
+        b[148] = new byte[]{0, 9, 91, 25, 30, -98, -112, -77, -77, -57, -120, 105, -87, -108, -44, -87, 85, 16, -48, 82, -10, 8, 90, 96, 8, -61, -87, -24, 43, -82, 83, 57, 18, -99, 101, -23, 82, 59, -50, -119, 32, -28, 52, -8, 40, 76, -8, 41, -126, 104, 55, -71, -117, -52, -79, 126, 55, -102, 67, -58, 80, 96, -67, 107, 0, -45, -123, 124, -122, 66, 30, -82, -35, 103, -42, -74, 104, 98, 61, 26, -105, -98, 49, 94, -109, -31, 15, 119, 66, -40, 94, -101, 59, -42, 122, 39, -24, 47, 102, -18, 1 [...]
+        b[149] = new byte[]{-99, 101, -101, 6, 28, -50, 110, -84, 4, 22, 31, -45, -120, -92, 68, 114, -54, -117, 97, -76, 99, 33, -58, 95, -108, -102, 104, -105, 94, -116, -117, -122, 3, 47, -95, 25, -82, 45, -74, -87, 25, -45, -126, -80, 109, 33, -113, -121, -119, -28, -40, 90, -30, -38, 9, 41, 63, 7, -43, -100, 98, -24, -24, 75, -94, 91, -27, -36, -96, -36, 84, 58, 92, 95, 91, 97, -93, 80, 27, 29, -80, -16, 49, -32, -57, 73, 54, -98, -95, -1, -47, 77, 108, 1, 77, 36, 126, -35, -10, 104 [...]
+        b[150] = new byte[]{88, -39, 53, 70, 125, -86, -76, 111, -96, -109, 64, 4, 123, 10, -32, -93, -26, -111, 108, -38, -58, -32, 40, 16, -92, -28, 124, 82, -114, -36, -38, 109, -105, 65, -113, 12, 84, 59, -72, -71, 16, 58, -81, 54, 6, 25, -40, 42, 77, -62, 2, 42, 76, -67, 50, -15, -34, 37, -29, 86, 84, 5, -50, -58, 96, 56, 17, -43, -48, -37, 18, 45, 20, -105, 80, -73, 16, 109, -25, -89, 26, 119, -47, 65, 93, 123, 51, -37, 92, -107, -80, -6, -7, 119, -114, 119, 105, -72, -69, 79, 117, [...]
+        b[151] = new byte[]{-63, 89, -94, 59, -87, -99, 127, 102, -102, -122, -78, 101, 114, 105, -63, 15, 68, 26, -25, -52, -68, 2, -4, -41, -76, -98, 120, 34, 108, 96, 60, -77, -25, -48, -48, -112, 34, -71, -108, -57, 51, 89, 53, 51, -125, 19, 117, -114, -22, 70, 76, 16, 38, -109, -3, 17, 42, 79, 115, -24, 56, 26, 125, -78, -48, -121, 8, 83, 87, 56, -50, -3, -17, -46, 120, -32, 45, 89, 69, 77, 50, 60, 40, 90, -45, 73, 16, 100, 17, 121, 18, 103, 11, -118, -43, 66, -49, 93, 45, 63, -56,  [...]
+        b[152] = new byte[]{58, -120, -107, 102, -117, 8, -8, -95, -76, 17, -108, -18, -7, 106, 71, -18, 66, -120, 75, 25, -114, -41, 52, 88, 105, 35, -52, 4, -59, -76, 3, 36, 98, 11, 104, -103, 84, 73, 14, 50, 34, -89, -41, 101, -49, -88, -128, -46, 91, -7, 21, 3, -97, 28, -66, -1, -14, -79, 48, 51, 40, -76, -18, -17, -59, 40, -6, -59, 92, 37, -19, -64, -76, -73, 96, 120, 15, 111, 57, 17, 68, 45, 51, -8, -65, -48, -48, -2, 96, 38, 122, 23, -73, 55, -52, 100, -7, 84, -53, 99, -84, 71, 90 [...]
+        b[153] = new byte[]{-9, -74, 85, -79, 54, 48, 15, -59, 107, -128, -35, 69, 56, -124, 89, -14, 57, -68, 56, -56, 43, -60, 109, -24, -43, -94, 104, 98, -45, -43, 89, 122, 125, 114, 56, -27, -127, 122, -109, 49, -107, 108, -95, 106, -9, -90, -66, -23, -71, -36, 62, 45, -118, 53, 18, 60, -9, 38, -104, -108, 60, 122, -106, 113, -99, -113, 90, -75, -84, -20, -12, 117, 106, 70, 6, -69, 7, 66, 4, 118, 47, 8, 100, -36, 101, -127, 94, -1, 43, -75, 0, 31, 48, -25, 54, 44, -105, 87, -119, 71 [...]
+        b[154] = new byte[]{-48, -44, -104, 41, 59, -63, 40, -94, 39, -64, -65, 79, 39, -6, 86, 81, 101, 87, -30, 8, -59, -34, 40, 44, 3, 106, -86, 64, -53, 17, 123, 13, 37, 35, 82, -36, 8, 29, 124, 120, 96, -104, -109, 64, 39, -55, 64, -98, -9, -36, 57, -107, 97, -58, 21, 67, 12, 120, 126, -125, 101, -56, -128, -54, 85, -122, 120, 57, -11, -12, -105, 115, 84, -28, -34, -68, 21, -92, -36, -78, 46, -116, -115, 70, -66, -63, 1, -34, -123, 106, 127, 102, 101, -12, -122, 94, 12, 96, -109, -2 [...]
+        b[155] = new byte[]{-26, -119, 62, -83, -126, 56, 44, 40, 6, 107, 106, 108, 25, 67, 127, 125, -39, 19, -38, 4, 4, 78, -128, 125, 29, 24, -123, 93, 10, 94, -39, -121, 16, -68, 67, 118, -49, -74, 37, 36, 33, 19, -57, -120, -46, 91, 13, 58, -89, -106, 60, -75, -105, 41, -45, -55, -88, 40, -42, 48, 80, -98, 52, 14, -13, -23, 26, 80, -58, -5, 5, 41, 22, 16, -72, -110, 71, -24, -22, -8, -6, 78, -80, -93, -25, 42, 22, 38, 46, 67, -6, -89, 96, 31, 100, -12, 37, -27, -116, -13, 71, 24, 55 [...]
+        b[156] = new byte[]{40, 124, -45, 106, 85, 61, -64, -12, -89, 34, 56, 121, -125, 71, -121, -117, 81, -44, 104, 91, -97, -60, -102, 87, -90, 48, -34, -48, -35, -16, 16, -94, 13, -87, -72, 51, -123, -72, -9, 41, -2, 42, 90, 54, -10, 119, 80, 62, -48, -55, 110, -10, -42, 5, -2, 64, 61, 56, -40, -35, 107, -104, -40, 125, 24, 2, 30, 110, 102, 82, -72, -44, -47, 48, 50, 79, -79, 16, 21, -99, -82, -23, 97, 74, -2, -63, 71, 63, -17, -78, 112, -108, 36, -14, 78, -54, 44, -11, 22, 3, -109, [...]
+        b[157] = new byte[]{70, -78, 85, -60, -126, -88, 13, 123, 66, -66, 37, -116, -65, -12, -105, 48, -18, 54, 14, 126, -108, 88, -30, -125, -53, 104, 97, -40, 4, -105, -78, -60, -12, 123, -31, -70, -101, -79, 117, -37, 125, 34, 37, 105, 68, 55, 76, 1, 71, -54, 126, 6, 84, -35, 6, 20, 43, -97, 110, 116, -9, -61, -9, 43, 94, -85, 6, 102, 105, -49, 15, -7, 118, 103, -84, 32, -100, 97, 96, -10, -116, -32, 104, -102, 58, 12, -19, 22, 59, -110, 113, 56, 36, -103, 93, 9, -105, -5, -39, -11, [...]
+        b[158] = new byte[]{-77, 46, 45, -26, -79, 64, -17, -111, -111, 4, 79, -125, -87, -81, 108, 67, 24, -49, -106, -30, -83, -4, -103, -60, 99, -98, 32, -72, 121, -54, -87, -57, 38, -57, 113, -58, -117, 34, 116, -115, 64, 62, 122, -34, 23, 59, -59, -32, -21, -36, 2, 3, -36, 85, -60, -106, 80, 47, -67, -13, -13, 73, -107, 124, -121, -8, -36, 114, 10, 59, 24, 49, 79, 98, 35, 27, -79, 10, 48, -32, -1, -85, 30, -115, -100, -60, -17, 123, -128, 107, -54, 8, 11, -75, -78, -48, 81, -28, 95, [...]
+        b[159] = new byte[]{102, -49, -63, 124, 90, 22, 34, 102, 26, -69, 103, 89, 45, -66, -55, -99, -25, -109, 66, -98, -20, 67, 78, -78, -94, 113, 42, -47, -122, -72, 4, -45, -119, 27, 47, -7, 116, 97, -8, -38, -116, -19, -48, -6, 79, -40, -122, 127, 75, -97, 23, -19, -21, 21, -127, -50, -93, 3, 92, -73, 5, -52, 99, -36, -61, -24, 14, 52, 9, 73, -111, -59, 18, -44, 119, 27, 125, 83, -15, -31, 121, 58, -109, -43, 11, -121, 112, -10, -49, 92, -106, 89, 76, -45, -101, 111, 113, -23, -84, [...]
+        b[160] = new byte[]{-123, -41, -125, 38, -28, 103, -103, -65, 42, -12, 70, 30, 115, -49, -97, -70, -44, -1, 10, -6, -95, -90, -86, 20, 118, -39, -122, -24, 77, -11, 70, -74, 9, 14, -49, 122, 51, -107, -97, -98, 15, 116, 32, 74, -85, -99, -58, 94, -30, -75, 88, 14, -121, 17, 100, -83, -73, 118, -6, -83, 37, -93, -31, 77, 64, 87, 94, 30, 54, 35, 35, 37, 82, 122, -24, -21, -46, -120, -5, 78, -7, 22, -10, 24, -62, 5, 90, 81, -35, 116, -81, -79, 49, 88, -50, 89, -20, 48, -112, -37, 31 [...]
+        b[161] = new byte[]{10, 80, -126, 58, -3, 38, 15, -33, -1, 45, 29, 14, -118, -63, -33, 106, 108, 92, 78, -7, -91, -64, -62, -32, 0, -124, 45, -34, 22, -50, -115, 19, -28, 95, 1, 32, 104, 60, -49, -46, -18, -117, 55, -64, 77, -63, -45, -107, -61, -30, -31, -83, -68, -52, 35, -52, -48, -52, 123, -24, -18, 97, -113, -111, 2, 2, 121, -24, -90, -1, 31, -79, -104, 99, -48, -74, 101, -89, 95, 16, -106, -120, -67, 110, 127, -1, 30, 71, -107, -82, -53, -47, 43, -14, -55, 19, 7, -54, -58,  [...]
+        b[162] = new byte[]{22, -49, -128, -104, 80, -89, 82, -65, -30, -101, 15, 3, -48, 106, 77, -119, -46, 15, -10, -84, 22, -13, 36, 64, -50, 107, 106, 61, 47, -81, 79, -87, -7, 83, -122, 5, 65, -54, 96, 111, 57, -21, 96, -18, 19, 62, -87, 21, 23, 106, 51, -42, 106, 96, 45, -126, 32, -57, -5, -74, 94, -54, -19, -106, 49, -105, -29, -94, -33, 99, -61, -78, 80, -10, -80, -29, -9, 90, -33, -60, 6, -98, 10, 8, -107, 45, -100, 55, 77, 92, -128, -35, -34, 125, 40, -52, -106, 118, 69, -93,  [...]
+        b[163] = new byte[]{-62, 3, -72, 13, -47, -103, -53, -40, 53, -36, -117, -114, -122, 66, 70, 37, -60, -24, -56, -69, -126, 5, 89, -67, 79, -9, 60, -87, -114, 13, 58, 23, -107, 83, 83, 86, -38, 15, 44, 60, -118, 62, 70, 33, 44, 73, 36, -4, -77, 30, -66, 38, 31, -64, -2, 70, -126, -59, -117, -55, -12, 43, 32, -100, 24, -39, 48, -59, -111, -79, -35, -4, -36, 118, 64, -96, -101, 100, -57, 2, -81, -54, -121, -105, -49, 48, -2, -90, -31, 111, -88, -92, 1, 16, -86, -27, 4, 76, 31, 125,  [...]
+        b[164] = new byte[]{18, 69, -19, -45, 100, -102, 69, 66, 35, 22, 106, 11, -57, 35, -70, 55, -24, 34, 47, -120, -128, -31, -10, 52, 19, 22, -88, -6, 104, -32, 17, -10, 126, 90, -2, -80, -9, -111, -105, 28, 18, 53, -58, 86, 12, 84, -71, 14, 114, 123, -67, -99, -21, 28, -67, -59, -48, 31, 67, -85, -88, -65, 110, 126, -118, -60, 81, 49, -109, 74, 13, -100, -117, -82, -26, -32, 106, -16, 2, -68, -116, -53, -18, 94, 82, -114, -5, 67, -111, -87, 88, -89, -20, -125, -55, -61, 108, 63, 26 [...]
+        b[165] = new byte[]{58, -32, 106, -57, -110, -59, 38, -70, 17, 108, 57, -8, -41, -18, 26, -52, 81, -27, 42, 12, 58, 108, -56, 27, -79, 17, -102, 43, -43, 39, 62, -8, -71, -59, -7, -107, -31, 34, -48, -39, -116, -56, -122, -118, 70, -117, 81, 121, -20, -66, -81, 42, -23, 26, 91, 69, -27, 22, 79, -59, 127, -108, -35, -28, -125, 2, -19, 79, -92, -67, 114, -91, 127, -57, -58, 32, -124, 60, 21, -95, -56, -46, -10, -56, 95, -49, 78, 38, 80, 106, -108, -128, -86, 126, -44, -115, -119, 8 [...]
+        b[166] = new byte[]{72, -17, -17, 14, -54, -103, 13, -46, 38, 57, -47, -11, -10, -58, 72, -20, 85, 21, -122, 92, 117, 16, -115, 23, 70, -65, 0, -83, 59, -128, 27, -111, 124, 44, 50, -69, -24, 23, 45, -40, 46, -33, 93, 53, 40, -62, 41, 87, -100, -107, -95, 67, 27, -37, 26, 43, -91, -111, 65, -110, -71, 88, -43, 63, 93, -77, 105, -49, 91, 74, 20, 105, -81, 82, -9, -71, -57, 94, -18, 125, 95, -9, 47, -51, 112, 114, 66, -63, -38, -109, 46, -82, -47, 99, 40, 8, -75, 14, 41, -91, 1, -9 [...]
+        b[167] = new byte[]{-75, -110, -1, -88, 0, -116, 59, -44, -77, -102, 2, 97, 89, 3, 44, 108, -88, 4, -26, 83, -64, 17, -68, 103, -36, -44, 123, -25, 78, 34, -106, 0, 43, 71, -56, -5, -70, -3, 74, 23, -114, -82, 67, 40, -21, -112, 73, -14, 6, -118, -26, 96, 31, -6, -100, -79, -91, 30, 27, 122, -40, -124, 31, -76, -58, 31, -26, 1, -23, 28, 87, -45, -66, -23, 17, 40, 95, 59, -37, -52, -120, 96, 0, 24, 28, -12, 63, 90, 49, -13, 29, -43, 82, -87, 66, 106, 23, 102, -68, 68, 78, -110, -6 [...]
+        b[168] = new byte[]{25, 23, -69, -72, 93, 112, 31, -97, -5, -44, 29, -17, -104, 97, 126, -92, -35, -57, -12, -14, -114, -42, -46, -16, -78, 118, -12, 15, -113, -49, -101, -77, -18, -28, -96, 30, -32, -25, -34, -106, 71, -59, 32, 24, 50, -114, -22, 25, -82, -105, -124, -112, 102, 103, 111, -22, -97, -8, -87, -5, 42, -35, 97, 15, 6, 43, -4, -58, -3, 123, 11, -80, 57, 123, 27, 34, -110, -48, 50, 7, -31, -48, -114, 87, -80, -6, -42, -95, -57, 110, 87, 57, -2, -69, -9, 38, -35, -54, - [...]
+        b[169] = new byte[]{-16, 16, -59, -69, -19, -67, -106, -101, 101, 25, 40, -36, 101, -18, -32, -123, 102, -108, -128, -116, -37, -71, 74, 76, -27, 112, -59, 110, -46, 85, 64, -15, 29, -35, -80, 4, -47, -63, -111, -107, 1, 61, 18, 18, -105, -117, -110, 127, 34, -55, 24, 54, -76, 55, -25, -69, 65, -124, 15, -108, 52, 51, 87, 10, 38, -45, -40, 6, 70, -89, 53, -128, 115, 1, 58, 116, -1, -75, -32, 91, -111, 47, -111, -79, -86, 31, -19, 122, -29, -40, 42, -66, 72, 34, 126, -52, -35, 38, [...]
+        b[170] = new byte[]{-78, 35, -46, 92, 62, 46, -33, -91, -104, -75, 59, -17, 15, 52, 101, 20, -8, -82, 100, -55, -47, 115, 58, -53, -35, -32, 53, -25, -34, 121, 36, 48, -100, -21, -11, 118, 10, -5, -70, -101, -15, -49, 59, -94, 113, -94, 12, 78, -47, -90, 19, 103, -101, 94, -115, -128, -50, 33, -104, 1, -53, -115, 3, -127, 70, 76, -88, -14, 118, 34, -106, 35, -78, 101, 27, -114, 50, 84, -14, -17, -50, -89, 8, 76, -94, 126, 118, -26, 109, -17, -48, 70, 37, -65, 40, -10, 66, -99, -2 [...]
+        b[171] = new byte[]{-5, -3, 120, 62, 113, 80, 85, -98, -63, 76, 114, -108, -66, 68, -19, 70, -74, 18, -19, 105, -49, 52, 62, 96, 103, -106, -14, 50, 21, 43, 12, -71, 9, 107, -91, 15, 5, 94, -13, -46, 122, -61, 50, 39, -60, -93, -9, 80, 125, 74, -73, 18, 48, -94, 27, -84, 70, 86, 26, -44, -68, 12, -32, -58, -93, -112, 101, 53, -75, 99, -38, 125, 51, 66, -106, 91, -31, 52, 94, -16, -112, -90, -111, -59, -90, -29, 42, 23, 91, -40, -80, 93, 14, 15, -96, 12, -120, 79, 73, -76, 105, -4 [...]
+        b[172] = new byte[]{-33, 82, 53, -115, -81, -127, -7, -86, 41, 42, 76, -19, 27, 50, 88, -68, -111, 22, 2, -56, 114, -96, 0, 21, -25, 43, -34, -32, -71, -49, -46, 71, 72, -103, 68, 26, 84, 68, -46, -70, -114, 66, 12, -122, 43, -17, 51, 60, 48, 32, -11, 121, -125, -23, 46, 39, 38, 26, 112, 62, 11, -35, -69, -93, -44, 6, 1, 82, -9, 114, -45, -65, 12, 37, -95, 54, 41, -42, -20, -39, -98, 96, -125, 62, -93, -121, 98, 40, 25, 3, 62, 49, -26, 73, 102, -66, -98, -82, 39, -81, -24, 14, 10 [...]
+        b[173] = new byte[]{93, -76, 95, 14, -95, -98, -35, -25, -120, -42, -47, -15, -15, 73, -49, -99, -32, -63, -25, -77, 124, 85, -28, -110, -51, 124, -43, 8, -44, -96, -60, -31, 31, 119, -89, 127, -70, 126, 66, 15, 17, -58, -6, 110, 48, -34, -46, 27, -75, 41, 50, -31, 29, -66, -52, -63, 126, 75, -105, 17, -67, 51, -80, 103, -5, -34, 122, 6, 45, 44, -92, -15, 3, 73, -107, 121, -43, -117, 22, 71, -31, -2, -2, 13, -128, -14, 126, 52, 69, 62, 115, 41, 91, 73, 38, 75, 1, -32, 104, 124, 5 [...]
+        b[174] = new byte[]{-116, 97, 35, -4, 6, -127, 121, -10, -100, -10, -29, -100, -104, 107, -114, -10, 113, -2, 55, -20, -52, -80, 46, 42, 1, -18, -103, 80, 67, 12, 33, 119, 83, 26, 116, -106, -105, -75, -19, -45, -7, -54, -85, 35, -93, -35, -111, -10, -29, -47, -16, -112, -97, 27, -97, -112, -66, -47, -68, -50, -91, 13, 94, 3, 115, -15, 18, -82, -111, 124, -93, 43, -116, 114, 79, 38, 100, -39, 94, -76, -124, 73, 56, -33, -113, 122, 13, 45, 79, -62, -86, -96, -50, -87, -33, 51, -99 [...]
+        b[175] = new byte[]{68, 12, -51, 11, 25, 79, -39, 47, -4, 45, -10, -58, -74, 84, -125, 74, 26, 49, -15, -60, -96, -104, -109, 14, 115, 108, 79, 22, -49, 30, -127, -107, 73, -117, 9, 102, -99, 45, -38, 5, 98, -113, 69, -74, -15, -111, -104, -107, 85, -119, 110, -32, 99, 73, 55, 6, -24, 113, -50, -99, -126, -71, 118, -16, 117, -64, -79, -120, -92, 19, -100, 48, -95, 13, 76, 120, -30, 86, 83, 124, -13, 22, 38, 4, 54, 30, -46, 44, 20, 31, -115, 83, -48, 30, -25, 28, -74, -65, 15, -23 [...]
+        b[176] = new byte[]{-45, -56, 102, 102, -101, 65, 24, -94, -86, 71, -92, 51, -12, 99, 92, -39, 105, 53, 122, -40, 20, -4, -86, 32, 110, 35, -48, -104, 8, 121, 33, 121, 83, 5, -49, 123, 14, -31, 19, -96, -66, 1, 111, -49, 61, -99, -13, -101, 85, 15, -42, 122, 89, -94, 9, 47, 48, 18, 52, -127, 118, 105, -27, -110, 69, 59, -3, -66, 84, 79, 115, -8, -109, 90, 65, -23, -100, 79, 31, -44, 37, 118, 62, 90, 107, 57, 0, -1, 32, -101, -46, 76, -61, 124, -103, 92, 116, 83, -95, -43, -32, 28 [...]
+        b[177] = new byte[]{-48, 104, 107, -127, -76, -110, 28, -14, -42, -73, 36, -74, -102, 116, -79, -84, -48, 35, -3, -36, -85, 21, 7, 49, 34, 3, -29, 79, -65, -69, -15, 38, 117, 101, 49, -100, -45, 123, -20, -102, 86, 120, 103, -10, -50, 59, -50, 4, -9, 34, -101, -107, -94, 57, 117, 33, -43, 94, -68, 121, -20, -67, 36, -118, 66, -4, -74, 2, -126, -80, 9, 20, 52, -19, -27, -1, -116, -17, -28, 87, -62, -83, 20, -32, 27, 30, 44, 21, 49, 65, -44, -45, 92, 45, -52, 26, -126, 75, -59, -51 [...]
+        b[178] = new byte[]{-39, 81, -94, 49, 95, -33, -38, 19, 89, 2, 60, 55, 125, -41, -121, -57, -4, 17, 33, 92, -34, 63, 77, 124, -107, -100, -89, -49, 4, -78, 72, 111, -13, 64, 28, 114, 70, 104, -73, 98, 98, -107, 102, 104, 119, 104, -101, -89, -70, 42, -90, -67, -37, 116, -112, -98, -91, 95, -77, 60, 5, -88, -40, 28, -16, -127, -110, -94, 78, -57, -54, 15, 39, -14, -75, -96, 0, -15, 86, 9, -38, -67, -98, -67, 116, -90, 43, 75, 47, 127, 62, 110, -84, 31, 24, -59, -83, -44, -77, -11, [...]
+        b[179] = new byte[]{-120, -60, -126, -121, 89, -71, -67, -53, 119, 11, -78, -60, -97, -100, 10, 69, -117, 90, -105, 59, -58, -22, -110, -102, -124, 109, 125, -83, 54, -6, 103, -38, -69, -7, -69, -125, -80, -62, -7, -56, -50, -115, -88, 59, -24, 87, 27, 119, 14, -2, -54, 71, 7, 82, -33, 17, -65, 63, 38, -5, 108, -111, -81, 67, 102, -72, 22, 20, 103, 77, -82, 7, -68, -5, -27, -35, -54, 73, 116, -56, 2, 10, -5, 23, 121, 117, -24, 48, -66, 41, 31, 49, 101, -92, -3, 27, 54, -61, 40, - [...]
+        b[180] = new byte[]{-124, -34, 62, -57, -5, 10, -12, 84, 89, -97, -103, 101, 107, 14, -1, 92, 49, -80, -122, -35, -63, 112, -116, 64, 20, -2, 9, -96, 106, -107, 64, 44, 60, 115, -110, 14, -107, 42, -118, 16, -27, 98, 98, -53, 53, -102, 123, -28, -93, -87, 21, -83, -51, -94, 48, 64, 60, -121, -60, 108, -80, -98, 29, 36, 26, 69, 13, -97, -37, -111, -24, 66, -54, 20, 38, 90, -101, 41, 102, -48, 47, 68, -34, 125, -102, 62, -89, -57, 68, -127, -126, 86, 6, 113, -61, -14, -82, 125, -34 [...]
     }
 
     /* These are chunked versions of the strings above (chunked by commons-codec-1.3.jar) */
@@ -250,140 +250,131 @@ public class Base64Codec13Test {
 
     }
 
-    /* Here are the randomly generated byte[] arrays we generated to exercise commons-codec-1.3.jar */
-    private static void initBYTES() {
-        final byte[][] b = BYTES;
-        b[0] = new byte[]{};
-        b[1] = new byte[]{-72};
-        b[2] = new byte[]{-49, -36};
-        b[3] = new byte[]{77, 15, -103};
-        b[4] = new byte[]{110, 24, -44, 96};
-        b[5] = new byte[]{-43, -61, -67, -75, -33};
-        b[6] = new byte[]{-80, -52, 71, -96, -105, -7};
-        b[7] = new byte[]{-115, 7, 15, -108, 59, 25, -49};
-        b[8] = new byte[]{76, 6, -113, -99, -11, -65, 9, -123};
-        b[9] = new byte[]{113, 116, -39, -69, 12, -41, 60, -29, 82};
-        b[10] = new byte[]{46, -39, -1, 101, 53, 120, 34, 52, -6, 56};
-        b[11] = new byte[]{-23, -8, 126, -115, -43, 55, -43, 35, -90, 90, -73};
-        b[12] = new byte[]{19, -2, 76, -96, 62, 42, 10, -16, -18, 77, -63, 64};
-        b[13] = new byte[]{-38, 127, 88, -55, -16, -116, -56, -59, -34, -103, -69, 108, -79};
-        b[14] = new byte[]{-88, 25, 26, -36, 26, -70, 87, 125, 71, -103, -55, -121, -114, 70};
-        b[15] = new byte[]{90, -4, -103, 123, -87, 16, -14, -100, -69, -101, 110, 110, 113, -84, 9};
-        b[16] = new byte[]{-95, -118, 113, 51, 46, -127, 74, -106, 87, -123, 90, 78, 71, -89, 87, -104};
-        b[63] = new byte[]{-55, -20, 69, 104, -46, -102, 63, -27, 100, 87, 1, 20, -65, 20, 23, 108, 45, 7, 72, 40, -65, -78, -77, -104, -19, -51, 55, -22, 84, -10, -27, -6, -20, -29, 24, -56, -66, -99, -75, -32, -111, -62, -125, -77, -117, -3, 118, 86, -36, -125, 30, -24, 32, -32, 72, -64, -102, 104, -113, 117, 121, 24, 12};
-        b[64] = new byte[]{-66, 74, -96, -98, -30, 119, -90, 92, 77, -74, -117, -34, -120, -62, 110, 96, -77, 122, -63, -108, 11, -91, -67, -59, -125, -113, 63, -52, 121, 29, 22, -32, -18, 114, -29, 10, 89, 84, 78, -2, 120, -123, 70, 2, -84, 22, -89, 49, -85, -91, 96, 11, 28, 16, 109, -29, -30, 63, -37, 17, -97, 28, -5, -62};
-        b[65] = new byte[]{96, 121, 44, -36, 96, -101, -38, -27, 69, -29, -74, 54, -76, 40, -98, -120, 49, -119, -13, -65, 81, -101, -105, 65, -123, 8, 80, -117, 54, 33, 125, 99, -88, -8, 26, -63, -37, -14, -66, 19, -68, 25, 89, 56, -99, -41, -119, 76, -92, -50, -76, -5, -112, -76, 55, -46, 77, 40, 7, 1, 17, 39, -86, 101, -110};
-        b[66] = new byte[]{-49, -50, 121, -42, 57, -112, -89, -12, 44, -9, -101, 112, -37, 110, -66, 28, 33, -42, -82, -30, -79, -4, -101, -33, 4, 39, -48, -26, -99, 31, 23, -66, -26, -111, 42, 105, -21, -95, 57, -25, 104, -92, -38, 12, -100, -84, 16, 108, 48, 47, -51, 111, 57, -64, -127, 54, 104, 51, 54, 113, 122, 23, -55, -62, -18, 61};
-        b[67] = new byte[]{86, -60, 118, -62, 26, -86, -2, -92, 38, -33, -115, -66, 76, -36, -11, -106, 3, -103, 50, -123, -101, -92, 44, -2, -110, 61, -77, 126, 90, -76, -97, 30, -46, -3, 23, -124, 84, -11, 9, 114, -88, 12, -75, 92, -21, -81, 97, 85, 64, -9, -63, 0, 126, 85, 70, 52, 126, -122, 76, 112, -65, -122, -20, -79, 9, -84, -15};
-        b[68] = new byte[]{-25, 25, -120, -89, -57, 84, 37, -100, -28, -118, -62, 36, -72, 67, -20, -100, -11, -17, -52, 55, -116, -93, -113, 42, 88, 87, -57, 34, 125, -102, -65, 120, -21, -26, -86, 25, 28, 43, 52, 45, -13, 68, -55, -22, 66, -34, -3, -84, 107, 73, -62, 83, 65, 101, -86, -55, -125, -55, 50, 57, -1, 104, -19, -25, 59, 11, -75, 93};
-        b[69] = new byte[]{-76, 97, 32, 94, 56, 37, 80, 31, 77, 108, 43, 98, 75, -49, 0, 122, -46, -19, 70, -88, 66, 2, 120, 115, 57, 66, -107, -126, -10, -55, 100, 122, -114, 3, -84, 124, -72, -22, 43, 3, 91, 119, 53, -58, -120, 3, 77, 25, -87, -77, -40, 0, -69, -72, 47, 50, 38, -30, 46, 37, 0, -65, 80, -126, 33, -1, 38, 14, -37};
-        b[70] = new byte[]{-128, 91, 113, 18, 22, 9, 106, 16, -26, 83, -105, 105, -71, -42, 44, -23, -108, -20, -88, 12, 126, -77, 104, -2, -45, -96, 52, -51, -20, -101, -35, 78, -25, -123, -111, 108, 110, 64, -125, -107, -37, 52, 17, -123, 40, -87, -22, -39, -87, -109, -26, -20, 94, -126, 12, -29, -125, -35, -43, 59, -99, -119, -98, -108, 77, 3, -57, 35, 14, -12};
-        b[71] = new byte[]{-113, -8, 127, -44, -100, -96, 96, 14, 91, -114, -37, 113, -51, 12, 107, -26, 0, 109, -126, 31, -128, 97, 90, 51, -124, 94, 22, -126, -9, 20, -2, 14, 61, -65, 72, 84, -53, -95, 93, -123, -10, 94, -64, 98, -66, 62, 27, 115, -113, -76, 90, 108, -114, 105, -37, 53, -14, -50, -7, 38, 45, 7, 69, -123, -46, 57, 82, 110, 14, -26, -52};
-        b[72] = new byte[]{-101, -23, 24, 84, 106, 35, 33, 30, 105, -127, -68, -5, -92, 98, 102, -38, 15, -73, -86, -87, 59, 126, 25, 119, 114, -116, 26, -39, -27, 107, -122, 72, -69, 90, -121, -14, -53, 9, -47, 123, 58, -109, -60, -23, 1, -127, 81, 115, -22, 114, -84, -14, -84, 105, 109, -74, -13, 0, -73, 45, 112, -9, -116, -78, -97, 93, -91, 117, 31, -71, 66, 107};
-        b[73] = new byte[]{-92, -10, -122, -100, -54, -12, 81, -119, -91, 118, 114, 85, -109, -15, 126, -35, 96, -119, 39, 90, -10, -94, -37, -61, -28, -94, 93, -73, 107, -75, 70, 116, -70, 47, 8, 71, -121, 2, -62, -87, -11, -68, 59, -12, 4, -125, -115, -42, 119, 18, -88, -104, 98, -1, 36, -51, -9, -74, 127, -63, -10, -109, 15, -96, -123, 52, 65, 49, -93, -85, 97, -111, -93};
-        b[74] = new byte[]{-104, -20, 115, 27, 44, -90, -23, 63, -63, -60, 37, 121, -99, 40, -120, 96, -55, 95, 1, 73, -126, 55, -72, 45, -17, -26, 83, 50, 13, 100, 119, -61, -19, -118, -71, 62, 36, 94, 93, -109, -59, 18, 109, 96, 110, -1, -42, 111, 54, 14, 89, -70, 34, 66, 120, 108, 31, 105, 90, 106, -91, -99, -54, -9, 36, -123, -20, 47, 59, 38, -5, -75, 69, 65};
-        b[75] = new byte[]{85, -126, -50, 32, 78, 3, -98, 28, 73, -97, 113, 74, 75, -3, -111, 28, 113, -40, 46, 86, 98, 25, 87, 85, -2, 78, 46, 5, -69, 64, 96, 117, 18, 78, -108, 115, 105, -90, 15, 24, -48, 21, -115, -45, 112, 109, 49, -56, -118, 25, -98, -70, 79, -7, 97, 5, 50, -16, -47, 108, -60, -118, 38, -8, -72, -69, 110, 117, -94, 6, -127, -54, 4, -13, -5};
-        b[76] = new byte[]{-19, -6, 12, -92, -99, 19, -110, 112, -102, -74, 53, 34, 75, 27, 103, -72, -92, -94, -49, -124, 47, -105, -8, -99, 89, -113, 84, 42, 36, -27, -114, -124, 7, 103, -32, -68, 109, -59, 44, 114, 114, 63, 109, -102, -11, -35, -18, -128, -65, 37, 33, -29, -77, 37, -91, -47, -81, -52, -119, -76, -26, -91, 29, 49, 101, -117, -95, -110, 78, 104, 102, 47, 14, 107, -21, 89};
-        b[77] = new byte[]{-113, 20, 18, 26, 33, 108, -7, -67, 83, 124, 78, 37, 13, 64, 15, 80, -14, 116, 73, 103, -108, -126, 93, 55, -84, -82, -102, -70, 39, -106, 37, -58, -85, 12, -127, -52, -9, -72, 6, 56, 115, 38, -56, 123, -99, 68, -54, -92, 102, 98, 36, -59, -124, 96, 98, 0, -126, 82, 15, -55, 121, 79, 117, 57, -112, -9, -76, -66, 20, -5, 3, 97, 74, 28, -80, 123, -49};
-        b[78] = new byte[]{80, 105, -121, -2, 9, 123, -73, 112, -28, -13, 77, 111, 70, 20, 67, 17, -72, 44, 125, 40, 109, 29, -99, 96, 101, 9, -8, 40, -42, 121, 66, -52, 55, 90, 33, -93, 91, 66, 38, 34, 117, 71, 107, -30, -46, 28, 28, -53, 82, 60, 2, -47, -99, -25, 92, -18, 34, -29, -32, -94, 41, -118, -128, -78, -109, -107, -120, 78, -106, -87, 85, 24, -15, -108, -107, -48, -24, 56};
-        b[79] = new byte[]{-63, -47, 40, 98, 98, 110, 70, 120, 54, -49, 98, 36, 2, 36, -96, 39, 80, -106, -39, 81, 59, 31, -70, 23, -91, -123, -124, 20, 83, -68, -100, 109, 27, 102, 126, -49, 30, 20, -4, 43, 40, 90, 59, 106, -30, 118, 95, 30, 80, 76, -84, -115, -83, 21, 92, 80, -14, 66, -92, -96, 102, 123, -35, 80, -86, -62, 25, -22, 86, 25, -106, -16, -45, -3, 27, 15, 11, 55, 2};
-        b[80] = new byte[]{-26, 70, 106, -126, -75, 27, -73, -22, -51, -28, 21, -128, 117, -41, -108, -74, 111, 83, 25, 62, 55, -67, -118, 65, -24, -9, -78, 67, 4, -14, -53, -43, 91, -81, 79, -108, -1, -124, 51, -53, 66, 48, -33, -76, 90, -37, -35, -57, -102, 73, -87, -127, 12, -18, 73, -59, 105, 112, -120, -123, 25, 115, -64, 21, 108, 19, -95, 31, -101, -94, -4, 46, -19, -91, -29, -117, -15, 103, 51, 9};
-        b[81] = new byte[]{19, -114, -69, 48, -55, -119, 110, 108, 47, -16, -23, -100, -39, 55, 92, -56, -54, -1, -33, 64, 124, -117, 53, -101, 127, -32, -128, -72, -101, 112, -21, -74, -11, -125, -37, 107, -124, 46, -89, -32, 102, 39, 94, 55, -106, -12, 54, 47, -103, 106, 8, 36, -4, 116, -50, -11, 63, 67, -24, 42, -65, 71, 45, 122, 13, -101, -57, -45, -10, -102, -72, 12, 12, 4, 91, -23, -24, 40, -62, -88, -15};
-        b[82] = new byte[]{86, -101, 124, -123, -122, -8, -113, 29, 69, -5, -76, 68, 95, -78, -70, -26, -2, -98, 59, -111, 117, 24, 56, 63, 43, -60, -107, 45, 96, -46, -89, 75, 43, -70, -106, 4, 66, 64, 85, 71, 25, -63, -11, -39, -95, 74, -113, 87, 30, -100, -8, 11, -54, 81, -105, -54, -4, -39, -4, 87, 102, -23, -90, 17, -2, 20, -40, -24, 116, 14, 42, 121, -82, 115, 109, 12, -65, -120, 38, -14, -4, -107};
-        b[121] = new byte[]{-123, -2, -67, -58, -65, 102, -76, 87, -8, 55, 120, -10, -72, 15, 76, -128, -78, -7, 103, 47, 120, 30, 59, -2, 85, 8, -67, -29, -30, -46, -13, -34, -10, 36, -104, 3, 28, 36, 14, -64, -2, 112, -123, -44, 36, 87, -28, -119, -91, 121, 34, -56, 113, -102, 74, -60, 56, 126, 23, -87, 63, 12, -18, 101, -63, 41, 96, 68, 126, 109, -23, -14, -42, 63, -116, -48, 116, -103, 123, 126, -116, 117, 18, 33, -107, 58, -89, -93, -18, 42, -79, 119, 36, 47, 64, -93, 94, -58, 36, 3 [...]
-        b[122] = new byte[]{-56, -84, -45, -121, -104, 79, -89, -33, -49, 5, -26, 109, -83, -107, -20, 20, 112, 17, -9, 44, 14, 51, 120, 81, 104, 16, -28, -128, 111, 68, -45, -36, 5, 91, -61, 25, 15, 76, 76, 25, -24, 28, -89, 68, 43, 76, -105, 15, -15, 6, 14, 105, -120, 83, 13, 88, -90, 62, -85, 13, 77, 83, -90, -115, -40, -28, -67, 47, -74, 90, 24, -55, 91, -119, -107, 57, 116, 60, 40, -128, -3, -41, 38, -127, -76, -6, 62, 13, 43, 75, -28, 99, 32, 114, -41, 15, -28, -54, 21, 127, 85, 10 [...]
-        b[123] = new byte[]{114, -63, 102, -62, -16, -13, -96, -18, 8, 59, -84, -110, 12, 14, 1, -39, 94, -34, -104, 71, -83, 3, 0, -96, 59, -82, -77, -50, 87, -42, 111, 114, -125, -84, -9, -59, 101, -51, -55, -126, -66, 62, 118, 86, -108, -112, 66, 3, 29, -121, -117, 28, 68, -35, 78, -53, 22, 58, 93, -118, -84, -15, -63, 18, -59, 11, -92, 52, -47, -5, 115, -95, -70, -75, -37, -43, 10, -10, 54, -15, -30, 28, 91, -86, 79, 113, -98, 111, -95, 24, -61, 102, -91, 109, -12, -26, 95, 23, 33, - [...]
-        b[124] = new byte[]{-28, -119, -15, -68, -84, 41, -96, 37, 123, 16, -82, -4, 59, 53, 63, -76, -65, 127, 54, 98, -75, -32, -6, -16, -10, -45, -126, 3, 34, -66, -58, -107, 13, 45, -102, -30, -71, 81, 21, 118, 10, 104, 103, 78, 107, -106, 43, -97, 105, 64, -58, 28, 127, 29, 60, 7, -90, -16, 111, 67, 55, -11, 78, 62, 75, 65, -22, -11, -54, -75, -51, -92, 49, 72, 39, 49, 56, -103, -62, -1, -44, 85, -33, -79, -54, -87, -45, -16, -14, -60, 116, -44, 60, -84, 37, -79, -54, 32, -100, 45,  [...]
-        b[125] = new byte[]{112, 76, 123, -95, 59, 18, 29, 101, 5, 62, 63, 118, 114, -53, 93, -53, -100, 6, 109, 23, 49, 31, -27, 81, 88, -33, 36, 104, -44, -45, 8, -11, -86, 73, -55, 50, 83, -43, -28, -2, 56, -7, -2, 8, -3, 12, 92, 35, 126, -64, -110, -89, -83, 49, -70, -41, -8, -2, -79, 90, -98, 59, 112, -86, -44, 96, -23, -46, 75, 63, -126, 64, -126, -109, -118, -77, 0, -27, 30, 46, -107, -73, -68, -59, -1, 14, -57, -119, -45, 31, -38, -57, 109, -106, -54, -77, 107, 38, 102, 79, 97, - [...]
-        b[126] = new byte[]{1, -27, -34, -75, 86, -29, -5, -71, -90, 26, 32, -84, -36, 17, -108, 73, -112, -53, -106, -83, -88, 116, -53, 13, -16, -112, 7, 64, -50, -72, 10, 92, -68, -53, -104, -16, -17, -109, -23, 33, 42, 28, 89, 17, 69, 66, 105, -105, 96, -2, -36, -112, -87, -83, -70, 18, 47, 15, -81, 71, -75, -100, 70, -124, -44, 108, -105, 89, 117, -127, 124, -54, 22, 27, 22, -54, 71, 17, -76, 111, 59, 23, -53, 18, -43, 75, -1, -117, -92, 47, 26, 36, 72, 13, 81, 6, 24, -116, -42, -81 [...]
-        b[127] = new byte[]{106, 61, 127, -13, -1, -108, -15, 83, -73, 15, 104, -128, -62, -12, 23, 103, -127, -12, 43, 11, 110, -52, 57, -72, 36, 32, -68, -5, 109, -100, 114, -87, 62, 83, 50, -81, -86, 49, -84, -13, -75, -25, -125, 7, -20, 49, -12, -92, 120, 101, 64, -117, -91, 65, -22, -41, -51, 37, 56, -40, 114, -42, -93, -19, 31, 29, -62, 29, -113, 33, -14, -46, -82, -10, -87, -121, 14, 48, 52, 29, -111, 18, 58, 101, -100, -6, 35, -96, -26, -3, 108, -43, 13, -75, 75, -35, 43, 118, -1 [...]
-        b[128] = new byte[]{-110, 35, 46, 23, -3, 66, 49, 25, 96, -95, 47, -18, 44, -87, -11, -104, -42, 69, 100, -47, -55, 54, 68, 80, -98, 43, -50, -81, 56, -4, 29, 0, 26, -125, 12, -17, 77, 123, -20, 26, 2, 61, -123, 117, -9, -87, -89, -103, 47, -33, -15, -4, -22, -66, 99, -111, 122, 14, 31, -80, 94, -113, -76, -110, -98, -119, 106, 1, 99, -67, -76, -55, 113, 4, -88, -64, 92, -56, -62, 14, -1, 87, -37, 26, -98, -51, 13, 19, 65, 35, -93, 14, 65, 125, -110, -81, -118, 17, 72, -29, -85,  [...]
-        b[129] = new byte[]{97, 121, -126, 90, 24, -115, -49, -113, -56, -121, 44, 80, 33, -120, -32, 54, -8, -41, -7, 124, 3, -120, -12, -46, 4, -58, -123, 16, -71, -71, 95, -58, 56, -110, 113, -111, -98, 65, 120, -1, 56, -79, -14, 95, 112, 28, 22, -2, -20, 40, 31, -82, -66, 58, -84, 94, -34, -120, -116, -38, 0, 82, -29, 46, 56, -34, -61, 46, -73, 118, -32, 73, -119, 86, -60, 90, 58, -123, 59, 71, -18, -23, 63, 98, 34, 59, -124, 104, 93, -84, 78, -102, 111, -71, -109, 79, 31, 31, 52, -6 [...]
-        b[130] = new byte[]{24, -105, -44, -96, 24, -81, 91, -101, -86, 14, -107, 49, 77, 23, -29, 25, 99, 88, 124, -35, -1, 117, 49, 109, 117, 26, -126, 32, 126, 75, -39, -51, 103, 89, 125, 29, -127, -115, -37, 107, 95, -97, 91, -10, 23, -44, -24, 121, 107, 14, 37, 11, -96, 72, -118, 36, -31, -116, -102, 21, -43, 90, -51, -98, 85, -13, 109, -59, 28, 51, 47, -122, -80, 53, 20, 7, -60, 30, -14, 80, 111, 125, -17, -19, -31, 25, -115, 60, 29, 33, 86, 10, -46, -13, -39, -19, 110, -27, 52, 74 [...]
-        b[131] = new byte[]{121, 55, -85, 54, -50, -35, 58, -94, 64, -60, 12, 92, 49, 4, 103, 80, 55, 54, 112, 24, -10, -57, 72, -44, -42, 13, 67, -36, 111, -101, -37, 105, 3, -49, -78, 65, -52, -20, -65, -101, 24, 70, 92, 4, 55, -41, 125, 37, 106, -11, -116, -124, -119, -110, 6, 68, 94, 83, -20, -12, 3, 93, -60, 97, 83, 20, -65, -45, -59, -52, 62, -8, -20, -96, -81, -98, -49, -110, 10, -114, 118, 96, -47, -63, -45, -49, 122, 111, -119, 120, -18, -81, 33, -69, -56, -20, 15, 94, -45, 103, [...]
-        b[132] = new byte[]{-107, -70, -58, -78, 54, -13, 19, -99, -75, -85, -53, 115, 84, 117, 123, -67, -60, -49, 114, 21, 39, -52, -113, -44, 125, -28, 118, 71, -25, 38, 57, -83, -67, 98, 88, -49, 88, -72, 109, -11, 108, 118, 38, -72, -30, 42, -2, 14, 127, -103, -41, 123, -71, 47, -122, 47, -117, 97, 75, -123, 86, -88, 26, -88, -127, 97, 11, -13, -53, 110, -93, -123, -119, 61, -107, 101, -59, -24, -83, 58, 26, 69, 63, 66, 46, 42, -107, -27, -66, -89, 28, -33, -45, -57, 62, -110, 35, - [...]
-        b[133] = new byte[]{-103, 12, 0, 63, 54, 51, 127, 28, -3, 21, 113, 34, 103, -93, 60, -69, 90, 13, -36, 66, 91, 21, -119, -115, 85, -6, 102, -6, 61, 3, -86, 5, 62, 56, -14, 56, 81, 17, -63, 34, -79, 120, -58, -9, 76, -68, 3, -25, -47, 107, -102, -83, -76, 50, -3, -107, 77, -47, -30, -117, -19, 46, 10, -36, -53, -38, -97, 71, -27, 3, 6, -103, 116, -113, -98, -28, 122, 100, 127, 19, -88, 25, 58, 124, 14, 78, 68, 21, 53, -29, -103, -97, -20, -8, 106, 39, 120, -15, 16, 16, 99, 85, 60, [...]
-        b[134] = new byte[]{-36, 110, -99, -41, 101, 24, -30, 94, 86, -20, -39, -16, -48, 18, -12, 30, 117, 98, 86, 15, 82, 116, 75, -117, 50, -89, -103, -61, 45, 17, -108, -108, 127, 98, -41, 32, 119, -7, -120, -60, -117, -105, 92, 9, 70, -122, -8, 104, 95, -91, -36, -40, 17, -108, -19, 26, 83, -117, 88, -40, 43, 48, 60, -21, 43, -91, -46, 63, 122, 117, -73, 4, -32, -21, 107, 63, -39, 84, 4, -103, 92, 99, -41, -106, -49, -97, 93, -68, -70, -118, -57, 11, 119, 112, 67, -127, -62, -77, -3 [...]
-        b[135] = new byte[]{3, 24, 43, 100, -92, -59, -109, -110, 111, 44, 45, -61, 4, 0, -121, -62, -99, -70, -24, 92, 74, 35, -4, -89, -12, 95, -75, -75, -119, 51, 47, -98, -47, 86, -50, 71, 8, -106, 18, -29, -75, 110, 27, 68, -12, 19, 108, 42, -52, 122, -100, 44, -93, -48, 49, -107, -108, -18, -10, -47, -93, 35, 6, 52, -67, -39, -75, -95, -24, 102, -92, -22, 114, -81, 74, 90, -45, -125, 11, -29, -89, 18, -12, -110, -17, -19, 79, -31, 41, -112, 14, -20, -117, -40, -62, 127, 120, -112,  [...]
-        b[136] = new byte[]{106, -39, 6, -14, 93, -108, -4, -39, -26, -5, 50, -18, -17, 56, -34, -98, -73, -36, 1, 84, 9, 49, 74, -121, -118, 97, 89, -35, -60, 31, 105, 74, 120, -85, 42, -59, -97, 85, 34, -63, -99, -9, -113, -82, -107, -73, -83, -34, 85, -92, -1, 21, 124, 126, 46, 81, 39, -80, 121, -6, 1, 51, -63, 50, -99, -30, 17, -118, 1, 37, -116, -115, -90, 60, -1, -51, 19, -95, 5, -73, 51, -99, 0, 12, 117, 101, 19, 115, 34, -120, -98, -7, -58, -33, 30, -124, -58, 0, 87, -89, 42, -97 [...]
-        b[137] = new byte[]{117, -56, -108, -42, 100, -121, 25, -64, 113, 56, 5, 65, -128, -100, 123, -28, -98, -125, 105, 7, 65, 101, -12, -56, -51, 13, 56, 90, 25, 36, 117, 19, 46, -92, -26, 86, 74, 123, -11, -9, 24, 115, -14, 24, -114, -7, -103, -37, 6, -48, -55, -72, -18, 107, 30, -59, 6, -52, 127, -29, 97, -89, 31, 103, 32, -112, -9, 110, 43, -95, 27, -28, -121, 116, -11, -53, 27, 11, -85, 118, -101, 100, -107, 2, 15, -47, -40, -100, -12, -60, 45, 88, 111, -41, -25, 4, 23, -122, -88 [...]
-        b[138] = new byte[]{118, 4, 117, 60, -10, -100, 6, -5, 72, 44, 25, -96, -33, 123, 61, 41, 107, 110, 115, -82, -25, 118, 29, -21, 8, 118, 127, -108, -125, 123, -80, 67, 96, 108, 90, -119, 67, 46, 67, 11, 117, -56, 120, 116, -43, -18, -123, -99, -6, -46, 80, 105, 124, 104, 11, -67, 127, 73, 78, -47, -49, -93, -126, -108, 3, 10, 92, -74, -52, -49, -59, 58, 68, -8, -86, -97, 115, 59, 49, 16, -112, 112, 55, -51, -116, 14, 92, 8, -39, 39, 93, 63, 68, -121, 63, -56, 100, 95, -5, -107, - [...]
-        b[139] = new byte[]{-43, 15, 43, 126, -99, 71, -72, 107, 49, -70, -76, -32, 24, -58, -92, -58, 62, 82, -64, -47, 123, 18, 44, 87, -59, 83, -25, 124, 96, 3, 88, 55, 50, -126, 30, 66, -44, 19, 23, -86, 34, -11, 2, -27, 87, 57, 81, 78, -79, -84, -99, 124, -75, -122, 11, -62, -101, -121, -14, 98, 47, -95, -2, -41, 105, 88, -84, -47, -108, 79, -36, -119, 68, -116, -47, 14, 46, 23, -54, 83, 39, -83, -116, 1, -73, 0, -119, -114, -127, -46, -117, -121, -79, -49, -110, -74, -118, 30, 120, [...]
-        b[140] = new byte[]{-61, 77, 83, -100, -13, -1, 23, 117, 103, -117, 119, -63, 117, 93, -10, 6, 118, -37, -32, -99, 69, 113, -74, -124, -7, 121, -8, -30, 122, 57, -70, 14, -5, 83, -63, 82, -42, 4, -90, -36, -70, -119, -13, 36, -14, 93, -37, -77, -105, -101, -10, 119, 0, 68, 127, 56, -124, 125, 59, -78, -86, 7, -117, 46, -64, -104, 76, 24, -41, -103, -125, -120, 29, 10, 44, 18, 94, -125, -56, 9, 39, -69, -123, -54, -25, 103, -112, 91, -31, 94, -77, -41, -110, -77, 99, 106, -8, 110, [...]
-        b[141] = new byte[]{57, -4, -56, 23, 127, 19, -89, -104, 53, 91, -105, -107, 110, -71, 43, 49, -19, 12, -101, -73, -76, -64, 22, 32, -26, 21, 111, 46, -103, -1, -28, -59, -71, 56, 87, 38, 68, 59, -127, -89, 94, 90, -55, 16, 103, 39, 91, 1, 35, -35, -2, 8, -39, 116, 47, 3, -4, 67, 76, -3, 33, 113, 99, 76, 68, 121, -128, 118, 117, 41, -15, -68, 53, 95, -88, 105, -62, -115, 27, -74, -104, -83, -75, 31, -74, 68, -117, -2, -125, -33, 68, -45, -34, -49, -91, 52, 22, -27, -96, -67, 90,  [...]
-        b[142] = new byte[]{-30, 26, 23, -46, -56, -22, -106, 68, -119, 61, 74, -70, -37, -72, -119, -112, -42, 17, 110, -48, -2, 87, 106, -124, -84, 43, -109, -118, 70, -98, 68, 49, 25, -67, 81, -42, -65, 55, 111, -62, 62, 22, -41, 28, 73, -113, 63, -78, 28, 3, 122, -49, 97, 35, 9, 104, -99, 113, 43, 21, -127, 55, -93, 67, 86, -57, -14, -28, -13, 38, 8, 127, -50, -83, -14, 25, 68, -84, 38, -126, 86, -83, -25, 42, -58, -56, 30, -15, -79, 1, -114, 73, -66, -87, 67, -68, 27, 121, 0, -100,  [...]
-        b[143] = new byte[]{51, -9, 114, -41, -116, 77, 109, -109, 17, 124, 120, -118, 40, 87, 102, 15, -13, -85, 16, 31, -68, 49, -20, 107, 68, -17, 38, 50, 29, 34, -28, -70, -51, 3, -107, -108, -76, -75, -35, -63, 71, -64, -54, -58, 38, 106, 95, 120, 49, 42, 13, 37, -8, 38, -64, 96, -88, -88, -36, 37, 89, -112, 86, -42, 74, 80, 104, -9, 106, -78, -71, -10, 114, -9, 58, 37, -58, 86, -12, 89, 78, -57, 78, -61, 17, 18, 70, 109, -98, -91, -22, -121, -37, -51, -107, -96, 23, -20, -97, -6, 2 [...]
-        b[144] = new byte[]{26, 2, -21, -38, 23, 119, -100, -82, -72, 33, -101, -12, 38, 75, 10, 1, 63, -14, 36, -44, 55, -15, -84, -82, 91, 32, 103, 88, -72, -41, 108, 73, -109, -45, -113, 20, 14, -102, 108, -82, -71, -49, -22, 24, -92, 70, -114, 111, -39, 57, 71, 26, 16, -10, 117, -52, 6, -12, -46, -54, -36, -8, 124, 34, -126, 40, -11, 103, -10, -67, -107, -127, 7, -28, -116, 35, -47, 105, -127, -100, 65, 88, -79, 35, -64, 118, -50, 90, -63, -38, 17, 3, 21, -79, 7, -28, -33, -63, 22, 6 [...]
-        b[145] = new byte[]{91, -39, 74, 112, -80, -22, 52, 100, 0, 27, -5, 10, 64, -42, -111, -103, -29, -108, -104, -78, 123, 25, -61, 13, -88, 22, -122, 103, -82, 125, 70, 120, -21, -23, 20, -21, 126, 121, -92, -89, -106, 125, -103, -32, 11, -97, 5, -24, 30, 51, -29, -51, 36, 3, 38, 117, 88, -79, -113, -79, -56, -55, -18, 62, 9, 122, -128, -59, 64, -124, 9, -66, 94, -102, -40, 86, -101, 39, 123, -117, -19, -5, -70, 35, 82, -90, -81, 84, -16, 106, 47, 46, 93, -74, 120, 105, -42, -89, - [...]
-        b[146] = new byte[]{-119, -126, -25, -26, 31, 101, 34, 16, -1, -57, -39, -88, 104, -12, 103, 77, 126, -90, 36, 66, 74, 78, 24, 56, 89, 124, 82, -20, -118, -47, -37, 54, -27, 31, 110, -82, 58, 66, 13, -49, 71, 73, 53, 50, 85, 122, -37, 52, 100, -42, 3, -98, -55, -45, -20, -99, -94, 35, 118, 58, -123, 53, 86, 60, 106, 24, 83, -113, 73, -36, 29, -117, -124, 36, 68, -77, 64, -39, 67, 112, -69, -45, -51, 5, -74, 35, -100, 124, 118, -33, 4, -77, 103, -48, 60, -126, 43, 82, -34, 0, 46,  [...]
-        b[147] = new byte[]{74, 84, 73, 17, -50, -25, -91, 53, 47, 66, -81, 18, -128, 22, 10, -103, 86, 63, -33, 1, -40, -89, 104, 44, 15, 22, -97, 55, -14, 75, 82, -31, 42, 18, 57, -106, 50, -43, -69, 127, 16, 18, -117, -25, -113, 95, -120, 38, 36, -102, -117, -124, 62, 109, -8, 6, 113, -120, 44, 24, 43, 114, -9, 113, -21, -119, -57, -124, -30, -87, 88, 9, -49, -57, 122, -79, -50, -33, -127, 101, -27, -70, 29, 74, -8, 23, 6, 61, -74, 123, -8, 42, -72, 86, -56, 26, -20, -111, 1, 85, -23, [...]
-        b[148] = new byte[]{0, 9, 91, 25, 30, -98, -112, -77, -77, -57, -120, 105, -87, -108, -44, -87, 85, 16, -48, 82, -10, 8, 90, 96, 8, -61, -87, -24, 43, -82, 83, 57, 18, -99, 101, -23, 82, 59, -50, -119, 32, -28, 52, -8, 40, 76, -8, 41, -126, 104, 55, -71, -117, -52, -79, 126, 55, -102, 67, -58, 80, 96, -67, 107, 0, -45, -123, 124, -122, 66, 30, -82, -35, 103, -42, -74, 104, 98, 61, 26, -105, -98, 49, 94, -109, -31, 15, 119, 66, -40, 94, -101, 59, -42, 122, 39, -24, 47, 102, -18, 1 [...]
-        b[149] = new byte[]{-99, 101, -101, 6, 28, -50, 110, -84, 4, 22, 31, -45, -120, -92, 68, 114, -54, -117, 97, -76, 99, 33, -58, 95, -108, -102, 104, -105, 94, -116, -117, -122, 3, 47, -95, 25, -82, 45, -74, -87, 25, -45, -126, -80, 109, 33, -113, -121, -119, -28, -40, 90, -30, -38, 9, 41, 63, 7, -43, -100, 98, -24, -24, 75, -94, 91, -27, -36, -96, -36, 84, 58, 92, 95, 91, 97, -93, 80, 27, 29, -80, -16, 49, -32, -57, 73, 54, -98, -95, -1, -47, 77, 108, 1, 77, 36, 126, -35, -10, 104 [...]
-        b[150] = new byte[]{88, -39, 53, 70, 125, -86, -76, 111, -96, -109, 64, 4, 123, 10, -32, -93, -26, -111, 108, -38, -58, -32, 40, 16, -92, -28, 124, 82, -114, -36, -38, 109, -105, 65, -113, 12, 84, 59, -72, -71, 16, 58, -81, 54, 6, 25, -40, 42, 77, -62, 2, 42, 76, -67, 50, -15, -34, 37, -29, 86, 84, 5, -50, -58, 96, 56, 17, -43, -48, -37, 18, 45, 20, -105, 80, -73, 16, 109, -25, -89, 26, 119, -47, 65, 93, 123, 51, -37, 92, -107, -80, -6, -7, 119, -114, 119, 105, -72, -69, 79, 117, [...]
-        b[151] = new byte[]{-63, 89, -94, 59, -87, -99, 127, 102, -102, -122, -78, 101, 114, 105, -63, 15, 68, 26, -25, -52, -68, 2, -4, -41, -76, -98, 120, 34, 108, 96, 60, -77, -25, -48, -48, -112, 34, -71, -108, -57, 51, 89, 53, 51, -125, 19, 117, -114, -22, 70, 76, 16, 38, -109, -3, 17, 42, 79, 115, -24, 56, 26, 125, -78, -48, -121, 8, 83, 87, 56, -50, -3, -17, -46, 120, -32, 45, 89, 69, 77, 50, 60, 40, 90, -45, 73, 16, 100, 17, 121, 18, 103, 11, -118, -43, 66, -49, 93, 45, 63, -56,  [...]
-        b[152] = new byte[]{58, -120, -107, 102, -117, 8, -8, -95, -76, 17, -108, -18, -7, 106, 71, -18, 66, -120, 75, 25, -114, -41, 52, 88, 105, 35, -52, 4, -59, -76, 3, 36, 98, 11, 104, -103, 84, 73, 14, 50, 34, -89, -41, 101, -49, -88, -128, -46, 91, -7, 21, 3, -97, 28, -66, -1, -14, -79, 48, 51, 40, -76, -18, -17, -59, 40, -6, -59, 92, 37, -19, -64, -76, -73, 96, 120, 15, 111, 57, 17, 68, 45, 51, -8, -65, -48, -48, -2, 96, 38, 122, 23, -73, 55, -52, 100, -7, 84, -53, 99, -84, 71, 90 [...]
-        b[153] = new byte[]{-9, -74, 85, -79, 54, 48, 15, -59, 107, -128, -35, 69, 56, -124, 89, -14, 57, -68, 56, -56, 43, -60, 109, -24, -43, -94, 104, 98, -45, -43, 89, 122, 125, 114, 56, -27, -127, 122, -109, 49, -107, 108, -95, 106, -9, -90, -66, -23, -71, -36, 62, 45, -118, 53, 18, 60, -9, 38, -104, -108, 60, 122, -106, 113, -99, -113, 90, -75, -84, -20, -12, 117, 106, 70, 6, -69, 7, 66, 4, 118, 47, 8, 100, -36, 101, -127, 94, -1, 43, -75, 0, 31, 48, -25, 54, 44, -105, 87, -119, 71 [...]
-        b[154] = new byte[]{-48, -44, -104, 41, 59, -63, 40, -94, 39, -64, -65, 79, 39, -6, 86, 81, 101, 87, -30, 8, -59, -34, 40, 44, 3, 106, -86, 64, -53, 17, 123, 13, 37, 35, 82, -36, 8, 29, 124, 120, 96, -104, -109, 64, 39, -55, 64, -98, -9, -36, 57, -107, 97, -58, 21, 67, 12, 120, 126, -125, 101, -56, -128, -54, 85, -122, 120, 57, -11, -12, -105, 115, 84, -28, -34, -68, 21, -92, -36, -78, 46, -116, -115, 70, -66, -63, 1, -34, -123, 106, 127, 102, 101, -12, -122, 94, 12, 96, -109, -2 [...]
-        b[155] = new byte[]{-26, -119, 62, -83, -126, 56, 44, 40, 6, 107, 106, 108, 25, 67, 127, 125, -39, 19, -38, 4, 4, 78, -128, 125, 29, 24, -123, 93, 10, 94, -39, -121, 16, -68, 67, 118, -49, -74, 37, 36, 33, 19, -57, -120, -46, 91, 13, 58, -89, -106, 60, -75, -105, 41, -45, -55, -88, 40, -42, 48, 80, -98, 52, 14, -13, -23, 26, 80, -58, -5, 5, 41, 22, 16, -72, -110, 71, -24, -22, -8, -6, 78, -80, -93, -25, 42, 22, 38, 46, 67, -6, -89, 96, 31, 100, -12, 37, -27, -116, -13, 71, 24, 55 [...]
-        b[156] = new byte[]{40, 124, -45, 106, 85, 61, -64, -12, -89, 34, 56, 121, -125, 71, -121, -117, 81, -44, 104, 91, -97, -60, -102, 87, -90, 48, -34, -48, -35, -16, 16, -94, 13, -87, -72, 51, -123, -72, -9, 41, -2, 42, 90, 54, -10, 119, 80, 62, -48, -55, 110, -10, -42, 5, -2, 64, 61, 56, -40, -35, 107, -104, -40, 125, 24, 2, 30, 110, 102, 82, -72, -44, -47, 48, 50, 79, -79, 16, 21, -99, -82, -23, 97, 74, -2, -63, 71, 63, -17, -78, 112, -108, 36, -14, 78, -54, 44, -11, 22, 3, -109, [...]
-        b[157] = new byte[]{70, -78, 85, -60, -126, -88, 13, 123, 66, -66, 37, -116, -65, -12, -105, 48, -18, 54, 14, 126, -108, 88, -30, -125, -53, 104, 97, -40, 4, -105, -78, -60, -12, 123, -31, -70, -101, -79, 117, -37, 125, 34, 37, 105, 68, 55, 76, 1, 71, -54, 126, 6, 84, -35, 6, 20, 43, -97, 110, 116, -9, -61, -9, 43, 94, -85, 6, 102, 105, -49, 15, -7, 118, 103, -84, 32, -100, 97, 96, -10, -116, -32, 104, -102, 58, 12, -19, 22, 59, -110, 113, 56, 36, -103, 93, 9, -105, -5, -39, -11, [...]
-        b[158] = new byte[]{-77, 46, 45, -26, -79, 64, -17, -111, -111, 4, 79, -125, -87, -81, 108, 67, 24, -49, -106, -30, -83, -4, -103, -60, 99, -98, 32, -72, 121, -54, -87, -57, 38, -57, 113, -58, -117, 34, 116, -115, 64, 62, 122, -34, 23, 59, -59, -32, -21, -36, 2, 3, -36, 85, -60, -106, 80, 47, -67, -13, -13, 73, -107, 124, -121, -8, -36, 114, 10, 59, 24, 49, 79, 98, 35, 27, -79, 10, 48, -32, -1, -85, 30, -115, -100, -60, -17, 123, -128, 107, -54, 8, 11, -75, -78, -48, 81, -28, 95, [...]
-        b[159] = new byte[]{102, -49, -63, 124, 90, 22, 34, 102, 26, -69, 103, 89, 45, -66, -55, -99, -25, -109, 66, -98, -20, 67, 78, -78, -94, 113, 42, -47, -122, -72, 4, -45, -119, 27, 47, -7, 116, 97, -8, -38, -116, -19, -48, -6, 79, -40, -122, 127, 75, -97, 23, -19, -21, 21, -127, -50, -93, 3, 92, -73, 5, -52, 99, -36, -61, -24, 14, 52, 9, 73, -111, -59, 18, -44, 119, 27, 125, 83, -15, -31, 121, 58, -109, -43, 11, -121, 112, -10, -49, 92, -106, 89, 76, -45, -101, 111, 113, -23, -84, [...]
-        b[160] = new byte[]{-123, -41, -125, 38, -28, 103, -103, -65, 42, -12, 70, 30, 115, -49, -97, -70, -44, -1, 10, -6, -95, -90, -86, 20, 118, -39, -122, -24, 77, -11, 70, -74, 9, 14, -49, 122, 51, -107, -97, -98, 15, 116, 32, 74, -85, -99, -58, 94, -30, -75, 88, 14, -121, 17, 100, -83, -73, 118, -6, -83, 37, -93, -31, 77, 64, 87, 94, 30, 54, 35, 35, 37, 82, 122, -24, -21, -46, -120, -5, 78, -7, 22, -10, 24, -62, 5, 90, 81, -35, 116, -81, -79, 49, 88, -50, 89, -20, 48, -112, -37, 31 [...]
-        b[161] = new byte[]{10, 80, -126, 58, -3, 38, 15, -33, -1, 45, 29, 14, -118, -63, -33, 106, 108, 92, 78, -7, -91, -64, -62, -32, 0, -124, 45, -34, 22, -50, -115, 19, -28, 95, 1, 32, 104, 60, -49, -46, -18, -117, 55, -64, 77, -63, -45, -107, -61, -30, -31, -83, -68, -52, 35, -52, -48, -52, 123, -24, -18, 97, -113, -111, 2, 2, 121, -24, -90, -1, 31, -79, -104, 99, -48, -74, 101, -89, 95, 16, -106, -120, -67, 110, 127, -1, 30, 71, -107, -82, -53, -47, 43, -14, -55, 19, 7, -54, -58,  [...]
-        b[162] = new byte[]{22, -49, -128, -104, 80, -89, 82, -65, -30, -101, 15, 3, -48, 106, 77, -119, -46, 15, -10, -84, 22, -13, 36, 64, -50, 107, 106, 61, 47, -81, 79, -87, -7, 83, -122, 5, 65, -54, 96, 111, 57, -21, 96, -18, 19, 62, -87, 21, 23, 106, 51, -42, 106, 96, 45, -126, 32, -57, -5, -74, 94, -54, -19, -106, 49, -105, -29, -94, -33, 99, -61, -78, 80, -10, -80, -29, -9, 90, -33, -60, 6, -98, 10, 8, -107, 45, -100, 55, 77, 92, -128, -35, -34, 125, 40, -52, -106, 118, 69, -93,  [...]
-        b[163] = new byte[]{-62, 3, -72, 13, -47, -103, -53, -40, 53, -36, -117, -114, -122, 66, 70, 37, -60, -24, -56, -69, -126, 5, 89, -67, 79, -9, 60, -87, -114, 13, 58, 23, -107, 83, 83, 86, -38, 15, 44, 60, -118, 62, 70, 33, 44, 73, 36, -4, -77, 30, -66, 38, 31, -64, -2, 70, -126, -59, -117, -55, -12, 43, 32, -100, 24, -39, 48, -59, -111, -79, -35, -4, -36, 118, 64, -96, -101, 100, -57, 2, -81, -54, -121, -105, -49, 48, -2, -90, -31, 111, -88, -92, 1, 16, -86, -27, 4, 76, 31, 125,  [...]
-        b[164] = new byte[]{18, 69, -19, -45, 100, -102, 69, 66, 35, 22, 106, 11, -57, 35, -70, 55, -24, 34, 47, -120, -128, -31, -10, 52, 19, 22, -88, -6, 104, -32, 17, -10, 126, 90, -2, -80, -9, -111, -105, 28, 18, 53, -58, 86, 12, 84, -71, 14, 114, 123, -67, -99, -21, 28, -67, -59, -48, 31, 67, -85, -88, -65, 110, 126, -118, -60, 81, 49, -109, 74, 13, -100, -117, -82, -26, -32, 106, -16, 2, -68, -116, -53, -18, 94, 82, -114, -5, 67, -111, -87, 88, -89, -20, -125, -55, -61, 108, 63, 26 [...]
-        b[165] = new byte[]{58, -32, 106, -57, -110, -59, 38, -70, 17, 108, 57, -8, -41, -18, 26, -52, 81, -27, 42, 12, 58, 108, -56, 27, -79, 17, -102, 43, -43, 39, 62, -8, -71, -59, -7, -107, -31, 34, -48, -39, -116, -56, -122, -118, 70, -117, 81, 121, -20, -66, -81, 42, -23, 26, 91, 69, -27, 22, 79, -59, 127, -108, -35, -28, -125, 2, -19, 79, -92, -67, 114, -91, 127, -57, -58, 32, -124, 60, 21, -95, -56, -46, -10, -56, 95, -49, 78, 38, 80, 106, -108, -128, -86, 126, -44, -115, -119, 8 [...]
-        b[166] = new byte[]{72, -17, -17, 14, -54, -103, 13, -46, 38, 57, -47, -11, -10, -58, 72, -20, 85, 21, -122, 92, 117, 16, -115, 23, 70, -65, 0, -83, 59, -128, 27, -111, 124, 44, 50, -69, -24, 23, 45, -40, 46, -33, 93, 53, 40, -62, 41, 87, -100, -107, -95, 67, 27, -37, 26, 43, -91, -111, 65, -110, -71, 88, -43, 63, 93, -77, 105, -49, 91, 74, 20, 105, -81, 82, -9, -71, -57, 94, -18, 125, 95, -9, 47, -51, 112, 114, 66, -63, -38, -109, 46, -82, -47, 99, 40, 8, -75, 14, 41, -91, 1, -9 [...]
-        b[167] = new byte[]{-75, -110, -1, -88, 0, -116, 59, -44, -77, -102, 2, 97, 89, 3, 44, 108, -88, 4, -26, 83, -64, 17, -68, 103, -36, -44, 123, -25, 78, 34, -106, 0, 43, 71, -56, -5, -70, -3, 74, 23, -114, -82, 67, 40, -21, -112, 73, -14, 6, -118, -26, 96, 31, -6, -100, -79, -91, 30, 27, 122, -40, -124, 31, -76, -58, 31, -26, 1, -23, 28, 87, -45, -66, -23, 17, 40, 95, 59, -37, -52, -120, 96, 0, 24, 28, -12, 63, 90, 49, -13, 29, -43, 82, -87, 66, 106, 23, 102, -68, 68, 78, -110, -6 [...]
-        b[168] = new byte[]{25, 23, -69, -72, 93, 112, 31, -97, -5, -44, 29, -17, -104, 97, 126, -92, -35, -57, -12, -14, -114, -42, -46, -16, -78, 118, -12, 15, -113, -49, -101, -77, -18, -28, -96, 30, -32, -25, -34, -106, 71, -59, 32, 24, 50, -114, -22, 25, -82, -105, -124, -112, 102, 103, 111, -22, -97, -8, -87, -5, 42, -35, 97, 15, 6, 43, -4, -58, -3, 123, 11, -80, 57, 123, 27, 34, -110, -48, 50, 7, -31, -48, -114, 87, -80, -6, -42, -95, -57, 110, 87, 57, -2, -69, -9, 38, -35, -54, - [...]
-        b[169] = new byte[]{-16, 16, -59, -69, -19, -67, -106, -101, 101, 25, 40, -36, 101, -18, -32, -123, 102, -108, -128, -116, -37, -71, 74, 76, -27, 112, -59, 110, -46, 85, 64, -15, 29, -35, -80, 4, -47, -63, -111, -107, 1, 61, 18, 18, -105, -117, -110, 127, 34, -55, 24, 54, -76, 55, -25, -69, 65, -124, 15, -108, 52, 51, 87, 10, 38, -45, -40, 6, 70, -89, 53, -128, 115, 1, 58, 116, -1, -75, -32, 91, -111, 47, -111, -79, -86, 31, -19, 122, -29, -40, 42, -66, 72, 34, 126, -52, -35, 38, [...]
-        b[170] = new byte[]{-78, 35, -46, 92, 62, 46, -33, -91, -104, -75, 59, -17, 15, 52, 101, 20, -8, -82, 100, -55, -47, 115, 58, -53, -35, -32, 53, -25, -34, 121, 36, 48, -100, -21, -11, 118, 10, -5, -70, -101, -15, -49, 59, -94, 113, -94, 12, 78, -47, -90, 19, 103, -101, 94, -115, -128, -50, 33, -104, 1, -53, -115, 3, -127, 70, 76, -88, -14, 118, 34, -106, 35, -78, 101, 27, -114, 50, 84, -14, -17, -50, -89, 8, 76, -94, 126, 118, -26, 109, -17, -48, 70, 37, -65, 40, -10, 66, -99, -2 [...]
-        b[171] = new byte[]{-5, -3, 120, 62, 113, 80, 85, -98, -63, 76, 114, -108, -66, 68, -19, 70, -74, 18, -19, 105, -49, 52, 62, 96, 103, -106, -14, 50, 21, 43, 12, -71, 9, 107, -91, 15, 5, 94, -13, -46, 122, -61, 50, 39, -60, -93, -9, 80, 125, 74, -73, 18, 48, -94, 27, -84, 70, 86, 26, -44, -68, 12, -32, -58, -93, -112, 101, 53, -75, 99, -38, 125, 51, 66, -106, 91, -31, 52, 94, -16, -112, -90, -111, -59, -90, -29, 42, 23, 91, -40, -80, 93, 14, 15, -96, 12, -120, 79, 73, -76, 105, -4 [...]
-        b[172] = new byte[]{-33, 82, 53, -115, -81, -127, -7, -86, 41, 42, 76, -19, 27, 50, 88, -68, -111, 22, 2, -56, 114, -96, 0, 21, -25, 43, -34, -32, -71, -49, -46, 71, 72, -103, 68, 26, 84, 68, -46, -70, -114, 66, 12, -122, 43, -17, 51, 60, 48, 32, -11, 121, -125, -23, 46, 39, 38, 26, 112, 62, 11, -35, -69, -93, -44, 6, 1, 82, -9, 114, -45, -65, 12, 37, -95, 54, 41, -42, -20, -39, -98, 96, -125, 62, -93, -121, 98, 40, 25, 3, 62, 49, -26, 73, 102, -66, -98, -82, 39, -81, -24, 14, 10 [...]
-        b[173] = new byte[]{93, -76, 95, 14, -95, -98, -35, -25, -120, -42, -47, -15, -15, 73, -49, -99, -32, -63, -25, -77, 124, 85, -28, -110, -51, 124, -43, 8, -44, -96, -60, -31, 31, 119, -89, 127, -70, 126, 66, 15, 17, -58, -6, 110, 48, -34, -46, 27, -75, 41, 50, -31, 29, -66, -52, -63, 126, 75, -105, 17, -67, 51, -80, 103, -5, -34, 122, 6, 45, 44, -92, -15, 3, 73, -107, 121, -43, -117, 22, 71, -31, -2, -2, 13, -128, -14, 126, 52, 69, 62, 115, 41, 91, 73, 38, 75, 1, -32, 104, 124, 5 [...]
-        b[174] = new byte[]{-116, 97, 35, -4, 6, -127, 121, -10, -100, -10, -29, -100, -104, 107, -114, -10, 113, -2, 55, -20, -52, -80, 46, 42, 1, -18, -103, 80, 67, 12, 33, 119, 83, 26, 116, -106, -105, -75, -19, -45, -7, -54, -85, 35, -93, -35, -111, -10, -29, -47, -16, -112, -97, 27, -97, -112, -66, -47, -68, -50, -91, 13, 94, 3, 115, -15, 18, -82, -111, 124, -93, 43, -116, 114, 79, 38, 100, -39, 94, -76, -124, 73, 56, -33, -113, 122, 13, 45, 79, -62, -86, -96, -50, -87, -33, 51, -99 [...]
-        b[175] = new byte[]{68, 12, -51, 11, 25, 79, -39, 47, -4, 45, -10, -58, -74, 84, -125, 74, 26, 49, -15, -60, -96, -104, -109, 14, 115, 108, 79, 22, -49, 30, -127, -107, 73, -117, 9, 102, -99, 45, -38, 5, 98, -113, 69, -74, -15, -111, -104, -107, 85, -119, 110, -32, 99, 73, 55, 6, -24, 113, -50, -99, -126, -71, 118, -16, 117, -64, -79, -120, -92, 19, -100, 48, -95, 13, 76, 120, -30, 86, 83, 124, -13, 22, 38, 4, 54, 30, -46, 44, 20, 31, -115, 83, -48, 30, -25, 28, -74, -65, 15, -23 [...]
-        b[176] = new byte[]{-45, -56, 102, 102, -101, 65, 24, -94, -86, 71, -92, 51, -12, 99, 92, -39, 105, 53, 122, -40, 20, -4, -86, 32, 110, 35, -48, -104, 8, 121, 33, 121, 83, 5, -49, 123, 14, -31, 19, -96, -66, 1, 111, -49, 61, -99, -13, -101, 85, 15, -42, 122, 89, -94, 9, 47, 48, 18, 52, -127, 118, 105, -27, -110, 69, 59, -3, -66, 84, 79, 115, -8, -109, 90, 65, -23, -100, 79, 31, -44, 37, 118, 62, 90, 107, 57, 0, -1, 32, -101, -46, 76, -61, 124, -103, 92, 116, 83, -95, -43, -32, 28 [...]
-        b[177] = new byte[]{-48, 104, 107, -127, -76, -110, 28, -14, -42, -73, 36, -74, -102, 116, -79, -84, -48, 35, -3, -36, -85, 21, 7, 49, 34, 3, -29, 79, -65, -69, -15, 38, 117, 101, 49, -100, -45, 123, -20, -102, 86, 120, 103, -10, -50, 59, -50, 4, -9, 34, -101, -107, -94, 57, 117, 33, -43, 94, -68, 121, -20, -67, 36, -118, 66, -4, -74, 2, -126, -80, 9, 20, 52, -19, -27, -1, -116, -17, -28, 87, -62, -83, 20, -32, 27, 30, 44, 21, 49, 65, -44, -45, 92, 45, -52, 26, -126, 75, -59, -51 [...]
-        b[178] = new byte[]{-39, 81, -94, 49, 95, -33, -38, 19, 89, 2, 60, 55, 125, -41, -121, -57, -4, 17, 33, 92, -34, 63, 77, 124, -107, -100, -89, -49, 4, -78, 72, 111, -13, 64, 28, 114, 70, 104, -73, 98, 98, -107, 102, 104, 119, 104, -101, -89, -70, 42, -90, -67, -37, 116, -112, -98, -91, 95, -77, 60, 5, -88, -40, 28, -16, -127, -110, -94, 78, -57, -54, 15, 39, -14, -75, -96, 0, -15, 86, 9, -38, -67, -98, -67, 116, -90, 43, 75, 47, 127, 62, 110, -84, 31, 24, -59, -83, -44, -77, -11, [...]
-        b[179] = new byte[]{-120, -60, -126, -121, 89, -71, -67, -53, 119, 11, -78, -60, -97, -100, 10, 69, -117, 90, -105, 59, -58, -22, -110, -102, -124, 109, 125, -83, 54, -6, 103, -38, -69, -7, -69, -125, -80, -62, -7, -56, -50, -115, -88, 59, -24, 87, 27, 119, 14, -2, -54, 71, 7, 82, -33, 17, -65, 63, 38, -5, 108, -111, -81, 67, 102, -72, 22, 20, 103, 77, -82, 7, -68, -5, -27, -35, -54, 73, 116, -56, 2, 10, -5, 23, 121, 117, -24, 48, -66, 41, 31, 49, 101, -92, -3, 27, 54, -61, 40, - [...]
-        b[180] = new byte[]{-124, -34, 62, -57, -5, 10, -12, 84, 89, -97, -103, 101, 107, 14, -1, 92, 49, -80, -122, -35, -63, 112, -116, 64, 20, -2, 9, -96, 106, -107, 64, 44, 60, 115, -110, 14, -107, 42, -118, 16, -27, 98, 98, -53, 53, -102, 123, -28, -93, -87, 21, -83, -51, -94, 48, 64, 60, -121, -60, 108, -80, -98, 29, 36, 26, 69, 13, -97, -37, -111, -24, 66, -54, 20, 38, 90, -101, 41, 102, -48, 47, 68, -34, 125, -102, 62, -89, -57, 68, -127, -126, 86, 6, 113, -61, -14, -82, 125, -34 [...]
+    /* These strings were generated from random byte[] arrays fed into commons-codec-1.3.jar */
+    private static void initSTRINGS() {
+        final String[] s = STRINGS;
+        s[0] = "";
+        s[1] = "uA==";
+        s[2] = "z9w=";
+        s[3] = "TQ+Z";
+        s[4] = "bhjUYA==";
+        s[5] = "1cO9td8=";
+        s[6] = "sMxHoJf5";
+        s[7] = "jQcPlDsZzw==";
+        s[8] = "TAaPnfW/CYU=";
+        s[9] = "cXTZuwzXPONS";
+        s[10] = "Ltn/ZTV4IjT6OA==";
+        s[11] = "6fh+jdU31SOmWrc=";
+        s[12] = "E/5MoD4qCvDuTcFA";
+        s[13] = "2n9YyfCMyMXembtssQ==";
+        s[14] = "qBka3Bq6V31HmcmHjkY=";
+        s[15] = "WvyZe6kQ8py7m25ucawJ";
+        s[16] = "oYpxMy6BSpZXhVpOR6dXmA==";
+        s[63] = "yexFaNKaP+VkVwEUvxQXbC0HSCi/srOY7c036lT25frs4xjIvp214JHCg7OL/XZW3IMe6CDgSMCaaI91eRgM";
+        s[64] = "vkqgnuJ3plxNtoveiMJuYLN6wZQLpb3Fg48/zHkdFuDucuMKWVRO/niFRgKsFqcxq6VgCxwQbePiP9sRnxz7wg==";
+        s[65] = "YHks3GCb2uVF47Y2tCieiDGJ879Rm5dBhQhQizYhfWOo+BrB2/K+E7wZWTid14lMpM60+5C0N9JNKAcBESeqZZI=";
+        s[66] = "z8551jmQp/Qs95tw226+HCHWruKx/JvfBCfQ5p0fF77mkSpp66E552ik2gycrBBsMC/NbznAgTZoMzZxehfJwu49";
+        s[67] = "VsR2whqq/qQm342+TNz1lgOZMoWbpCz+kj2zflq0nx7S/ReEVPUJcqgMtVzrr2FVQPfBAH5VRjR+hkxwv4bssQms8Q==";
+        s[68] = "5xmIp8dUJZzkisIkuEPsnPXvzDeMo48qWFfHIn2av3jr5qoZHCs0LfNEyepC3v2sa0nCU0FlqsmDyTI5/2jt5zsLtV0=";
+        s[69] = "tGEgXjglUB9NbCtiS88AetLtRqhCAnhzOUKVgvbJZHqOA6x8uOorA1t3NcaIA00ZqbPYALu4LzIm4i4lAL9QgiH/Jg7b";
+        s[70] = "gFtxEhYJahDmU5dpudYs6ZTsqAx+s2j+06A0zeyb3U7nhZFsbkCDlds0EYUoqerZqZPm7F6CDOOD3dU7nYmelE0DxyMO9A==";
+        s[71] = "j/h/1JygYA5bjttxzQxr5gBtgh+AYVozhF4WgvcU/g49v0hUy6FdhfZewGK+Phtzj7RabI5p2zXyzvkmLQdFhdI5Um4O5sw=";
+        s[72] = "m+kYVGojIR5pgbz7pGJm2g+3qqk7fhl3cowa2eVrhki7WofyywnRezqTxOkBgVFz6nKs8qxpbbbzALctcPeMsp9dpXUfuUJr";
+        s[73] = "pPaGnMr0UYmldnJVk/F+3WCJJ1r2otvD5KJdt2u1RnS6LwhHhwLCqfW8O/QEg43WdxKomGL/JM33tn/B9pMPoIU0QTGjq2GRow==";
+        s[74] = "mOxzGyym6T/BxCV5nSiIYMlfAUmCN7gt7+ZTMg1kd8Ptirk+JF5dk8USbWBu/9ZvNg5ZuiJCeGwfaVpqpZ3K9ySF7C87Jvu1RUE=";
+        s[75] = "VYLOIE4DnhxJn3FKS/2RHHHYLlZiGVdV/k4uBbtAYHUSTpRzaaYPGNAVjdNwbTHIihmeuk/5YQUy8NFsxIom+Li7bnWiBoHKBPP7";
+        s[76] = "7foMpJ0TknCatjUiSxtnuKSiz4Qvl/idWY9UKiTljoQHZ+C8bcUscnI/bZr13e6AvyUh47MlpdGvzIm05qUdMWWLoZJOaGYvDmvrWQ==";
+        s[77] = "jxQSGiFs+b1TfE4lDUAPUPJ0SWeUgl03rK6auieWJcarDIHM97gGOHMmyHudRMqkZmIkxYRgYgCCUg/JeU91OZD3tL4U+wNhShywe88=";
+        s[78] = "UGmH/gl7t3Dk801vRhRDEbgsfShtHZ1gZQn4KNZ5Qsw3WiGjW0ImInVHa+LSHBzLUjwC0Z3nXO4i4+CiKYqAspOViE6WqVUY8ZSV0Og4";
+        s[79] = "wdEoYmJuRng2z2IkAiSgJ1CW2VE7H7oXpYWEFFO8nG0bZn7PHhT8KyhaO2ridl8eUEysja0VXFDyQqSgZnvdUKrCGepWGZbw0/0bDws3Ag==";
+        s[80] = "5kZqgrUbt+rN5BWAddeUtm9TGT43vYpB6PeyQwTyy9Vbr0+U/4Qzy0Iw37Ra293HmkmpgQzuScVpcIiFGXPAFWwToR+bovwu7aXji/FnMwk=";
+        s[81] = "E467MMmJbmwv8Omc2TdcyMr/30B8izWbf+CAuJtw67b1g9trhC6n4GYnXjeW9DYvmWoIJPx0zvU/Q+gqv0cteg2bx9P2mrgMDARb6egowqjx";
+        s[82] = "Vpt8hYb4jx1F+7REX7K65v6eO5F1GDg/K8SVLWDSp0srupYEQkBVRxnB9dmhSo9XHpz4C8pRl8r82fxXZummEf4U2Oh0Dip5rnNtDL+IJvL8lQ==";
+        s[121] = "hf69xr9mtFf4N3j2uA9MgLL5Zy94Hjv+VQi94+LS8972JJgDHCQOwP5whdQkV+SJpXkiyHGaSsQ4fhepPwzuZcEpYER+beny1j+M0HSZe36MdRIhlTqno+4qsXckL0CjXsYkJJM0NAfOYjHAus5G1bgi9VhmiMfAMA==";
+        s[122] = "yKzTh5hPp9/PBeZtrZXsFHAR9ywOM3hRaBDkgG9E09wFW8MZD0xMGegcp0QrTJcP8QYOaYhTDVimPqsNTVOmjdjkvS+2WhjJW4mVOXQ8KID91yaBtPo+DStL5GMgctcP5MoVf1Vp8w/mYtofqbllfDm5NfYzh2A7ijY=";
+        s[123] = "csFmwvDzoO4IO6ySDA4B2V7emEetAwCgO66zzlfWb3KDrPfFZc3Jgr4+dlaUkEIDHYeLHETdTssWOl2KrPHBEsULpDTR+3OhurXb1Qr2NvHiHFuqT3Geb6EYw2albfTmXxch82ablt4WKl4qPcSey54v6tsCuUuZzrkt";
+        s[124] = "5InxvKwpoCV7EK78OzU/tL9/NmK14Prw9tOCAyK+xpUNLZriuVEVdgpoZ05rliufaUDGHH8dPAem8G9DN/VOPktB6vXKtc2kMUgnMTiZwv/UVd+xyqnT8PLEdNQ8rCWxyiCcLdXFf0+xcE7qCcwzC+D7+cRW+i6dnpZkyw==";
+        s[125] = "cEx7oTsSHWUFPj92cstdy5wGbRcxH+VRWN8kaNTTCPWqSckyU9Xk/jj5/gj9DFwjfsCSp60xutf4/rFanjtwqtRg6dJLP4JAgpOKswDlHi6Vt7zF/w7HidMf2sdtlsqzayZmT2Hn7iOo3CExzr5Z5JfmMFAX8R9peUN4t5U=";
+        s[126] = "AeXetVbj+7mmGiCs3BGUSZDLlq2odMsN8JAHQM64Cly8y5jw75PpISocWRFFQmmXYP7ckKmtuhIvD69HtZxGhNRsl1l1gXzKFhsWykcRtG87F8sS1Uv/i6QvGiRIDVEGGIzWrzRIISkBb9wCxJ2HESfleWwrz/GqryjoN26B";
+        s[127] = "aj1/8/+U8VO3D2iAwvQXZ4H0KwtuzDm4JCC8+22ccqk+UzKvqjGs87XngwfsMfSkeGVAi6VB6tfNJTjYctaj7R8dwh2PIfLSrvaphw4wNB2REjplnPojoOb9bNUNtUvdK3b1bArOWugIRJWLnMl72yEHFb1iBfBmn7uIa7KT2Q==";
+        s[128] = "kiMuF/1CMRlgoS/uLKn1mNZFZNHJNkRQnivOrzj8HQAagwzvTXvsGgI9hXX3qaeZL9/x/Oq+Y5F6Dh+wXo+0kp6JagFjvbTJcQSowFzIwg7/V9sans0NE0Ejow5BfZKvihFI46sHiALl1qzoXqLQq+5fZGIFRyyY8wFW1uiNu9k=";
+        s[129] = "YXmCWhiNz4/IhyxQIYjgNvjX+XwDiPTSBMaFELm5X8Y4knGRnkF4/zix8l9wHBb+7Cgfrr46rF7eiIzaAFLjLjjewy63duBJiVbEWjqFO0fu6T9iIjuEaF2sTppvuZNPHx80vN+HLAnAVmgFESw5APXWn15dizvuUfVHd5isCqbA";
+        s[130] = "GJfUoBivW5uqDpUxTRfjGWNYfN3/dTFtdRqCIH5L2c1nWX0dgY3ba1+fW/YX1Oh5aw4lC6BIiiThjJoV1VrNnlXzbcUcMy+GsDUUB8Qe8lBvfe/t4RmNPB0hVgrS89ntbuU0SsCmWw+9DqM3nidPebANKERig1zZTBBKgpVf7HPFCA==";
+        s[131] = "eTerNs7dOqJAxAxcMQRnUDc2cBj2x0jU1g1D3G+b22kDz7JBzOy/mxhGXAQ3130lavWMhImSBkReU+z0A13EYVMUv9PFzD747KCvns+SCo52YNHB0896b4l47q8hu8jsD17TZ2uWWJhS4cNnSE1jeM6NoXGKvf90yxfzwucNYc4RdaQ=";
+        s[132] = "lbrGsjbzE521q8tzVHV7vcTPchUnzI/UfeR2R+cmOa29YljPWLht9Wx2JrjiKv4Of5nXe7kvhi+LYUuFVqgaqIFhC/PLbqOFiT2VZcXorToaRT9CLiqV5b6nHN/Txz6SI7MiD3hnk7psDbglPOo+ytqc9sFHj7UkR1ZctQjwFYwJjlxf";
+        s[133] = "mQwAPzYzfxz9FXEiZ6M8u1oN3EJbFYmNVfpm+j0DqgU+OPI4URHBIrF4xvdMvAPn0WuarbQy/ZVN0eKL7S4K3Mvan0flAwaZdI+e5HpkfxOoGTp8Dk5EFTXjmZ/s+GonePEQEGNVPL1WYoD6xXqAAvMLKtyrFcpoiGS9eDBlsZDQzPzz/g==";
+        s[134] = "3G6d12UY4l5W7Nnw0BL0HnViVg9SdEuLMqeZwy0RlJR/Ytcgd/mIxIuXXAlGhvhoX6Xc2BGU7RpTi1jYKzA86yul0j96dbcE4OtrP9lUBJlcY9eWz59dvLqKxwt3cEOBwrPf69MHuIa256es3AOCobfC8RQScW0PQ0QUa1VHB/eXSsVTSWg=";
+        s[135] = "AxgrZKTFk5JvLC3DBACHwp266FxKI/yn9F+1tYkzL57RVs5HCJYS47VuG0T0E2wqzHqcLKPQMZWU7vbRoyMGNL3ZtaHoZqTqcq9KWtODC+OnEvSS7+1P4SmQDuyL2MJ/eJABJKNcu1K/Lk0buAaO0FvX6OGBcPzu1+dv/ZkwuORK07qRnxqQ";
+        s[136] = "atkG8l2U/Nnm+zLu7zjenrfcAVQJMUqHimFZ3cQfaUp4qyrFn1UiwZ33j66Vt63eVaT/FXx+LlEnsHn6ATPBMp3iEYoBJYyNpjz/zROhBbcznQAMdWUTcyKInvnG3x6ExgBXpyqfxxp/Pm8by7LlSUT5MKHdcu+TEfUXRokCr2iPnt7NYsNDfA==";
+        s[137] = "dciU1mSHGcBxOAVBgJx75J6DaQdBZfTIzQ04WhkkdRMupOZWSnv19xhz8hiO+ZnbBtDJuO5rHsUGzH/jYacfZyCQ924roRvkh3T1yxsLq3abZJUCD9HYnPTELVhv1+cEF4aoO3vGOu2FpfLUn5QTd0PozsIqcqZVB2V57B7DjfizUe3D8Yf5Vco=";
+        s[138] = "dgR1PPacBvtILBmg33s9KWtuc67ndh3rCHZ/lIN7sENgbFqJQy5DC3XIeHTV7oWd+tJQaXxoC71/SU7Rz6OClAMKXLbMz8U6RPiqn3M7MRCQcDfNjA5cCNknXT9Ehz/IZF/7lcWrwxBKYm4B98lPkpZtR2QHndiQ3venzWrP0P5y27mReaFuaJ++";
+        s[139] = "1Q8rfp1HuGsxurTgGMakxj5SwNF7EixXxVPnfGADWDcygh5C1BMXqiL1AuVXOVFOsaydfLWGC8Kbh/JiL6H+12lYrNGUT9yJRIzRDi4XylMnrYwBtwCJjoHSi4exz5K2ih54utVAuzXZg6mnc9ied/mNRjj9d2HFD5mv0w/qTN/WFxEmtuZM/nMMag==";
+        s[140] = "w01TnPP/F3Vni3fBdV32Bnbb4J1FcbaE+Xn44no5ug77U8FS1gSm3LqJ8yTyXduzl5v2dwBEfziEfTuyqgeLLsCYTBjXmYOIHQosEl6DyAknu4XK52eQW+Fes9eSs2Nq+G4aaR4y4leeFNmCoZ9BQmAAZr0LFkqnvqaKmBVgcgxPs7/8SQHnpqvaU6Y=";
+        s[141] = "OfzIF38Tp5g1W5eVbrkrMe0Mm7e0wBYg5hVvLpn/5MW5OFcmRDuBp15ayRBnJ1sBI93+CNl0LwP8Q0z9IXFjTER5gHZ1KfG8NV+oacKNG7aYrbUftkSL/oPfRNPez6U0FuWgvVrXUB6cwKTWvwb9KoD7s6AGYRdH50ZgJdBniFD7dKoOQnJ/ECuTUXI+";
+        s[142] = "4hoX0sjqlkSJPUq627iJkNYRbtD+V2qErCuTikaeRDEZvVHWvzdvwj4W1xxJjz+yHAN6z2EjCWidcSsVgTejQ1bH8uTzJgh/zq3yGUSsJoJWrecqxsge8bEBjkm+qUO8G3kAnC6FMjJ2NYQeXf6OK6OgsqyJwlHPTyAms2/IoYTB4iEqgIFG/2fNEJEIag==";
+        s[143] = "M/dy14xNbZMRfHiKKFdmD/OrEB+8MexrRO8mMh0i5LrNA5WUtLXdwUfAysYmal94MSoNJfgmwGCoqNwlWZBW1kpQaPdqsrn2cvc6JcZW9FlOx07DERJGbZ6l6ofbzZWgF+yf+hvT6jnJvXBVCTT3lfO3qo4leNuEJwsuU6erXGC3Ch53uPtGIrdDUpcX6/U=";
+        s[144] = "GgLr2hd3nK64IZv0JksKAT/yJNQ38ayuWyBnWLjXbEmT048UDppsrrnP6hikRo5v2TlHGhD2dcwG9NLK3Ph8IoIo9Wf2vZWBB+SMI9FpgZxBWLEjwHbOWsHaEQMVsQfk38EWQP0Fr6VyMKlEQfpsRkuCpp1KxscaxK7g5BgXUlb0a2x0F+C9hEB0OVPsj4JN";
+        s[145] = "W9lKcLDqNGQAG/sKQNaRmeOUmLJ7GcMNqBaGZ659Rnjr6RTrfnmkp5Z9meALnwXoHjPjzSQDJnVYsY+xyMnuPgl6gMVAhAm+XprYVpsne4vt+7ojUqavVPBqLy5dtnhp1qfcnAiV5cZhHXX7NbxkUOzptjEGCQjnhSH4rPbZtgoIWE8Z6boF3l/thLnFX+AiiQ==";
+        s[146] = "iYLn5h9lIhD/x9moaPRnTX6mJEJKThg4WXxS7IrR2zblH26uOkINz0dJNTJVets0ZNYDnsnT7J2iI3Y6hTVWPGoYU49J3B2LhCREs0DZQ3C7080FtiOcfHbfBLNn0DyCK1LeAC7YB/bNdiyhLqH8fKl+0+KhiPDIUBJY2e7IbZR/9t0sxJbIXx6cRvI5AXex12o=";
+        s[147] = "SlRJEc7npTUvQq8SgBYKmVY/3wHYp2gsDxafN/JLUuEqEjmWMtW7fxASi+ePX4gmJJqLhD5t+AZxiCwYK3L3ceuJx4TiqVgJz8d6sc7fgWXluh1K+BcGPbZ7+Cq4Vsga7JEBVekviEZ5Ah4apNr8RkB7oMOUVPGxRcyyaVE4zBW+scA6c1yi/HQXddQ9rWyLUsVo";
+        s[148] = "AAlbGR6ekLOzx4hpqZTUqVUQ0FL2CFpgCMOp6CuuUzkSnWXpUjvOiSDkNPgoTPgpgmg3uYvMsX43mkPGUGC9awDThXyGQh6u3WfWtmhiPRqXnjFek+EPd0LYXps71non6C9m7nUlYNWzBJ1YzrzWjlB5LLPBN8bsZG6RbdZkYMxJ9J5ta/c30m8wDDNuTm0nEE0ZVQ==";
+        s[149] = "nWWbBhzObqwEFh/TiKREcsqLYbRjIcZflJpol16Mi4YDL6EZri22qRnTgrBtIY+HieTYWuLaCSk/B9WcYujoS6Jb5dyg3FQ6XF9bYaNQGx2w8DHgx0k2nqH/0U1sAU0kft32aD2orqCMIprbO1WJIt2auRnvcOTFoOax926nAkxvR3nrFVDevFjDbugpWHkGwic6G7o=";
+        s[150] = "WNk1Rn2qtG+gk0AEewrgo+aRbNrG4CgQpOR8Uo7c2m2XQY8MVDu4uRA6rzYGGdgqTcICKky9MvHeJeNWVAXOxmA4EdXQ2xItFJdQtxBt56cad9FBXXsz21yVsPr5d453abi7T3XfHVTToekiOlxAJs+bpat9cFRbIdHghO9wc/ucoArT53vpYsnyeVnmZG2PX48lXpNS";
+        s[151] = "wVmiO6mdf2aahrJlcmnBD0Qa58y8AvzXtJ54ImxgPLPn0NCQIrmUxzNZNTODE3WO6kZMECaT/REqT3PoOBp9stCHCFNXOM7979J44C1ZRU0yPCha00kQZBF5EmcLitVCz10tP8gG1fiIvMjwpd2ZTOaY4/g4NeJHLjJPll0c5nbH7n4v+1I+xG7/7k7G6N8sp21pbgpTYA==";
+        s[152] = "OoiVZosI+KG0EZTu+WpH7kKISxmO1zRYaSPMBMW0AyRiC2iZVEkOMiKn12XPqIDSW/kVA58cvv/ysTAzKLTu78Uo+sVcJe3AtLdgeA9vORFELTP4v9DQ/mAmehe3N8xk+VTLY6xHWi6f4j9cTDW/BDyJSDRY00oYoHlvnjgHo4CHBo0sMGgX3CwcnK2hpMFVtB/3qPl6v2w=";
+        s[153] = "97ZVsTYwD8VrgN1FOIRZ8jm8OMgrxG3o1aJoYtPVWXp9cjjlgXqTMZVsoWr3pr7pudw+LYo1Ejz3JpiUPHqWcZ2PWrWs7PR1akYGuwdCBHYvCGTcZYFe/yu1AB8w5zYsl1eJR45g0u1DlXfx5BUAUzc4yJDjc48Ls62bn8t0EJ7+30sWwifqKuz2EHpsqp1j/iMlwzKJGjGE";
+        s[154] = "0NSYKTvBKKInwL9PJ/pWUWVX4gjF3igsA2qqQMsRew0lI1LcCB18eGCYk0AnyUCe99w5lWHGFUMMeH6DZciAylWGeDn19JdzVOTevBWk3LIujI1GvsEB3oVqf2Zl9IZeDGCT4+bQKBWvgcXHjysZfnn/5z9Xz06qrPqac5LfS36fDcwnkrUYQWDsL2Ike32ALmOnkcDjNq1BoA==";
+        s[155] = "5ok+rYI4LCgGa2psGUN/fdkT2gQEToB9HRiFXQpe2YcQvEN2z7YlJCETx4jSWw06p5Y8tZcp08moKNYwUJ40DvPpGlDG+wUpFhC4kkfo6vj6TrCj5yoWJi5D+qdgH2T0JeWM80cYN0bsOsetdaqNhDONlYXZ2lVYkyVS/wzw8K5xX87EWktwOwFq/yYhuWCYJ9GZL7QuDipJjEE=";
+        s[156] = "KHzTalU9wPSnIjh5g0eHi1HUaFufxJpXpjDe0N3wEKINqbgzhbj3Kf4qWjb2d1A+0Mlu9tYF/kA9ONjda5jYfRgCHm5mUrjU0TAyT7EQFZ2u6WFK/sFHP++ycJQk8k7KLPUWA5OWScy1EO+dYF4d0r6K5O+7H/rpknxN6M9FlP8sH83DXK1Sd+UXL32D+4flF580FaZ5B3Tkx3dH";
+        s[157] = "RrJVxIKoDXtCviWMv/SXMO42Dn6UWOKDy2hh2ASXssT0e+G6m7F1230iJWlEN0wBR8p+BlTdBhQrn25098P3K16rBmZpzw/5dmesIJxhYPaM4GiaOgztFjuScTgkmV0Jl/vZ9eCXdEVNISeXkIixM4pssTFuUV7PY/Upzdj55rDKGLr1eT7AFVSNP30PhL8zZs8MANqKBeKBBDvtww==";
+        s[158] = "sy4t5rFA75GRBE+Dqa9sQxjPluKt/JnEY54guHnKqccmx3HGiyJ0jUA+et4XO8Xg69wCA9xVxJZQL73z80mVfIf43HIKOxgxT2IjG7EKMOD/qx6NnMTve4BryggLtbLQUeRfhriQeY7h65tD9ierhccXoXDpGnmBn9m2BQP78y+Qhc4eIsa3LcxbQJUIwvURjFp/rgMD7lhOLboa/2Y=";
+        s[159] = "Zs/BfFoWImYau2dZLb7JneeTQp7sQ06yonEq0Ya4BNOJGy/5dGH42ozt0PpP2IZ/S58X7esVgc6jA1y3Bcxj3MPoDjQJSZHFEtR3G31T8eF5OpPVC4dw9s9clllM05tvcemssLdcd85UP/xBaDrmpAl8ZDSc73zflK3nJw8e0HQFYntNnlZPFyyyBLHnLycb6Jlvq7F2OqrZR+FXZnL3";
+        s[160] = "hdeDJuRnmb8q9EYec8+futT/CvqhpqoUdtmG6E31RrYJDs96M5Wfng90IEqrncZe4rVYDocRZK23dvqtJaPhTUBXXh42IyMlUnro69KI+075FvYYwgVaUd10r7ExWM5Z7DCQ2x8Tm1meK2YCTPkF1VXXexl1UjYCnRQuQxppdophMwroJK8VqlJbFFslchTSBFuI7wgcdy+f/LHMbMsusQ==";
+        s[161] = "ClCCOv0mD9//LR0OisHfamxcTvmlwMLgAIQt3hbOjRPkXwEgaDzP0u6LN8BNwdOVw+LhrbzMI8zQzHvo7mGPkQICeeim/x+xmGPQtmWnXxCWiL1uf/8eR5Wuy9Er8skTB8rG4/ubb2ssvCkubObPAkMSOgFnX9UtxnCN4+nMNV2vvn4xMTSvvQyYWewfnlNkflTyva1epE9RVW2RqRtJikY=";
+        s[162] = "Fs+AmFCnUr/imw8D0GpNidIP9qwW8yRAzmtqPS+vT6n5U4YFQcpgbznrYO4TPqkVF2oz1mpgLYIgx/u2XsrtljGX46LfY8OyUPaw4/da38QGngoIlS2cN01cgN3efSjMlnZFo1x8T9p0Nn1IgRgevOd5ezVUL7WdY7eeiE1pXXcGBgDYn7NDQph0dC6HDlBiS95bDFcZ+6FYigE4WybpsOHL";
+        s[163] = "wgO4DdGZy9g13IuOhkJGJcToyLuCBVm9T/c8qY4NOheVU1NW2g8sPIo+RiEsSST8sx6+Jh/A/kaCxYvJ9CsgnBjZMMWRsd383HZAoJtkxwKvyoeXzzD+puFvqKQBEKrlBEwffXhLDoFQAW2ycYtBGztl0GsUtoOob2nv7ienx1xD6KNZNaxYx2ObRAYS/e8LS3pg5dku9MPBp1X12m8ZIXRAaw==";
+        s[164] = "EkXt02SaRUIjFmoLxyO6N+giL4iA4fY0Exao+mjgEfZ+Wv6w95GXHBI1xlYMVLkOcnu9nescvcXQH0OrqL9uforEUTGTSg2ci67m4GrwAryMy+5eUo77Q5GpWKfsg8nDbD8a3gUI/9EE0sCNp7tMaKwoJ56cxhbG3TJYpqWTpq3/S3q76x+3ETL+zxh6EMh8MJPfWcIxlDS7evKqdPgS00KgUtk=";
+        s[165] = "OuBqx5LFJroRbDn41+4azFHlKgw6bMgbsRGaK9UnPvi5xfmV4SLQ2YzIhopGi1F57L6vKukaW0XlFk/Ff5Td5IMC7U+kvXKlf8fGIIQ8FaHI0vbIX89OJlBqlICqftSNiVRxtaE+aCh0rBoDfgPwuC8qBC20I1O3ZLuKfeUVGkMOLEWeZLS6mmcn3cSERj9o/dEl8QYwQvhH+VG6YWF//yki1Vu8";
+        s[166] = "SO/vDsqZDdImOdH19sZI7FUVhlx1EI0XRr8ArTuAG5F8LDK76Bct2C7fXTUowilXnJWhQxvbGiulkUGSuVjVP12zac9bShRpr1L3ucde7n1f9y/NcHJCwdqTLq7RYygItQ4ppQGiP9jXf2Dn/qmVZZTh+SY3AZCIS+OVo2LAiYJHWnzzoX8Zt+dOYiOA/ZQKZieVJlc8ks+2xqYPD55eH0btZn5hzA==";
+        s[167] = "tZL/qACMO9SzmgJhWQMsbKgE5lPAEbxn3NR7504ilgArR8j7uv1KF46uQyjrkEnyBormYB/6nLGlHht62IQftMYf5gHpHFfTvukRKF8728yIYAAYHPQ/WjHzHdVSqUJqF2a8RE6SvvY+KSKWLMU3hjn1f6dqX599hYD7AnbPGTpFKDU5sLFOXbuynU1sPUhP+a4Hev9yNU6atLDo4CkX/Yq3FbpWVuQ=";
+        s[168] = "GRe7uF1wH5/71B3vmGF+pN3H9PKO1tLwsnb0D4/Pm7Pu5KAe4OfelkfFIBgyjuoZrpeEkGZnb+qf+Kn7Kt1hDwYr/Mb9ewuwOXsbIpLQMgfh0I5XsPrWocduVzn+u/cm3cr0Z11zsx0AZjTqvslACkDqiquY41JhtGdc22RCvIYom2l+zzMIMyCPsHeCSB1MBu8EWK3iP7SD3dWttwzMg0xanoPDgk0U";
+        s[169] = "8BDFu+29lptlGSjcZe7ghWaUgIzbuUpM5XDFbtJVQPEd3bAE0cGRlQE9EhKXi5J/IskYNrQ357tBhA+UNDNXCibT2AZGpzWAcwE6dP+14FuRL5Gxqh/teuPYKr5IIn7M3SbgOychZzLI7HGCvVhBUiJBu8orI3WmAIVcUhAsMGHsFveck/ZCXQA+Uq/WVnW1VNs6hSmIhsAFc51qsmsQK07z2Wptx4rRjw==";
+        s[170] = "siPSXD4u36WYtTvvDzRlFPiuZMnRczrL3eA15955JDCc6/V2Cvu6m/HPO6JxogxO0aYTZ5tejYDOIZgBy40DgUZMqPJ2IpYjsmUbjjJU8u/OpwhMon525m3v0EYlvyj2Qp3pwFKDkvncK3aNjN3KaaX6HuIy6kyqsDl0BTEnB5iJyHLRBCkeznTK019u48Yfsrz2oGuZcWzNj5/vKMdxQPiyJ9EHyox8Ark=";
+        s[171] = "+/14PnFQVZ7BTHKUvkTtRrYS7WnPND5gZ5byMhUrDLkJa6UPBV7z0nrDMifEo/dQfUq3EjCiG6xGVhrUvAzgxqOQZTW1Y9p9M0KWW+E0XvCQppHFpuMqF1vYsF0OD6AMiE9JtGnWs3JcaWP/XBF/CvhQlFGbHi3fbrD/haTEBnmpJWBgMdKribdbXHtBSFZ2MzCX2eDtxoDdRdEVGs4v/q8gVBS+WsnZ3TTF";
+        s[172] = "31I1ja+B+aopKkztGzJYvJEWAshyoAAV5yve4LnP0kdImUQaVETSuo5CDIYr7zM8MCD1eYPpLicmGnA+C927o9QGAVL3ctO/DCWhNinW7NmeYIM+o4diKBkDPjHmSWa+nq4nr+gOap4CtwL2wW2B5Yqt26pKgN9uAU5CmTL26hYFgMEOZfrkQ7XdYGy2CN8RJLmjeSFVVNBG/FTaK7tpuy0LQSkko6wczBYGeg==";
+        s[173] = "XbRfDqGe3eeI1tHx8UnPneDB57N8VeSSzXzVCNSgxOEfd6d/un5CDxHG+m4w3tIbtSky4R2+zMF+S5cRvTOwZ/veegYtLKTxA0mVedWLFkfh/v4NgPJ+NEU+cylbSSZLAeBofDvoJwnYKujN2KFa8PGAxr3Y8ry3qdkS8Ob1ZiHYAmLvKS9sGb/vjTvRy+a4Q7kOepsm7PYisinKelBAvDnjli6/lOutGrenjX4=";
+        s[174] = "jGEj/AaBefac9uOcmGuO9nH+N+zMsC4qAe6ZUEMMIXdTGnSWl7Xt0/nKqyOj3ZH249HwkJ8bn5C+0bzOpQ1eA3PxEq6RfKMrjHJPJmTZXrSESTjfj3oNLU/CqqDOqd8znTgN6nvnUdCeStLMh9bmWF1+0G11nDwg6GQWWQ0zjVDTq5j7ocXcFOyUcu0cyl5YDcUP0i2mA2JullInU2uBte7nToeSGB3FJxKueBbv";
+        s[175] = "RAzNCxlP2S/8LfbGtlSDShox8cSgmJMOc2xPFs8egZVJiwlmnS3aBWKPRbbxkZiVVYlu4GNJNwbocc6dgrl28HXAsYikE5wwoQ1MeOJWU3zzFiYENh7SLBQfjVPQHucctr8P6Rl7YL5wHc+aC+m92R3bnzm5rp1PeHm7uzy2iUUN0cgfbwJ4FrpXhVMTsAUpTbg1+037EWcGOuxir4dG2xBfgOwa+ejFHkw7y0LWRw==";
+        s[176] = "08hmZptBGKKqR6Qz9GNc2Wk1etgU/KogbiPQmAh5IXlTBc97DuEToL4Bb889nfObVQ/WelmiCS8wEjSBdmnlkkU7/b5UT3P4k1pB6ZxPH9Qldj5aazkA/yCb0kzDfJlcdFOh1eAcu5LvwTXOizmPwsDvJEnOkaDZrKESZshsHU2A6Mx6awk9/orf6iBlJHQIIH3l4o3b1gx2TNb/hUgdAlwtQDhvKO3skB0PS+rcWAw=";
+        s[177] = "0GhrgbSSHPLWtyS2mnSxrNAj/dyrFQcxIgPjT7+78SZ1ZTGc03vsmlZ4Z/bOO84E9yKblaI5dSHVXrx57L0kikL8tgKCsAkUNO3l/4zv5FfCrRTgGx4sFTFB1NNcLcwagkvFzde764DjYmj4YZhYsXSZCVKi0uu5M8fpgGDZ9UMSFR008cbhaIoFLWSANqiNJYSvTQZhGWfLtIPGLN+gIOMcaKhx1b5vg6OYSz6ScAM/";
+        s[178] = "2VGiMV/f2hNZAjw3fdeHx/wRIVzeP018lZynzwSySG/zQBxyRmi3YmKVZmh3aJunuiqmvdt0kJ6lX7M8BajYHPCBkqJOx8oPJ/K1oADxVgnavZ69dKYrSy9/Pm6sHxjFrdSz9TelUK9sgoFTWS6GxgzWEqXRBDDpGUnsNbSEcWLPKVLNNoYAcltY98JZaNSZBXcpa9FeSN7sVU43q2IEcDx3ZkJzRJpl/lb7n+ivMwX/OQ==";
+        s[179] = "iMSCh1m5vct3C7LEn5wKRYtalzvG6pKahG19rTb6Z9q7+buDsML5yM6NqDvoVxt3Dv7KRwdS3xG/Pyb7bJGvQ2a4FhRnTa4HvPvl3cpJdMgCCvsXeXXoML4pHzFlpP0bNsMoupmhQ0khAW51PAr4B165u1y5ULpruxE+dGx/HJUQyMfGhOSZ5jDKKxD5TNYQkDEY28Xqln6Fj8duzQLzMIgSoD8KGZKD8jm6/f8Vwvf43NE=";
+        s[180] = "hN4+x/sK9FRZn5llaw7/XDGwht3BcIxAFP4JoGqVQCw8c5IOlSqKEOViYss1mnvko6kVrc2iMEA8h8RssJ4dJBpFDZ/bkehCyhQmWpspZtAvRN59mj6nx0SBglYGccPyrn3e0uvvGJ5nYmjTA7gqB0Y+FFGAYwgAO345ipxTrMFsnJ8a913GzpobJdcHiw5hfqYK2iqo8STzVljaGMc5WSzP69vFDTHSS39YSfbE890TPBgm";
     }
 
-    /**
-     * Tests to make sure Base64's implementation of the org.apache.commons.codec.Encoder
-     * interface is behaving identical to commons-codec-1.3.jar.
-     *
-     * @throws EncoderException problem
-     */
-    @Test
-    public void testEncoder() throws EncoderException {
-        final Encoder enc = new Base64();
-        for (int i = 0; i < STRINGS.length; i++) {
-            if (STRINGS[i] != null) {
-                final byte[] base64 = utf8(STRINGS[i]);
-                final byte[] binary = BYTES[i];
-                assertArrayEquals(base64, (byte[]) enc.encode(binary), "Encoder test-" + i);
-            }
-        }
+    private static byte[] utf8(final String s) {
+
+        // We would use commons-codec-1.4.jar own utility method for this, but we
+        // need this class to be able to run against commons-codec-1.3.jar, hence the
+        // duplication here.
+
+        return s != null ? s.getBytes(StandardCharsets.UTF_8) : null;
     }
 
     /**
-     * Tests to make sure Base64's implementation of the org.apache.commons.codec.Decoder
+     * Tests to make sure Base64's implementation of the org.apache.commons.codec.BinaryDecoder
      * interface is behaving identical to commons-codec-1.3.jar.
      *
      * @throws DecoderException problem
      */
     @Test
-    public void testDecoder() throws DecoderException {
-        final Decoder dec = new Base64();
+    public void testBinaryDecoder() throws DecoderException {
+        final BinaryDecoder dec = new Base64();
         for (int i = 0; i < STRINGS.length; i++) {
             if (STRINGS[i] != null) {
                 final byte[] base64 = utf8(STRINGS[i]);
                 final byte[] binary = BYTES[i];
-                assertArrayEquals(binary, (byte[]) dec.decode(base64), "Decoder test-" + i);
+                assertArrayEquals(binary, dec.decode(base64), "BinaryDecoder test-" + i);
             }
         }
     }
@@ -407,35 +398,37 @@ public class Base64Codec13Test {
     }
 
     /**
-     * Tests to make sure Base64's implementation of the org.apache.commons.codec.BinaryDecoder
+     * Tests to make sure Base64's implementation of the org.apache.commons.codec.Decoder
      * interface is behaving identical to commons-codec-1.3.jar.
      *
      * @throws DecoderException problem
      */
     @Test
-    public void testBinaryDecoder() throws DecoderException {
-        final BinaryDecoder dec = new Base64();
+    public void testDecoder() throws DecoderException {
+        final Decoder dec = new Base64();
         for (int i = 0; i < STRINGS.length; i++) {
             if (STRINGS[i] != null) {
                 final byte[] base64 = utf8(STRINGS[i]);
                 final byte[] binary = BYTES[i];
-                assertArrayEquals(binary, dec.decode(base64), "BinaryDecoder test-" + i);
+                assertArrayEquals(binary, (byte[]) dec.decode(base64), "Decoder test-" + i);
             }
         }
     }
 
     /**
-     * Tests to make sure Base64's implementation of Base64.encodeBase64()
-     * static method is behaving identical to commons-codec-1.3.jar.
+     * Tests to make sure Base64's implementation of the org.apache.commons.codec.Encoder
+     * interface is behaving identical to commons-codec-1.3.jar.
+     *
+     * @throws EncoderException problem
      */
     @Test
-    public void testStaticEncode() {
+    public void testEncoder() throws EncoderException {
+        final Encoder enc = new Base64();
         for (int i = 0; i < STRINGS.length; i++) {
             if (STRINGS[i] != null) {
                 final byte[] base64 = utf8(STRINGS[i]);
                 final byte[] binary = BYTES[i];
-                assertArrayEquals(base64, Base64.encodeBase64(binary),
-                        "static Base64.encodeBase64() test-" + i);
+                assertArrayEquals(base64, (byte[]) enc.encode(binary), "Encoder test-" + i);
             }
         }
     }
@@ -457,45 +450,52 @@ public class Base64Codec13Test {
     }
 
     /**
-     * Tests to make sure Base64's implementation of Base64.encodeBase64Chunked()
-     * static method is behaving identical to commons-codec-1.3.jar.
+     * Tests to make sure Base64's implementation of Base64.decodeBase64()
+     * static method is behaving identical to commons-codec-1.3.jar when
+     * supplied with chunked input.
      */
     @Test
-    public void testStaticEncodeChunked() {
+    public void testStaticDecodeChunked() {
         for (int i = 0; i < STRINGS.length; i++) {
             if (STRINGS[i] != null) {
                 final byte[] base64Chunked = utf8(CHUNKED_STRINGS[i]);
                 final byte[] binary = BYTES[i];
-                assertArrayEquals(base64Chunked, Base64.encodeBase64Chunked(binary),
-                        "static Base64.encodeBase64Chunked() test-" + i);
+                assertArrayEquals(binary, Base64.decodeBase64(base64Chunked),
+                        "static Base64.decodeBase64Chunked() test-" + i);
             }
         }
     }
 
     /**
-     * Tests to make sure Base64's implementation of Base64.decodeBase64()
-     * static method is behaving identical to commons-codec-1.3.jar when
-     * supplied with chunked input.
+     * Tests to make sure Base64's implementation of Base64.encodeBase64()
+     * static method is behaving identical to commons-codec-1.3.jar.
      */
     @Test
-    public void testStaticDecodeChunked() {
+    public void testStaticEncode() {
         for (int i = 0; i < STRINGS.length; i++) {
             if (STRINGS[i] != null) {
-                final byte[] base64Chunked = utf8(CHUNKED_STRINGS[i]);
+                final byte[] base64 = utf8(STRINGS[i]);
                 final byte[] binary = BYTES[i];
-                assertArrayEquals(binary, Base64.decodeBase64(base64Chunked),
-                        "static Base64.decodeBase64Chunked() test-" + i);
+                assertArrayEquals(base64, Base64.encodeBase64(binary),
+                        "static Base64.encodeBase64() test-" + i);
             }
         }
     }
 
 
-    private static byte[] utf8(final String s) {
-
-        // We would use commons-codec-1.4.jar own utility method for this, but we
-        // need this class to be able to run against commons-codec-1.3.jar, hence the
-        // duplication here.
-
-        return s != null ? s.getBytes(StandardCharsets.UTF_8) : null;
+    /**
+     * Tests to make sure Base64's implementation of Base64.encodeBase64Chunked()
+     * static method is behaving identical to commons-codec-1.3.jar.
+     */
+    @Test
+    public void testStaticEncodeChunked() {
+        for (int i = 0; i < STRINGS.length; i++) {
+            if (STRINGS[i] != null) {
+                final byte[] base64Chunked = utf8(CHUNKED_STRINGS[i]);
+                final byte[] binary = BYTES[i];
+                assertArrayEquals(base64Chunked, Base64.encodeBase64Chunked(binary),
+                        "static Base64.encodeBase64Chunked() test-" + i);
+            }
+        }
     }
 }
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 422be5bb..4e45ad9a 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base64InputStreamTest.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base64InputStreamTest.java
@@ -50,105 +50,6 @@ public class Base64InputStreamTest {
 
     private static final String STRING_FIXTURE = "Hello World";
 
-    /**
-     * Tests the problem reported in CODEC-130. Missing / wrong implementation of skip.
-     */
-    @Test
-    public void testCodec130() throws IOException {
-        final ByteArrayOutputStream bos = new ByteArrayOutputStream();
-        try (final Base64OutputStream base64os = new Base64OutputStream(bos)) {
-            base64os.write(StringUtils.getBytesUtf8(STRING_FIXTURE));
-        }
-
-        final ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
-        final Base64InputStream ins = new Base64InputStream(bis);
-
-        // we skip the first character read from the reader
-        ins.skip(1);
-        final byte[] decodedBytes = BaseNTestData.streamToBytes(ins, new byte[64]);
-        final String str = StringUtils.newStringUtf8(decodedBytes);
-
-        assertEquals(STRING_FIXTURE.substring(1), str);
-    }
-
-    /**
-     * Tests the bug reported in CODEC-105. Bad interactions with InputStream when reading one byte at a time.
-     */
-    @Test
-    public void testCodec105() throws IOException {
-        try (final Base64InputStream in = new Base64InputStream(new Codec105ErrorInputStream(), true, 0, null)) {
-            for (int i = 0; i < 5; i++) {
-                in.read();
-            }
-        }
-    }
-
-    /**
-     * Test for the CODEC-101 bug: InputStream.read(byte[]) should never return 0 because Java's builtin InputStreamReader hates that.
-     *
-     * @throws Exception
-     *             for some failure scenarios.
-     */
-    @Test
-    public void testCodec101() throws Exception {
-        final byte[] codec101 = StringUtils.getBytesUtf8(Base64TestData.CODEC_101_INPUT_LENGTH_IS_MULTIPLE_OF_3);
-        final ByteArrayInputStream bais = new ByteArrayInputStream(codec101);
-        try (final Base64InputStream in = new Base64InputStream(bais)) {
-            final byte[] result = new byte[8192];
-            int c = in.read(result);
-            assertTrue(c > 0, "Codec101: First read successful [c=" + c + "]");
-
-            c = in.read(result);
-            assertTrue(c < 0, "Codec101: Second read should report end-of-stream [c=" + c + "]");
-        }
-    }
-
-    /**
-     * Another test for the CODEC-101 bug: In commons-codec-1.4 this test shows InputStreamReader explicitly hating an
-     * InputStream.read(byte[]) return of 0:
-     *
-     * java.io.IOException: Underlying input stream returned zero bytes at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:268) at
-     * sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306) at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158) at
-     * java.io.InputStreamReader.read(InputStreamReader.java:167) at java.io.BufferedReader.fill(BufferedReader.java:136) at
-     * java.io.BufferedReader.readLine(BufferedReader.java:299) at java.io.BufferedReader.readLine(BufferedReader.java:362) at
-     * org.apache.commons.codec.binary.Base64InputStreamTest.testInputStreamReader(Base64InputStreamTest.java:75)
-     *
-     * But in commons-codec-1.5 it's fixed. :-)
-     *
-     * @throws Exception
-     *             for some failure scenarios.
-     */
-    @Test
-    public void testInputStreamReader() throws Exception {
-        final byte[] codec101 = StringUtils.getBytesUtf8(Base64TestData.CODEC_101_INPUT_LENGTH_IS_MULTIPLE_OF_3);
-        final ByteArrayInputStream bais = new ByteArrayInputStream(codec101);
-        final Base64InputStream in = new Base64InputStream(bais);
-        final InputStreamReader isr = new InputStreamReader(in);
-        try (final BufferedReader br = new BufferedReader(isr)) {
-            final String line = br.readLine();
-            assertNotNull(line, "Codec101:  InputStreamReader works!");
-        }
-    }
-
-    /**
-     * Test the Base64InputStream implementation against the special NPE inducing input identified in the CODEC-98 bug.
-     *
-     * @throws Exception
-     *             for some failure scenarios.
-     */
-    @Test
-    public void testCodec98NPE() throws Exception {
-        final byte[] codec98 = StringUtils.getBytesUtf8(Base64TestData.CODEC_98_NPE);
-        final ByteArrayInputStream data = new ByteArrayInputStream(codec98);
-        final Base64InputStream stream = new Base64InputStream(data);
-
-        // This line causes an NPE in commons-codec-1.4.jar:
-        final byte[] decodedBytes = BaseNTestData.streamToBytes(stream, new byte[1024]);
-
-        final String decoded = StringUtils.newStringUtf8(decodedBytes);
-        assertEquals(Base64TestData.CODEC_98_NPE_DECODED, decoded, "codec-98 NPE Base64InputStream");
-    }
-
     /**
      * Tests skipping past the end of a stream.
      *
@@ -169,6 +70,13 @@ public class Base64InputStreamTest {
         }
     }
 
+    private void testBase64EmptyInputStream(final int chuckSize) throws Exception {
+        final byte[] emptyEncoded = {};
+        final byte[] emptyDecoded = {};
+        testByteByByte(emptyEncoded, emptyDecoded, chuckSize, CRLF);
+        testByChunk(emptyEncoded, emptyDecoded, chuckSize, CRLF);
+    }
+
     /**
      * Tests the Base64InputStream implementation against empty input.
      *
@@ -191,13 +99,6 @@ public class Base64InputStreamTest {
         testBase64EmptyInputStream(BaseNCodec.PEM_CHUNK_SIZE);
     }
 
-    private void testBase64EmptyInputStream(final int chuckSize) throws Exception {
-        final byte[] emptyEncoded = {};
-        final byte[] emptyDecoded = {};
-        testByteByByte(emptyEncoded, emptyDecoded, chuckSize, CRLF);
-        testByChunk(emptyEncoded, emptyDecoded, chuckSize, CRLF);
-    }
-
     /**
      * Tests the Base64InputStream implementation.
      *
@@ -388,6 +289,105 @@ public class Base64InputStreamTest {
         in.close();
     }
 
+    /**
+     * Test for the CODEC-101 bug: InputStream.read(byte[]) should never return 0 because Java's builtin InputStreamReader hates that.
+     *
+     * @throws Exception
+     *             for some failure scenarios.
+     */
+    @Test
+    public void testCodec101() throws Exception {
+        final byte[] codec101 = StringUtils.getBytesUtf8(Base64TestData.CODEC_101_INPUT_LENGTH_IS_MULTIPLE_OF_3);
+        final ByteArrayInputStream bais = new ByteArrayInputStream(codec101);
+        try (final Base64InputStream in = new Base64InputStream(bais)) {
+            final byte[] result = new byte[8192];
+            int c = in.read(result);
+            assertTrue(c > 0, "Codec101: First read successful [c=" + c + "]");
+
+            c = in.read(result);
+            assertTrue(c < 0, "Codec101: Second read should report end-of-stream [c=" + c + "]");
+        }
+    }
+
+    /**
+     * Tests the bug reported in CODEC-105. Bad interactions with InputStream when reading one byte at a time.
+     */
+    @Test
+    public void testCodec105() throws IOException {
+        try (final Base64InputStream in = new Base64InputStream(new Codec105ErrorInputStream(), true, 0, null)) {
+            for (int i = 0; i < 5; i++) {
+                in.read();
+            }
+        }
+    }
+
+    /**
+     * Tests the problem reported in CODEC-130. Missing / wrong implementation of skip.
+     */
+    @Test
+    public void testCodec130() throws IOException {
+        final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        try (final Base64OutputStream base64os = new Base64OutputStream(bos)) {
+            base64os.write(StringUtils.getBytesUtf8(STRING_FIXTURE));
+        }
+
+        final ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
+        final Base64InputStream ins = new Base64InputStream(bis);
+
+        // we skip the first character read from the reader
+        ins.skip(1);
+        final byte[] decodedBytes = BaseNTestData.streamToBytes(ins, new byte[64]);
+        final String str = StringUtils.newStringUtf8(decodedBytes);
+
+        assertEquals(STRING_FIXTURE.substring(1), str);
+    }
+
+    /**
+     * Test the Base64InputStream implementation against the special NPE inducing input identified in the CODEC-98 bug.
+     *
+     * @throws Exception
+     *             for some failure scenarios.
+     */
+    @Test
+    public void testCodec98NPE() throws Exception {
+        final byte[] codec98 = StringUtils.getBytesUtf8(Base64TestData.CODEC_98_NPE);
+        final ByteArrayInputStream data = new ByteArrayInputStream(codec98);
+        final Base64InputStream stream = new Base64InputStream(data);
+
+        // This line causes an NPE in commons-codec-1.4.jar:
+        final byte[] decodedBytes = BaseNTestData.streamToBytes(stream, new byte[1024]);
+
+        final String decoded = StringUtils.newStringUtf8(decodedBytes);
+        assertEquals(Base64TestData.CODEC_98_NPE_DECODED, decoded, "codec-98 NPE Base64InputStream");
+    }
+
+    /**
+     * Another test for the CODEC-101 bug: In commons-codec-1.4 this test shows InputStreamReader explicitly hating an
+     * InputStream.read(byte[]) return of 0:
+     *
+     * java.io.IOException: Underlying input stream returned zero bytes at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:268) at
+     * sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306) at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158) at
+     * java.io.InputStreamReader.read(InputStreamReader.java:167) at java.io.BufferedReader.fill(BufferedReader.java:136) at
+     * java.io.BufferedReader.readLine(BufferedReader.java:299) at java.io.BufferedReader.readLine(BufferedReader.java:362) at
+     * org.apache.commons.codec.binary.Base64InputStreamTest.testInputStreamReader(Base64InputStreamTest.java:75)
+     *
+     * But in commons-codec-1.5 it's fixed. :-)
+     *
+     * @throws Exception
+     *             for some failure scenarios.
+     */
+    @Test
+    public void testInputStreamReader() throws Exception {
+        final byte[] codec101 = StringUtils.getBytesUtf8(Base64TestData.CODEC_101_INPUT_LENGTH_IS_MULTIPLE_OF_3);
+        final ByteArrayInputStream bais = new ByteArrayInputStream(codec101);
+        final Base64InputStream in = new Base64InputStream(bais);
+        final InputStreamReader isr = new InputStreamReader(in);
+        try (final BufferedReader br = new BufferedReader(isr)) {
+            final String line = br.readLine();
+            assertNotNull(line, "Codec101:  InputStreamReader works!");
+        }
+    }
+
     /**
      * Tests markSupported.
      *
@@ -404,6 +404,24 @@ public class Base64InputStreamTest {
         }
     }
 
+    /**
+     * Tests read returning 0
+     *
+     * @throws Exception
+     *             for some failure scenarios.
+     */
+    @Test
+    public void testRead0() throws Exception {
+        final byte[] decoded = StringUtils.getBytesUtf8(STRING_FIXTURE);
+        final byte[] buf = new byte[1024];
+        int bytesRead = 0;
+        final ByteArrayInputStream bin = new ByteArrayInputStream(decoded);
+        try (final Base64InputStream in = new Base64InputStream(bin, true, 4, new byte[] { 0, 0, 0 })) {
+            bytesRead = in.read(buf, 0, 0);
+            assertEquals(0, bytesRead, "Base64InputStream.read(buf, 0, 0) returns 0");
+        }
+    }
+
     /**
      * Tests read using different buffer sizes
      *
@@ -428,24 +446,6 @@ public class Base64InputStreamTest {
         assertArrayEquals(decoded, out.toByteArray());
     }
 
-    /**
-     * Tests read returning 0
-     *
-     * @throws Exception
-     *             for some failure scenarios.
-     */
-    @Test
-    public void testRead0() throws Exception {
-        final byte[] decoded = StringUtils.getBytesUtf8(STRING_FIXTURE);
-        final byte[] buf = new byte[1024];
-        int bytesRead = 0;
-        final ByteArrayInputStream bin = new ByteArrayInputStream(decoded);
-        try (final Base64InputStream in = new Base64InputStream(bin, true, 4, new byte[] { 0, 0, 0 })) {
-            bytesRead = in.read(buf, 0, 0);
-            assertEquals(0, bytesRead, "Base64InputStream.read(buf, 0, 0) returns 0");
-        }
-    }
-
     /**
      * Tests read with null.
      *
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 4c1d229f..0758bb6d 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base64OutputStreamTest.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base64OutputStreamTest.java
@@ -40,25 +40,11 @@ public class Base64OutputStreamTest {
 
     private static final String STRING_FIXTURE = "Hello World";
 
-    /**
-     * Test the Base64OutputStream implementation against the special NPE inducing input
-     * identified in the CODEC-98 bug.
-     *
-     * @throws Exception for some failure scenarios.
-     */
-    @Test
-    public void testCodec98NPE() throws Exception {
-        final byte[] codec98 = StringUtils.getBytesUtf8(Base64TestData.CODEC_98_NPE);
-        final byte[] codec98_1024 = new byte[1024];
-        System.arraycopy(codec98, 0, codec98_1024, 0, codec98.length);
-        final ByteArrayOutputStream data = new ByteArrayOutputStream(1024);
-        try (final Base64OutputStream stream = new Base64OutputStream(data, false)) {
-            stream.write(codec98_1024, 0, 1024);
-        }
-
-        final byte[] decodedBytes = data.toByteArray();
-        final String decoded = StringUtils.newStringUtf8(decodedBytes);
-        assertEquals(Base64TestData.CODEC_98_NPE_DECODED, decoded, "codec-98 NPE Base64OutputStream");
+    private void testBase64EmptyOutputStream(final int chunkSize) throws Exception {
+        final byte[] emptyEncoded = {};
+        final byte[] emptyDecoded = {};
+        testByteByByte(emptyEncoded, emptyDecoded, chunkSize, CR_LF);
+        testByChunk(emptyEncoded, emptyDecoded, chunkSize, CR_LF);
     }
 
 
@@ -84,13 +70,6 @@ public class Base64OutputStreamTest {
         testBase64EmptyOutputStream(BaseNCodec.PEM_CHUNK_SIZE);
     }
 
-    private void testBase64EmptyOutputStream(final int chunkSize) throws Exception {
-        final byte[] emptyEncoded = {};
-        final byte[] emptyDecoded = {};
-        testByteByByte(emptyEncoded, emptyDecoded, chunkSize, CR_LF);
-        testByChunk(emptyEncoded, emptyDecoded, chunkSize, CR_LF);
-    }
-
     /**
      * Test the Base64OutputStream implementation
      *
@@ -287,35 +266,24 @@ public class Base64OutputStreamTest {
     }
 
     /**
-     * Tests Base64OutputStream.write for expected IndexOutOfBoundsException conditions.
+     * Test the Base64OutputStream implementation against the special NPE inducing input
+     * identified in the CODEC-98 bug.
      *
-     * @throws Exception
-     *             for some failure scenarios.
+     * @throws Exception for some failure scenarios.
      */
     @Test
-    public void testWriteOutOfBounds() throws Exception {
-        final byte[] buf = new byte[1024];
-        final ByteArrayOutputStream bout = new ByteArrayOutputStream();
-        try (final Base64OutputStream out = new Base64OutputStream(bout)) {
-            assertThrows(IndexOutOfBoundsException.class, () -> out.write(buf, -1, 1), "Base64OutputStream.write(buf, -1, 1)");
-            assertThrows(IndexOutOfBoundsException.class, () -> out.write(buf, 1, -1), "Base64OutputStream.write(buf, 1, -1)");
-            assertThrows(IndexOutOfBoundsException.class, () -> out.write(buf, buf.length + 1, 0), "Base64OutputStream.write(buf, buf.length + 1, 0)");
-            assertThrows(IndexOutOfBoundsException.class, () -> out.write(buf, buf.length - 1, 2), "Base64OutputStream.write(buf, buf.length - 1, 2)");
+    public void testCodec98NPE() throws Exception {
+        final byte[] codec98 = StringUtils.getBytesUtf8(Base64TestData.CODEC_98_NPE);
+        final byte[] codec98_1024 = new byte[1024];
+        System.arraycopy(codec98, 0, codec98_1024, 0, codec98.length);
+        final ByteArrayOutputStream data = new ByteArrayOutputStream(1024);
+        try (final Base64OutputStream stream = new Base64OutputStream(data, false)) {
+            stream.write(codec98_1024, 0, 1024);
         }
-    }
 
-    /**
-     * Tests Base64OutputStream.write(null).
-     *
-     * @throws Exception
-     *             for some failure scenarios.
-     */
-    @Test
-    public void testWriteToNullCoverage() throws Exception {
-        final ByteArrayOutputStream bout = new ByteArrayOutputStream();
-        try (final Base64OutputStream out = new Base64OutputStream(bout)) {
-            assertThrows(NullPointerException.class, () -> out.write(null, 0, 0));
-        }
+        final byte[] decodedBytes = data.toByteArray();
+        final String decoded = StringUtils.newStringUtf8(decodedBytes);
+        assertEquals(Base64TestData.CODEC_98_NPE_DECODED, decoded, "codec-98 NPE Base64OutputStream");
     }
 
     /**
@@ -347,4 +315,36 @@ public class Base64OutputStreamTest {
             });
         }
     }
+
+    /**
+     * Tests Base64OutputStream.write for expected IndexOutOfBoundsException conditions.
+     *
+     * @throws Exception
+     *             for some failure scenarios.
+     */
+    @Test
+    public void testWriteOutOfBounds() throws Exception {
+        final byte[] buf = new byte[1024];
+        final ByteArrayOutputStream bout = new ByteArrayOutputStream();
+        try (final Base64OutputStream out = new Base64OutputStream(bout)) {
+            assertThrows(IndexOutOfBoundsException.class, () -> out.write(buf, -1, 1), "Base64OutputStream.write(buf, -1, 1)");
+            assertThrows(IndexOutOfBoundsException.class, () -> out.write(buf, 1, -1), "Base64OutputStream.write(buf, 1, -1)");
+            assertThrows(IndexOutOfBoundsException.class, () -> out.write(buf, buf.length + 1, 0), "Base64OutputStream.write(buf, buf.length + 1, 0)");
+            assertThrows(IndexOutOfBoundsException.class, () -> out.write(buf, buf.length - 1, 2), "Base64OutputStream.write(buf, buf.length - 1, 2)");
+        }
+    }
+
+    /**
+     * Tests Base64OutputStream.write(null).
+     *
+     * @throws Exception
+     *             for some failure scenarios.
+     */
+    @Test
+    public void testWriteToNullCoverage() throws Exception {
+        final ByteArrayOutputStream bout = new ByteArrayOutputStream();
+        try (final Base64OutputStream out = new Base64OutputStream(bout)) {
+            assertThrows(NullPointerException.class, () -> out.write(null, 0, 0));
+        }
+    }
 }
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 151bfef1..5855911f 100644
--- a/src/test/java/org/apache/commons/codec/binary/Base64Test.java
+++ b/src/test/java/org/apache/commons/codec/binary/Base64Test.java
@@ -72,6 +72,60 @@ public class Base64Test {
             '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
     };
 
+    /**
+     * Test base 64 decoding of the final trailing bits. Trailing encoded bytes
+     * cannot fit exactly into 6-bit characters so the last character has a limited
+     * alphabet where the final bits are zero. This asserts that illegal final
+     * characters throw an exception when decoding.
+     *
+     * @param nbits the number of trailing bits (must be a factor of 6 and {@code <24})
+     */
+    private static void assertBase64DecodingOfTrailingBits(final int nbits) {
+        final Base64 codec = new Base64(0, null, false, CodecPolicy.STRICT);
+        // Requires strict decoding
+        assertTrue(codec.isStrictDecoding());
+        assertEquals(CodecPolicy.STRICT, codec.getCodecPolicy());
+        // A lenient decoder should not re-encode to the same bytes
+        final Base64 defaultCodec = new Base64();
+        assertFalse(defaultCodec.isStrictDecoding());
+        assertEquals(CodecPolicy.LENIENT, defaultCodec.getCodecPolicy());
+
+        // Create the encoded bytes. The first characters must be valid so fill with 'zero'
+        // then pad to the block size.
+        final int length = nbits / 6;
+        final byte[] encoded = new byte[4];
+        Arrays.fill(encoded, 0, length, STANDARD_ENCODE_TABLE[0]);
+        Arrays.fill(encoded, length, encoded.length, (byte) '=');
+        // Compute how many bits would be discarded from 8-bit bytes
+        final int discard = nbits % 8;
+        final int emptyBitsMask = (1 << discard) - 1;
+        // Special case when an impossible number of trailing characters
+        final boolean invalid = length == 1;
+        // Enumerate all 64 possible final characters in the last position
+        final int last = length - 1;
+        for (int i = 0; i < 64; i++) {
+            encoded[last] = STANDARD_ENCODE_TABLE[i];
+            // If the lower bits are set we expect an exception. This is not a valid
+            // final character.
+            if (invalid || (i & emptyBitsMask) != 0) {
+                assertThrows(IllegalArgumentException.class, () -> codec.decode(encoded),
+                        "Final base-64 digit should not be allowed");
+                // The default lenient mode should decode this
+                final byte[] decoded = defaultCodec.decode(encoded);
+                // Re-encoding should not match the original array as it was invalid
+                assertFalse(Arrays.equals(encoded, defaultCodec.encode(decoded)));
+            } else {
+                // Otherwise this should decode
+                final byte[] decoded = codec.decode(encoded);
+                // Compute the bits that were encoded. This should match the final decoded byte.
+                final int bitsEncoded = i >> discard;
+                assertEquals(bitsEncoded, decoded[decoded.length - 1], "Invalid decoding of last character");
+                // Re-encoding should match the original array (requires the same padding character)
+                assertArrayEquals(encoded, codec.encode(decoded));
+            }
+        }
+    }
+
     private final Random random = new Random();
 
     /**
@@ -81,24 +135,6 @@ public class Base64Test {
         return this.random;
     }
 
-    /**
-     * Test the isStringBase64 method.
-     */
-    @Test
-    public void testIsStringBase64() {
-        final String nullString = null;
-        final String emptyString = "";
-        final String validString = "abc===defg\n\r123456\r789\r\rABC\n\nDEF==GHI\r\nJKL==============";
-        final String invalidString = validString + (char) 0; // append null character
-
-        assertThrows(NullPointerException.class, () -> Base64.isBase64(nullString),
-                "Base64.isStringBase64() should not be null-safe.");
-
-        assertTrue(Base64.isBase64(emptyString), "Base64.isStringBase64(empty-string) is true");
-        assertTrue(Base64.isBase64(validString), "Base64.isStringBase64(valid-string) is true");
-        assertFalse(Base64.isBase64(invalidString), "Base64.isStringBase64(invalid-string) is false");
-    }
-
     /**
      * Test the Base64 implementation
      */
@@ -131,19 +167,42 @@ public class Base64Test {
         assertEquals("Hello World", decodeString, "decode hello world");
     }
 
+    @Test
+    public void testBase64AtBufferEnd() {
+        testBase64InBuffer(100, 0);
+    }
+
+    @Test
+    public void testBase64AtBufferMiddle() {
+        testBase64InBuffer(100, 100);
+    }
+
     @Test
     public void testBase64AtBufferStart() {
         testBase64InBuffer(0, 100);
     }
 
     @Test
-    public void testBase64AtBufferEnd() {
-        testBase64InBuffer(100, 0);
+    public void testBase64DecodingOfTrailing12Bits() {
+        assertBase64DecodingOfTrailingBits(12);
     }
 
     @Test
-    public void testBase64AtBufferMiddle() {
-        testBase64InBuffer(100, 100);
+    public void testBase64DecodingOfTrailing18Bits() {
+        assertBase64DecodingOfTrailingBits(18);
+    }
+
+    @Test
+    public void testBase64DecodingOfTrailing6Bits() {
+        assertBase64DecodingOfTrailingBits(6);
+    }
+
+    @Test
+    public void testBase64ImpossibleSamples() {
+        final Base64 codec = new Base64(0, null, false, CodecPolicy.STRICT);
+        for (final String s : BASE64_IMPOSSIBLE_CASES) {
+            assertThrows(IllegalArgumentException.class, () -> codec.decode(s));
+        }
     }
 
     private void testBase64InBuffer(final int startPasSize, final int endPadSize) {
@@ -157,25 +216,34 @@ public class Base64Test {
         assertEquals("SGVsbG8gV29ybGQ=", encodedContent, "encoding hello world");
     }
 
-    /**
-     * Test our decode with pad character in the middle. (Our current
-     * implementation: halt decode and return what we've got so far).
-     *
-     * The point of this test is not to say
-     * "this is the correct way to decode base64." The point is simply to keep
-     * us aware of the current logic since 1.4 so we don't accidentally break it
-     * without realizing.
-     *
-     * Note for historians. The 1.3 logic would decode to:
-     * "Hello World\u0000Hello World" -- null in the middle --- and 1.4
-     * unwittingly changed it to current logic.
-     */
     @Test
-    public void testDecodeWithInnerPad() {
-        final String content = "SGVsbG8gV29ybGQ=SGVsbG8gV29ybGQ=";
-        final byte[] result = Base64.decodeBase64(content);
-        final byte[] shouldBe = StringUtils.getBytesUtf8("Hello World");
-        assertArrayEquals(result, shouldBe, "decode should halt at pad (=)");
+    public void testByteToStringVariations() throws DecoderException {
+        final Base64 base64 = new Base64(0);
+        final byte[] b1 = StringUtils.getBytesUtf8("Hello World");
+        final byte[] b2 = {};
+        final byte[] b3 = null;
+        final byte[] b4 = Hex.decodeHex("2bf7cc2701fe4397b49ebeed5acc7090"); // for
+                                                                                            // url-safe
+                                                                                            // tests
+
+        assertEquals("SGVsbG8gV29ybGQ=", base64.encodeToString(b1),
+                "byteToString Hello World");
+        assertEquals( "SGVsbG8gV29ybGQ=", Base64.encodeBase64String(b1),
+                "byteToString static Hello World");
+        assertEquals("", base64.encodeToString(b2),
+                "byteToString \"\"");
+        assertEquals("", Base64.encodeBase64String(b2),
+                "byteToString static \"\"");
+        assertNull(base64.encodeToString(b3),
+                "byteToString null");
+        assertNull(Base64.encodeBase64String(b3),
+                "byteToString static null");
+        assertEquals("K/fMJwH+Q5e0nr7tWsxwkA==", base64.encodeToString(b4),
+                "byteToString UUID");
+        assertEquals("K/fMJwH+Q5e0nr7tWsxwkA==", Base64.encodeBase64String(b4),
+                "byteToString static UUID");
+        assertEquals("K_fMJwH-Q5e0nr7tWsxwkA", Base64.encodeBase64URLSafeString(b4),
+                "byteToString static-url-safe UUID");
     }
 
     /**
@@ -192,6 +260,49 @@ public class Base64Test {
         assertArrayEquals(expectedEncode, actualEncode, "chunkedEncodeMultipleOf76");
     }
 
+    @Test
+    public void testCodec112() { // size calculation assumes always chunked
+        final byte[] in = { 0 };
+        final byte[] out = Base64.encodeBase64(in);
+        Base64.encodeBase64(in, false, false, out.length);
+        // TODO Assert??
+    }
+
+    /**
+     * 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() {
+        // 1GiB file to encode: 2^30 bytes
+        final int size1GiB = 1 << 30;
+
+        // Expecting a size of 4 output bytes per 3 input bytes plus the trailing bytes
+        // padded to a block size of 4.
+        final int blocks = (int) Math.ceil(size1GiB / 3.0);
+        final int expectedLength = 4 * 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 headroom
+        final long estimatedMemory = (long) size1GiB * 4 + expectedLength + 32 * 1024;
+        Assumptions.assumeTrue(presumableFreeMemory > estimatedMemory,
+                "Not enough free memory for the test");
+
+        final byte[] bytes = new byte[size1GiB];
+        final byte[] encoded = Base64.encodeBase64(bytes);
+        assertEquals(expectedLength, encoded.length);
+    }
+
     /**
      * CODEC-68: isBase64 throws ArrayIndexOutOfBoundsException on some
      * non-BASE64 bytes
@@ -261,6 +372,31 @@ public class Base64Test {
                 "Exception not thrown when passing in null to encodeInteger(BigInteger)");
     }
 
+    @Test
+    public void testConstructor_Int_ByteArray_Boolean() {
+        final Base64 base64 = new Base64(65, new byte[] { '\t' }, false);
+        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);
+        assertEquals(expectedResult, result, "new Base64(65, \\t, false)");
+    }
+
+    @Test
+    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(BaseNTestData.DECODED);
+        String expectedResult = Base64TestData.ENCODED_64_CHARS_PER_LINE;
+        expectedResult = expectedResult.replace("=", ""); // url-safe has no
+                                                                // == padding.
+        expectedResult = expectedResult.replace('\n', '\t');
+        expectedResult = expectedResult.replace('+', '-');
+        expectedResult = expectedResult.replace('/', '_');
+        final String result = StringUtils.newStringUtf8(encoded);
+        assertEquals(result, expectedResult, "new Base64(64, \\t, true)");
+    }
+
     @Test
     public void testConstructors() {
         Base64 base64;
@@ -290,29 +426,10 @@ public class Base64Test {
         assertNotNull(base64);
     }
 
-    @Test
-    public void testConstructor_Int_ByteArray_Boolean() {
-        final Base64 base64 = new Base64(65, new byte[] { '\t' }, false);
-        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);
-        assertEquals(expectedResult, result, "new Base64(65, \\t, false)");
-    }
-
-    @Test
-    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(BaseNTestData.DECODED);
-        String expectedResult = Base64TestData.ENCODED_64_CHARS_PER_LINE;
-        expectedResult = expectedResult.replace("=", ""); // url-safe has no
-                                                                // == padding.
-        expectedResult = expectedResult.replace('\n', '\t');
-        expectedResult = expectedResult.replace('+', '-');
-        expectedResult = expectedResult.replace('/', '_');
-        final String result = StringUtils.newStringUtf8(encoded);
-        assertEquals(result, expectedResult, "new Base64(64, \\t, true)");
+    private void testDecodeEncode(final String encodedText) {
+        final String decodedText = StringUtils.newStringUsAscii(Base64.decodeBase64(encodedText));
+        final String encodedText2 = Base64.encodeBase64String(StringUtils.getBytesUtf8(decodedText));
+        assertEquals(encodedText, encodedText2);
     }
 
     /**
@@ -354,6 +471,27 @@ public class Base64Test {
         assertEquals(0, Base64.decodeBase64("\n".getBytes(CHARSET_UTF8)).length);
     }
 
+    /**
+     * Test our decode with pad character in the middle. (Our current
+     * implementation: halt decode and return what we've got so far).
+     *
+     * The point of this test is not to say
+     * "this is the correct way to decode base64." The point is simply to keep
+     * us aware of the current logic since 1.4 so we don't accidentally break it
+     * without realizing.
+     *
+     * Note for historians. The 1.3 logic would decode to:
+     * "Hello World\u0000Hello World" -- null in the middle --- and 1.4
+     * unwittingly changed it to current logic.
+     */
+    @Test
+    public void testDecodeWithInnerPad() {
+        final String content = "SGVsbG8gV29ybGQ=SGVsbG8gV29ybGQ=";
+        final byte[] result = Base64.decodeBase64(content);
+        final byte[] shouldBe = StringUtils.getBytesUtf8("Hello World");
+        assertArrayEquals(result, shouldBe, "decode should halt at pad (=)");
+    }
+
     @Test
     public void testDecodeWithWhitespace() throws Exception {
 
@@ -394,6 +532,12 @@ public class Base64Test {
         assertNull(Base64.decodeBase64((byte[]) null), "empty base64 encode");
     }
 
+    private void testEncodeDecode(final String plainText) {
+        final String encodedText = Base64.encodeBase64String(StringUtils.getBytesUtf8(plainText));
+        final String decodedText = StringUtils.newStringUsAscii(Base64.decodeBase64(encodedText));
+        assertEquals(plainText, decodedText);
+    }
+
     // encode/decode a large random array
     @Test
     public void testEncodeDecodeRandom() {
@@ -428,18 +572,26 @@ public class Base64Test {
         testEncodeOverMaxSize(2);
     }
 
-    @Test
-    public void testCodec112() { // size calculation assumes always chunked
-        final byte[] in = { 0 };
-        final byte[] out = Base64.encodeBase64(in);
-        Base64.encodeBase64(in, false, false, out.length);
-        // TODO Assert??
-    }
-
     private void testEncodeOverMaxSize(final int maxSize) {
         assertThrows(IllegalArgumentException.class, () -> Base64.encodeBase64(BaseNTestData.DECODED, true, false, maxSize));
     }
 
+    /**
+     * Tests a lineSeparator much bigger than DEFAULT_BUFFER_SIZE.
+     *
+     * @see "<a href='https://mail-archives.apache.org/mod_mbox/commons-dev/201202.mbox/%3C4F3C85D7.5060706@snafu.de%3E'>dev@commons.apache.org</a>"
+     */
+    @Test
+    public void testHugeLineSeparator() {
+        final int BaseNCodec_DEFAULT_BUFFER_SIZE = 8192;
+        final int Base64_BYTES_PER_ENCODED_BLOCK = 4;
+        final byte[] baLineSeparator = new byte[BaseNCodec_DEFAULT_BUFFER_SIZE * 4 - 3];
+        final Base64 b64 = new Base64(Base64_BYTES_PER_ENCODED_BLOCK, baLineSeparator);
+        final String strOriginal = "Hello World";
+        final String strDecoded = new String(b64.decode(b64.encode(StringUtils.getBytesUtf8(strOriginal))));
+        assertEquals(strOriginal, strDecoded, "testDEFAULT_BUFFER_SIZE");
+    }
+
     @Test
     public void testIgnoringNonBase64InDecode() throws Exception {
         assertEquals("The quick brown fox jumped over the lazy dogs.",
@@ -467,6 +619,24 @@ public class Base64Test {
         assertFalse(Base64.isBase64(new byte[] { '$' }));
     }
 
+    /**
+     * Test the isStringBase64 method.
+     */
+    @Test
+    public void testIsStringBase64() {
+        final String nullString = null;
+        final String emptyString = "";
+        final String validString = "abc===defg\n\r123456\r789\r\rABC\n\nDEF==GHI\r\nJKL==============";
+        final String invalidString = validString + (char) 0; // append null character
+
+        assertThrows(NullPointerException.class, () -> Base64.isBase64(nullString),
+                "Base64.isStringBase64() should not be null-safe.");
+
+        assertTrue(Base64.isBase64(emptyString), "Base64.isStringBase64(empty-string) is true");
+        assertTrue(Base64.isBase64(validString), "Base64.isStringBase64(valid-string) is true");
+        assertFalse(Base64.isBase64(invalidString), "Base64.isStringBase64(invalid-string) is false");
+    }
+
     /**
      * Tests isUrlSafe.
      */
@@ -558,6 +728,12 @@ public class Base64Test {
         assertEquals(original, dest, "dest string does not equal original");
     }
 
+    @Test
+    public void testObjectEncode() throws Exception {
+        final Base64 b64 = new Base64();
+        assertEquals("SGVsbG8gV29ybGQ=", new String(b64.encode("Hello World".getBytes(CHARSET_UTF8))));
+    }
+
     @Test
     public void testObjectEncodeWithInvalidParameter() {
         assertThrows(EncoderException.class, () -> new Base64().encode("Yadayadayada"),
@@ -578,12 +754,6 @@ public class Base64Test {
         assertEquals(original, dest, "dest string does not equal original");
     }
 
-    @Test
-    public void testObjectEncode() throws Exception {
-        final Base64 b64 = new Base64();
-        assertEquals("SGVsbG8gV29ybGQ=", new String(b64.encode("Hello World".getBytes(CHARSET_UTF8))));
-    }
-
     @Test
     public void testPairs() {
         assertEquals("AAA=", new String(Base64.encodeBase64(new byte[] { 0, 0 })));
@@ -593,6 +763,14 @@ public class Base64Test {
         }
     }
 
+    /**
+     * Tests RFC 1421 section 4.3.2.4 chuck size definition.
+     */
+    @Test
+    public void testRfc1421Section6Dot8ChunkSizeDefinition() {
+        assertEquals(64, BaseNCodec.PEM_CHUNK_SIZE);
+    }
+
     /**
      * Tests RFC 2045 section 2.1 CRLF definition.
      */
@@ -609,14 +787,6 @@ public class Base64Test {
         assertEquals(76, BaseNCodec.MIME_CHUNK_SIZE);
     }
 
-    /**
-     * Tests RFC 1421 section 4.3.2.4 chuck size definition.
-     */
-    @Test
-    public void testRfc1421Section6Dot8ChunkSizeDefinition() {
-        assertEquals(64, BaseNCodec.PEM_CHUNK_SIZE);
-    }
-
     /**
      * Tests RFC 4648 section 10 test vectors.
      * <ul>
@@ -643,6 +813,32 @@ public class Base64Test {
         assertEquals("foobar", StringUtils.newStringUsAscii(Base64.decodeBase64("Zm9vYmFy")));
     }
 
+    /**
+     * Tests RFC 4648 section 10 test vectors.
+     * <ul>
+     * <li>BASE64("") = ""</li>
+     * <li>BASE64("f") = "Zg=="</li>
+     * <li>BASE64("fo") = "Zm8="</li>
+     * <li>BASE64("foo") = "Zm9v"</li>
+     * <li>BASE64("foob") = "Zm9vYg=="</li>
+     * <li>BASE64("fooba") = "Zm9vYmE="</li>
+     * <li>BASE64("foobar") = "Zm9vYmFy"</li>
+     * </ul>
+     *
+     * @see <a href="http://tools.ietf.org/html/rfc4648">http://tools.ietf.org/
+     *      html/rfc4648</a>
+     */
+    @Test
+    public void testRfc4648Section10DecodeEncode() {
+        testDecodeEncode("");
+        testDecodeEncode("Zg==");
+        testDecodeEncode("Zm8=");
+        testDecodeEncode("Zm9v");
+        testDecodeEncode("Zm9vYg==");
+        testDecodeEncode("Zm9vYmE=");
+        testDecodeEncode("Zm9vYmFy");
+    }
+
     /**
      * Tests RFC 4648 section 10 test vectors.
      * <ul>
@@ -696,38 +892,6 @@ public class Base64Test {
         assertEquals("Zm9vYmFy", Base64.encodeBase64String(StringUtils.getBytesUtf8("foobar")));
     }
 
-    /**
-     * Tests RFC 4648 section 10 test vectors.
-     * <ul>
-     * <li>BASE64("") = ""</li>
-     * <li>BASE64("f") = "Zg=="</li>
-     * <li>BASE64("fo") = "Zm8="</li>
-     * <li>BASE64("foo") = "Zm9v"</li>
-     * <li>BASE64("foob") = "Zm9vYg=="</li>
-     * <li>BASE64("fooba") = "Zm9vYmE="</li>
-     * <li>BASE64("foobar") = "Zm9vYmFy"</li>
-     * </ul>
-     *
-     * @see <a href="http://tools.ietf.org/html/rfc4648">http://tools.ietf.org/
-     *      html/rfc4648</a>
-     */
-    @Test
-    public void testRfc4648Section10DecodeEncode() {
-        testDecodeEncode("");
-        testDecodeEncode("Zg==");
-        testDecodeEncode("Zm8=");
-        testDecodeEncode("Zm9v");
-        testDecodeEncode("Zm9vYg==");
-        testDecodeEncode("Zm9vYmE=");
-        testDecodeEncode("Zm9vYmFy");
-    }
-
-    private void testDecodeEncode(final String encodedText) {
-        final String decodedText = StringUtils.newStringUsAscii(Base64.decodeBase64(encodedText));
-        final String encodedText2 = Base64.encodeBase64String(StringUtils.getBytesUtf8(decodedText));
-        assertEquals(encodedText, encodedText2);
-    }
-
     /**
      * Tests RFC 4648 section 10 test vectors.
      * <ul>
@@ -754,12 +918,6 @@ public class Base64Test {
         testEncodeDecode("foobar");
     }
 
-    private void testEncodeDecode(final String plainText) {
-        final String encodedText = Base64.encodeBase64String(StringUtils.getBytesUtf8(plainText));
-        final String decodedText = StringUtils.newStringUsAscii(Base64.decodeBase64(encodedText));
-        assertEquals(plainText, decodedText);
-    }
-
     @Test
     public void testSingletons() {
         assertEquals("AA==", new String(Base64.encodeBase64(new byte[] { (byte) 0 })));
@@ -982,6 +1140,30 @@ public class Base64Test {
         assertEquals("aA==\r\n", new String(Base64.encodeBase64Chunked(new byte[] { (byte) 104 })));
     }
 
+    @Test
+    public void testStringToByteVariations() throws DecoderException {
+        final Base64 base64 = new Base64();
+        final String s1 = "SGVsbG8gV29ybGQ=\r\n";
+        final String s2 = "";
+        final String s3 = null;
+        final String s4a = "K/fMJwH+Q5e0nr7tWsxwkA==\r\n";
+        final String s4b = "K_fMJwH-Q5e0nr7tWsxwkA";
+        final byte[] b4 = Hex.decodeHex("2bf7cc2701fe4397b49ebeed5acc7090"); // for
+                                                                                            // url-safe
+                                                                                            // tests
+
+        assertEquals("Hello World", StringUtils.newStringUtf8(base64.decode(s1)), "StringToByte Hello World");
+        assertEquals("Hello World", StringUtils.newStringUtf8((byte[]) base64.decode((Object) s1)), "StringToByte Hello World");
+        assertEquals("Hello World", StringUtils.newStringUtf8(Base64.decodeBase64(s1)), "StringToByte static Hello World");
+        assertEquals("", StringUtils.newStringUtf8(base64.decode(s2)), "StringToByte \"\"");
... 7498 lines suppressed ...