You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by se...@apache.org on 2011/01/27 20:28:04 UTC

svn commit: r1064262 - in /commons/proper/codec/trunk/src: java/org/apache/commons/codec/binary/ test/org/apache/commons/codec/binary/

Author: sebb
Date: Thu Jan 27 19:28:04 2011
New Revision: 1064262

URL: http://svn.apache.org/viewvc?rev=1064262&view=rev
Log:
More refactoring

Added:
    commons/proper/codec/trunk/src/test/org/apache/commons/codec/binary/BaseNCodecTest.java   (with props)
Modified:
    commons/proper/codec/trunk/src/java/org/apache/commons/codec/binary/Base32.java
    commons/proper/codec/trunk/src/java/org/apache/commons/codec/binary/BaseNCodec.java
    commons/proper/codec/trunk/src/test/org/apache/commons/codec/binary/Base32Test.java

Modified: commons/proper/codec/trunk/src/java/org/apache/commons/codec/binary/Base32.java
URL: http://svn.apache.org/viewvc/commons/proper/codec/trunk/src/java/org/apache/commons/codec/binary/Base32.java?rev=1064262&r1=1064261&r2=1064262&view=diff
==============================================================================
--- commons/proper/codec/trunk/src/java/org/apache/commons/codec/binary/Base32.java (original)
+++ commons/proper/codec/trunk/src/java/org/apache/commons/codec/binary/Base32.java Thu Jan 27 19:28:04 2011
@@ -55,10 +55,6 @@ public class Base32 extends BaseNCodec {
     /**
      * Chunk separator per RFC 2045 section 2.1.
      *
-     * <p>
-     * N.B. The next major release may break compatibility and make this field private.
-     * </p>
-     * 
      * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 2.1</a>
      */
     private static final byte[] CHUNK_SEPARATOR = {'\r', '\n'};
@@ -84,11 +80,6 @@ public class Base32 extends BaseNCodec {
     };
 
     /**
-     * Byte used to pad output.
-     */
-    private static final byte PAD = '=';
-
-    /**
      * This array is a lookup table that translates Unicode characters drawn from the "Base32 Alphabet" (as specified in
      * Table 3 of RFC 2045) into their 5-bit positive integer equivalents. Characters that are not in the Base32
      * alphabet but fall within the bounds of the array are translated to -1.
@@ -123,9 +114,6 @@ public class Base32 extends BaseNCodec {
     /** Mask used to extract 5 bits, used when encoding Base32 bytes */
     private static final int MASK_5BITS = 0x1f;
 
-    /** Mask used to extract 8 bits, used in decoding Base32 bytes */
-    private static final int MASK_8BITS = 0xff;
-
     // The static final fields above are used for the original static byte[] methods on Base32.
     // The private member fields below are used with the new streaming approach, which requires
     // some state be preserved between calls of encode() and decode().
@@ -135,12 +123,10 @@ public class Base32 extends BaseNCodec {
      */
     private final byte[] encodeTable;
 
-    private final byte[] decodeTable;
     /**
-     * Line length for encoding. Not used when decoding. A value of zero or less implies no chunking of the Base32
-     * encoded data.
+     * Decode table to use.
      */
-    private final int lineLength;
+    private final byte[] decodeTable;
 
     /**
      * Line separator for encoding. Not used when decoding. Only used if lineLength > 0.
@@ -149,15 +135,13 @@ public class Base32 extends BaseNCodec {
 
     /**
      * Convenience variable to help us determine when our buffer is going to run out of room and needs resizing.
-     * <code>decodeSize = 3 + lineSeparator.length;</code>
-     * TODO 3?
+     * <code>decodeSize = {@link BYTES_PER_ENCODED_BLOCK} - 1 + lineSeparator.length;</code>
      */
     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;</code>
-     * TODO 4? is that BYTES_PER_ENCODED_BLOCK? - probably yes
+     * <code>encodeSize = {@link BYTES_PER_ENCODED_BLOCK} + lineSeparator.length;</code>
      */
     private final int encodeSize;
 
@@ -235,25 +219,12 @@ public class Base32 extends BaseNCodec {
      * @param useHex if <code>true</code>, then use Base32 Hex alphabet, otherwise use Base32 alphabet
      * @throws IllegalArgumentException
      *             The provided lineSeparator included some Base32 characters. That's not going to work!
+     *             Or the lineLength > 0 and lineSeparator is null.
      */
     public Base32(int lineLength, byte[] lineSeparator, boolean useHex) {
-        if (lineSeparator == null) {
-            lineLength = 0;  // disable chunk-separating
-            lineSeparator = CHUNK_SEPARATOR;  // this just gets ignored
-        }
-        this.lineLength = lineLength > 0 ? (lineLength / BYTES_PER_ENCODED_BLOCK) * BYTES_PER_ENCODED_BLOCK : 0;
-        this.lineSeparator = new byte[lineSeparator.length];
-        System.arraycopy(lineSeparator, 0, this.lineSeparator, 0, lineSeparator.length);
-        if (lineLength > 0) {
-            this.encodeSize = BYTES_PER_ENCODED_BLOCK + lineSeparator.length;
-        } else {
-            this.encodeSize = BYTES_PER_ENCODED_BLOCK;
-        }
-        this.decodeSize = this.encodeSize - 1;
-        if (containsBase32Byte(lineSeparator)) {
-            String sep = StringUtils.newStringUtf8(lineSeparator);
-            throw new IllegalArgumentException("lineSeperator must not contain Base32 characters: [" + sep + "]");
-        }
+        super(BYTES_PER_UNENCODED_BLOCK, BYTES_PER_ENCODED_BLOCK, 
+                lineLength, 
+                lineSeparator == null ? 0 : lineSeparator.length);
         if (useHex){
             this.encodeTable = BASE32HEX_ENCODE_TABLE;
             this.decodeTable = BASE32HEX_DECODE_TABLE;            
@@ -261,254 +232,34 @@ public class Base32 extends BaseNCodec {
             this.encodeTable = BASE32_ENCODE_TABLE;
             this.decodeTable = BASE32_DECODE_TABLE;            
         }
-    }
-
-    /**
-     * Returns whether or not the <code>octet</code> is in the Base32 alphabet.
-     * 
-     * @param octet
-     *            The value to test
-     * @return <code>true</code> if the value is defined in the the Base32 alphabet (or pad), <code>false</code> otherwise.
-     */
-    public boolean isBase32(byte octet) {
-        return octet == PAD || (octet >= 0 && octet < BASE32_DECODE_TABLE.length && BASE32_DECODE_TABLE[octet] != -1);
-    }
-
-    /**
-     * Returns whether or not the <code>octet</code> is in the Base32 Hex alphabet.
-     * 
-     * @param octet
-     *            The value to test
-     * @return <code>true</code> if the value is defined in the the Base32 Hex alphabet (or pad), <code>false</code> otherwise.
-     */
-    public boolean isBase32Hex(byte octet) {
-        return octet == PAD || (octet >= 0 && octet < BASE32HEX_DECODE_TABLE.length && BASE32HEX_DECODE_TABLE[octet] != -1);
-    }
-
-    /**
-     * Tests a given String to see if it contains only valid characters within the Base32 alphabet. Currently the
-     * method treats whitespace as valid.
-     * 
-     * @param base32
-     *            String to test
-     * @return <code>true</code> if all characters in the String are valid characters in the Base32 alphabet or if
-     *         the String is empty; <code>false</code>, otherwise
-     */
-    public boolean isBase32(String base32) {
-        return isBase32(StringUtils.getBytesUtf8(base32));
-    }
-
-    /**
-     * Tests a given byte array to see if it contains only valid characters within the Base32 alphabet. Currently the
-     * method treats whitespace as valid.
-     * 
-     * @param arrayOctet
-     *            byte array to test
-     * @return <code>true</code> if all bytes are valid characters in the Base32 alphabet or if the byte array is empty;
-     *         <code>false</code>, otherwise
-     */    
-    public boolean isBase32(byte[] arrayOctet) {
-        for (int i = 0; i < arrayOctet.length; i++) {
-            if (!isBase32(arrayOctet[i]) && !isWhiteSpace(arrayOctet[i])) {
-                return false;
+        if (lineLength > 0) {
+            if (lineSeparator == null) {
+                throw new IllegalArgumentException("lineLength "+lineLength+" > 0, but lineSeparator is null");
             }
-        }
-        return true;
-    }
-    
-    /**
-     * Tests a given byte array to see if it contains any characters within the Base32 alphabet.
-     * Does not allow white-space.
-     * 
-     * @param arrayOctet
-     *            byte array to test
-     * @return <code>true</code> if any byte is a valid character in the Base32 alphabet; <code>false</code> otherwise
-     */
-    private boolean containsBase32Byte(byte[] arrayOctet) {
-        for (int i = 0; i < arrayOctet.length; i++) {
-            if (isBase32(arrayOctet[i])) {
-                return true;
+            // Must be done after initialising the tables
+            if (containsAlphabetOrPad(lineSeparator)) {
+                String sep = StringUtils.newStringUtf8(lineSeparator);
+                throw new IllegalArgumentException("lineSeperator must not contain Base32 characters: [" + sep + "]");
             }
+            this.encodeSize = BYTES_PER_ENCODED_BLOCK + lineSeparator.length;
+            this.lineSeparator = new byte[lineSeparator.length];
+            System.arraycopy(lineSeparator, 0, this.lineSeparator, 0, lineSeparator.length);
+        } else {
+            this.encodeSize = BYTES_PER_ENCODED_BLOCK;
+            this.lineSeparator = null;
         }
-        return false;
-    }
-
-    /**
-     * Encodes binary data using the Base32 algorithm but does not chunk the output.
-     * 
-     * @param binaryData
-     *            binary data to encode
-     * @return byte[] containing Base32 characters in their UTF-8 representation.
-     */
-    public static byte[] encodeBase32(byte[] binaryData) {
-        return encodeBase32(binaryData, false);
-    }
-
-    /**
-     * Encodes binary data using the Base32 algorithm but does not chunk the output.
-     *
-     * @param binaryData
-     *            binary data to encode
-     * @return String containing Base32 characters.
-     */    
-    public static String encodeBase32String(byte[] binaryData) {
-        return StringUtils.newStringUtf8(encodeBase32(binaryData, false));
-    }
-    
-    /**
-     * Encodes binary data using the Base32 algorithm but does not chunk the output.
-     *
-     * @param binaryData
-     *            binary data to encode
-     * @return String containing Base32Hex characters.
-     */    
-    public static String encodeBase32HexString(byte[] binaryData) {
-        return StringUtils.newStringUtf8(encodeBase32Hex(binaryData, false));
-    }
-    
-    /**
-     * Encodes binary data using the Base32 algorithm and chunks the encoded output into 76 character blocks
-     * 
-     * @param binaryData
-     *            binary data to encode
-     * @return Base32 characters chunked in 76 character blocks
-     */
-    public static byte[] encodeBase32Chunked(byte[] binaryData) {
-        return encodeBase32(binaryData, true);
-    }
-
-    /**
-     * Encodes binary data using the Base32 algorithm, optionally chunking the output into 76 character blocks.
-     * 
-     * @param binaryData
-     *            Array containing binary data to encode.
-     * @param isChunked
-     *            if <code>true</code> this encoder will chunk the Base32 output into 76 character blocks
-     * @return Base32-encoded data.
-     * @throws IllegalArgumentException
-     *             Thrown when the input array needs an output array bigger than {@link Integer#MAX_VALUE}
-     */
-    public static byte[] encodeBase32(byte[] binaryData, boolean isChunked) {
-        return encodeBase32(binaryData, isChunked, Integer.MAX_VALUE);
-    }
-
-    /**
-     * Encodes binary data using the Base32 Hex algorithm, optionally chunking the output into 76 character blocks.
-     * 
-     * @param binaryData
-     *            Array containing binary data to encode.
-     * @param isChunked
-     *            if <code>true</code> this encoder will chunk the Base32 output into 76 character blocks
-     * @return Base32Hex-encoded data.
-     * @throws IllegalArgumentException
-     *             Thrown when the input array needs an output array bigger than {@link Integer#MAX_VALUE}
-     */
-    public static byte[] encodeBase32Hex(byte[] binaryData, boolean isChunked) {
-        return encodeBase32Hex(binaryData, isChunked, Integer.MAX_VALUE);
-    }
-
-    /**
-     * Encodes binary data using the Base32 algorithm, optionally chunking the output into 76 character blocks.
-     * 
-     * @param binaryData
-     *            Array containing binary data to encode.
-     * @param isChunked
-     *            if <code>true</code> this encoder will chunk the Base32 output into 76 character blocks
-     * @param maxResultSize
-     *            The maximum result size to accept.
-     * @return Base32-encoded data.
-     * @throws IllegalArgumentException
-     *             Thrown when the input array needs an output array bigger than maxResultSize
-     */
-    public static byte[] encodeBase32(byte[] binaryData, boolean isChunked, int maxResultSize) {
-        if (binaryData == null || binaryData.length == 0) {
-            return binaryData;
-        }
-
-        long len = getEncodeLength(binaryData, MIME_CHUNK_SIZE, CHUNK_SEPARATOR);
-        if (len > maxResultSize) {
-            throw new IllegalArgumentException("Input array too big, the output array would be bigger (" +
-                len +
-                ") than the specified maxium size of " +
-                maxResultSize);
-        }
-                
-        Base32 b64 = isChunked ? new Base32(MIME_CHUNK_SIZE, CHUNK_SEPARATOR) : new Base32();
-        return b64.encode(binaryData);
-    }
-
-    /**
-     * Encodes binary data using the Base32Hex algorithm, optionally chunking the output into 76 character blocks.
-     * 
-     * @param binaryData
-     *            Array containing binary data to encode.
-     * @param isChunked
-     *            if <code>true</code> this encoder will chunk the Base32 output into 76 character blocks
-     * @param maxResultSize
-     *            The maximum result size to accept.
-     * @return Base32Hex-encoded data.
-     * @throws IllegalArgumentException
-     *             Thrown when the input array needs an output array bigger than maxResultSize
-     */
-    public static byte[] encodeBase32Hex(byte[] binaryData, boolean isChunked, int maxResultSize) {
-        if (binaryData == null || binaryData.length == 0) {
-            return binaryData;
-        }
-
-        long len = getEncodeLength(binaryData, MIME_CHUNK_SIZE, CHUNK_SEPARATOR);
-        if (len > maxResultSize) {
-            throw new IllegalArgumentException("Input array too big, the output array would be bigger (" +
-                len +
-                ") than the specified maxium size of " +
-                maxResultSize);
-        }
-                
-        Base32 b64 = isChunked ? new Base32(MIME_CHUNK_SIZE, CHUNK_SEPARATOR, true) : new Base32(true);
-        return b64.encode(binaryData);
-    }
-
-    /**
-     * Decodes a Base32 String into octets
-     *
-     * @param base32String
-     *            String containing Base32 data
-     * @return Array containing decoded data.
-     */
-    public static byte[] decodeBase32(String base32String) {
-        return new Base32().decode(base32String);
-    }
-
-    /**
-     * Decodes Base32 data into octets
-     * 
-     * @param base32Data
-     *            Byte array containing Base32 data
-     * @return Array containing decoded data.
-     */
-    public static byte[] decodeBase32(byte[] base32Data) {
-        return new Base32().decode(base32Data);
-    }
-
-    /**
-     * Decodes a Base32 Hex String into octets
-     *
-     * @param base32HexString
-     *            String containing Base32Hex data
-     * @return Array containing decoded data.
-     */
-    public static byte[] decodeBase32Hex(String base32HexString) {
-        return new Base32(true).decode(base32HexString);
+        this.decodeSize = this.encodeSize - 1;
     }
 
     /**
-     * Decodes Base32 Hex data into octets
+     * Returns whether or not the <code>octet</code> is in the Base32 alphabet.
      * 
-     * @param base32HexData
-     *            Byte array containing Base32Hex data
-     * @return Array containing decoded data.
+     * @param octet
+     *            The value to test
+     * @return <code>true</code> if the value is defined in the the Base32 alphabet <code>false</code> otherwise.
      */
-    public static byte[] decodeBase32Hex(byte[] base32HexData) {
-        return new Base32(true).decode(base32HexData);
+    public boolean isInAlphabet(byte octet) {
+        return (octet >= 0 && octet < decodeTable.length && decodeTable[octet] != -1);
     }
 
     /**
@@ -533,13 +284,14 @@ public class Base32 extends BaseNCodec {
         // encoding.
         if (inAvail < 0) {
             eof = true;
-            if (buffer == null || buffer.length - pos < encodeSize) {
-                resizeBuffer();
+            if (0 == modulus) {
+                return; // no leftovers to process
             }
+            ensureBufferSize(encodeSize);
             switch (modulus) { // % 5
                 case 1 : // Only 1 octet; take top 5 bits then remainder
-                    buffer[pos++] = encodeTable[(int)(x >> 3) & MASK_5BITS]; // 8-1*5 = 3
-                    buffer[pos++] = encodeTable[(int)(x << 2) & MASK_5BITS]; // 5-3=2
+                    buffer[pos++] = encodeTable[(int)(bitWorkArea >> 3) & MASK_5BITS]; // 8-1*5 = 3
+                    buffer[pos++] = encodeTable[(int)(bitWorkArea << 2) & MASK_5BITS]; // 5-3=2
                     buffer[pos++] = PAD;
                     buffer[pos++] = PAD;
                     buffer[pos++] = PAD;
@@ -549,63 +301,58 @@ public class Base32 extends BaseNCodec {
                     break;
     
                 case 2 : // 2 octets = 16 bits to use
-                    buffer[pos++] = encodeTable[(int)(x >> 11) & MASK_5BITS]; // 16-1*5 = 11
-                    buffer[pos++] = encodeTable[(int)(x >>  6) & MASK_5BITS]; // 16-2*5 = 6
-                    buffer[pos++] = encodeTable[(int)(x >>  1) & MASK_5BITS]; // 16-3*5 = 1
-                    buffer[pos++] = encodeTable[(int)(x <<  4) & MASK_5BITS]; // 5-1 = 4
+                    buffer[pos++] = encodeTable[(int)(bitWorkArea >> 11) & MASK_5BITS]; // 16-1*5 = 11
+                    buffer[pos++] = encodeTable[(int)(bitWorkArea >>  6) & MASK_5BITS]; // 16-2*5 = 6
+                    buffer[pos++] = encodeTable[(int)(bitWorkArea >>  1) & MASK_5BITS]; // 16-3*5 = 1
+                    buffer[pos++] = encodeTable[(int)(bitWorkArea <<  4) & MASK_5BITS]; // 5-1 = 4
                     buffer[pos++] = PAD;
                     buffer[pos++] = PAD;
                     buffer[pos++] = PAD;
                     buffer[pos++] = PAD;
                     break;
                 case 3 : // 3 octets = 24 bits to use
-                    buffer[pos++] = encodeTable[(int)(x >> 19) & MASK_5BITS]; // 24-1*5 = 19
-                    buffer[pos++] = encodeTable[(int)(x >> 14) & MASK_5BITS]; // 24-2*5 = 14
-                    buffer[pos++] = encodeTable[(int)(x >>  9) & MASK_5BITS]; // 24-3*5 = 9
-                    buffer[pos++] = encodeTable[(int)(x >>  4) & MASK_5BITS]; // 24-4*5 = 4
-                    buffer[pos++] = encodeTable[(int)(x <<  1) & MASK_5BITS]; // 5-4 = 1
+                    buffer[pos++] = encodeTable[(int)(bitWorkArea >> 19) & MASK_5BITS]; // 24-1*5 = 19
+                    buffer[pos++] = encodeTable[(int)(bitWorkArea >> 14) & MASK_5BITS]; // 24-2*5 = 14
+                    buffer[pos++] = encodeTable[(int)(bitWorkArea >>  9) & MASK_5BITS]; // 24-3*5 = 9
+                    buffer[pos++] = encodeTable[(int)(bitWorkArea >>  4) & MASK_5BITS]; // 24-4*5 = 4
+                    buffer[pos++] = encodeTable[(int)(bitWorkArea <<  1) & MASK_5BITS]; // 5-4 = 1
                     buffer[pos++] = PAD;
                     buffer[pos++] = PAD;
                     buffer[pos++] = PAD;
                     break;
                 case 4 : // 4 octets = 32 bits to use
-                    buffer[pos++] = encodeTable[(int)(x >> 27) & MASK_5BITS]; // 32-1*5 = 27
-                    buffer[pos++] = encodeTable[(int)(x >> 22) & MASK_5BITS]; // 32-2*5 = 22
-                    buffer[pos++] = encodeTable[(int)(x >> 17) & MASK_5BITS]; // 32-3*5 = 17
-                    buffer[pos++] = encodeTable[(int)(x >> 12) & MASK_5BITS]; // 32-4*5 = 12
-                    buffer[pos++] = encodeTable[(int)(x >>  7) & MASK_5BITS]; // 32-5*5 =  7
-                    buffer[pos++] = encodeTable[(int)(x >>  2) & MASK_5BITS]; // 32-6*5 =  2
-                    buffer[pos++] = encodeTable[(int)(x <<  3) & MASK_5BITS]; // 5-2 = 3
+                    buffer[pos++] = encodeTable[(int)(bitWorkArea >> 27) & MASK_5BITS]; // 32-1*5 = 27
+                    buffer[pos++] = encodeTable[(int)(bitWorkArea >> 22) & MASK_5BITS]; // 32-2*5 = 22
+                    buffer[pos++] = encodeTable[(int)(bitWorkArea >> 17) & MASK_5BITS]; // 32-3*5 = 17
+                    buffer[pos++] = encodeTable[(int)(bitWorkArea >> 12) & MASK_5BITS]; // 32-4*5 = 12
+                    buffer[pos++] = encodeTable[(int)(bitWorkArea >>  7) & MASK_5BITS]; // 32-5*5 =  7
+                    buffer[pos++] = encodeTable[(int)(bitWorkArea >>  2) & MASK_5BITS]; // 32-6*5 =  2
+                    buffer[pos++] = encodeTable[(int)(bitWorkArea <<  3) & MASK_5BITS]; // 5-2 = 3
                     buffer[pos++] = PAD;
                     break;
             }
-            // Don't want to append the CRLF two times in a row, so make sure previous
-            // character is not from CRLF!
-            byte b = lineSeparator[lineSeparator.length - 1];
-            if (lineLength > 0 && pos > 0 && buffer[pos-1] != b) {
+            if (lineLength > 0){ // add chunk separator if required
                 System.arraycopy(lineSeparator, 0, buffer, pos, lineSeparator.length);
                 pos += lineSeparator.length;
-            }
+            }            
         } else {
             for (int i = 0; i < inAvail; i++) {
-                if (buffer == null || buffer.length - pos < encodeSize) {
-                    resizeBuffer();
-                }
+                ensureBufferSize(encodeSize);
                 modulus = (++modulus) % BITS_PER_ENCODED_CHAR;
                 int b = in[inPos++];
                 if (b < 0) {
                     b += 256;
                 }
-                x = (x << 8) + b; // ??
+                bitWorkArea = (bitWorkArea << 8) + b; // ??
                 if (0 == modulus) { // we have enough bytes to create our output 
-                    buffer[pos++] = encodeTable[(int)(x >> 35) & MASK_5BITS];
-                    buffer[pos++] = encodeTable[(int)(x >> 30) & MASK_5BITS];
-                    buffer[pos++] = encodeTable[(int)(x >> 25) & MASK_5BITS];
-                    buffer[pos++] = encodeTable[(int)(x >> 20) & MASK_5BITS];
-                    buffer[pos++] = encodeTable[(int)(x >> 15) & MASK_5BITS];
-                    buffer[pos++] = encodeTable[(int)(x >> 10) & MASK_5BITS];
-                    buffer[pos++] = encodeTable[(int)(x >> 5) & MASK_5BITS];
-                    buffer[pos++] = encodeTable[(int)x & MASK_5BITS];
+                    buffer[pos++] = encodeTable[(int)(bitWorkArea >> 35) & MASK_5BITS];
+                    buffer[pos++] = encodeTable[(int)(bitWorkArea >> 30) & MASK_5BITS];
+                    buffer[pos++] = encodeTable[(int)(bitWorkArea >> 25) & MASK_5BITS];
+                    buffer[pos++] = encodeTable[(int)(bitWorkArea >> 20) & MASK_5BITS];
+                    buffer[pos++] = encodeTable[(int)(bitWorkArea >> 15) & MASK_5BITS];
+                    buffer[pos++] = encodeTable[(int)(bitWorkArea >> 10) & MASK_5BITS];
+                    buffer[pos++] = encodeTable[(int)(bitWorkArea >> 5) & MASK_5BITS];
+                    buffer[pos++] = encodeTable[(int)bitWorkArea & MASK_5BITS];
                     currentLinePos += BYTES_PER_ENCODED_BLOCK;
                     if (lineLength > 0 && lineLength <= currentLinePos) {
                         System.arraycopy(lineSeparator, 0, buffer, pos, lineSeparator.length);
@@ -646,26 +393,24 @@ public class Base32 extends BaseNCodec {
             eof = true;
         }
         for (int i = 0; i < inAvail; i++) {
-            if (buffer == null || buffer.length - pos < decodeSize) {
-                resizeBuffer();
-            }
             byte b = in[inPos++];
             if (b == PAD) {
                 // We're done.
                 eof = true;
                 break;
             } else {
+                ensureBufferSize(decodeSize);
                 if (b >= 0 && b < this.decodeTable.length) {
                     int result = this.decodeTable[b];
                     if (result >= 0) {
                         modulus = (++modulus) % BYTES_PER_ENCODED_BLOCK;
-                        x = (x << BITS_PER_ENCODED_CHAR) + result; // collect decoded bytes
+                        bitWorkArea = (bitWorkArea << BITS_PER_ENCODED_CHAR) + result; // collect decoded bytes
                         if (modulus == 0) { // we can output the 5 bytes
-                            buffer[pos++] = (byte) ((x >> 32) & MASK_8BITS);
-                            buffer[pos++] = (byte) ((x >> 24) & MASK_8BITS);
-                            buffer[pos++] = (byte) ((x >> 16) & MASK_8BITS);
-                            buffer[pos++] = (byte) ((x >> 8) & MASK_8BITS);
-                            buffer[pos++] = (byte) (x & MASK_8BITS);
+                            buffer[pos++] = (byte) ((bitWorkArea >> 32) & MASK_8BITS);
+                            buffer[pos++] = (byte) ((bitWorkArea >> 24) & MASK_8BITS);
+                            buffer[pos++] = (byte) ((bitWorkArea >> 16) & MASK_8BITS);
+                            buffer[pos++] = (byte) ((bitWorkArea >> 8) & MASK_8BITS);
+                            buffer[pos++] = (byte) (bitWorkArea & MASK_8BITS);
                         }
                     }
                 }
@@ -675,76 +420,42 @@ public class Base32 extends BaseNCodec {
         // Two forms of EOF as far as Base32 decoder is concerned: actual
         // EOF (-1) and first time '=' character is encountered in stream.
         // This approach makes the '=' padding characters completely optional.
-        if (eof && modulus != 0) {
-            if (buffer == null || buffer.length - pos < decodeSize) {
-                resizeBuffer();
-            }
+        if (eof && modulus >= 2) { // if modulus < 2, nothing to do
+            ensureBufferSize(decodeSize);
     
             //  we ignore partial bytes, i.e. only multiples of 8 count
             switch (modulus) {
                 case 2 : // 10 bits, drop 2 and output one byte
-                    buffer[pos++] = (byte) ((x >> 2) & MASK_8BITS);
+                    buffer[pos++] = (byte) ((bitWorkArea >> 2) & MASK_8BITS);
                     break;
                 case 3 : // 15 bits, drop 7 and output 1 byte
-                    buffer[pos++] = (byte) ((x >> 7) & MASK_8BITS);
+                    buffer[pos++] = (byte) ((bitWorkArea >> 7) & MASK_8BITS);
                     break;
                 case 4 : // 20 bits = 2*8 + 4
-                    x = x >> 4; // drop 4 bits
-                    buffer[pos++] = (byte) ((x >> 8) & MASK_8BITS);
-                    buffer[pos++] = (byte) ((x) & MASK_8BITS);
+                    bitWorkArea = bitWorkArea >> 4; // drop 4 bits
+                    buffer[pos++] = (byte) ((bitWorkArea >> 8) & MASK_8BITS);
+                    buffer[pos++] = (byte) ((bitWorkArea) & MASK_8BITS);
                     break;
                 case 5 : // 25bits = 3*8 + 1
-                    x = x >> 1;
-                    buffer[pos++] = (byte) ((x >> 16) & MASK_8BITS);
-                    buffer[pos++] = (byte) ((x >> 8) & MASK_8BITS);
-                    buffer[pos++] = (byte) ((x) & MASK_8BITS);
+                    bitWorkArea = bitWorkArea >> 1;
+                    buffer[pos++] = (byte) ((bitWorkArea >> 16) & MASK_8BITS);
+                    buffer[pos++] = (byte) ((bitWorkArea >> 8) & MASK_8BITS);
+                    buffer[pos++] = (byte) ((bitWorkArea) & MASK_8BITS);
                     break;
                 case 6 : // 30bits = 3*8 + 6
-                    x = x >> 6;
-                    buffer[pos++] = (byte) ((x >> 16) & MASK_8BITS);
-                    buffer[pos++] = (byte) ((x >> 8) & MASK_8BITS);
-                    buffer[pos++] = (byte) ((x) & MASK_8BITS);
+                    bitWorkArea = bitWorkArea >> 6;
+                    buffer[pos++] = (byte) ((bitWorkArea >> 16) & MASK_8BITS);
+                    buffer[pos++] = (byte) ((bitWorkArea >> 8) & MASK_8BITS);
+                    buffer[pos++] = (byte) ((bitWorkArea) & MASK_8BITS);
                     break;
                 case 7 : // 35 = 4*8 +3
-                    x = x >> 3;
-                    buffer[pos++] = (byte) ((x >> 24) & MASK_8BITS);
-                    buffer[pos++] = (byte) ((x >> 16) & MASK_8BITS);
-                    buffer[pos++] = (byte) ((x >> 8) & MASK_8BITS);
-                    buffer[pos++] = (byte) ((x) & MASK_8BITS);
+                    bitWorkArea = bitWorkArea >> 3;
+                    buffer[pos++] = (byte) ((bitWorkArea >> 24) & MASK_8BITS);
+                    buffer[pos++] = (byte) ((bitWorkArea >> 16) & MASK_8BITS);
+                    buffer[pos++] = (byte) ((bitWorkArea >> 8) & MASK_8BITS);
+                    buffer[pos++] = (byte) ((bitWorkArea) & MASK_8BITS);
                     break;
             }
         }
     }
-
-  /**
-  * Pre-calculates the amount of space needed to Base32-encode the supplied array.
-  *
-  * @param pArray byte[] array which will later be encoded
-  * @param chunkSize line-length of the output (<= 0 means no chunking) between each
-  *        chunkSeparator (e.g. CRLF).
-  * @param chunkSeparator the sequence of bytes used to separate chunks of output (e.g. CRLF).
-  *
-  * @return amount of space needed to encoded the supplied array.  Returns
-  *         a long since a max-len array will require Integer.MAX_VALUE + 33%.
-  */
- private static long getEncodeLength(byte[] pArray, int chunkSize,
-         byte[] chunkSeparator) {
-             // Base32 always encodes to multiples of 8 (BYTES_PER_ENCODED_CHUNK).
-             chunkSize = (chunkSize / BYTES_PER_ENCODED_BLOCK) * BYTES_PER_ENCODED_BLOCK;
-         
-             long len = (pArray.length * BYTES_PER_ENCODED_BLOCK) / BYTES_PER_UNENCODED_BLOCK;
-             long mod = len % BYTES_PER_ENCODED_BLOCK;
-             if (mod != 0) {
-                 len += BYTES_PER_ENCODED_BLOCK - mod;
-             }
-             if (chunkSize > 0) {
-                 boolean lenChunksPerfectly = len % chunkSize == 0;
-                 len += (len / chunkSize) * chunkSeparator.length;
-                 if (!lenChunksPerfectly) {
-                     len += chunkSeparator.length;
-                 }
-             }
-             return len;
-         }
-
 }

Modified: commons/proper/codec/trunk/src/java/org/apache/commons/codec/binary/BaseNCodec.java
URL: http://svn.apache.org/viewvc/commons/proper/codec/trunk/src/java/org/apache/commons/codec/binary/BaseNCodec.java?rev=1064262&r1=1064261&r2=1064262&view=diff
==============================================================================
--- commons/proper/codec/trunk/src/java/org/apache/commons/codec/binary/BaseNCodec.java (original)
+++ commons/proper/codec/trunk/src/java/org/apache/commons/codec/binary/BaseNCodec.java Thu Jan 27 19:28:04 2011
@@ -51,7 +51,38 @@ public abstract class BaseNCodec impleme
 
     private static final int DEFAULT_BUFFER_RESIZE_FACTOR = 2;
 
+    /**
+     * Defines the default buffer size - currently {@value}
+     * - must be large enough for at least one encoded block+separator
+     */
     private static final int DEFAULT_BUFFER_SIZE = 8192;
+
+    /** Mask used to extract 8 bits, used in decoding bytes */
+    protected static final int MASK_8BITS = 0xff;
+
+    /**
+     * Byte used to pad output.
+     */
+    protected final byte PAD = '='; // instance variable just in case it needs to vary later
+
+    /** 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 nearest multiple of encodedBlockSize.
+     */
+    protected final int lineLength;
+    
+    /**
+     * Size of chunk separator. Not used unless {@link #lineLength} > 0. 
+     */
+    private final int chunkSeparatorLength;
+
     /**
      * Buffer for streaming.
      */
@@ -74,10 +105,10 @@ public abstract class BaseNCodec impleme
     protected boolean eof;
 
     /**
-     * Place holder for the bytes we're dealing with for our based logic. Bitwise operations store and extract the
-     * encoding or decoding from this variable.
+     * Place holder for the bytes we're dealing with for our based logic. 
+     * Bitwise operations store and extract the encoding or decoding from this variable.
      */
-    protected long x;
+    protected long bitWorkArea;
 
     /**
      * Variable tracks how many characters have been written to the current line. Only used when encoding. We use it to
@@ -91,7 +122,18 @@ public abstract class BaseNCodec impleme
      */
     protected int modulus;
 
-    protected BaseNCodec(){
+    /**
+     * Note <code>lineLength</code> is rounded down to the nearest multiple of {@link encodedBlockSize}
+     * @param unencodedBlockSize the size of an unencoded block (e.g. Base64 = 3)
+     * @param encodedBlockSize the size of an encoded block (e.g. Base64 = 4)
+     * @param lineLength if &gt; 0, use chunking with a length <code>lineLength</code>
+     * @param chunkSeparatorLength the chunk separator length, if relevant
+     */
+    protected BaseNCodec(int unencodedBlockSize, int encodedBlockSize, int lineLength, int chunkSeparatorLength){
+        this.unencodedBlockSize = unencodedBlockSize;
+        this.encodedBlockSize = encodedBlockSize;
+        this.lineLength = (lineLength > 0  && chunkSeparatorLength > 0) ? (lineLength / encodedBlockSize) * encodedBlockSize : 0;
+        this.chunkSeparatorLength = chunkSeparatorLength;
     }
 
     /**
@@ -112,10 +154,19 @@ public abstract class BaseNCodec impleme
         return buffer != null ? pos - readPos : 0;
     }
 
-    /** Doubles our buffer. */
-    protected void resizeBuffer() {
+    /**
+     * Get the default buffer size. Can be overridden.
+     * 
+     * @return {@link DEFAULT_BUFFER_RESIZE_SIZE}
+     */
+    protected int getDefaultBufferSize() {
+        return DEFAULT_BUFFER_SIZE;
+    }
+
+    /** Increases our buffer by the {@link DEFAULT_BUFFER_RESIZE_FACTOR}. */
+    private void resizeBuffer() {
         if (buffer == null) {
-            buffer = new byte[DEFAULT_BUFFER_SIZE];
+            buffer = new byte[getDefaultBufferSize()];
             pos = 0;
             readPos = 0;
         } else {
@@ -126,8 +177,19 @@ public abstract class BaseNCodec impleme
     }
 
     /**
-     * Extracts buffered data into the provided byte[] array, starting at position bPos, up to a maximum of bAvail
-     * bytes. Returns how many bytes were actually extracted.
+     * Ensure that the buffer has room for <code>size</code> bytes
+     * 
+     * @param size minimum spare space required
+     */
+    protected void ensureBufferSize(int size){
+        if ((buffer == null) || (buffer.length < pos + size)){
+            resizeBuffer();
+        }
+    }
+
+    /**
+     * Extracts buffered data into the provided byte[] array, starting at position bPos, 
+     * up to a maximum of bAvail bytes. Returns how many bytes were actually extracted.
      * 
      * @param b
      *            byte[] array to extract the buffered data into.
@@ -143,7 +205,7 @@ public abstract class BaseNCodec impleme
             System.arraycopy(buffer, readPos, b, bPos, len);
             readPos += len;
             if (readPos >= pos) {
-                buffer = null;
+                buffer = null; // so hasData() will return false, and this method can return -1
             }
             return len;
         }
@@ -170,7 +232,7 @@ public abstract class BaseNCodec impleme
     }
 
     /**
-     * Resets this Base32 object to its initial newly constructed state.
+     * Resets this object to its initial newly constructed state.
      */
     private void reset() {
         buffer = null;
@@ -180,34 +242,37 @@ public abstract class BaseNCodec impleme
         modulus = 0;
         eof = false;
     }
+
     /**
-     * Encodes an Object using the Base32 algorithm. This method is provided in order to satisfy the requirements of the
+     * Encodes an Object using the Base-N 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 byte[].
      * 
      * @param pObject
      *            Object to encode
-     * @return An object (of type byte[]) containing the Base32 encoded data which corresponds to the byte[] supplied.
+     * @return An object (of type byte[]) containing the Base-N encoded data which corresponds to the byte[] supplied.
      * @throws EncoderException
      *             if the parameter supplied is not of type byte[]
      */
     public Object encode(Object pObject) throws EncoderException {
         if (!(pObject instanceof byte[])) {
-            throw new EncoderException("Parameter supplied to Base32 encode is not a byte[]");
+            throw new EncoderException("Parameter supplied to Base-N encode is not a byte[]");
         }
         return encode((byte[]) pObject);
     }
+
     /**
-     * Encodes a byte[] containing binary data, into a String containing characters in the Base32 alphabet.
+     * Encodes a byte[] containing binary data, into a String containing characters in the Base-N alphabet.
      *
      * @param pArray
      *            a byte array containing binary data
-     * @return A String containing only Base32 character data
+     * @return A String containing only Base-N character data
      */
     public String encodeToString(byte[] pArray) {
         return StringUtils.newStringUtf8(encode(pArray));
     }
+
     /**
-     * Decodes an Object using the Base32 algorithm. This method is provided in order to satisfy the requirements of the
+     * Decodes an Object using the Base-N algorithm. This method is provided in order to satisfy the requirements of the
      * Decoder interface, and will throw a DecoderException if the supplied object is not of type byte[] or String.
      * 
      * @param pObject
@@ -222,24 +287,26 @@ public abstract class BaseNCodec impleme
         } else if (pObject instanceof String) {
             return decode((String) pObject);
         } else {
-            throw new DecoderException("Parameter supplied to Base32 decode is not a byte[] or a String");
+            throw new DecoderException("Parameter supplied to Base-N decode is not a byte[] or a String");
         }
     }
+
     /**
-     * Decodes a String containing characters in the Base32 alphabet.
+     * Decodes a String containing characters in the Base-N alphabet.
      *
      * @param pArray
-     *            A String containing Base32 character data
+     *            A String containing Base-N character data
      * @return a byte array containing binary data
      */
     public byte[] decode(String pArray) {
         return decode(StringUtils.getBytesUtf8(pArray));
     }
+
     /**
-     * Decodes a byte[] containing characters in the Base32 alphabet.
+     * Decodes a byte[] containing characters in the Base-N alphabet.
      * 
      * @param pArray
-     *            A byte array containing Base32 character data
+     *            A byte array containing Base-N character data
      * @return a byte array containing binary data
      */
     public byte[] decode(byte[] pArray) {
@@ -253,12 +320,13 @@ public abstract class BaseNCodec impleme
         readResults(result, 0, result.length);
         return result;
     }
+
     /**
-     * Encodes a byte[] containing binary data, into a byte[] containing characters in the Base32 alphabet.
+     * Encodes a byte[] containing binary data, into a byte[] containing characters in the alphabet.
      * 
      * @param pArray
      *            a byte array containing binary data
-     * @return A byte array containing only Base32 character data
+     * @return A byte array containing only the basen alphabetic character data
      */
     public byte[] encode(byte[] pArray) {
         reset();        
@@ -272,7 +340,100 @@ public abstract class BaseNCodec impleme
         return buf;
     }
     
+    /**
+     * Encodes a byte[] containing binary data, into a String containing characters in the appropriate alphabet.
+     * Uses UTF8 encoding.
+     * 
+     * @param pArray a byte array containing binary data
+     * @return String containing only character data in the appropriate alphabet.
+    */
+    public String encodeAsString(byte[] pArray){
+        return StringUtils.newStringUtf8(encode(pArray));
+    }
+
     abstract void encode(byte[] pArray, int i, int length);  // package protected for access from I/O streams
 
     abstract void decode(byte[] pArray, int i, int length); // package protected for access from I/O streams
+    
+    /**
+     * Returns whether or not the <code>octet</code> is in the current alphabet.
+     * Does not allow whitespace or pad.
+     * 
+     * @param octet The value to test
+     * 
+     * @return <code>true</code> if the value is defined in the current alphabet, <code>false</code> otherwise.
+     */
+    protected abstract boolean isInAlphabet(byte b);
+    
+    /**
+     * Tests a given byte array to see if it contains only valid characters within the alphabet.
+     * The method optionally treats whitespace and pad as valid.
+     * 
+     * @param arrayOctet byte array to test
+     * @param allowWSPad if <code>true</code>, then whitespace and PAD are also allowed
+     * 
+     * @return <code>true</code> if all bytes are valid characters in the alphabet or if the byte array is empty;
+     *         <code>false</code>, otherwise
+     */    
+    public boolean isInAlphabet(byte[] arrayOctet, boolean allowWSPad) {
+        for (int i = 0; i < arrayOctet.length; i++) {
+            if (!isInAlphabet(arrayOctet[i]) &&
+                    (!allowWSPad || (arrayOctet[i] != PAD) && !isWhiteSpace(arrayOctet[i]))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Tests a given String to see if it contains only valid characters within the alphabet. 
+     * The method treats whitespace and PAD as valid.
+     * 
+     * @param basen String to test
+     * @return <code>true</code> if all characters in the String are valid characters in the alphabet or if
+     *         the String is empty; <code>false</code>, otherwise
+     * @see #isInAlphabet(byte[], boolean)
+     */
+    public boolean isInAlphabet(String basen) {
+        return isInAlphabet(StringUtils.getBytesUtf8(basen), true);
+    }
+
+    /**
+     * Tests a given byte array to see if it contains any characters within the alphabet or PAD.
+     * 
+     * Intended for use in checking line-ending arrays
+     * 
+     * @param arrayOctet
+     *            byte array to test
+     * @return <code>true</code> if any byte is a valid character in the alphabet or PAD; <code>false</code> otherwise
+     */
+    protected boolean containsAlphabetOrPad(byte[] arrayOctet) {
+        if (arrayOctet == null) {
+            return false;
+        }
+        for (int i = 0; i < arrayOctet.length; i++) {
+            if (PAD == arrayOctet[i] || isInAlphabet(arrayOctet[i])) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Calculates the amount of space needed to encode the supplied array.
+     *
+     * @param pArray byte[] array which will later be encoded
+     *
+     * @return amount of space needed to encoded the supplied array.  Returns
+     *         a long since a max-len array will require > Integer.MAX_VALUE
+     */
+    public long getEncodedLength(byte[] pArray) {
+        // Calculate non-chunked size - rounded up to allow for padding
+        long len = ((pArray.length + unencodedBlockSize-1)  / unencodedBlockSize) * encodedBlockSize;
+        if (lineLength > 0) { // We're using chunking
+            // Round up to nearest multiple
+            len += ((len + lineLength-1) / lineLength) * chunkSeparatorLength;
+        }
+        return len;
+    }
 }

Modified: commons/proper/codec/trunk/src/test/org/apache/commons/codec/binary/Base32Test.java
URL: http://svn.apache.org/viewvc/commons/proper/codec/trunk/src/test/org/apache/commons/codec/binary/Base32Test.java?rev=1064262&r1=1064261&r2=1064262&view=diff
==============================================================================
--- commons/proper/codec/trunk/src/test/org/apache/commons/codec/binary/Base32Test.java (original)
+++ commons/proper/codec/trunk/src/test/org/apache/commons/codec/binary/Base32Test.java Thu Jan 27 19:28:04 2011
@@ -18,6 +18,8 @@
 
 package org.apache.commons.codec.binary;
 
+import java.util.Arrays;
+
 import junit.framework.TestCase;
 
 public class Base32Test extends TestCase {
@@ -44,15 +46,59 @@ public class Base32Test extends TestCase
 
 
     public void testBase32Samples() throws Exception {
+        Base32 codec = new Base32();
         for (int i = 0; i < BASE32_TEST_CASES.length; i++) {
-                assertEquals(BASE32_TEST_CASES[i][1], Base32.encodeBase32String(BASE32_TEST_CASES[i][0].getBytes("UTF-8")));
+                assertEquals(BASE32_TEST_CASES[i][1], codec.encodeAsString(BASE32_TEST_CASES[i][0].getBytes("UTF-8")));
         }
     }
 
     public void testBase32HexSamples() throws Exception {
+        Base32 codec = new Base32(true);
         for (int i = 0; i < BASE32HEX_TEST_CASES.length; i++) {
-                assertEquals(BASE32HEX_TEST_CASES[i][1], Base32.encodeBase32HexString(BASE32HEX_TEST_CASES[i][0].getBytes("UTF-8")));
+                assertEquals(BASE32HEX_TEST_CASES[i][1], codec.encodeAsString(BASE32HEX_TEST_CASES[i][0].getBytes("UTF-8")));
         }
     }
 
+    public void testSingleCharEncoding() {
+        for (int i = 0; i < 20; i++) {
+            Base32 codec = new Base32();
+            byte unencoded[] = new byte[i];
+            byte allInOne[] = codec.encode(unencoded);
+            codec = new Base32();
+            for (int j=0; j< unencoded.length; j++) {
+                codec.encode(unencoded, j, 1);
+            }
+            codec.encode(unencoded, 0, -1);
+            byte singly[] = new byte[allInOne.length];
+            int bytes = codec.readResults(singly, 0, 100);
+            if (!Arrays.equals(allInOne, singly)){
+                fail();
+            }
+        }
+    }
+
+    public void testRandomBytes() {
+        for (int i = 0; i < 20; i++) {
+            Base32 codec = new Base32();
+            byte[][] b = Base32TestData.randomData(codec, i);
+            assertEquals(""+i+" "+codec.lineLength,b[1].length,codec.getEncodedLength(b[0]));
+            //assertEquals(b[0],codec.decode(b[1]));
+        }
+    }
+    public void testRandomBytesChunked() {
+        for (int i = 0; i < 20; i++) {
+            Base32 codec = new Base32(10);
+            byte[][] b = Base32TestData.randomData(codec, i);
+            assertEquals(""+i+" "+codec.lineLength,b[1].length,codec.getEncodedLength(b[0]));
+            //assertEquals(b[0],codec.decode(b[1]));
+        }
+    }
+    public void testRandomBytesHex() {
+        for (int i = 0; i < 20; i++) {
+            Base32 codec = new Base32(true);
+            byte[][] b = Base32TestData.randomData(codec, i);
+            assertEquals(""+i+" "+codec.lineLength,b[1].length,codec.getEncodedLength(b[0]));
+            //assertEquals(b[0],codec.decode(b[1]));
+        }
+    }
 }

Added: commons/proper/codec/trunk/src/test/org/apache/commons/codec/binary/BaseNCodecTest.java
URL: http://svn.apache.org/viewvc/commons/proper/codec/trunk/src/test/org/apache/commons/codec/binary/BaseNCodecTest.java?rev=1064262&view=auto
==============================================================================
--- commons/proper/codec/trunk/src/test/org/apache/commons/codec/binary/BaseNCodecTest.java (added)
+++ commons/proper/codec/trunk/src/test/org/apache/commons/codec/binary/BaseNCodecTest.java Thu Jan 27 19:28:04 2011
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ */
+
+package org.apache.commons.codec.binary;
+
+import junit.framework.TestCase;
+
+public class BaseNCodecTest extends TestCase {
+
+    BaseNCodec codec;
+    
+    public void setUp(){
+        codec = new BaseNCodec(0, 0, 0, 0) {
+            protected boolean isInAlphabet(byte b) {
+                return b=='O' || b == 'K'; // allow OK
+            }
+            
+            void encode(byte[] pArray, int i, int length) {
+            }
+            
+            void decode(byte[] pArray, int i, int length) {
+            }
+        };        
+    }
+
+    public void testBaseNCodec() {
+        assertNotNull(codec);
+    }
+
+//    public void testHasData() {
+//        fail("Not yet implemented");
+//    }
+//
+//    public void testAvail() {
+//        fail("Not yet implemented");
+//    }
+//
+//    public void testEnsureBufferSize() {
+//        fail("Not yet implemented");
+//    }
+//
+//    public void testReadResults() {
+//        fail("Not yet implemented");
+//    }
+//
+    public void testIsWhiteSpace() {
+        assertTrue(BaseNCodec.isWhiteSpace((byte) ' '));
+        assertTrue(BaseNCodec.isWhiteSpace((byte) '\n'));
+        assertTrue(BaseNCodec.isWhiteSpace((byte) '\r'));
+        assertTrue(BaseNCodec.isWhiteSpace((byte) '\t'));
+    }
+//
+//    public void testEncodeObject() {
+//        fail("Not yet implemented");
+//    }
+//
+//    public void testEncodeToString() {
+//        fail("Not yet implemented");
+//    }
+//
+//    public void testDecodeObject() {
+//        fail("Not yet implemented");
+//    }
+//
+//    public void testDecodeString() {
+//        fail("Not yet implemented");
+//    }
+//
+//    public void testDecodeByteArray() {
+//        fail("Not yet implemented");
+//    }
+//
+//    public void testEncodeByteArray() {
+//        fail("Not yet implemented");
+//    }
+//
+//    public void testEncodeAsString() {
+//        fail("Not yet implemented");
+//    }
+//
+//    public void testEncodeByteArrayIntInt() {
+//        fail("Not yet implemented");
+//    }
+//
+//    public void testDecodeByteArrayIntInt() {
+//        fail("Not yet implemented");
+//    }
+//
+    public void testIsInAlphabetByte() {
+        assertFalse(codec.isInAlphabet((byte) 0));
+        assertFalse(codec.isInAlphabet((byte) 'a'));
+        assertTrue(codec.isInAlphabet((byte) 'O'));
+        assertTrue(codec.isInAlphabet((byte) 'K'));
+    }
+
+    public void testIsInAlphabetByteArrayBoolean() {
+        assertTrue(codec.isInAlphabet(new byte[]{}, false));
+        assertTrue(codec.isInAlphabet(new byte[]{'O'}, false));
+        assertFalse(codec.isInAlphabet(new byte[]{'O',' '}, false));
+        assertFalse(codec.isInAlphabet(new byte[]{' '}, false));
+        assertTrue(codec.isInAlphabet(new byte[]{}, true));
+        assertTrue(codec.isInAlphabet(new byte[]{'O'}, true));
+        assertTrue(codec.isInAlphabet(new byte[]{'O',' '}, true));
+        assertTrue(codec.isInAlphabet(new byte[]{' '}, true));
+    }
+
+    public void testIsInAlphabetString() {
+        assertTrue(codec.isInAlphabet("OK"));
+        assertTrue(codec.isInAlphabet("O=K= \t\n\r"));
+    }
+
+    public void testContainsAlphabetOrPad() {
+        assertTrue(codec.containsAlphabetOrPad("OK".getBytes()));
+        assertTrue(codec.containsAlphabetOrPad("OK ".getBytes()));
+        assertFalse(codec.containsAlphabetOrPad("ok ".getBytes()));
+        assertTrue(codec.containsAlphabetOrPad(new byte[]{codec.PAD}));
+    }
+
+//    public void testGetEncodedLength() {
+//        fail("Not yet implemented");
+//    }
+}

Propchange: commons/proper/codec/trunk/src/test/org/apache/commons/codec/binary/BaseNCodecTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/codec/trunk/src/test/org/apache/commons/codec/binary/BaseNCodecTest.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision