Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 219cc9a

Browse files
committed
New methods added.
1 parent 8d32965 commit 219cc9a

File tree

4 files changed

+147
-32
lines changed

4 files changed

+147
-32
lines changed

CHANGES.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ Base64Coder Changes
44

55
2010-02-23 chdh
66
New directory layout and build script.
7+
Methods added:
8+
encode(byte[],int,int)
9+
encode(byte[],int,int)
10+
decode(char[],int,int)
11+
encodeLines(byte[])
12+
encodeLines(byte[],int,int,int,String)
13+
decodeLines(String)
714

815
2010-01-27 chdh
916
Package name added.

build.xml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,27 @@
44
<property name="srcDir" location="src/main/java"/>
55
<property name="classesDir" location="target/classes"/>
66
<property name="javaDocDir" location="target/javadoc"/>
7+
<property name="jarFile" location="target/base64coder.jar"/>
78
<property name="junitJar" location="lib/junit-4.8.1.jar"/>
89
<property name="testSrcDir" location="src/test/java"/>
910
<property name="testClassesDir" location="target/test-classes"/>
1011
<property name="testReportsDir" location="target/test-reports"/>
1112

1213
<target name="buildAll" description="Compiles and generates the API docs."
13-
depends="compile, javaDoc">
14+
depends="buildJar, javaDoc">
1415
</target>
1516

16-
<target name="compile" description="Compiles the main class.">
17+
<target name="buildJar" description="Compiles the Java source and builds the JAR file.">
1718
<delete dir="${classesDir}" failonerror="true"/>
1819
<mkdir dir="${classesDir}"/>
1920
<javac srcdir="${srcDir}" deprecation="true" includeAntRuntime="false" debug="true" debuglevel="lines,source"
2021
target="1.5" destdir="${classesDir}">
2122
<compilerarg line="-Xlint -Xmaxerrs 6"/>
2223
</javac>
24+
<jar destfile="${jarFile}">
25+
<fileset dir="${classesDir}"/>
26+
</jar>
27+
<delete dir="${classesDir}" failonerror="true"/>
2328
</target>
2429

2530
<target name="compileTest" description="Compiles the test class.">
@@ -31,7 +36,7 @@
3136
<compilerarg line="-Xlint -Xmaxerrs 6"/>
3237
<classpath>
3338
<pathelement location="${junitJar}"/>
34-
<pathelement location="${classesDir}"/>
39+
<pathelement location="${jarFile}"/>
3540
</classpath>
3641
</javac>
3742
</target>
@@ -59,7 +64,7 @@
5964
<junit haltonfailure="on">
6065
<classpath>
6166
<pathelement location="${junitJar}"/>
62-
<pathelement location="${classesDir}"/>
67+
<pathelement location="${jarFile}"/>
6368
<pathelement location="${testClassesDir}"/>
6469
</classpath>
6570
<formatter type="plain"/>

src/main/java/biz/source_code/base64Coder/Base64Coder.java

Lines changed: 97 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,12 @@
2424
* Project home page: <a href="http://www.source-code.biz">www.source-code.biz</a><br>
2525
* Author: Christian d'Heureuse, Inventec Informatik AG, Zurich, Switzerland<br>
2626
* Multi-licensed: EPL/LGPL/AL/BSD.
27-
*
2827
*/
29-
3028
public class Base64Coder {
3129

30+
// The line separator string of the operating system.
31+
private static final String systemLineSeparator = System.getProperty("line.separator");
32+
3233
// Mapping table from 6-bit nibbles to Base64 characters.
3334
private static char[] map1 = new char[64];
3435
static {
@@ -48,37 +49,81 @@ public class Base64Coder {
4849
* Encodes a string into Base64 format.
4950
* No blanks or line breaks are inserted.
5051
* @param s a String to be encoded.
51-
* @return A String with the Base64 encoded data.
52+
* @return a String with the Base64 encoded data.
5253
*/
5354
public static String encodeString (String s) {
5455
return new String(encode(s.getBytes())); }
5556

57+
/**
58+
* Encodes a byte array into Base 64 format and splits the output into lines of 76 characters.
59+
* This method is compatible with <code>sun.misc.BASE64Encoder.encodeBuffer(byte[])</code>.
60+
* @param in an array containing the data bytes to be encoded.
61+
* @return a String with the Base64 encoded data, split into lines.
62+
*/
63+
public static String encodeLines (byte[] in) {
64+
return encodeLines(in, 0, in.length, 76, systemLineSeparator); }
65+
66+
/**
67+
* Encodes a byte array into Base 64 format and splits the output into lines.
68+
* @param in an array containing the data bytes to be encoded.
69+
* #param iOff offset of the first byte in <code>in</code> to be processed.
70+
* #param iLen number of bytes to be processed in <code>in</code> starting at <code>iOff</code>.
71+
* @param lineLen line length for the output data. Should be a multiple of 4.
72+
* @param lineSeparator the line separator to be used to split the output lines.
73+
* @return a String with the Base64 encoded data, split into lines.
74+
*/
75+
public static String encodeLines (byte[] in, int iOff, int iLen, int lineLen, String lineSeparator) {
76+
int blockLen = (lineLen*3) / 4;
77+
if (blockLen <= 0) throw new IllegalArgumentException();
78+
int lines = (iLen+blockLen-1) / blockLen;
79+
int bufLen = ((iLen+2)/3)*4 + lines*lineSeparator.length();
80+
StringBuilder buf = new StringBuilder(bufLen);
81+
int ip = 0;
82+
while (ip < iLen) {
83+
int l = Math.min(iLen-ip, blockLen);
84+
buf.append (encode(in, iOff+ip, l));
85+
buf.append (lineSeparator);
86+
ip += l; }
87+
return buf.toString(); }
88+
5689
/**
5790
* Encodes a byte array into Base64 format.
5891
* No blanks or line breaks are inserted.
5992
* @param in an array containing the data bytes to be encoded.
60-
* @return A character array with the Base64 encoded data.
93+
* @return a character array with the Base64 encoded data.
6194
*/
6295
public static char[] encode (byte[] in) {
63-
return encode(in, in.length); }
96+
return encode(in, 0, in.length); }
6497

6598
/**
6699
* Encodes a byte array into Base64 format.
67100
* No blanks or line breaks are inserted.
68-
* @param in an array containing the data bytes to be encoded.
69-
* @param iLen number of bytes to process in <code>in</code>.
70-
* @return A character array with the Base64 encoded data.
101+
* @param in an array containing the data bytes to be encoded.
102+
* @param iLen number of bytes to process in <code>in</code>.
103+
* @return a character array with the Base64 encoded data.
71104
*/
72105
public static char[] encode (byte[] in, int iLen) {
106+
return encode(in, 0, iLen); }
107+
108+
/**
109+
* Encodes a byte array into Base64 format.
110+
* No blanks or line breaks are inserted.
111+
* @param in an array containing the data bytes to be encoded.
112+
* @param iOff offset of the first byte in <code>in</code> to be processed.
113+
* @param iLen number of bytes to process in <code>in</code> starting at <code>iOff</code>.
114+
* @return a character array with the Base64 encoded data.
115+
*/
116+
public static char[] encode (byte[] in, int iOff, int iLen) {
73117
int oDataLen = (iLen*4+2)/3; // output length without padding
74118
int oLen = ((iLen+2)/3)*4; // output length including padding
75119
char[] out = new char[oLen];
76-
int ip = 0;
120+
int ip = iOff;
121+
int iEnd = iOff + iLen;
77122
int op = 0;
78-
while (ip < iLen) {
123+
while (ip < iEnd) {
79124
int i0 = in[ip++] & 0xff;
80-
int i1 = ip < iLen ? in[ip++] & 0xff : 0;
81-
int i2 = ip < iLen ? in[ip++] & 0xff : 0;
125+
int i1 = ip < iEnd ? in[ip++] & 0xff : 0;
126+
int i2 = ip < iEnd ? in[ip++] & 0xff : 0;
82127
int o0 = i0 >>> 2;
83128
int o1 = ((i0 & 3) << 4) | (i1 >>> 4);
84129
int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6);
@@ -91,17 +136,36 @@ public static char[] encode (byte[] in, int iLen) {
91136

92137
/**
93138
* Decodes a string from Base64 format.
139+
* No blanks or line breaks are allowed within the Base64 encoded data.
94140
* @param s a Base64 String to be decoded.
95-
* @return A String containing the decoded data.
141+
* @return a String containing the decoded data.
96142
* @throws IllegalArgumentException if the input is not valid Base64 encoded data.
97143
*/
98144
public static String decodeString (String s) {
99145
return new String(decode(s)); }
100146

147+
/**
148+
* Decodes a byte array from Base64 format and ignores line separators and blanks.
149+
* CR, LF, Tab and Space characters are ignored in the input data.
150+
* This method is compatible with <code>sun.misc.BASE64Decoder.decodeBuffer(String)</code>.
151+
* @param s a Base64 String to be decoded.
152+
* @return an array containing the decoded data bytes.
153+
* @throws IllegalArgumentException if the input is not valid Base64 encoded data.
154+
*/
155+
public static byte[] decodeLines (String s) {
156+
char[] buf = new char[s.length()];
157+
int p = 0;
158+
for (int ip = 0; ip < s.length(); ip++) {
159+
char c = s.charAt(ip);
160+
if (c != ' ' && c != '\r' && c != '\n' && c != '\t')
161+
buf[p++] = c; }
162+
return decode(buf, 0, p); }
163+
101164
/**
102165
* Decodes a byte array from Base64 format.
166+
* No blanks or line breaks are allowed within the Base64 encoded data.
103167
* @param s a Base64 String to be decoded.
104-
* @return An array containing the decoded data bytes.
168+
* @return an array containing the decoded data bytes.
105169
* @throws IllegalArgumentException if the input is not valid Base64 encoded data.
106170
*/
107171
public static byte[] decode (String s) {
@@ -111,22 +175,34 @@ public static byte[] decode (String s) {
111175
* Decodes a byte array from Base64 format.
112176
* No blanks or line breaks are allowed within the Base64 encoded data.
113177
* @param in a character array containing the Base64 encoded data.
114-
* @return An array containing the decoded data bytes.
178+
* @return an array containing the decoded data bytes.
115179
* @throws IllegalArgumentException if the input is not valid Base64 encoded data.
116180
*/
117181
public static byte[] decode (char[] in) {
118-
int iLen = in.length;
182+
return decode(in, 0, in.length); }
183+
184+
/**
185+
* Decodes a byte array from Base64 format.
186+
* No blanks or line breaks are allowed within the Base64 encoded data.
187+
* @param in a character array containing the Base64 encoded data.
188+
* @param iOff offset of the first character in <code>in</code> to be processed.
189+
* @param iLen number of characters to process in <code>in</code> starting at <code>iOff</code>.
190+
* @return an array containing the decoded data bytes.
191+
* @throws IllegalArgumentException if the input is not valid Base64 encoded data.
192+
*/
193+
public static byte[] decode (char[] in, int iOff, int iLen) {
119194
if (iLen%4 != 0) throw new IllegalArgumentException ("Length of Base64 encoded input string is not a multiple of 4.");
120-
while (iLen > 0 && in[iLen-1] == '=') iLen--;
195+
while (iLen > 0 && in[iOff+iLen-1] == '=') iLen--;
121196
int oLen = (iLen*3) / 4;
122197
byte[] out = new byte[oLen];
123-
int ip = 0;
198+
int ip = iOff;
199+
int iEnd = iOff + iLen;
124200
int op = 0;
125-
while (ip < iLen) {
201+
while (ip < iEnd) {
126202
int i0 = in[ip++];
127203
int i1 = in[ip++];
128-
int i2 = ip < iLen ? in[ip++] : 'A';
129-
int i3 = ip < iLen ? in[ip++] : 'A';
204+
int i2 = ip < iEnd ? in[ip++] : 'A';
205+
int i3 = ip < iEnd ? in[ip++] : 'A';
130206
if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127)
131207
throw new IllegalArgumentException ("Illegal character in Base64 encoded data.");
132208
int b0 = map2[i0];

src/test/java/TestBase64Coder.java

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
// Tests for the Base64Coder class.
22

33
import biz.source_code.base64Coder.Base64Coder;
4-
import static org.junit.Assert.*;
4+
import java.util.Random;
5+
import static org.junit.Assert.fail;
6+
import static org.junit.Assert.assertEquals;
7+
import static org.junit.Assert.assertArrayEquals;
58
import org.junit.Test;
69

710
public class TestBase64Coder {
@@ -25,21 +28,45 @@ private static void check (String plainText, String base64Text) {
2528
fail ("Check failed for \""+plainText+"\" / \""+base64Text+"\"."); }
2629

2730
// Test Base64Coder against sun.misc.BASE64Encoder/Decoder with random data.
31+
// Line length below 76.
2832
@Test
2933
public void test2() throws Exception {
30-
sun.misc.BASE64Encoder enc = new sun.misc.BASE64Encoder();
31-
sun.misc.BASE64Decoder dec = new sun.misc.BASE64Decoder();
32-
java.util.Random rnd = new java.util.Random(0x538afb92);
34+
final int maxLineLen = 76 - 1; // the Sun encoder adds a CR/LF when a line is longer
35+
final int maxDataBlockLen = (maxLineLen*3) / 4;
36+
sun.misc.BASE64Encoder sunEncoder = new sun.misc.BASE64Encoder();
37+
sun.misc.BASE64Decoder sunDecoder = new sun.misc.BASE64Decoder();
38+
Random rnd = new Random(0x538afb92);
3339
for (int i=0; i<50000; i++) {
34-
int len = rnd.nextInt(55);
40+
int len = rnd.nextInt(maxDataBlockLen+1);
3541
byte[] b0 = new byte[len];
3642
rnd.nextBytes(b0);
3743
String e1 = new String(Base64Coder.encode(b0));
38-
String e2 = enc.encode(b0);
44+
String e2 = sunEncoder.encode(b0);
3945
assertEquals (e2, e1);
4046
byte[] b1 = Base64Coder.decode(e1);
41-
byte[] b2 = dec.decodeBuffer(e2);
47+
byte[] b2 = sunDecoder.decodeBuffer(e2);
4248
assertArrayEquals (b0, b1);
4349
assertArrayEquals (b0, b2); }}
4450

51+
// Test Base64Coder line encoding/decoding against sun.misc.BASE64Encoder/Decoder
52+
// with random data.
53+
@Test
54+
public void test3() throws Exception {
55+
final int maxDataBlockLen = 512;
56+
sun.misc.BASE64Encoder sunEncoder = new sun.misc.BASE64Encoder();
57+
sun.misc.BASE64Decoder sunDecoder = new sun.misc.BASE64Decoder();
58+
Random rnd = new Random(0x39ac7d6e);
59+
for (int i=0; i<10000; i++) {
60+
int len = rnd.nextInt(maxDataBlockLen+1);
61+
byte[] b0 = new byte[len];
62+
rnd.nextBytes(b0);
63+
String e1 = new String(Base64Coder.encodeLines(b0));
64+
String e2 = sunEncoder.encodeBuffer(b0);
65+
assertEquals (e2, e1);
66+
byte[] b1 = Base64Coder.decodeLines(e1);
67+
byte[] b2 = sunDecoder.decodeBuffer(e2);
68+
assertArrayEquals (b0, b1);
69+
assertArrayEquals (b0, b2); }}
70+
71+
4572
} // end class TestBase64Coder

0 commit comments

Comments
 (0)